summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/DocBook/80211.tmpl1
-rw-r--r--Documentation/nfc/nfc-hci.txt33
-rw-r--r--MAINTAINERS9
-rw-r--r--drivers/bcma/bcma_private.h9
-rw-r--r--drivers/bcma/core.c10
-rw-r--r--drivers/bcma/driver_chipcommon.c5
-rw-r--r--drivers/bcma/driver_chipcommon_pmu.c369
-rw-r--r--drivers/bcma/driver_mips.c24
-rw-r--r--drivers/bcma/driver_pci_host.c18
-rw-r--r--drivers/bcma/host_pci.c5
-rw-r--r--drivers/bcma/main.c19
-rw-r--r--drivers/bcma/scan.c30
-rw-r--r--drivers/bcma/sprom.c26
-rw-r--r--drivers/bluetooth/ath3k.c3
-rw-r--r--drivers/bluetooth/bluecard_cs.c10
-rw-r--r--drivers/bluetooth/bpa10x.c2
-rw-r--r--drivers/bluetooth/bt3c_cs.c4
-rw-r--r--drivers/bluetooth/btmrvl_drv.h2
-rw-r--r--drivers/bluetooth/btmrvl_main.c14
-rw-r--r--drivers/bluetooth/btmrvl_sdio.c11
-rw-r--r--drivers/bluetooth/btuart_cs.c4
-rw-r--r--drivers/bluetooth/btusb.c16
-rw-r--r--drivers/bluetooth/dtl1_cs.c4
-rw-r--r--drivers/bluetooth/hci_bcsp.c2
-rw-r--r--drivers/bluetooth/hci_h4.c2
-rw-r--r--drivers/bluetooth/hci_ldisc.c2
-rw-r--r--drivers/bluetooth/hci_ll.c6
-rw-r--r--drivers/misc/Kconfig1
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/iwmc3200top/Kconfig20
-rw-r--r--drivers/misc/iwmc3200top/Makefile29
-rw-r--r--drivers/misc/iwmc3200top/debugfs.c137
-rw-r--r--drivers/misc/iwmc3200top/debugfs.h58
-rw-r--r--drivers/misc/iwmc3200top/fw-download.c358
-rw-r--r--drivers/misc/iwmc3200top/fw-msg.h113
-rw-r--r--drivers/misc/iwmc3200top/iwmc3200top.h205
-rw-r--r--drivers/misc/iwmc3200top/log.c348
-rw-r--r--drivers/misc/iwmc3200top/log.h171
-rw-r--r--drivers/misc/iwmc3200top/main.c662
-rw-r--r--drivers/net/wimax/i2400m/Kconfig22
-rw-r--r--drivers/net/wimax/i2400m/Makefile8
-rw-r--r--drivers/net/wimax/i2400m/driver.c3
-rw-r--r--drivers/net/wimax/i2400m/fw.c3
-rw-r--r--drivers/net/wimax/i2400m/i2400m-sdio.h157
-rw-r--r--drivers/net/wimax/i2400m/i2400m.h13
-rw-r--r--drivers/net/wimax/i2400m/sdio-debug-levels.h22
-rw-r--r--drivers/net/wimax/i2400m/sdio-fw.c210
-rw-r--r--drivers/net/wimax/i2400m/sdio-rx.c301
-rw-r--r--drivers/net/wimax/i2400m/sdio-tx.c177
-rw-r--r--drivers/net/wimax/i2400m/sdio.c602
-rw-r--r--drivers/net/wireless/Kconfig1
-rw-r--r--drivers/net/wireless/Makefile2
-rw-r--r--drivers/net/wireless/airo.c4
-rw-r--r--drivers/net/wireless/ath/ath.h1
-rw-r--r--drivers/net/wireless/ath/ath5k/Kconfig8
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c21
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c268
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.h8
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.c8
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h43
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_mbox.c2
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c28
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c27
-rw-r--r--drivers/net/wireless/ath/ath6kl/target.h1
-rw-r--r--drivers/net/wireless/ath/ath6kl/txrx.c48
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c158
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h58
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.c489
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.h32
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c176
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_hw.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c13
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c87
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mci.c327
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mci.h32
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_paprd.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c116
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h53
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h882
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9340_initvals.h755
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h9
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9485_initvals.h1404
-rw-r--r--drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h1284
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h772
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h7
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/gpio.c37
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_beacon.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_gpio.c122
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c83
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c73
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h15
-rw-r--r--drivers/net/wireless/ath/ath9k/link.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c72
-rw-r--r--drivers/net/wireless/ath/ath9k/mci.c179
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c17
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h24
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c43
-rw-r--r--drivers/net/wireless/ath/carl9170/carl9170.h11
-rw-r--r--drivers/net/wireless/ath/carl9170/fw.c3
-rw-r--r--drivers/net/wireless/ath/carl9170/fwdesc.h3
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c6
-rw-r--r--drivers/net/wireless/ath/carl9170/rx.c49
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c69
-rw-r--r--drivers/net/wireless/ath/carl9170/version.h8
-rw-r--r--drivers/net/wireless/ath/key.c4
-rw-r--r--drivers/net/wireless/b43/phy_n.c17
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/Makefile2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd.h3
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h8
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c29
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c126
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h59
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c9
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c667
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c17
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c3
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/aiutils.c128
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/aiutils.h16
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/ampdu.c5
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/channel.c1223
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/channel.h4
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/dma.c15
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c19
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.c123
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c22
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c140
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/pmu.c172
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/pmu.h3
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/pub.h2
-rw-r--r--drivers/net/wireless/brcm80211/include/brcm_hw_ids.h1
-rw-r--r--drivers/net/wireless/brcm80211/include/soc.h62
-rw-r--r--drivers/net/wireless/iwlegacy/3945-rs.c2
-rw-r--r--drivers/net/wireless/iwlegacy/4965-mac.c4
-rw-r--r--drivers/net/wireless/iwlegacy/common.c23
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/debugfs.c6
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c12
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rxon.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c4
-rw-r--r--drivers/net/wireless/iwmc3200wifi/Kconfig39
-rw-r--r--drivers/net/wireless/iwmc3200wifi/Makefile10
-rw-r--r--drivers/net/wireless/iwmc3200wifi/bus.h57
-rw-r--r--drivers/net/wireless/iwmc3200wifi/cfg80211.c882
-rw-r--r--drivers/net/wireless/iwmc3200wifi/cfg80211.h31
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.c1002
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.h509
-rw-r--r--drivers/net/wireless/iwmc3200wifi/debug.h123
-rw-r--r--drivers/net/wireless/iwmc3200wifi/debugfs.c488
-rw-r--r--drivers/net/wireless/iwmc3200wifi/eeprom.c234
-rw-r--r--drivers/net/wireless/iwmc3200wifi/eeprom.h127
-rw-r--r--drivers/net/wireless/iwmc3200wifi/fw.c416
-rw-r--r--drivers/net/wireless/iwmc3200wifi/fw.h100
-rw-r--r--drivers/net/wireless/iwmc3200wifi/hal.c470
-rw-r--r--drivers/net/wireless/iwmc3200wifi/hal.h237
-rw-r--r--drivers/net/wireless/iwmc3200wifi/iwm.h367
-rw-r--r--drivers/net/wireless/iwmc3200wifi/lmac.h484
-rw-r--r--drivers/net/wireless/iwmc3200wifi/main.c847
-rw-r--r--drivers/net/wireless/iwmc3200wifi/netdev.c191
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.c1701
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.h60
-rw-r--r--drivers/net/wireless/iwmc3200wifi/sdio.c509
-rw-r--r--drivers/net/wireless/iwmc3200wifi/sdio.h64
-rw-r--r--drivers/net/wireless/iwmc3200wifi/trace.c3
-rw-r--r--drivers/net/wireless/iwmc3200wifi/trace.h283
-rw-r--r--drivers/net/wireless/iwmc3200wifi/tx.c529
-rw-r--r--drivers/net/wireless/iwmc3200wifi/umac.h789
-rw-r--r--drivers/net/wireless/libertas/cfg.c1
-rw-r--r--drivers/net/wireless/libertas/host.h1
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c22
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.c5
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.h7
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c192
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c7
-rw-r--r--drivers/net/wireless/mwifiex/fw.h44
-rw-r--r--drivers/net/wireless/mwifiex/ie.c191
-rw-r--r--drivers/net/wireless/mwifiex/init.c1
-rw-r--r--drivers/net/wireless/mwifiex/ioctl.h15
-rw-r--r--drivers/net/wireless/mwifiex/main.c7
-rw-r--r--drivers/net/wireless/mwifiex/main.h20
-rw-r--r--drivers/net/wireless/mwifiex/scan.c25
-rw-r--r--drivers/net/wireless/mwifiex/sdio.c6
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c60
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c57
-rw-r--r--drivers/net/wireless/mwifiex/sta_event.c9
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c3
-rw-r--r--drivers/net/wireless/mwifiex/txrx.c10
-rw-r--r--drivers/net/wireless/mwifiex/uap_cmd.c314
-rw-r--r--drivers/net/wireless/mwifiex/usb.c28
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c3
-rw-r--r--drivers/net/wireless/orinoco/cfg.c2
-rw-r--r--drivers/net/wireless/p54/txrx.c6
-rw-r--r--drivers/net/wireless/rndis_wlan.c7
-rw-r--r--drivers/net/wireless/rt2x00/Kconfig8
-rw-r--r--drivers/net/wireless/rt2x00/rt2800.h173
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c365
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c82
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c9
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c10
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h5
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c20
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/dev.c2
-rw-r--r--drivers/net/wireless/rtlwifi/cam.c5
-rw-r--r--drivers/net/wireless/rtlwifi/pci.c17
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/sw.c3
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/phy.c3
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/sw.c1
-rw-r--r--drivers/net/wireless/ti/wl1251/acx.c2
-rw-r--r--drivers/net/wireless/ti/wl1251/cmd.c9
-rw-r--r--drivers/net/wireless/ti/wl1251/event.c3
-rw-r--r--drivers/net/wireless/ti/wl1251/main.c67
-rw-r--r--drivers/net/wireless/ti/wl1251/spi.c4
-rw-r--r--drivers/net/wireless/ti/wl1251/wl1251.h1
-rw-r--r--drivers/net/wireless/ti/wl12xx/cmd.c16
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c376
-rw-r--r--drivers/net/wireless/ti/wl12xx/wl12xx.h14
-rw-r--r--drivers/net/wireless/ti/wl18xx/acx.h34
-rw-r--r--drivers/net/wireless/ti/wl18xx/io.c39
-rw-r--r--drivers/net/wireless/ti/wl18xx/io.h4
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c386
-rw-r--r--drivers/net/wireless/ti/wl18xx/wl18xx.h7
-rw-r--r--drivers/net/wireless/ti/wlcore/Kconfig1
-rw-r--r--drivers/net/wireless/ti/wlcore/acx.c8
-rw-r--r--drivers/net/wireless/ti/wlcore/acx.h5
-rw-r--r--drivers/net/wireless/ti/wlcore/boot.c135
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c99
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.h27
-rw-r--r--drivers/net/wireless/ti/wlcore/conf.h8
-rw-r--r--drivers/net/wireless/ti/wlcore/debugfs.c255
-rw-r--r--drivers/net/wireless/ti/wlcore/event.c15
-rw-r--r--drivers/net/wireless/ti/wlcore/hw_ops.h12
-rw-r--r--drivers/net/wireless/ti/wlcore/ini.h22
-rw-r--r--drivers/net/wireless/ti/wlcore/init.c59
-rw-r--r--drivers/net/wireless/ti/wlcore/io.c61
-rw-r--r--drivers/net/wireless/ti/wlcore/io.h145
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c419
-rw-r--r--drivers/net/wireless/ti/wlcore/ps.c16
-rw-r--r--drivers/net/wireless/ti/wlcore/rx.c41
-rw-r--r--drivers/net/wireless/ti/wlcore/rx.h10
-rw-r--r--drivers/net/wireless/ti/wlcore/scan.c11
-rw-r--r--drivers/net/wireless/ti/wlcore/sdio.c56
-rw-r--r--drivers/net/wireless/ti/wlcore/spi.c20
-rw-r--r--drivers/net/wireless/ti/wlcore/testmode.c27
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.c86
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.h4
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h49
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore_i.h23
-rw-r--r--drivers/nfc/nfcwilink.c7
-rw-r--r--drivers/nfc/pn533.c224
-rw-r--r--drivers/nfc/pn544_hci.c37
-rw-r--r--include/linux/bcma/bcma.h37
-rw-r--r--include/linux/bcma/bcma_driver_chipcommon.h37
-rw-r--r--include/linux/ieee80211.h212
-rw-r--r--include/linux/nfc.h14
-rw-r--r--include/linux/nl80211.h178
-rw-r--r--include/net/bluetooth/a2mp.h126
-rw-r--r--include/net/bluetooth/bluetooth.h39
-rw-r--r--include/net/bluetooth/hci.h105
-rw-r--r--include/net/bluetooth/hci_core.h29
-rw-r--r--include/net/bluetooth/l2cap.h205
-rw-r--r--include/net/cfg80211.h209
-rw-r--r--include/net/mac80211.h119
-rw-r--r--include/net/nfc/hci.h19
-rw-r--r--include/net/nfc/nfc.h2
-rw-r--r--net/bluetooth/Makefile3
-rw-r--r--net/bluetooth/a2mp.c568
-rw-r--r--net/bluetooth/af_bluetooth.c14
-rw-r--r--net/bluetooth/bnep/core.c21
-rw-r--r--net/bluetooth/bnep/netdev.c16
-rw-r--r--net/bluetooth/bnep/sock.c18
-rw-r--r--net/bluetooth/hci_conn.c98
-rw-r--r--net/bluetooth/hci_core.c214
-rw-r--r--net/bluetooth/hci_event.c357
-rw-r--r--net/bluetooth/hci_sock.c59
-rw-r--r--net/bluetooth/hci_sysfs.c99
-rw-r--r--net/bluetooth/hidp/core.c26
-rw-r--r--net/bluetooth/hidp/sock.c16
-rw-r--r--net/bluetooth/l2cap_core.c2146
-rw-r--r--net/bluetooth/l2cap_sock.c130
-rw-r--r--net/bluetooth/lib.c7
-rw-r--r--net/bluetooth/mgmt.c91
-rw-r--r--net/bluetooth/rfcomm/core.c32
-rw-r--r--net/bluetooth/rfcomm/sock.c21
-rw-r--r--net/bluetooth/rfcomm/tty.c9
-rw-r--r--net/bluetooth/sco.c43
-rw-r--r--net/bluetooth/smp.c18
-rw-r--r--net/mac80211/Kconfig56
-rw-r--r--net/mac80211/Makefile6
-rw-r--r--net/mac80211/agg-rx.c34
-rw-r--r--net/mac80211/agg-tx.c75
-rw-r--r--net/mac80211/cfg.c178
-rw-r--r--net/mac80211/debug.h170
-rw-r--r--net/mac80211/debugfs.c2
-rw-r--r--net/mac80211/debugfs_key.c16
-rw-r--r--net/mac80211/debugfs_netdev.c48
-rw-r--r--net/mac80211/driver-ops.h39
-rw-r--r--net/mac80211/driver-trace.c9
-rw-r--r--net/mac80211/ht.c10
-rw-r--r--net/mac80211/ibss.c91
-rw-r--r--net/mac80211/ieee80211_i.h51
-rw-r--r--net/mac80211/iface.c319
-rw-r--r--net/mac80211/key.c24
-rw-r--r--net/mac80211/main.c31
-rw-r--r--net/mac80211/mesh.c16
-rw-r--r--net/mac80211/mesh.h4
-rw-r--r--net/mac80211/mesh_hwmp.c166
-rw-r--r--net/mac80211/mesh_pathtbl.c30
-rw-r--r--net/mac80211/mesh_plink.c65
-rw-r--r--net/mac80211/mesh_sync.c47
-rw-r--r--net/mac80211/mlme.c311
-rw-r--r--net/mac80211/offchannel.c27
-rw-r--r--net/mac80211/pm.c10
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c10
-rw-r--r--net/mac80211/rx.c131
-rw-r--r--net/mac80211/scan.c116
-rw-r--r--net/mac80211/sta_info.c44
-rw-r--r--net/mac80211/sta_info.h5
-rw-r--r--net/mac80211/status.c20
-rw-r--r--net/mac80211/tkip.c43
-rw-r--r--net/mac80211/trace.c75
-rw-r--r--net/mac80211/trace.h (renamed from net/mac80211/driver-trace.h)80
-rw-r--r--net/mac80211/tx.c90
-rw-r--r--net/mac80211/util.c61
-rw-r--r--net/mac80211/wme.c11
-rw-r--r--net/mac80211/wme.h2
-rw-r--r--net/nfc/core.c38
-rw-r--r--net/nfc/hci/command.c26
-rw-r--r--net/nfc/hci/core.c104
-rw-r--r--net/nfc/hci/hci.h12
-rw-r--r--net/nfc/hci/shdlc.c38
-rw-r--r--net/nfc/llcp/llcp.c342
-rw-r--r--net/nfc/llcp/llcp.h5
-rw-r--r--net/nfc/llcp/sock.c33
-rw-r--r--net/nfc/nci/core.c5
-rw-r--r--net/nfc/nci/ntf.c15
-rw-r--r--net/nfc/netlink.c9
-rw-r--r--net/nfc/rawsock.c5
-rw-r--r--net/wireless/Makefile2
-rw-r--r--net/wireless/ap.c46
-rw-r--r--net/wireless/chan.c60
-rw-r--r--net/wireless/core.c170
-rw-r--r--net/wireless/core.h97
-rw-r--r--net/wireless/ibss.c11
-rw-r--r--net/wireless/mesh.c36
-rw-r--r--net/wireless/mlme.c51
-rw-r--r--net/wireless/nl80211.c726
-rw-r--r--net/wireless/nl80211.h16
-rw-r--r--net/wireless/reg.c7
-rw-r--r--net/wireless/scan.c24
-rw-r--r--net/wireless/sme.c10
-rw-r--r--net/wireless/util.c173
-rw-r--r--net/wireless/wext-compat.c9
367 files changed, 15167 insertions, 25119 deletions
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl
index f3e214f9e256..42e7f030cb16 100644
--- a/Documentation/DocBook/80211.tmpl
+++ b/Documentation/DocBook/80211.tmpl
@@ -404,7 +404,6 @@
!Finclude/net/mac80211.h ieee80211_get_tkip_p1k
!Finclude/net/mac80211.h ieee80211_get_tkip_p1k_iv
!Finclude/net/mac80211.h ieee80211_get_tkip_p2k
-!Finclude/net/mac80211.h ieee80211_key_removed
</chapter>
<chapter id="powersave">
diff --git a/Documentation/nfc/nfc-hci.txt b/Documentation/nfc/nfc-hci.txt
index 320f9336c781..89a339c9b079 100644
--- a/Documentation/nfc/nfc-hci.txt
+++ b/Documentation/nfc/nfc-hci.txt
@@ -178,3 +178,36 @@ ANY_GET_PARAMETER to the reader A gate to get information on the target
that was discovered).
Typically, such an event will be propagated to NFC Core from MSGRXWQ context.
+
+Error management
+----------------
+
+Errors that occur synchronously with the execution of an NFC Core request are
+simply returned as the execution result of the request. These are easy.
+
+Errors that occur asynchronously (e.g. in a background protocol handling thread)
+must be reported such that upper layers don't stay ignorant that something
+went wrong below and know that expected events will probably never happen.
+Handling of these errors is done as follows:
+
+- driver (pn544) fails to deliver an incoming frame: it stores the error such
+that any subsequent call to the driver will result in this error. Then it calls
+the standard nfc_shdlc_recv_frame() with a NULL argument to report the problem
+above. shdlc stores a EREMOTEIO sticky status, which will trigger SMW to
+report above in turn.
+
+- SMW is basically a background thread to handle incoming and outgoing shdlc
+frames. This thread will also check the shdlc sticky status and report to HCI
+when it discovers it is not able to run anymore because of an unrecoverable
+error that happened within shdlc or below. If the problem occurs during shdlc
+connection, the error is reported through the connect completion.
+
+- HCI: if an internal HCI error happens (frame is lost), or HCI is reported an
+error from a lower layer, HCI will either complete the currently executing
+command with that error, or notify NFC Core directly if no command is executing.
+
+- NFC Core: when NFC Core is notified of an error from below and polling is
+active, it will send a tag discovered event with an empty tag list to the user
+space to let it know that the poll operation will never be able to detect a tag.
+If polling is not active and the error was sticky, lower levels will return it
+at next invocation.
diff --git a/MAINTAINERS b/MAINTAINERS
index 3075a2a29511..1b2b77da1584 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1595,6 +1595,7 @@ M: Arend van Spriel <arend@broadcom.com>
M: Franky (Zhenhui) Lin <frankyl@broadcom.com>
M: Kan Yan <kanyan@broadcom.com>
L: linux-wireless@vger.kernel.org
+L: brcm80211-dev-list@broadcom.com
S: Supported
F: drivers/net/wireless/brcm80211/
@@ -3653,14 +3654,6 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git
S: Supported
F: drivers/net/wireless/iwlwifi/
-INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi)
-M: Samuel Ortiz <samuel.ortiz@intel.com>
-M: Intel Linux Wireless <ilw@linux.intel.com>
-L: linux-wireless@vger.kernel.org
-S: Supported
-W: http://wireless.kernel.org/en/users/Drivers/iwmc3200wifi
-F: drivers/net/wireless/iwmc3200wifi/
-
INTEL MANAGEMENT ENGINE (mei)
M: Tomas Winkler <tomas.winkler@intel.com>
L: linux-kernel@vger.kernel.org
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index b81755bb4798..f6589eb7c45f 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -10,6 +10,15 @@
#define BCMA_CORE_SIZE 0x1000
+#define bcma_err(bus, fmt, ...) \
+ pr_err("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
+#define bcma_warn(bus, fmt, ...) \
+ pr_warn("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
+#define bcma_info(bus, fmt, ...) \
+ pr_info("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
+#define bcma_debug(bus, fmt, ...) \
+ pr_debug("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
+
struct bcma_bus;
/* main.c */
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c
index bc6e89212ad3..63c8b470536f 100644
--- a/drivers/bcma/core.c
+++ b/drivers/bcma/core.c
@@ -75,7 +75,7 @@ void bcma_core_set_clockmode(struct bcma_device *core,
udelay(10);
}
if (i)
- pr_err("HT force timeout\n");
+ bcma_err(core->bus, "HT force timeout\n");
break;
case BCMA_CLKMODE_DYNAMIC:
bcma_set32(core, BCMA_CLKCTLST, ~BCMA_CLKCTLST_FORCEHT);
@@ -102,9 +102,9 @@ void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on)
udelay(10);
}
if (i)
- pr_err("PLL enable timeout\n");
+ bcma_err(core->bus, "PLL enable timeout\n");
} else {
- pr_warn("Disabling PLL not supported yet!\n");
+ bcma_warn(core->bus, "Disabling PLL not supported yet!\n");
}
}
EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
@@ -120,8 +120,8 @@ u32 bcma_core_dma_translation(struct bcma_device *core)
else
return BCMA_DMA_TRANSLATION_DMA32_CMT;
default:
- pr_err("DMA translation unknown for host %d\n",
- core->bus->hosttype);
+ bcma_err(core->bus, "DMA translation unknown for host %d\n",
+ core->bus->hosttype);
}
return BCMA_DMA_TRANSLATION_NONE;
}
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index e9f1b3fd252c..a4c3ebcc4c86 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -44,7 +44,7 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
if (cc->capabilities & BCMA_CC_CAP_PMU)
bcma_pmu_init(cc);
if (cc->capabilities & BCMA_CC_CAP_PCTL)
- pr_err("Power control not implemented!\n");
+ bcma_err(cc->core->bus, "Power control not implemented!\n");
if (cc->core->id.rev >= 16) {
if (cc->core->bus->sprom.leddc_on_time &&
@@ -137,8 +137,7 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
| BCMA_CC_CORECTL_UARTCLKEN);
}
} else {
- pr_err("serial not supported on this device ccrev: 0x%x\n",
- ccrev);
+ bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n", ccrev);
return;
}
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index 61ce4054b3c3..44326178db29 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -3,7 +3,8 @@
* ChipCommon Power Management Unit driver
*
* Copyright 2009, Michael Buesch <m@bues.ch>
- * Copyright 2007, Broadcom Corporation
+ * Copyright 2007, 2011, Broadcom Corporation
+ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
@@ -54,39 +55,19 @@ void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
}
EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
-static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
-{
- struct bcma_bus *bus = cc->core->bus;
-
- switch (bus->chipinfo.id) {
- case 0x4313:
- case 0x4331:
- case 43224:
- case 43225:
- break;
- default:
- pr_err("PLL init unknown for device 0x%04X\n",
- bus->chipinfo.id);
- }
-}
-
static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
{
struct bcma_bus *bus = cc->core->bus;
u32 min_msk = 0, max_msk = 0;
switch (bus->chipinfo.id) {
- case 0x4313:
+ case BCMA_CHIP_ID_BCM4313:
min_msk = 0x200D;
max_msk = 0xFFFF;
break;
- case 0x4331:
- case 43224:
- case 43225:
- break;
default:
- pr_err("PMU resource config unknown for device 0x%04X\n",
- bus->chipinfo.id);
+ bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n",
+ bus->chipinfo.id);
}
/* Set the resource masks. */
@@ -94,22 +75,9 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk);
if (max_msk)
bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk);
-}
-
-void bcma_pmu_swreg_init(struct bcma_drv_cc *cc)
-{
- struct bcma_bus *bus = cc->core->bus;
- switch (bus->chipinfo.id) {
- case 0x4313:
- case 0x4331:
- case 43224:
- case 43225:
- break;
- default:
- pr_err("PMU switch/regulators init unknown for device "
- "0x%04X\n", bus->chipinfo.id);
- }
+ /* Add some delay; allow resources to come up and settle. */
+ mdelay(2);
}
/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */
@@ -123,8 +91,11 @@ void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable)
val |= BCMA_CHIPCTL_4331_EXTPA_EN;
if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11)
val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
+ else if (bus->chipinfo.rev > 0)
+ val |= BCMA_CHIPCTL_4331_EXTPA_EN2;
} else {
val &= ~BCMA_CHIPCTL_4331_EXTPA_EN;
+ val &= ~BCMA_CHIPCTL_4331_EXTPA_EN2;
val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
}
bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);
@@ -135,28 +106,38 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
struct bcma_bus *bus = cc->core->bus;
switch (bus->chipinfo.id) {
- case 0x4313:
- bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7);
+ case BCMA_CHIP_ID_BCM4313:
+ /* enable 12 mA drive strenth for 4313 and set chipControl
+ register bit 1 */
+ bcma_chipco_chipctl_maskset(cc, 0,
+ BCMA_CCTRL_4313_12MA_LED_DRIVE,
+ BCMA_CCTRL_4313_12MA_LED_DRIVE);
break;
- case 0x4331:
- case 43431:
+ case BCMA_CHIP_ID_BCM4331:
+ case BCMA_CHIP_ID_BCM43431:
/* Ext PA lines must be enabled for tx on BCM4331 */
bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true);
break;
- case 43224:
+ case BCMA_CHIP_ID_BCM43224:
+ case BCMA_CHIP_ID_BCM43421:
+ /* enable 12 mA drive strenth for 43224 and set chipControl
+ register bit 15 */
if (bus->chipinfo.rev == 0) {
- pr_err("Workarounds for 43224 rev 0 not fully "
- "implemented\n");
- bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0);
+ bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL,
+ BCMA_CCTRL_43224_GPIO_TOGGLE,
+ BCMA_CCTRL_43224_GPIO_TOGGLE);
+ bcma_chipco_chipctl_maskset(cc, 0,
+ BCMA_CCTRL_43224A0_12MA_LED_DRIVE,
+ BCMA_CCTRL_43224A0_12MA_LED_DRIVE);
} else {
- bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
+ bcma_chipco_chipctl_maskset(cc, 0,
+ BCMA_CCTRL_43224B0_12MA_LED_DRIVE,
+ BCMA_CCTRL_43224B0_12MA_LED_DRIVE);
}
break;
- case 43225:
- break;
default:
- pr_err("Workarounds unknown for device 0x%04X\n",
- bus->chipinfo.id);
+ bcma_debug(bus, "Workarounds unknown or not needed for device 0x%04X\n",
+ bus->chipinfo.id);
}
}
@@ -167,8 +148,8 @@ void bcma_pmu_init(struct bcma_drv_cc *cc)
pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP);
cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION);
- pr_debug("Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev,
- pmucap);
+ bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n",
+ cc->pmu.rev, pmucap);
if (cc->pmu.rev == 1)
bcma_cc_mask32(cc, BCMA_CC_PMU_CTL,
@@ -177,12 +158,7 @@ void bcma_pmu_init(struct bcma_drv_cc *cc)
bcma_cc_set32(cc, BCMA_CC_PMU_CTL,
BCMA_CC_PMU_CTL_NOILPONW);
- if (cc->core->id.id == 0x4329 && cc->core->id.rev == 2)
- pr_err("Fix for 4329b0 bad LPOM state not implemented!\n");
-
- bcma_pmu_pll_init(cc);
bcma_pmu_resources_init(cc);
- bcma_pmu_swreg_init(cc);
bcma_pmu_workarounds(cc);
}
@@ -191,23 +167,22 @@ u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
struct bcma_bus *bus = cc->core->bus;
switch (bus->chipinfo.id) {
- case 0x4716:
- case 0x4748:
- case 47162:
- case 0x4313:
- case 0x5357:
- case 0x4749:
- case 53572:
+ case BCMA_CHIP_ID_BCM4716:
+ case BCMA_CHIP_ID_BCM4748:
+ case BCMA_CHIP_ID_BCM47162:
+ case BCMA_CHIP_ID_BCM4313:
+ case BCMA_CHIP_ID_BCM5357:
+ case BCMA_CHIP_ID_BCM4749:
+ case BCMA_CHIP_ID_BCM53572:
/* always 20Mhz */
return 20000 * 1000;
- case 0x5356:
- case 0x5300:
+ case BCMA_CHIP_ID_BCM5356:
+ case BCMA_CHIP_ID_BCM4706:
/* always 25Mhz */
return 25000 * 1000;
default:
- pr_warn("No ALP clock specified for %04X device, "
- "pmu rev. %d, using default %d Hz\n",
- bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
+ bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
+ bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
}
return BCMA_CC_PMU_ALP_CLOCK;
}
@@ -224,7 +199,8 @@ static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
BUG_ON(!m || m > 4);
- if (bus->chipinfo.id == 0x5357 || bus->chipinfo.id == 0x4749) {
+ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
+ bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) {
/* Detect failure in clock setting */
tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
if (tmp & 0x40000)
@@ -250,33 +226,62 @@ static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
return (fc / div) * 1000000;
}
+static u32 bcma_pmu_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
+{
+ u32 tmp, ndiv, p1div, p2div;
+ u32 clock;
+
+ BUG_ON(!m || m > 4);
+
+ /* Get N, P1 and P2 dividers to determine CPU clock */
+ tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PMU6_4706_PROCPLL_OFF);
+ ndiv = (tmp & BCMA_CC_PMU6_4706_PROC_NDIV_INT_MASK)
+ >> BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT;
+ p1div = (tmp & BCMA_CC_PMU6_4706_PROC_P1DIV_MASK)
+ >> BCMA_CC_PMU6_4706_PROC_P1DIV_SHIFT;
+ p2div = (tmp & BCMA_CC_PMU6_4706_PROC_P2DIV_MASK)
+ >> BCMA_CC_PMU6_4706_PROC_P2DIV_SHIFT;
+
+ tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
+ if (tmp & BCMA_CC_CHIPST_4706_PKG_OPTION)
+ /* Low cost bonding: Fixed reference clock 25MHz and m = 4 */
+ clock = (25000000 / 4) * ndiv * p2div / p1div;
+ else
+ /* Fixed reference clock 25MHz and m = 2 */
+ clock = (25000000 / 2) * ndiv * p2div / p1div;
+
+ if (m == BCMA_CC_PMU5_MAINPLL_SSB)
+ clock = clock / 4;
+
+ return clock;
+}
+
/* query bus clock frequency for PMU-enabled chipcommon */
u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
{
struct bcma_bus *bus = cc->core->bus;
switch (bus->chipinfo.id) {
- case 0x4716:
- case 0x4748:
- case 47162:
+ case BCMA_CHIP_ID_BCM4716:
+ case BCMA_CHIP_ID_BCM4748:
+ case BCMA_CHIP_ID_BCM47162:
return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
BCMA_CC_PMU5_MAINPLL_SSB);
- case 0x5356:
+ case BCMA_CHIP_ID_BCM5356:
return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
BCMA_CC_PMU5_MAINPLL_SSB);
- case 0x5357:
- case 0x4749:
+ case BCMA_CHIP_ID_BCM5357:
+ case BCMA_CHIP_ID_BCM4749:
return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
BCMA_CC_PMU5_MAINPLL_SSB);
- case 0x5300:
- return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
- BCMA_CC_PMU5_MAINPLL_SSB);
- case 53572:
+ case BCMA_CHIP_ID_BCM4706:
+ return bcma_pmu_clock_bcm4706(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
+ BCMA_CC_PMU5_MAINPLL_SSB);
+ case BCMA_CHIP_ID_BCM53572:
return 75000000;
default:
- pr_warn("No backplane clock specified for %04X device, "
- "pmu rev. %d, using default %d Hz\n",
- bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
+ bcma_warn(bus, "No backplane clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
+ bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
}
return BCMA_CC_PMU_HT_CLOCK;
}
@@ -286,17 +291,21 @@ u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc)
{
struct bcma_bus *bus = cc->core->bus;
- if (bus->chipinfo.id == 53572)
+ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53572)
return 300000000;
if (cc->pmu.rev >= 5) {
u32 pll;
switch (bus->chipinfo.id) {
- case 0x5356:
+ case BCMA_CHIP_ID_BCM4706:
+ return bcma_pmu_clock_bcm4706(cc,
+ BCMA_CC_PMU4706_MAINPLL_PLL0,
+ BCMA_CC_PMU5_MAINPLL_CPU);
+ case BCMA_CHIP_ID_BCM5356:
pll = BCMA_CC_PMU5356_MAINPLL_PLL0;
break;
- case 0x5357:
- case 0x4749:
+ case BCMA_CHIP_ID_BCM5357:
+ case BCMA_CHIP_ID_BCM4749:
pll = BCMA_CC_PMU5357_MAINPLL_PLL0;
break;
default:
@@ -304,10 +313,188 @@ u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc)
break;
}
- /* TODO: if (bus->chipinfo.id == 0x5300)
- return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */
return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
}
return bcma_pmu_get_clockcontrol(cc);
}
+
+static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset,
+ u32 value)
+{
+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value);
+}
+
+void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
+{
+ u32 tmp = 0;
+ u8 phypll_offset = 0;
+ u8 bcm5357_bcm43236_p1div[] = {0x1, 0x5, 0x5};
+ u8 bcm5357_bcm43236_ndiv[] = {0x30, 0xf6, 0xfc};
+ struct bcma_bus *bus = cc->core->bus;
+
+ switch (bus->chipinfo.id) {
+ case BCMA_CHIP_ID_BCM5357:
+ case BCMA_CHIP_ID_BCM4749:
+ case BCMA_CHIP_ID_BCM53572:
+ /* 5357[ab]0, 43236[ab]0, and 6362b0 */
+
+ /* BCM5357 needs to touch PLL1_PLLCTL[02],
+ so offset PLL0_PLLCTL[02] by 6 */
+ phypll_offset = (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
+ bus->chipinfo.id == BCMA_CHIP_ID_BCM4749 ||
+ bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0;
+
+ /* RMW only the P1 divider */
+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR,
+ BCMA_CC_PMU_PLL_CTL0 + phypll_offset);
+ tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
+ tmp &= (~(BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK));
+ tmp |= (bcm5357_bcm43236_p1div[spuravoid] << BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT);
+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp);
+
+ /* RMW only the int feedback divider */
+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR,
+ BCMA_CC_PMU_PLL_CTL2 + phypll_offset);
+ tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
+ tmp &= ~(BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK);
+ tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT;
+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp);
+
+ tmp = 1 << 10;
+ break;
+
+ case BCMA_CHIP_ID_BCM4331:
+ case BCMA_CHIP_ID_BCM43431:
+ if (spuravoid == 2) {
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+ 0x11500014);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+ 0x0FC00a08);
+ } else if (spuravoid == 1) {
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+ 0x11500014);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+ 0x0F600a08);
+ } else {
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+ 0x11100014);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+ 0x03000a08);
+ }
+ tmp = 1 << 10;
+ break;
+
+ case BCMA_CHIP_ID_BCM43224:
+ case BCMA_CHIP_ID_BCM43225:
+ case BCMA_CHIP_ID_BCM43421:
+ if (spuravoid == 1) {
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+ 0x11500010);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
+ 0x000C0C06);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+ 0x0F600a08);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
+ 0x00000000);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
+ 0x2001E920);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
+ 0x88888815);
+ } else {
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+ 0x11100010);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
+ 0x000c0c06);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+ 0x03000a08);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
+ 0x00000000);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
+ 0x200005c0);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
+ 0x88888815);
+ }
+ tmp = 1 << 10;
+ break;
+
+ case BCMA_CHIP_ID_BCM4716:
+ case BCMA_CHIP_ID_BCM4748:
+ case BCMA_CHIP_ID_BCM47162:
+ if (spuravoid == 1) {
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+ 0x11500060);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
+ 0x080C0C06);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+ 0x0F600000);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
+ 0x00000000);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
+ 0x2001E924);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
+ 0x88888815);
+ } else {
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+ 0x11100060);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
+ 0x080c0c06);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+ 0x03000000);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
+ 0x00000000);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
+ 0x200005c0);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
+ 0x88888815);
+ }
+
+ tmp = 3 << 9;
+ break;
+
+ case BCMA_CHIP_ID_BCM43227:
+ case BCMA_CHIP_ID_BCM43228:
+ case BCMA_CHIP_ID_BCM43428:
+ /* LCNXN */
+ /* PLL Settings for spur avoidance on/off mode,
+ no on2 support for 43228A0 */
+ if (spuravoid == 1) {
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+ 0x01100014);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
+ 0x040C0C06);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+ 0x03140A08);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
+ 0x00333333);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
+ 0x202C2820);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
+ 0x88888815);
+ } else {
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+ 0x11100014);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
+ 0x040c0c06);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+ 0x03000a08);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
+ 0x00000000);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
+ 0x200005c0);
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
+ 0x88888815);
+ }
+ tmp = 1 << 10;
+ break;
+ default:
+ bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
+ bus->chipinfo.id);
+ break;
+ }
+
+ tmp |= bcma_cc_read32(cc, BCMA_CC_PMU_CTL);
+ bcma_cc_write32(cc, BCMA_CC_PMU_CTL, tmp);
+}
+EXPORT_SYMBOL_GPL(bcma_pmu_spuravoid_pllupdate);
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c
index c3e9dff4224e..ef34ed25bf00 100644
--- a/drivers/bcma/driver_mips.c
+++ b/drivers/bcma/driver_mips.c
@@ -22,15 +22,15 @@
/* The 47162a0 hangs when reading MIPS DMP registers registers */
static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
{
- return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 &&
- dev->id.id == BCMA_CORE_MIPS_74K;
+ return dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM47162 &&
+ dev->bus->chipinfo.rev == 0 && dev->id.id == BCMA_CORE_MIPS_74K;
}
/* The 5357b0 hangs when reading USB20H DMP registers */
static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
{
- return (dev->bus->chipinfo.id == 0x5357 ||
- dev->bus->chipinfo.id == 0x4749) &&
+ return (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
+ dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) &&
dev->bus->chipinfo.pkg == 11 &&
dev->id.id == BCMA_CORE_USB20_HOST;
}
@@ -143,8 +143,8 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
1 << irqflag);
}
- pr_info("set_irq: core 0x%04x, irq %d => %d\n",
- dev->id.id, oldirq + 2, irq + 2);
+ bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n",
+ dev->id.id, oldirq + 2, irq + 2);
}
static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
@@ -173,7 +173,7 @@ u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
return bcma_pmu_get_clockcpu(&bus->drv_cc);
- pr_err("No PMU available, need this to get the cpu clock\n");
+ bcma_err(bus, "No PMU available, need this to get the cpu clock\n");
return 0;
}
EXPORT_SYMBOL(bcma_cpu_clock);
@@ -185,10 +185,10 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
case BCMA_CC_FLASHT_STSER:
case BCMA_CC_FLASHT_ATSER:
- pr_err("Serial flash not supported.\n");
+ bcma_err(bus, "Serial flash not supported.\n");
break;
case BCMA_CC_FLASHT_PARA:
- pr_info("found parallel flash.\n");
+ bcma_info(bus, "found parallel flash.\n");
bus->drv_cc.pflash.window = 0x1c000000;
bus->drv_cc.pflash.window_size = 0x02000000;
@@ -199,7 +199,7 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
bus->drv_cc.pflash.buswidth = 2;
break;
default:
- pr_err("flash not supported.\n");
+ bcma_err(bus, "flash not supported.\n");
}
}
@@ -209,7 +209,7 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
struct bcma_device *core;
bus = mcore->core->bus;
- pr_info("Initializing MIPS core...\n");
+ bcma_info(bus, "Initializing MIPS core...\n");
if (!mcore->setup_done)
mcore->assigned_irqs = 1;
@@ -244,7 +244,7 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
break;
}
}
- pr_info("IRQ reconfiguration done\n");
+ bcma_info(bus, "IRQ reconfiguration done\n");
bcma_core_mips_dump_irq(bus);
if (mcore->setup_done)
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c
index b9a86edfec39..cbae2c231336 100644
--- a/drivers/bcma/driver_pci_host.c
+++ b/drivers/bcma/driver_pci_host.c
@@ -36,7 +36,7 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
return false;
if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
- pr_info("This PCI core is disabled and not working\n");
+ bcma_info(bus, "This PCI core is disabled and not working\n");
return false;
}
@@ -215,7 +215,8 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
} else {
writel(val, mmio);
- if (chipid == 0x4716 || chipid == 0x4748)
+ if (chipid == BCMA_CHIP_ID_BCM4716 ||
+ chipid == BCMA_CHIP_ID_BCM4748)
readl(mmio);
}
@@ -340,6 +341,7 @@ static u8 __devinit bcma_find_pci_capability(struct bcma_drv_pci *pc,
*/
static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc)
{
+ struct bcma_bus *bus = pc->core->bus;
u8 cap_ptr, root_ctrl, root_cap, dev;
u16 val16;
int i;
@@ -378,7 +380,8 @@ static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc)
udelay(10);
}
if (val16 == 0x1)
- pr_err("PCI: Broken device in slot %d\n", dev);
+ bcma_err(bus, "PCI: Broken device in slot %d\n",
+ dev);
}
}
}
@@ -391,11 +394,11 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
u32 pci_membase_1G;
unsigned long io_map_base;
- pr_info("PCIEcore in host mode found\n");
+ bcma_info(bus, "PCIEcore in host mode found\n");
pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL);
if (!pc_host) {
- pr_err("can not allocate memory");
+ bcma_err(bus, "can not allocate memory");
return;
}
@@ -434,13 +437,14 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
* as mips can't generate 64-bit address on the
* backplane.
*/
- if (bus->chipinfo.id == 0x4716 || bus->chipinfo.id == 0x4748) {
+ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4716 ||
+ bus->chipinfo.id == BCMA_CHIP_ID_BCM4748) {
pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
BCMA_SOC_PCI_MEM_SZ - 1;
pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
BCMA_CORE_PCI_SBTOPCI_MEM | BCMA_SOC_PCI_MEM);
- } else if (bus->chipinfo.id == 0x5300) {
+ } else if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
tmp = BCMA_CORE_PCI_SBTOPCI_MEM;
tmp |= BCMA_CORE_PCI_SBTOPCI_PREF;
tmp |= BCMA_CORE_PCI_SBTOPCI_BURST;
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index 6c05cf470f96..11b32d2642df 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -18,7 +18,7 @@ static void bcma_host_pci_switch_core(struct bcma_device *core)
pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2,
core->wrap);
core->bus->mapped_core = core;
- pr_debug("Switched to core: 0x%X\n", core->id.id);
+ bcma_debug(core->bus, "Switched to core: 0x%X\n", core->id.id);
}
/* Provides access to the requested core. Returns base offset that has to be
@@ -188,7 +188,7 @@ static int __devinit bcma_host_pci_probe(struct pci_dev *dev,
/* SSB needed additional powering up, do we have any AMBA PCI cards? */
if (!pci_is_pcie(dev))
- pr_err("PCI card detected, report problems.\n");
+ bcma_err(bus, "PCI card detected, report problems.\n");
/* Map MMIO */
err = -ENOMEM;
@@ -268,6 +268,7 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 7e138ec21357..7ff4bac6f9e1 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -118,8 +118,9 @@ static int bcma_register_cores(struct bcma_bus *bus)
err = device_register(&core->dev);
if (err) {
- pr_err("Could not register dev for core 0x%03X\n",
- core->id.id);
+ bcma_err(bus,
+ "Could not register dev for core 0x%03X\n",
+ core->id.id);
continue;
}
core->dev_registered = true;
@@ -151,7 +152,7 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
/* Scan for devices (cores) */
err = bcma_bus_scan(bus);
if (err) {
- pr_err("Failed to scan: %d\n", err);
+ bcma_err(bus, "Failed to scan: %d\n", err);
return -1;
}
@@ -179,14 +180,14 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
/* Try to get SPROM */
err = bcma_sprom_get(bus);
if (err == -ENOENT) {
- pr_err("No SPROM available\n");
+ bcma_err(bus, "No SPROM available\n");
} else if (err)
- pr_err("Failed to get SPROM: %d\n", err);
+ bcma_err(bus, "Failed to get SPROM: %d\n", err);
/* Register found cores */
bcma_register_cores(bus);
- pr_info("Bus registered\n");
+ bcma_info(bus, "Bus registered\n");
return 0;
}
@@ -214,7 +215,7 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
/* Scan for chip common core */
err = bcma_bus_scan_early(bus, &match, core_cc);
if (err) {
- pr_err("Failed to scan for common core: %d\n", err);
+ bcma_err(bus, "Failed to scan for common core: %d\n", err);
return -1;
}
@@ -226,7 +227,7 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
/* Scan for mips core */
err = bcma_bus_scan_early(bus, &match, core_mips);
if (err) {
- pr_err("Failed to scan for mips core: %d\n", err);
+ bcma_err(bus, "Failed to scan for mips core: %d\n", err);
return -1;
}
@@ -244,7 +245,7 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
bcma_core_mips_init(&bus->drv_mips);
}
- pr_info("Early bus registered\n");
+ bcma_info(bus, "Early bus registered\n");
return 0;
}
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index 5ed0718fc660..a0272bbfc4f6 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -28,6 +28,12 @@ static const struct bcma_device_id_name bcma_arm_device_names[] = {
static const struct bcma_device_id_name bcma_bcm_device_names[] = {
{ BCMA_CORE_OOB_ROUTER, "OOB Router" },
+ { BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" },
+ { BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" },
+ { BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" },
+ { BCMA_CORE_AMEMC, "AMEMC (DDR)" },
+ { BCMA_CORE_ALTA, "ALTA (I2S)" },
+ { BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" },
{ BCMA_CORE_INVALID, "Invalid" },
{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
{ BCMA_CORE_ILINE20, "ILine 20" },
@@ -334,7 +340,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
if (tmp <= 0) {
return -EILSEQ;
} else {
- pr_info("Bridge found\n");
+ bcma_info(bus, "Bridge found\n");
return -ENXIO;
}
}
@@ -421,8 +427,8 @@ void bcma_init_bus(struct bcma_bus *bus)
chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
- pr_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n",
- chipinfo->id, chipinfo->rev, chipinfo->pkg);
+ bcma_info(bus, "Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n",
+ chipinfo->id, chipinfo->rev, chipinfo->pkg);
bus->init_done = true;
}
@@ -476,11 +482,10 @@ int bcma_bus_scan(struct bcma_bus *bus)
other_core = bcma_find_core_reverse(bus, core->id.id);
core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1;
- pr_info("Core %d found: %s "
- "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
- core->core_index, bcma_device_name(&core->id),
- core->id.manuf, core->id.id, core->id.rev,
- core->id.class);
+ bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
+ core->core_index, bcma_device_name(&core->id),
+ core->id.manuf, core->id.id, core->id.rev,
+ core->id.class);
list_add(&core->list, &bus->cores);
}
@@ -532,11 +537,10 @@ int __init bcma_bus_scan_early(struct bcma_bus *bus,
core->core_index = core_num++;
bus->nr_cores++;
- pr_info("Core %d found: %s "
- "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
- core->core_index, bcma_device_name(&core->id),
- core->id.manuf, core->id.id, core->id.rev,
- core->id.class);
+ bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
+ core->core_index, bcma_device_name(&core->id),
+ core->id.manuf, core->id.id, core->id.rev,
+ core->id.class);
list_add(&core->list, &bus->cores);
err = 0;
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index f16f42d36071..26823d97fd9f 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -60,11 +60,11 @@ static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus,
if (err)
goto fail;
- pr_debug("Using SPROM revision %d provided by"
- " platform.\n", bus->sprom.revision);
+ bcma_debug(bus, "Using SPROM revision %d provided by platform.\n",
+ bus->sprom.revision);
return 0;
fail:
- pr_warn("Using fallback SPROM failed (err %d)\n", err);
+ bcma_warn(bus, "Using fallback SPROM failed (err %d)\n", err);
return err;
}
@@ -468,11 +468,11 @@ static bool bcma_sprom_ext_available(struct bcma_bus *bus)
/* older chipcommon revisions use chip status register */
chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
switch (bus->chipinfo.id) {
- case 0x4313:
+ case BCMA_CHIP_ID_BCM4313:
present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT;
break;
- case 0x4331:
+ case BCMA_CHIP_ID_BCM4331:
present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT;
break;
@@ -494,16 +494,16 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
switch (bus->chipinfo.id) {
- case 0x4313:
+ case BCMA_CHIP_ID_BCM4313:
present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT;
break;
- case 0x4331:
+ case BCMA_CHIP_ID_BCM4331:
present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT;
break;
- case 43224:
- case 43225:
+ case BCMA_CHIP_ID_BCM43224:
+ case BCMA_CHIP_ID_BCM43225:
/* for these chips OTP is always available */
present = true;
break;
@@ -579,13 +579,15 @@ int bcma_sprom_get(struct bcma_bus *bus)
if (!sprom)
return -ENOMEM;
- if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431)
+ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
+ bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
- pr_debug("SPROM offset 0x%x\n", offset);
+ bcma_debug(bus, "SPROM offset 0x%x\n", offset);
bcma_sprom_read(bus, offset, sprom);
- if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431)
+ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
+ bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
err = bcma_sprom_valid(sprom);
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index ad591bd240ec..10308cd8a7ed 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -63,6 +63,7 @@ static struct usb_device_id ath3k_table[] = {
/* Atheros AR3011 with sflash firmware*/
{ USB_DEVICE(0x0CF3, 0x3002) },
+ { USB_DEVICE(0x0CF3, 0xE019) },
{ USB_DEVICE(0x13d3, 0x3304) },
{ USB_DEVICE(0x0930, 0x0215) },
{ USB_DEVICE(0x0489, 0xE03D) },
@@ -77,6 +78,7 @@ static struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x04CA, 0x3005) },
{ USB_DEVICE(0x13d3, 0x3362) },
{ USB_DEVICE(0x0CF3, 0xE004) },
+ { USB_DEVICE(0x0930, 0x0219) },
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE02C) },
@@ -101,6 +103,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU22 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 1fcd92380356..585c88e01893 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -231,12 +231,12 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
}
do {
- register unsigned int iobase = info->p_dev->resource[0]->start;
- register unsigned int offset;
- register unsigned char command;
- register unsigned long ready_bit;
+ unsigned int iobase = info->p_dev->resource[0]->start;
+ unsigned int offset;
+ unsigned char command;
+ unsigned long ready_bit;
register struct sk_buff *skb;
- register int len;
+ int len;
clear_bit(XMIT_WAKEUP, &(info->tx_state));
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index 609861a53c28..29caaed2d715 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -470,7 +470,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
hdev->flush = bpa10x_flush;
hdev->send = bpa10x_send_frame;
- set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
+ set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
err = hci_register_dev(hdev);
if (err < 0) {
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 308c8599ab55..b2b0fbbb43b5 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -186,9 +186,9 @@ static void bt3c_write_wakeup(bt3c_info_t *info)
return;
do {
- register unsigned int iobase = info->p_dev->resource[0]->start;
+ unsigned int iobase = info->p_dev->resource[0]->start;
register struct sk_buff *skb;
- register int len;
+ int len;
if (!pcmcia_dev_present(info->p_dev))
break;
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index 94f2d65131c4..27068d149380 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -136,7 +136,7 @@ int btmrvl_remove_card(struct btmrvl_private *priv);
void btmrvl_interrupt(struct btmrvl_private *priv);
-void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb);
+bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb);
int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb);
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd);
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index 681ca9d18e12..dc304def8400 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -44,23 +44,33 @@ void btmrvl_interrupt(struct btmrvl_private *priv)
}
EXPORT_SYMBOL_GPL(btmrvl_interrupt);
-void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
+bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
{
struct hci_event_hdr *hdr = (void *) skb->data;
struct hci_ev_cmd_complete *ec;
- u16 opcode, ocf;
+ u16 opcode, ocf, ogf;
if (hdr->evt == HCI_EV_CMD_COMPLETE) {
ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE);
opcode = __le16_to_cpu(ec->opcode);
ocf = hci_opcode_ocf(opcode);
+ ogf = hci_opcode_ogf(opcode);
+
if (ocf == BT_CMD_MODULE_CFG_REQ &&
priv->btmrvl_dev.sendcmdflag) {
priv->btmrvl_dev.sendcmdflag = false;
priv->adapter->cmd_complete = true;
wake_up_interruptible(&priv->adapter->cmd_wait_q);
}
+
+ if (ogf == OGF) {
+ BT_DBG("vendor event skipped: ogf 0x%4.4x", ogf);
+ kfree_skb(skb);
+ return false;
+ }
}
+
+ return true;
}
EXPORT_SYMBOL_GPL(btmrvl_check_evtpkt);
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index a853244e7fd7..cf7588edba0d 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -110,6 +110,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = {
/* Marvell SD8787 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
+ /* Marvell SD8787 Bluetooth AMP device */
+ { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911B),
+ .driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
/* Marvell SD8797 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
.driver_data = (unsigned long) &btmrvl_sdio_sd8797 },
@@ -562,10 +565,12 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
skb_put(skb, buf_len);
skb_pull(skb, SDIO_HEADER_LEN);
- if (type == HCI_EVENT_PKT)
- btmrvl_check_evtpkt(priv, skb);
+ if (type == HCI_EVENT_PKT) {
+ if (btmrvl_check_evtpkt(priv, skb))
+ hci_recv_frame(skb);
+ } else
+ hci_recv_frame(skb);
- hci_recv_frame(skb);
hdev->stat.byte_rx += buf_len;
break;
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index c4fc2f3fc32c..65b8d996840c 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -140,9 +140,9 @@ static void btuart_write_wakeup(btuart_info_t *info)
}
do {
- register unsigned int iobase = info->p_dev->resource[0]->start;
+ unsigned int iobase = info->p_dev->resource[0]->start;
register struct sk_buff *skb;
- register int len;
+ int len;
clear_bit(XMIT_WAKEUP, &(info->tx_state));
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index c9463af8e564..e27221411036 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -21,15 +21,7 @@
*
*/
-#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/skbuff.h>
-
#include <linux/usb.h>
#include <net/bluetooth/bluetooth.h>
@@ -125,6 +117,7 @@ static struct usb_device_id blacklist_table[] = {
/* Atheros 3011 with sflash firmware */
{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
+ { USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
@@ -139,6 +132,7 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
@@ -1026,7 +1020,7 @@ static int btusb_probe(struct usb_interface *intf,
data->isoc = usb_ifnum_to_if(data->udev, 1);
if (!reset)
- set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
+ set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) {
if (!disable_scofix)
@@ -1038,7 +1032,7 @@ static int btusb_probe(struct usb_interface *intf,
if (id->driver_info & BTUSB_DIGIANSWER) {
data->cmdreq_type = USB_TYPE_VENDOR;
- set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
+ set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
}
if (id->driver_info & BTUSB_CSR) {
@@ -1046,7 +1040,7 @@ static int btusb_probe(struct usb_interface *intf,
/* Old firmware would otherwise execute USB reset */
if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117)
- set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
+ set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
}
if (id->driver_info & BTUSB_SNIFFER) {
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 6e8d96189684..b1b37ccd3cd4 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -144,9 +144,9 @@ static void dtl1_write_wakeup(dtl1_info_t *info)
}
do {
- register unsigned int iobase = info->p_dev->resource[0]->start;
+ unsigned int iobase = info->p_dev->resource[0]->start;
register struct sk_buff *skb;
- register int len;
+ int len;
clear_bit(XMIT_WAKEUP, &(info->tx_state));
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 661a8dc4d2f8..57e502e06080 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -552,7 +552,7 @@ static u16 bscp_get_crc(struct bcsp_struct *bcsp)
static int bcsp_recv(struct hci_uart *hu, void *data, int count)
{
struct bcsp_struct *bcsp = hu->priv;
- register unsigned char *ptr;
+ unsigned char *ptr;
BT_DBG("hu %p count %d rx_state %d rx_count %ld",
hu, count, bcsp->rx_state, bcsp->rx_count);
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index 748329468d26..c60623f206d4 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -126,7 +126,7 @@ static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
static inline int h4_check_data_len(struct h4_struct *h4, int len)
{
- register int room = skb_tailroom(h4->rx_skb);
+ int room = skb_tailroom(h4->rx_skb);
BT_DBG("len %d room %d", len, room);
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index e564579a6115..2f9b796e106e 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -394,7 +394,7 @@ static int hci_uart_register_dev(struct hci_uart *hu)
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags))
- set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
+ set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags))
hdev->dev_type = HCI_AMP;
diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c
index b874c0efde24..ff6d589c34a5 100644
--- a/drivers/bluetooth/hci_ll.c
+++ b/drivers/bluetooth/hci_ll.c
@@ -348,7 +348,7 @@ static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb)
static inline int ll_check_data_len(struct ll_struct *ll, int len)
{
- register int room = skb_tailroom(ll->rx_skb);
+ int room = skb_tailroom(ll->rx_skb);
BT_DBG("len %d room %d", len, room);
@@ -374,11 +374,11 @@ static inline int ll_check_data_len(struct ll_struct *ll, int len)
static int ll_recv(struct hci_uart *hu, void *data, int count)
{
struct ll_struct *ll = hu->priv;
- register char *ptr;
+ char *ptr;
struct hci_event_hdr *eh;
struct hci_acl_hdr *ah;
struct hci_sco_hdr *sh;
- register int len, type, dlen;
+ int len, type, dlen;
BT_DBG("hu %p count %d rx_state %ld rx_count %ld", hu, count, ll->rx_state, ll->rx_count);
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 2661f6e366f9..154f3ef07631 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -511,7 +511,6 @@ config USB_SWITCH_FSA9480
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
-source "drivers/misc/iwmc3200top/Kconfig"
source "drivers/misc/ti-st/Kconfig"
source "drivers/misc/lis3lv02d/Kconfig"
source "drivers/misc/carma/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 456972faaeb3..b88df7a350b8 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -36,7 +36,6 @@ obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o
obj-$(CONFIG_DS1682) += ds1682.o
obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o
obj-$(CONFIG_C2PORT) += c2port/
-obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/
obj-$(CONFIG_HMC6352) += hmc6352.o
obj-y += eeprom/
obj-y += cb710/
diff --git a/drivers/misc/iwmc3200top/Kconfig b/drivers/misc/iwmc3200top/Kconfig
deleted file mode 100644
index 9e4b88fb57f1..000000000000
--- a/drivers/misc/iwmc3200top/Kconfig
+++ /dev/null
@@ -1,20 +0,0 @@
-config IWMC3200TOP
- tristate "Intel Wireless MultiCom Top Driver"
- depends on MMC && EXPERIMENTAL
- select FW_LOADER
- ---help---
- Intel Wireless MultiCom 3200 Top driver is responsible for
- for firmware load and enabled coms enumeration
-
-config IWMC3200TOP_DEBUG
- bool "Enable full debug output of iwmc3200top Driver"
- depends on IWMC3200TOP
- ---help---
- Enable full debug output of iwmc3200top Driver
-
-config IWMC3200TOP_DEBUGFS
- bool "Enable Debugfs debugging interface for iwmc3200top"
- depends on IWMC3200TOP
- ---help---
- Enable creation of debugfs files for iwmc3200top
-
diff --git a/drivers/misc/iwmc3200top/Makefile b/drivers/misc/iwmc3200top/Makefile
deleted file mode 100644
index fbf53fb4634e..000000000000
--- a/drivers/misc/iwmc3200top/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-# iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
-# drivers/misc/iwmc3200top/Makefile
-#
-# Copyright (C) 2009 Intel Corporation. All rights reserved.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License version
-# 2 as published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
-#
-#
-# Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
-# -
-#
-#
-
-obj-$(CONFIG_IWMC3200TOP) += iwmc3200top.o
-iwmc3200top-objs := main.o fw-download.o
-iwmc3200top-$(CONFIG_IWMC3200TOP_DEBUG) += log.o
-iwmc3200top-$(CONFIG_IWMC3200TOP_DEBUGFS) += debugfs.o
diff --git a/drivers/misc/iwmc3200top/debugfs.c b/drivers/misc/iwmc3200top/debugfs.c
deleted file mode 100644
index 62fbaec48207..000000000000
--- a/drivers/misc/iwmc3200top/debugfs.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/debufs.c
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
- * -
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio.h>
-#include <linux/debugfs.h>
-
-#include "iwmc3200top.h"
-#include "fw-msg.h"
-#include "log.h"
-#include "debugfs.h"
-
-
-
-/* Constants definition */
-#define HEXADECIMAL_RADIX 16
-
-/* Functions definition */
-
-
-#define DEBUGFS_ADD(name, parent) do { \
- dbgfs->dbgfs_##parent##_files.file_##name = \
- debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv, \
- &iwmct_dbgfs_##name##_ops); \
-} while (0)
-
-#define DEBUGFS_RM(name) do { \
- debugfs_remove(name); \
- name = NULL; \
-} while (0)
-
-#define DEBUGFS_READ_FUNC(name) \
-ssize_t iwmct_dbgfs_##name##_read(struct file *file, \
- char __user *user_buf, \
- size_t count, loff_t *ppos);
-
-#define DEBUGFS_WRITE_FUNC(name) \
-ssize_t iwmct_dbgfs_##name##_write(struct file *file, \
- const char __user *user_buf, \
- size_t count, loff_t *ppos);
-
-#define DEBUGFS_READ_FILE_OPS(name) \
- DEBUGFS_READ_FUNC(name) \
- static const struct file_operations iwmct_dbgfs_##name##_ops = { \
- .read = iwmct_dbgfs_##name##_read, \
- .open = iwmct_dbgfs_open_file_generic, \
- .llseek = generic_file_llseek, \
- };
-
-#define DEBUGFS_WRITE_FILE_OPS(name) \
- DEBUGFS_WRITE_FUNC(name) \
- static const struct file_operations iwmct_dbgfs_##name##_ops = { \
- .write = iwmct_dbgfs_##name##_write, \
- .open = iwmct_dbgfs_open_file_generic, \
- .llseek = generic_file_llseek, \
- };
-
-#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
- DEBUGFS_READ_FUNC(name) \
- DEBUGFS_WRITE_FUNC(name) \
- static const struct file_operations iwmct_dbgfs_##name##_ops = {\
- .write = iwmct_dbgfs_##name##_write, \
- .read = iwmct_dbgfs_##name##_read, \
- .open = iwmct_dbgfs_open_file_generic, \
- .llseek = generic_file_llseek, \
- };
-
-
-/* Debugfs file ops definitions */
-
-/*
- * Create the debugfs files and directories
- *
- */
-void iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name)
-{
- struct iwmct_debugfs *dbgfs;
-
- dbgfs = kzalloc(sizeof(struct iwmct_debugfs), GFP_KERNEL);
- if (!dbgfs) {
- LOG_ERROR(priv, DEBUGFS, "failed to allocate %zd bytes\n",
- sizeof(struct iwmct_debugfs));
- return;
- }
-
- priv->dbgfs = dbgfs;
- dbgfs->name = name;
- dbgfs->dir_drv = debugfs_create_dir(name, NULL);
- if (!dbgfs->dir_drv) {
- LOG_ERROR(priv, DEBUGFS, "failed to create debugfs dir\n");
- return;
- }
-
- return;
-}
-
-/**
- * Remove the debugfs files and directories
- *
- */
-void iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs)
-{
- if (!dbgfs)
- return;
-
- DEBUGFS_RM(dbgfs->dir_drv);
- kfree(dbgfs);
- dbgfs = NULL;
-}
-
diff --git a/drivers/misc/iwmc3200top/debugfs.h b/drivers/misc/iwmc3200top/debugfs.h
deleted file mode 100644
index 71d45759b40f..000000000000
--- a/drivers/misc/iwmc3200top/debugfs.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/debufs.h
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
- * -
- *
- */
-
-#ifndef __DEBUGFS_H__
-#define __DEBUGFS_H__
-
-
-#ifdef CONFIG_IWMC3200TOP_DEBUGFS
-
-struct iwmct_debugfs {
- const char *name;
- struct dentry *dir_drv;
- struct dir_drv_files {
- } dbgfs_drv_files;
-};
-
-void iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name);
-void iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs);
-
-#else /* CONFIG_IWMC3200TOP_DEBUGFS */
-
-struct iwmct_debugfs;
-
-static inline void
-iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name)
-{}
-
-static inline void
-iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs)
-{}
-
-#endif /* CONFIG_IWMC3200TOP_DEBUGFS */
-
-#endif /* __DEBUGFS_H__ */
-
diff --git a/drivers/misc/iwmc3200top/fw-download.c b/drivers/misc/iwmc3200top/fw-download.c
deleted file mode 100644
index e27afde6e99f..000000000000
--- a/drivers/misc/iwmc3200top/fw-download.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/fw-download.c
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
- * -
- *
- */
-
-#include <linux/firmware.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/slab.h>
-#include <asm/unaligned.h>
-
-#include "iwmc3200top.h"
-#include "log.h"
-#include "fw-msg.h"
-
-#define CHECKSUM_BYTES_NUM sizeof(u32)
-
-/**
- init parser struct with file
- */
-static int iwmct_fw_parser_init(struct iwmct_priv *priv, const u8 *file,
- size_t file_size, size_t block_size)
-{
- struct iwmct_parser *parser = &priv->parser;
- struct iwmct_fw_hdr *fw_hdr = &parser->versions;
-
- LOG_TRACE(priv, FW_DOWNLOAD, "-->\n");
-
- LOG_INFO(priv, FW_DOWNLOAD, "file_size=%zd\n", file_size);
-
- parser->file = file;
- parser->file_size = file_size;
- parser->cur_pos = 0;
- parser->entry_point = 0;
- parser->buf = kzalloc(block_size, GFP_KERNEL);
- if (!parser->buf) {
- LOG_ERROR(priv, FW_DOWNLOAD, "kzalloc error\n");
- return -ENOMEM;
- }
- parser->buf_size = block_size;
-
- /* extract fw versions */
- memcpy(fw_hdr, parser->file, sizeof(struct iwmct_fw_hdr));
- LOG_INFO(priv, FW_DOWNLOAD, "fw versions are:\n"
- "top %u.%u.%u gps %u.%u.%u bt %u.%u.%u tic %s\n",
- fw_hdr->top_major, fw_hdr->top_minor, fw_hdr->top_revision,
- fw_hdr->gps_major, fw_hdr->gps_minor, fw_hdr->gps_revision,
- fw_hdr->bt_major, fw_hdr->bt_minor, fw_hdr->bt_revision,
- fw_hdr->tic_name);
-
- parser->cur_pos += sizeof(struct iwmct_fw_hdr);
-
- LOG_TRACE(priv, FW_DOWNLOAD, "<--\n");
- return 0;
-}
-
-static bool iwmct_checksum(struct iwmct_priv *priv)
-{
- struct iwmct_parser *parser = &priv->parser;
- __le32 *file = (__le32 *)parser->file;
- int i, pad, steps;
- u32 accum = 0;
- u32 checksum;
- u32 mask = 0xffffffff;
-
- pad = (parser->file_size - CHECKSUM_BYTES_NUM) % 4;
- steps = (parser->file_size - CHECKSUM_BYTES_NUM) / 4;
-
- LOG_INFO(priv, FW_DOWNLOAD, "pad=%d steps=%d\n", pad, steps);
-
- for (i = 0; i < steps; i++)
- accum += le32_to_cpu(file[i]);
-
- if (pad) {
- mask <<= 8 * (4 - pad);
- accum += le32_to_cpu(file[steps]) & mask;
- }
-
- checksum = get_unaligned_le32((__le32 *)(parser->file +
- parser->file_size - CHECKSUM_BYTES_NUM));
-
- LOG_INFO(priv, FW_DOWNLOAD,
- "compare checksum accum=0x%x to checksum=0x%x\n",
- accum, checksum);
-
- return checksum == accum;
-}
-
-static int iwmct_parse_next_section(struct iwmct_priv *priv, const u8 **p_sec,
- size_t *sec_size, __le32 *sec_addr)
-{
- struct iwmct_parser *parser = &priv->parser;
- struct iwmct_dbg *dbg = &priv->dbg;
- struct iwmct_fw_sec_hdr *sec_hdr;
-
- LOG_TRACE(priv, FW_DOWNLOAD, "-->\n");
-
- while (parser->cur_pos + sizeof(struct iwmct_fw_sec_hdr)
- <= parser->file_size) {
-
- sec_hdr = (struct iwmct_fw_sec_hdr *)
- (parser->file + parser->cur_pos);
- parser->cur_pos += sizeof(struct iwmct_fw_sec_hdr);
-
- LOG_INFO(priv, FW_DOWNLOAD,
- "sec hdr: type=%s addr=0x%x size=%d\n",
- sec_hdr->type, sec_hdr->target_addr,
- sec_hdr->data_size);
-
- if (strcmp(sec_hdr->type, "ENT") == 0)
- parser->entry_point = le32_to_cpu(sec_hdr->target_addr);
- else if (strcmp(sec_hdr->type, "LBL") == 0)
- strcpy(dbg->label_fw, parser->file + parser->cur_pos);
- else if (((strcmp(sec_hdr->type, "TOP") == 0) &&
- (priv->barker & BARKER_DNLOAD_TOP_MSK)) ||
- ((strcmp(sec_hdr->type, "GPS") == 0) &&
- (priv->barker & BARKER_DNLOAD_GPS_MSK)) ||
- ((strcmp(sec_hdr->type, "BTH") == 0) &&
- (priv->barker & BARKER_DNLOAD_BT_MSK))) {
- *sec_addr = sec_hdr->target_addr;
- *sec_size = le32_to_cpu(sec_hdr->data_size);
- *p_sec = parser->file + parser->cur_pos;
- parser->cur_pos += le32_to_cpu(sec_hdr->data_size);
- return 1;
- } else if (strcmp(sec_hdr->type, "LOG") != 0)
- LOG_WARNING(priv, FW_DOWNLOAD,
- "skipping section type %s\n",
- sec_hdr->type);
-
- parser->cur_pos += le32_to_cpu(sec_hdr->data_size);
- LOG_INFO(priv, FW_DOWNLOAD,
- "finished with section cur_pos=%zd\n", parser->cur_pos);
- }
-
- LOG_TRACE(priv, INIT, "<--\n");
- return 0;
-}
-
-static int iwmct_download_section(struct iwmct_priv *priv, const u8 *p_sec,
- size_t sec_size, __le32 addr)
-{
- struct iwmct_parser *parser = &priv->parser;
- struct iwmct_fw_load_hdr *hdr = (struct iwmct_fw_load_hdr *)parser->buf;
- const u8 *cur_block = p_sec;
- size_t sent = 0;
- int cnt = 0;
- int ret = 0;
- u32 cmd = 0;
-
- LOG_TRACE(priv, FW_DOWNLOAD, "-->\n");
- LOG_INFO(priv, FW_DOWNLOAD, "Download address 0x%x size 0x%zx\n",
- addr, sec_size);
-
- while (sent < sec_size) {
- int i;
- u32 chksm = 0;
- u32 reset = atomic_read(&priv->reset);
- /* actual FW data */
- u32 data_size = min(parser->buf_size - sizeof(*hdr),
- sec_size - sent);
- /* Pad to block size */
- u32 trans_size = (data_size + sizeof(*hdr) +
- IWMC_SDIO_BLK_SIZE - 1) &
- ~(IWMC_SDIO_BLK_SIZE - 1);
- ++cnt;
-
- /* in case of reset, interrupt FW DOWNLAOD */
- if (reset) {
- LOG_INFO(priv, FW_DOWNLOAD,
- "Reset detected. Abort FW download!!!");
- ret = -ECANCELED;
- goto exit;
- }
-
- memset(parser->buf, 0, parser->buf_size);
- cmd |= IWMC_OPCODE_WRITE << CMD_HDR_OPCODE_POS;
- cmd |= IWMC_CMD_SIGNATURE << CMD_HDR_SIGNATURE_POS;
- cmd |= (priv->dbg.direct ? 1 : 0) << CMD_HDR_DIRECT_ACCESS_POS;
- cmd |= (priv->dbg.checksum ? 1 : 0) << CMD_HDR_USE_CHECKSUM_POS;
- hdr->data_size = cpu_to_le32(data_size);
- hdr->target_addr = addr;
-
- /* checksum is allowed for sizes divisible by 4 */
- if (data_size & 0x3)
- cmd &= ~CMD_HDR_USE_CHECKSUM_MSK;
-
- memcpy(hdr->data, cur_block, data_size);
-
-
- if (cmd & CMD_HDR_USE_CHECKSUM_MSK) {
-
- chksm = data_size + le32_to_cpu(addr) + cmd;
- for (i = 0; i < data_size >> 2; i++)
- chksm += ((u32 *)cur_block)[i];
-
- hdr->block_chksm = cpu_to_le32(chksm);
- LOG_INFO(priv, FW_DOWNLOAD, "Checksum = 0x%X\n",
- hdr->block_chksm);
- }
-
- LOG_INFO(priv, FW_DOWNLOAD, "trans#%d, len=%d, sent=%zd, "
- "sec_size=%zd, startAddress 0x%X\n",
- cnt, trans_size, sent, sec_size, addr);
-
- if (priv->dbg.dump)
- LOG_HEXDUMP(FW_DOWNLOAD, parser->buf, trans_size);
-
-
- hdr->cmd = cpu_to_le32(cmd);
- /* send it down */
- /* TODO: add more proper sending and error checking */
- ret = iwmct_tx(priv, parser->buf, trans_size);
- if (ret != 0) {
- LOG_INFO(priv, FW_DOWNLOAD,
- "iwmct_tx returned %d\n", ret);
- goto exit;
- }
-
- addr = cpu_to_le32(le32_to_cpu(addr) + data_size);
- sent += data_size;
- cur_block = p_sec + sent;
-
- if (priv->dbg.blocks && (cnt + 1) >= priv->dbg.blocks) {
- LOG_INFO(priv, FW_DOWNLOAD,
- "Block number limit is reached [%d]\n",
- priv->dbg.blocks);
- break;
- }
- }
-
- if (sent < sec_size)
- ret = -EINVAL;
-exit:
- LOG_TRACE(priv, FW_DOWNLOAD, "<--\n");
- return ret;
-}
-
-static int iwmct_kick_fw(struct iwmct_priv *priv, bool jump)
-{
- struct iwmct_parser *parser = &priv->parser;
- struct iwmct_fw_load_hdr *hdr = (struct iwmct_fw_load_hdr *)parser->buf;
- int ret;
- u32 cmd;
-
- LOG_TRACE(priv, FW_DOWNLOAD, "-->\n");
-
- memset(parser->buf, 0, parser->buf_size);
- cmd = IWMC_CMD_SIGNATURE << CMD_HDR_SIGNATURE_POS;
- if (jump) {
- cmd |= IWMC_OPCODE_JUMP << CMD_HDR_OPCODE_POS;
- hdr->target_addr = cpu_to_le32(parser->entry_point);
- LOG_INFO(priv, FW_DOWNLOAD, "jump address 0x%x\n",
- parser->entry_point);
- } else {
- cmd |= IWMC_OPCODE_LAST_COMMAND << CMD_HDR_OPCODE_POS;
- LOG_INFO(priv, FW_DOWNLOAD, "last command\n");
- }
-
- hdr->cmd = cpu_to_le32(cmd);
-
- LOG_HEXDUMP(FW_DOWNLOAD, parser->buf, sizeof(*hdr));
- /* send it down */
- /* TODO: add more proper sending and error checking */
- ret = iwmct_tx(priv, parser->buf, IWMC_SDIO_BLK_SIZE);
- if (ret)
- LOG_INFO(priv, FW_DOWNLOAD, "iwmct_tx returned %d", ret);
-
- LOG_TRACE(priv, FW_DOWNLOAD, "<--\n");
- return 0;
-}
-
-int iwmct_fw_load(struct iwmct_priv *priv)
-{
- const u8 *fw_name = FW_NAME(FW_API_VER);
- const struct firmware *raw;
- const u8 *pdata;
- size_t len;
- __le32 addr;
- int ret;
-
-
- LOG_INFO(priv, FW_DOWNLOAD, "barker download request 0x%x is:\n",
- priv->barker);
- LOG_INFO(priv, FW_DOWNLOAD, "******* Top FW %s requested ********\n",
- (priv->barker & BARKER_DNLOAD_TOP_MSK) ? "was" : "not");
- LOG_INFO(priv, FW_DOWNLOAD, "******* GPS FW %s requested ********\n",
- (priv->barker & BARKER_DNLOAD_GPS_MSK) ? "was" : "not");
- LOG_INFO(priv, FW_DOWNLOAD, "******* BT FW %s requested ********\n",
- (priv->barker & BARKER_DNLOAD_BT_MSK) ? "was" : "not");
-
-
- /* get the firmware */
- ret = request_firmware(&raw, fw_name, &priv->func->dev);
- if (ret < 0) {
- LOG_ERROR(priv, FW_DOWNLOAD, "%s request_firmware failed %d\n",
- fw_name, ret);
- goto exit;
- }
-
- if (raw->size < sizeof(struct iwmct_fw_sec_hdr)) {
- LOG_ERROR(priv, FW_DOWNLOAD, "%s smaller then (%zd) (%zd)\n",
- fw_name, sizeof(struct iwmct_fw_sec_hdr), raw->size);
- goto exit;
- }
-
- LOG_INFO(priv, FW_DOWNLOAD, "Read firmware '%s'\n", fw_name);
-
- /* clear parser struct */
- ret = iwmct_fw_parser_init(priv, raw->data, raw->size, priv->trans_len);
- if (ret < 0) {
- LOG_ERROR(priv, FW_DOWNLOAD,
- "iwmct_parser_init failed: Reason %d\n", ret);
- goto exit;
- }
-
- if (!iwmct_checksum(priv)) {
- LOG_ERROR(priv, FW_DOWNLOAD, "checksum error\n");
- ret = -EINVAL;
- goto exit;
- }
-
- /* download firmware to device */
- while (iwmct_parse_next_section(priv, &pdata, &len, &addr)) {
- ret = iwmct_download_section(priv, pdata, len, addr);
- if (ret) {
- LOG_ERROR(priv, FW_DOWNLOAD,
- "%s download section failed\n", fw_name);
- goto exit;
- }
- }
-
- ret = iwmct_kick_fw(priv, !!(priv->barker & BARKER_DNLOAD_JUMP_MSK));
-
-exit:
- kfree(priv->parser.buf);
- release_firmware(raw);
- return ret;
-}
diff --git a/drivers/misc/iwmc3200top/fw-msg.h b/drivers/misc/iwmc3200top/fw-msg.h
deleted file mode 100644
index 9e26b75bd482..000000000000
--- a/drivers/misc/iwmc3200top/fw-msg.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/fw-msg.h
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
- * -
- *
- */
-
-#ifndef __FWMSG_H__
-#define __FWMSG_H__
-
-#define COMM_TYPE_D2H 0xFF
-#define COMM_TYPE_H2D 0xEE
-
-#define COMM_CATEGORY_OPERATIONAL 0x00
-#define COMM_CATEGORY_DEBUG 0x01
-#define COMM_CATEGORY_TESTABILITY 0x02
-#define COMM_CATEGORY_DIAGNOSTICS 0x03
-
-#define OP_DBG_ZSTR_MSG cpu_to_le16(0x1A)
-
-#define FW_LOG_SRC_MAX 32
-#define FW_LOG_SRC_ALL 255
-
-#define FW_STRING_TABLE_ADDR cpu_to_le32(0x0C000000)
-
-#define CMD_DBG_LOG_LEVEL cpu_to_le16(0x0001)
-#define CMD_TST_DEV_RESET cpu_to_le16(0x0060)
-#define CMD_TST_FUNC_RESET cpu_to_le16(0x0062)
-#define CMD_TST_IFACE_RESET cpu_to_le16(0x0064)
-#define CMD_TST_CPU_UTILIZATION cpu_to_le16(0x0065)
-#define CMD_TST_TOP_DEEP_SLEEP cpu_to_le16(0x0080)
-#define CMD_TST_WAKEUP cpu_to_le16(0x0081)
-#define CMD_TST_FUNC_WAKEUP cpu_to_le16(0x0082)
-#define CMD_TST_FUNC_DEEP_SLEEP_REQUEST cpu_to_le16(0x0083)
-#define CMD_TST_GET_MEM_DUMP cpu_to_le16(0x0096)
-
-#define OP_OPR_ALIVE cpu_to_le16(0x0010)
-#define OP_OPR_CMD_ACK cpu_to_le16(0x001F)
-#define OP_OPR_CMD_NACK cpu_to_le16(0x0020)
-#define OP_TST_MEM_DUMP cpu_to_le16(0x0043)
-
-#define CMD_FLAG_PADDING_256 0x80
-
-#define FW_HCMD_BLOCK_SIZE 256
-
-struct msg_hdr {
- u8 type;
- u8 category;
- __le16 opcode;
- u8 seqnum;
- u8 flags;
- __le16 length;
-} __attribute__((__packed__));
-
-struct log_hdr {
- __le32 timestamp;
- u8 severity;
- u8 logsource;
- __le16 reserved;
-} __attribute__((__packed__));
-
-struct mdump_hdr {
- u8 dmpid;
- u8 frag;
- __le16 size;
- __le32 addr;
-} __attribute__((__packed__));
-
-struct top_msg {
- struct msg_hdr hdr;
- union {
- /* D2H messages */
- struct {
- struct log_hdr log_hdr;
- u8 data[1];
- } __attribute__((__packed__)) log;
-
- struct {
- struct log_hdr log_hdr;
- struct mdump_hdr md_hdr;
- u8 data[1];
- } __attribute__((__packed__)) mdump;
-
- /* H2D messages */
- struct {
- u8 logsource;
- u8 sevmask;
- } __attribute__((__packed__)) logdefs[FW_LOG_SRC_MAX];
- struct mdump_hdr mdump_req;
- } u;
-} __attribute__((__packed__));
-
-
-#endif /* __FWMSG_H__ */
diff --git a/drivers/misc/iwmc3200top/iwmc3200top.h b/drivers/misc/iwmc3200top/iwmc3200top.h
deleted file mode 100644
index 620973ed8bf9..000000000000
--- a/drivers/misc/iwmc3200top/iwmc3200top.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/iwmc3200top.h
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
- * -
- *
- */
-
-#ifndef __IWMC3200TOP_H__
-#define __IWMC3200TOP_H__
-
-#include <linux/workqueue.h>
-
-#define DRV_NAME "iwmc3200top"
-#define FW_API_VER 1
-#define _FW_NAME(api) DRV_NAME "." #api ".fw"
-#define FW_NAME(api) _FW_NAME(api)
-
-#define IWMC_SDIO_BLK_SIZE 256
-#define IWMC_DEFAULT_TR_BLK 64
-#define IWMC_SDIO_DATA_ADDR 0x0
-#define IWMC_SDIO_INTR_ENABLE_ADDR 0x14
-#define IWMC_SDIO_INTR_STATUS_ADDR 0x13
-#define IWMC_SDIO_INTR_CLEAR_ADDR 0x13
-#define IWMC_SDIO_INTR_GET_SIZE_ADDR 0x2C
-
-#define COMM_HUB_HEADER_LENGTH 16
-#define LOGGER_HEADER_LENGTH 10
-
-
-#define BARKER_DNLOAD_BT_POS 0
-#define BARKER_DNLOAD_BT_MSK BIT(BARKER_DNLOAD_BT_POS)
-#define BARKER_DNLOAD_GPS_POS 1
-#define BARKER_DNLOAD_GPS_MSK BIT(BARKER_DNLOAD_GPS_POS)
-#define BARKER_DNLOAD_TOP_POS 2
-#define BARKER_DNLOAD_TOP_MSK BIT(BARKER_DNLOAD_TOP_POS)
-#define BARKER_DNLOAD_RESERVED1_POS 3
-#define BARKER_DNLOAD_RESERVED1_MSK BIT(BARKER_DNLOAD_RESERVED1_POS)
-#define BARKER_DNLOAD_JUMP_POS 4
-#define BARKER_DNLOAD_JUMP_MSK BIT(BARKER_DNLOAD_JUMP_POS)
-#define BARKER_DNLOAD_SYNC_POS 5
-#define BARKER_DNLOAD_SYNC_MSK BIT(BARKER_DNLOAD_SYNC_POS)
-#define BARKER_DNLOAD_RESERVED2_POS 6
-#define BARKER_DNLOAD_RESERVED2_MSK (0x3 << BARKER_DNLOAD_RESERVED2_POS)
-#define BARKER_DNLOAD_BARKER_POS 8
-#define BARKER_DNLOAD_BARKER_MSK (0xffffff << BARKER_DNLOAD_BARKER_POS)
-
-#define IWMC_BARKER_REBOOT (0xdeadbe << BARKER_DNLOAD_BARKER_POS)
-/* whole field barker */
-#define IWMC_BARKER_ACK 0xfeedbabe
-
-#define IWMC_CMD_SIGNATURE 0xcbbc
-
-#define CMD_HDR_OPCODE_POS 0
-#define CMD_HDR_OPCODE_MSK_MSK (0xf << CMD_HDR_OPCODE_MSK_POS)
-#define CMD_HDR_RESPONSE_CODE_POS 4
-#define CMD_HDR_RESPONSE_CODE_MSK (0xf << CMD_HDR_RESPONSE_CODE_POS)
-#define CMD_HDR_USE_CHECKSUM_POS 8
-#define CMD_HDR_USE_CHECKSUM_MSK BIT(CMD_HDR_USE_CHECKSUM_POS)
-#define CMD_HDR_RESPONSE_REQUIRED_POS 9
-#define CMD_HDR_RESPONSE_REQUIRED_MSK BIT(CMD_HDR_RESPONSE_REQUIRED_POS)
-#define CMD_HDR_DIRECT_ACCESS_POS 10
-#define CMD_HDR_DIRECT_ACCESS_MSK BIT(CMD_HDR_DIRECT_ACCESS_POS)
-#define CMD_HDR_RESERVED_POS 11
-#define CMD_HDR_RESERVED_MSK BIT(0x1f << CMD_HDR_RESERVED_POS)
-#define CMD_HDR_SIGNATURE_POS 16
-#define CMD_HDR_SIGNATURE_MSK BIT(0xffff << CMD_HDR_SIGNATURE_POS)
-
-enum {
- IWMC_OPCODE_PING = 0,
- IWMC_OPCODE_READ = 1,
- IWMC_OPCODE_WRITE = 2,
- IWMC_OPCODE_JUMP = 3,
- IWMC_OPCODE_REBOOT = 4,
- IWMC_OPCODE_PERSISTENT_WRITE = 5,
- IWMC_OPCODE_PERSISTENT_READ = 6,
- IWMC_OPCODE_READ_MODIFY_WRITE = 7,
- IWMC_OPCODE_LAST_COMMAND = 15
-};
-
-struct iwmct_fw_load_hdr {
- __le32 cmd;
- __le32 target_addr;
- __le32 data_size;
- __le32 block_chksm;
- u8 data[0];
-};
-
-/**
- * struct iwmct_fw_hdr
- * holds all sw components versions
- */
-struct iwmct_fw_hdr {
- u8 top_major;
- u8 top_minor;
- u8 top_revision;
- u8 gps_major;
- u8 gps_minor;
- u8 gps_revision;
- u8 bt_major;
- u8 bt_minor;
- u8 bt_revision;
- u8 tic_name[31];
-};
-
-/**
- * struct iwmct_fw_sec_hdr
- * @type: function type
- * @data_size: section's data size
- * @target_addr: download address
- */
-struct iwmct_fw_sec_hdr {
- u8 type[4];
- __le32 data_size;
- __le32 target_addr;
-};
-
-/**
- * struct iwmct_parser
- * @file: fw image
- * @file_size: fw size
- * @cur_pos: position in file
- * @buf: temp buf for download
- * @buf_size: size of buf
- * @entry_point: address to jump in fw kick-off
- */
-struct iwmct_parser {
- const u8 *file;
- size_t file_size;
- size_t cur_pos;
- u8 *buf;
- size_t buf_size;
- u32 entry_point;
- struct iwmct_fw_hdr versions;
-};
-
-
-struct iwmct_work_struct {
- struct list_head list;
- ssize_t iosize;
-};
-
-struct iwmct_dbg {
- int blocks;
- bool dump;
- bool jump;
- bool direct;
- bool checksum;
- bool fw_download;
- int block_size;
- int download_trans_blks;
-
- char label_fw[256];
-};
-
-struct iwmct_debugfs;
-
-struct iwmct_priv {
- struct sdio_func *func;
- struct iwmct_debugfs *dbgfs;
- struct iwmct_parser parser;
- atomic_t reset;
- atomic_t dev_sync;
- u32 trans_len;
- u32 barker;
- struct iwmct_dbg dbg;
-
- /* drivers work items */
- struct work_struct bus_rescan_worker;
- struct work_struct isr_worker;
-
- /* drivers wait queue */
- wait_queue_head_t wait_q;
-
- /* rx request list */
- struct list_head read_req_list;
-};
-
-extern int iwmct_tx(struct iwmct_priv *priv, void *src, int count);
-extern int iwmct_fw_load(struct iwmct_priv *priv);
-
-extern void iwmct_dbg_init_params(struct iwmct_priv *drv);
-extern void iwmct_dbg_init_drv_attrs(struct device_driver *drv);
-extern void iwmct_dbg_remove_drv_attrs(struct device_driver *drv);
-extern int iwmct_send_hcmd(struct iwmct_priv *priv, u8 *cmd, u16 len);
-
-#endif /* __IWMC3200TOP_H__ */
diff --git a/drivers/misc/iwmc3200top/log.c b/drivers/misc/iwmc3200top/log.c
deleted file mode 100644
index a36a55a49cac..000000000000
--- a/drivers/misc/iwmc3200top/log.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/log.c
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
- * -
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/slab.h>
-#include <linux/ctype.h>
-#include "fw-msg.h"
-#include "iwmc3200top.h"
-#include "log.h"
-
-/* Maximal hexadecimal string size of the FW memdump message */
-#define LOG_MSG_SIZE_MAX 12400
-
-/* iwmct_logdefs is a global used by log macros */
-u8 iwmct_logdefs[LOG_SRC_MAX];
-static u8 iwmct_fw_logdefs[FW_LOG_SRC_MAX];
-
-
-static int _log_set_log_filter(u8 *logdefs, int size, u8 src, u8 logmask)
-{
- int i;
-
- if (src < size)
- logdefs[src] = logmask;
- else if (src == LOG_SRC_ALL)
- for (i = 0; i < size; i++)
- logdefs[i] = logmask;
- else
- return -1;
-
- return 0;
-}
-
-
-int iwmct_log_set_filter(u8 src, u8 logmask)
-{
- return _log_set_log_filter(iwmct_logdefs, LOG_SRC_MAX, src, logmask);
-}
-
-
-int iwmct_log_set_fw_filter(u8 src, u8 logmask)
-{
- return _log_set_log_filter(iwmct_fw_logdefs,
- FW_LOG_SRC_MAX, src, logmask);
-}
-
-
-static int log_msg_format_hex(char *str, int slen, u8 *ibuf,
- int ilen, char *pref)
-{
- int pos = 0;
- int i;
- int len;
-
- for (pos = 0, i = 0; pos < slen - 2 && pref[i] != '\0'; i++, pos++)
- str[pos] = pref[i];
-
- for (i = 0; pos < slen - 2 && i < ilen; pos += len, i++)
- len = snprintf(&str[pos], slen - pos - 1, " %2.2X", ibuf[i]);
-
- if (i < ilen)
- return -1;
-
- return 0;
-}
-
-/* NOTE: This function is not thread safe.
- Currently it's called only from sdio rx worker - no race there
-*/
-void iwmct_log_top_message(struct iwmct_priv *priv, u8 *buf, int len)
-{
- struct top_msg *msg;
- static char logbuf[LOG_MSG_SIZE_MAX];
-
- msg = (struct top_msg *)buf;
-
- if (len < sizeof(msg->hdr) + sizeof(msg->u.log.log_hdr)) {
- LOG_ERROR(priv, FW_MSG, "Log message from TOP "
- "is too short %d (expected %zd)\n",
- len, sizeof(msg->hdr) + sizeof(msg->u.log.log_hdr));
- return;
- }
-
- if (!(iwmct_fw_logdefs[msg->u.log.log_hdr.logsource] &
- BIT(msg->u.log.log_hdr.severity)) ||
- !(iwmct_logdefs[LOG_SRC_FW_MSG] & BIT(msg->u.log.log_hdr.severity)))
- return;
-
- switch (msg->hdr.category) {
- case COMM_CATEGORY_TESTABILITY:
- if (!(iwmct_logdefs[LOG_SRC_TST] &
- BIT(msg->u.log.log_hdr.severity)))
- return;
- if (log_msg_format_hex(logbuf, LOG_MSG_SIZE_MAX, buf,
- le16_to_cpu(msg->hdr.length) +
- sizeof(msg->hdr), "<TST>"))
- LOG_WARNING(priv, TST,
- "TOP TST message is too long, truncating...");
- LOG_WARNING(priv, TST, "%s\n", logbuf);
- break;
- case COMM_CATEGORY_DEBUG:
- if (msg->hdr.opcode == OP_DBG_ZSTR_MSG)
- LOG_INFO(priv, FW_MSG, "%s %s", "<DBG>",
- ((u8 *)msg) + sizeof(msg->hdr)
- + sizeof(msg->u.log.log_hdr));
- else {
- if (log_msg_format_hex(logbuf, LOG_MSG_SIZE_MAX, buf,
- le16_to_cpu(msg->hdr.length)
- + sizeof(msg->hdr),
- "<DBG>"))
- LOG_WARNING(priv, FW_MSG,
- "TOP DBG message is too long,"
- "truncating...");
- LOG_WARNING(priv, FW_MSG, "%s\n", logbuf);
- }
- break;
- default:
- break;
- }
-}
-
-static int _log_get_filter_str(u8 *logdefs, int logdefsz, char *buf, int size)
-{
- int i, pos, len;
- for (i = 0, pos = 0; (pos < size-1) && (i < logdefsz); i++) {
- len = snprintf(&buf[pos], size - pos - 1, "0x%02X%02X,",
- i, logdefs[i]);
- pos += len;
- }
- buf[pos-1] = '\n';
- buf[pos] = '\0';
-
- if (i < logdefsz)
- return -1;
- return 0;
-}
-
-int log_get_filter_str(char *buf, int size)
-{
- return _log_get_filter_str(iwmct_logdefs, LOG_SRC_MAX, buf, size);
-}
-
-int log_get_fw_filter_str(char *buf, int size)
-{
- return _log_get_filter_str(iwmct_fw_logdefs, FW_LOG_SRC_MAX, buf, size);
-}
-
-#define HEXADECIMAL_RADIX 16
-#define LOG_SRC_FORMAT 7 /* log level is in format of "0xXXXX," */
-
-ssize_t show_iwmct_log_level(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwmct_priv *priv = dev_get_drvdata(d);
- char *str_buf;
- int buf_size;
- ssize_t ret;
-
- buf_size = (LOG_SRC_FORMAT * LOG_SRC_MAX) + 1;
- str_buf = kzalloc(buf_size, GFP_KERNEL);
- if (!str_buf) {
- LOG_ERROR(priv, DEBUGFS,
- "failed to allocate %d bytes\n", buf_size);
- ret = -ENOMEM;
- goto exit;
- }
-
- if (log_get_filter_str(str_buf, buf_size) < 0) {
- ret = -EINVAL;
- goto exit;
- }
-
- ret = sprintf(buf, "%s", str_buf);
-
-exit:
- kfree(str_buf);
- return ret;
-}
-
-ssize_t store_iwmct_log_level(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwmct_priv *priv = dev_get_drvdata(d);
- char *token, *str_buf = NULL;
- long val;
- ssize_t ret = count;
- u8 src, mask;
-
- if (!count)
- goto exit;
-
- str_buf = kzalloc(count, GFP_KERNEL);
- if (!str_buf) {
- LOG_ERROR(priv, DEBUGFS,
- "failed to allocate %zd bytes\n", count);
- ret = -ENOMEM;
- goto exit;
- }
-
- memcpy(str_buf, buf, count);
-
- while ((token = strsep(&str_buf, ",")) != NULL) {
- while (isspace(*token))
- ++token;
- if (strict_strtol(token, HEXADECIMAL_RADIX, &val)) {
- LOG_ERROR(priv, DEBUGFS,
- "failed to convert string to long %s\n",
- token);
- ret = -EINVAL;
- goto exit;
- }
-
- mask = val & 0xFF;
- src = (val & 0XFF00) >> 8;
- iwmct_log_set_filter(src, mask);
- }
-
-exit:
- kfree(str_buf);
- return ret;
-}
-
-ssize_t show_iwmct_log_level_fw(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwmct_priv *priv = dev_get_drvdata(d);
- char *str_buf;
- int buf_size;
- ssize_t ret;
-
- buf_size = (LOG_SRC_FORMAT * FW_LOG_SRC_MAX) + 2;
-
- str_buf = kzalloc(buf_size, GFP_KERNEL);
- if (!str_buf) {
- LOG_ERROR(priv, DEBUGFS,
- "failed to allocate %d bytes\n", buf_size);
- ret = -ENOMEM;
- goto exit;
- }
-
- if (log_get_fw_filter_str(str_buf, buf_size) < 0) {
- ret = -EINVAL;
- goto exit;
- }
-
- ret = sprintf(buf, "%s", str_buf);
-
-exit:
- kfree(str_buf);
- return ret;
-}
-
-ssize_t store_iwmct_log_level_fw(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwmct_priv *priv = dev_get_drvdata(d);
- struct top_msg cmd;
- char *token, *str_buf = NULL;
- ssize_t ret = count;
- u16 cmdlen = 0;
- int i;
- long val;
- u8 src, mask;
-
- if (!count)
- goto exit;
-
- str_buf = kzalloc(count, GFP_KERNEL);
- if (!str_buf) {
- LOG_ERROR(priv, DEBUGFS,
- "failed to allocate %zd bytes\n", count);
- ret = -ENOMEM;
- goto exit;
- }
-
- memcpy(str_buf, buf, count);
-
- cmd.hdr.type = COMM_TYPE_H2D;
- cmd.hdr.category = COMM_CATEGORY_DEBUG;
- cmd.hdr.opcode = CMD_DBG_LOG_LEVEL;
-
- for (i = 0; ((token = strsep(&str_buf, ",")) != NULL) &&
- (i < FW_LOG_SRC_MAX); i++) {
-
- while (isspace(*token))
- ++token;
-
- if (strict_strtol(token, HEXADECIMAL_RADIX, &val)) {
- LOG_ERROR(priv, DEBUGFS,
- "failed to convert string to long %s\n",
- token);
- ret = -EINVAL;
- goto exit;
- }
-
- mask = val & 0xFF; /* LSB */
- src = (val & 0XFF00) >> 8; /* 2nd least significant byte. */
- iwmct_log_set_fw_filter(src, mask);
-
- cmd.u.logdefs[i].logsource = src;
- cmd.u.logdefs[i].sevmask = mask;
- }
-
- cmd.hdr.length = cpu_to_le16(i * sizeof(cmd.u.logdefs[0]));
- cmdlen = (i * sizeof(cmd.u.logdefs[0]) + sizeof(cmd.hdr));
-
- ret = iwmct_send_hcmd(priv, (u8 *)&cmd, cmdlen);
- if (ret) {
- LOG_ERROR(priv, DEBUGFS,
- "Failed to send %d bytes of fwcmd, ret=%zd\n",
- cmdlen, ret);
- goto exit;
- } else
- LOG_INFO(priv, DEBUGFS, "fwcmd sent (%d bytes)\n", cmdlen);
-
- ret = count;
-
-exit:
- kfree(str_buf);
- return ret;
-}
-
diff --git a/drivers/misc/iwmc3200top/log.h b/drivers/misc/iwmc3200top/log.h
deleted file mode 100644
index 4434bb16cea7..000000000000
--- a/drivers/misc/iwmc3200top/log.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/log.h
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
- * -
- *
- */
-
-#ifndef __LOG_H__
-#define __LOG_H__
-
-
-/* log severity:
- * The log levels here match FW log levels
- * so values need to stay as is */
-#define LOG_SEV_CRITICAL 0
-#define LOG_SEV_ERROR 1
-#define LOG_SEV_WARNING 2
-#define LOG_SEV_INFO 3
-#define LOG_SEV_INFOEX 4
-
-/* Log levels not defined for FW */
-#define LOG_SEV_TRACE 5
-#define LOG_SEV_DUMP 6
-
-#define LOG_SEV_FW_FILTER_ALL \
- (BIT(LOG_SEV_CRITICAL) | \
- BIT(LOG_SEV_ERROR) | \
- BIT(LOG_SEV_WARNING) | \
- BIT(LOG_SEV_INFO) | \
- BIT(LOG_SEV_INFOEX))
-
-#define LOG_SEV_FILTER_ALL \
- (BIT(LOG_SEV_CRITICAL) | \
- BIT(LOG_SEV_ERROR) | \
- BIT(LOG_SEV_WARNING) | \
- BIT(LOG_SEV_INFO) | \
- BIT(LOG_SEV_INFOEX) | \
- BIT(LOG_SEV_TRACE) | \
- BIT(LOG_SEV_DUMP))
-
-/* log source */
-#define LOG_SRC_INIT 0
-#define LOG_SRC_DEBUGFS 1
-#define LOG_SRC_FW_DOWNLOAD 2
-#define LOG_SRC_FW_MSG 3
-#define LOG_SRC_TST 4
-#define LOG_SRC_IRQ 5
-
-#define LOG_SRC_MAX 6
-#define LOG_SRC_ALL 0xFF
-
-/**
- * Default intitialization runtime log level
- */
-#ifndef LOG_SEV_FILTER_RUNTIME
-#define LOG_SEV_FILTER_RUNTIME \
- (BIT(LOG_SEV_CRITICAL) | \
- BIT(LOG_SEV_ERROR) | \
- BIT(LOG_SEV_WARNING))
-#endif
-
-#ifndef FW_LOG_SEV_FILTER_RUNTIME
-#define FW_LOG_SEV_FILTER_RUNTIME LOG_SEV_FILTER_ALL
-#endif
-
-#ifdef CONFIG_IWMC3200TOP_DEBUG
-/**
- * Log macros
- */
-
-#define priv2dev(priv) (&(priv->func)->dev)
-
-#define LOG_CRITICAL(priv, src, fmt, args...) \
-do { \
- if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_CRITICAL)) \
- dev_crit(priv2dev(priv), "%s %d: " fmt, \
- __func__, __LINE__, ##args); \
-} while (0)
-
-#define LOG_ERROR(priv, src, fmt, args...) \
-do { \
- if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_ERROR)) \
- dev_err(priv2dev(priv), "%s %d: " fmt, \
- __func__, __LINE__, ##args); \
-} while (0)
-
-#define LOG_WARNING(priv, src, fmt, args...) \
-do { \
- if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_WARNING)) \
- dev_warn(priv2dev(priv), "%s %d: " fmt, \
- __func__, __LINE__, ##args); \
-} while (0)
-
-#define LOG_INFO(priv, src, fmt, args...) \
-do { \
- if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_INFO)) \
- dev_info(priv2dev(priv), "%s %d: " fmt, \
- __func__, __LINE__, ##args); \
-} while (0)
-
-#define LOG_TRACE(priv, src, fmt, args...) \
-do { \
- if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_TRACE)) \
- dev_dbg(priv2dev(priv), "%s %d: " fmt, \
- __func__, __LINE__, ##args); \
-} while (0)
-
-#define LOG_HEXDUMP(src, ptr, len) \
-do { \
- if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_DUMP)) \
- print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, \
- 16, 1, ptr, len, false); \
-} while (0)
-
-void iwmct_log_top_message(struct iwmct_priv *priv, u8 *buf, int len);
-
-extern u8 iwmct_logdefs[];
-
-int iwmct_log_set_filter(u8 src, u8 logmask);
-int iwmct_log_set_fw_filter(u8 src, u8 logmask);
-
-ssize_t show_iwmct_log_level(struct device *d,
- struct device_attribute *attr, char *buf);
-ssize_t store_iwmct_log_level(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count);
-ssize_t show_iwmct_log_level_fw(struct device *d,
- struct device_attribute *attr, char *buf);
-ssize_t store_iwmct_log_level_fw(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count);
-
-#else
-
-#define LOG_CRITICAL(priv, src, fmt, args...)
-#define LOG_ERROR(priv, src, fmt, args...)
-#define LOG_WARNING(priv, src, fmt, args...)
-#define LOG_INFO(priv, src, fmt, args...)
-#define LOG_TRACE(priv, src, fmt, args...)
-#define LOG_HEXDUMP(src, ptr, len)
-
-static inline void iwmct_log_top_message(struct iwmct_priv *priv,
- u8 *buf, int len) {}
-static inline int iwmct_log_set_filter(u8 src, u8 logmask) { return 0; }
-static inline int iwmct_log_set_fw_filter(u8 src, u8 logmask) { return 0; }
-
-#endif /* CONFIG_IWMC3200TOP_DEBUG */
-
-int log_get_filter_str(char *buf, int size);
-int log_get_fw_filter_str(char *buf, int size);
-
-#endif /* __LOG_H__ */
diff --git a/drivers/misc/iwmc3200top/main.c b/drivers/misc/iwmc3200top/main.c
deleted file mode 100644
index 701eb600b127..000000000000
--- a/drivers/misc/iwmc3200top/main.c
+++ /dev/null
@@ -1,662 +0,0 @@
-/*
- * iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
- * drivers/misc/iwmc3200top/main.c
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
- * -
- *
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/debugfs.h>
-#include <linux/mmc/sdio_ids.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio.h>
-
-#include "iwmc3200top.h"
-#include "log.h"
-#include "fw-msg.h"
-#include "debugfs.h"
-
-
-#define DRIVER_DESCRIPTION "Intel(R) IWMC 3200 Top Driver"
-#define DRIVER_COPYRIGHT "Copyright (c) 2008 Intel Corporation."
-
-#define DRIVER_VERSION "0.1.62"
-
-MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR(DRIVER_COPYRIGHT);
-MODULE_FIRMWARE(FW_NAME(FW_API_VER));
-
-
-static inline int __iwmct_tx(struct iwmct_priv *priv, void *src, int count)
-{
- return sdio_memcpy_toio(priv->func, IWMC_SDIO_DATA_ADDR, src, count);
-
-}
-int iwmct_tx(struct iwmct_priv *priv, void *src, int count)
-{
- int ret;
- sdio_claim_host(priv->func);
- ret = __iwmct_tx(priv, src, count);
- sdio_release_host(priv->func);
- return ret;
-}
-/*
- * This workers main task is to wait for OP_OPR_ALIVE
- * from TOP FW until ALIVE_MSG_TIMOUT timeout is elapsed.
- * When OP_OPR_ALIVE received it will issue
- * a call to "bus_rescan_devices".
- */
-static void iwmct_rescan_worker(struct work_struct *ws)
-{
- struct iwmct_priv *priv;
- int ret;
-
- priv = container_of(ws, struct iwmct_priv, bus_rescan_worker);
-
- LOG_INFO(priv, FW_MSG, "Calling bus_rescan\n");
-
- ret = bus_rescan_devices(priv->func->dev.bus);
- if (ret < 0)
- LOG_INFO(priv, INIT, "bus_rescan_devices FAILED!!!\n");
-}
-
-static void op_top_message(struct iwmct_priv *priv, struct top_msg *msg)
-{
- switch (msg->hdr.opcode) {
- case OP_OPR_ALIVE:
- LOG_INFO(priv, FW_MSG, "Got ALIVE from device, wake rescan\n");
- schedule_work(&priv->bus_rescan_worker);
- break;
- default:
- LOG_INFO(priv, FW_MSG, "Received msg opcode 0x%X\n",
- msg->hdr.opcode);
- break;
- }
-}
-
-
-static void handle_top_message(struct iwmct_priv *priv, u8 *buf, int len)
-{
- struct top_msg *msg;
-
- msg = (struct top_msg *)buf;
-
- if (msg->hdr.type != COMM_TYPE_D2H) {
- LOG_ERROR(priv, FW_MSG,
- "Message from TOP with invalid message type 0x%X\n",
- msg->hdr.type);
- return;
- }
-
- if (len < sizeof(msg->hdr)) {
- LOG_ERROR(priv, FW_MSG,
- "Message from TOP is too short for message header "
- "received %d bytes, expected at least %zd bytes\n",
- len, sizeof(msg->hdr));
- return;
- }
-
- if (len < le16_to_cpu(msg->hdr.length) + sizeof(msg->hdr)) {
- LOG_ERROR(priv, FW_MSG,
- "Message length (%d bytes) is shorter than "
- "in header (%d bytes)\n",
- len, le16_to_cpu(msg->hdr.length));
- return;
- }
-
- switch (msg->hdr.category) {
- case COMM_CATEGORY_OPERATIONAL:
- op_top_message(priv, (struct top_msg *)buf);
- break;
-
- case COMM_CATEGORY_DEBUG:
- case COMM_CATEGORY_TESTABILITY:
- case COMM_CATEGORY_DIAGNOSTICS:
- iwmct_log_top_message(priv, buf, len);
- break;
-
- default:
- LOG_ERROR(priv, FW_MSG,
- "Message from TOP with unknown category 0x%X\n",
- msg->hdr.category);
- break;
- }
-}
-
-int iwmct_send_hcmd(struct iwmct_priv *priv, u8 *cmd, u16 len)
-{
- int ret;
- u8 *buf;
-
- LOG_TRACE(priv, FW_MSG, "Sending hcmd:\n");
-
- /* add padding to 256 for IWMC */
- ((struct top_msg *)cmd)->hdr.flags |= CMD_FLAG_PADDING_256;
-
- LOG_HEXDUMP(FW_MSG, cmd, len);
-
- if (len > FW_HCMD_BLOCK_SIZE) {
- LOG_ERROR(priv, FW_MSG, "size %d exceeded hcmd max size %d\n",
- len, FW_HCMD_BLOCK_SIZE);
- return -1;
- }
-
- buf = kzalloc(FW_HCMD_BLOCK_SIZE, GFP_KERNEL);
- if (!buf) {
- LOG_ERROR(priv, FW_MSG, "kzalloc error, buf size %d\n",
- FW_HCMD_BLOCK_SIZE);
- return -1;
- }
-
- memcpy(buf, cmd, len);
- ret = iwmct_tx(priv, buf, FW_HCMD_BLOCK_SIZE);
-
- kfree(buf);
- return ret;
-}
-
-
-static void iwmct_irq_read_worker(struct work_struct *ws)
-{
- struct iwmct_priv *priv;
- struct iwmct_work_struct *read_req;
- __le32 *buf = NULL;
- int ret;
- int iosize;
- u32 barker;
- bool is_barker;
-
- priv = container_of(ws, struct iwmct_priv, isr_worker);
-
- LOG_TRACE(priv, IRQ, "enter iwmct_irq_read_worker %p\n", ws);
-
- /* --------------------- Handshake with device -------------------- */
- sdio_claim_host(priv->func);
-
- /* all list manipulations have to be protected by
- * sdio_claim_host/sdio_release_host */
- if (list_empty(&priv->read_req_list)) {
- LOG_ERROR(priv, IRQ, "read_req_list empty in read worker\n");
- goto exit_release;
- }
-
- read_req = list_entry(priv->read_req_list.next,
- struct iwmct_work_struct, list);
-
- list_del(&read_req->list);
- iosize = read_req->iosize;
- kfree(read_req);
-
- buf = kzalloc(iosize, GFP_KERNEL);
- if (!buf) {
- LOG_ERROR(priv, IRQ, "kzalloc error, buf size %d\n", iosize);
- goto exit_release;
- }
-
- LOG_INFO(priv, IRQ, "iosize=%d, buf=%p, func=%d\n",
- iosize, buf, priv->func->num);
-
- /* read from device */
- ret = sdio_memcpy_fromio(priv->func, buf, IWMC_SDIO_DATA_ADDR, iosize);
- if (ret) {
- LOG_ERROR(priv, IRQ, "error %d reading buffer\n", ret);
- goto exit_release;
- }
-
- LOG_HEXDUMP(IRQ, (u8 *)buf, iosize);
-
- barker = le32_to_cpu(buf[0]);
-
- /* Verify whether it's a barker and if not - treat as regular Rx */
- if (barker == IWMC_BARKER_ACK ||
- (barker & BARKER_DNLOAD_BARKER_MSK) == IWMC_BARKER_REBOOT) {
-
- /* Valid Barker is equal on first 4 dwords */
- is_barker = (buf[1] == buf[0]) &&
- (buf[2] == buf[0]) &&
- (buf[3] == buf[0]);
-
- if (!is_barker) {
- LOG_WARNING(priv, IRQ,
- "Potentially inconsistent barker "
- "%08X_%08X_%08X_%08X\n",
- le32_to_cpu(buf[0]), le32_to_cpu(buf[1]),
- le32_to_cpu(buf[2]), le32_to_cpu(buf[3]));
- }
- } else {
- is_barker = false;
- }
-
- /* Handle Top CommHub message */
- if (!is_barker) {
- sdio_release_host(priv->func);
- handle_top_message(priv, (u8 *)buf, iosize);
- goto exit;
- } else if (barker == IWMC_BARKER_ACK) { /* Handle barkers */
- if (atomic_read(&priv->dev_sync) == 0) {
- LOG_ERROR(priv, IRQ,
- "ACK barker arrived out-of-sync\n");
- goto exit_release;
- }
-
- /* Continuing to FW download (after Sync is completed)*/
- atomic_set(&priv->dev_sync, 0);
- LOG_INFO(priv, IRQ, "ACK barker arrived "
- "- starting FW download\n");
- } else { /* REBOOT barker */
- LOG_INFO(priv, IRQ, "Received reboot barker: %x\n", barker);
- priv->barker = barker;
-
- if (barker & BARKER_DNLOAD_SYNC_MSK) {
- /* Send the same barker back */
- ret = __iwmct_tx(priv, buf, iosize);
- if (ret) {
- LOG_ERROR(priv, IRQ,
- "error %d echoing barker\n", ret);
- goto exit_release;
- }
- LOG_INFO(priv, IRQ, "Echoing barker to device\n");
- atomic_set(&priv->dev_sync, 1);
- goto exit_release;
- }
-
- /* Continuing to FW download (without Sync) */
- LOG_INFO(priv, IRQ, "No sync requested "
- "- starting FW download\n");
- }
-
- sdio_release_host(priv->func);
-
- if (priv->dbg.fw_download)
- iwmct_fw_load(priv);
- else
- LOG_ERROR(priv, IRQ, "FW download not allowed\n");
-
- goto exit;
-
-exit_release:
- sdio_release_host(priv->func);
-exit:
- kfree(buf);
- LOG_TRACE(priv, IRQ, "exit iwmct_irq_read_worker\n");
-}
-
-static void iwmct_irq(struct sdio_func *func)
-{
- struct iwmct_priv *priv;
- int val, ret;
- int iosize;
- int addr = IWMC_SDIO_INTR_GET_SIZE_ADDR;
- struct iwmct_work_struct *read_req;
-
- priv = sdio_get_drvdata(func);
-
- LOG_TRACE(priv, IRQ, "enter iwmct_irq\n");
-
- /* read the function's status register */
- val = sdio_readb(func, IWMC_SDIO_INTR_STATUS_ADDR, &ret);
-
- LOG_TRACE(priv, IRQ, "iir value = %d, ret=%d\n", val, ret);
-
- if (!val) {
- LOG_ERROR(priv, IRQ, "iir = 0, exiting ISR\n");
- goto exit_clear_intr;
- }
-
-
- /*
- * read 2 bytes of the transaction size
- * IMPORTANT: sdio transaction size has to be read before clearing
- * sdio interrupt!!!
- */
- val = sdio_readb(priv->func, addr++, &ret);
- iosize = val;
- val = sdio_readb(priv->func, addr++, &ret);
- iosize += val << 8;
-
- LOG_INFO(priv, IRQ, "READ size %d\n", iosize);
-
- if (iosize == 0) {
- LOG_ERROR(priv, IRQ, "READ size %d, exiting ISR\n", iosize);
- goto exit_clear_intr;
- }
-
- /* allocate a work structure to pass iosize to the worker */
- read_req = kzalloc(sizeof(struct iwmct_work_struct), GFP_KERNEL);
- if (!read_req) {
- LOG_ERROR(priv, IRQ, "failed to allocate read_req, exit ISR\n");
- goto exit_clear_intr;
- }
-
- INIT_LIST_HEAD(&read_req->list);
- read_req->iosize = iosize;
-
- list_add_tail(&priv->read_req_list, &read_req->list);
-
- /* clear the function's interrupt request bit (write 1 to clear) */
- sdio_writeb(func, 1, IWMC_SDIO_INTR_CLEAR_ADDR, &ret);
-
- schedule_work(&priv->isr_worker);
-
- LOG_TRACE(priv, IRQ, "exit iwmct_irq\n");
-
- return;
-
-exit_clear_intr:
- /* clear the function's interrupt request bit (write 1 to clear) */
- sdio_writeb(func, 1, IWMC_SDIO_INTR_CLEAR_ADDR, &ret);
-}
-
-
-static int blocks;
-module_param(blocks, int, 0604);
-MODULE_PARM_DESC(blocks, "max_blocks_to_send");
-
-static bool dump;
-module_param(dump, bool, 0604);
-MODULE_PARM_DESC(dump, "dump_hex_content");
-
-static bool jump = 1;
-module_param(jump, bool, 0604);
-
-static bool direct = 1;
-module_param(direct, bool, 0604);
-
-static bool checksum = 1;
-module_param(checksum, bool, 0604);
-
-static bool fw_download = 1;
-module_param(fw_download, bool, 0604);
-
-static int block_size = IWMC_SDIO_BLK_SIZE;
-module_param(block_size, int, 0404);
-
-static int download_trans_blks = IWMC_DEFAULT_TR_BLK;
-module_param(download_trans_blks, int, 0604);
-
-static bool rubbish_barker;
-module_param(rubbish_barker, bool, 0604);
-
-#ifdef CONFIG_IWMC3200TOP_DEBUG
-static int log_level[LOG_SRC_MAX];
-static unsigned int log_level_argc;
-module_param_array(log_level, int, &log_level_argc, 0604);
-MODULE_PARM_DESC(log_level, "log_level");
-
-static int log_level_fw[FW_LOG_SRC_MAX];
-static unsigned int log_level_fw_argc;
-module_param_array(log_level_fw, int, &log_level_fw_argc, 0604);
-MODULE_PARM_DESC(log_level_fw, "log_level_fw");
-#endif
-
-void iwmct_dbg_init_params(struct iwmct_priv *priv)
-{
-#ifdef CONFIG_IWMC3200TOP_DEBUG
- int i;
-
- for (i = 0; i < log_level_argc; i++) {
- dev_notice(&priv->func->dev, "log_level[%d]=0x%X\n",
- i, log_level[i]);
- iwmct_log_set_filter((log_level[i] >> 8) & 0xFF,
- log_level[i] & 0xFF);
- }
- for (i = 0; i < log_level_fw_argc; i++) {
- dev_notice(&priv->func->dev, "log_level_fw[%d]=0x%X\n",
- i, log_level_fw[i]);
- iwmct_log_set_fw_filter((log_level_fw[i] >> 8) & 0xFF,
- log_level_fw[i] & 0xFF);
- }
-#endif
-
- priv->dbg.blocks = blocks;
- LOG_INFO(priv, INIT, "blocks=%d\n", blocks);
- priv->dbg.dump = (bool)dump;
- LOG_INFO(priv, INIT, "dump=%d\n", dump);
- priv->dbg.jump = (bool)jump;
- LOG_INFO(priv, INIT, "jump=%d\n", jump);
- priv->dbg.direct = (bool)direct;
- LOG_INFO(priv, INIT, "direct=%d\n", direct);
- priv->dbg.checksum = (bool)checksum;
- LOG_INFO(priv, INIT, "checksum=%d\n", checksum);
- priv->dbg.fw_download = (bool)fw_download;
- LOG_INFO(priv, INIT, "fw_download=%d\n", fw_download);
- priv->dbg.block_size = block_size;
- LOG_INFO(priv, INIT, "block_size=%d\n", block_size);
- priv->dbg.download_trans_blks = download_trans_blks;
- LOG_INFO(priv, INIT, "download_trans_blks=%d\n", download_trans_blks);
-}
-
-/*****************************************************************************
- *
- * sysfs attributes
- *
- *****************************************************************************/
-static ssize_t show_iwmct_fw_version(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwmct_priv *priv = dev_get_drvdata(d);
- return sprintf(buf, "%s\n", priv->dbg.label_fw);
-}
-static DEVICE_ATTR(cc_label_fw, S_IRUGO, show_iwmct_fw_version, NULL);
-
-#ifdef CONFIG_IWMC3200TOP_DEBUG
-static DEVICE_ATTR(log_level, S_IWUSR | S_IRUGO,
- show_iwmct_log_level, store_iwmct_log_level);
-static DEVICE_ATTR(log_level_fw, S_IWUSR | S_IRUGO,
- show_iwmct_log_level_fw, store_iwmct_log_level_fw);
-#endif
-
-static struct attribute *iwmct_sysfs_entries[] = {
- &dev_attr_cc_label_fw.attr,
-#ifdef CONFIG_IWMC3200TOP_DEBUG
- &dev_attr_log_level.attr,
- &dev_attr_log_level_fw.attr,
-#endif
- NULL
-};
-
-static struct attribute_group iwmct_attribute_group = {
- .name = NULL, /* put in device directory */
- .attrs = iwmct_sysfs_entries,
-};
-
-
-static int iwmct_probe(struct sdio_func *func,
- const struct sdio_device_id *id)
-{
- struct iwmct_priv *priv;
- int ret;
- int val = 1;
- int addr = IWMC_SDIO_INTR_ENABLE_ADDR;
-
- dev_dbg(&func->dev, "enter iwmct_probe\n");
-
- dev_dbg(&func->dev, "IRQ polling period id %u msecs, HZ is %d\n",
- jiffies_to_msecs(2147483647), HZ);
-
- priv = kzalloc(sizeof(struct iwmct_priv), GFP_KERNEL);
- if (!priv) {
- dev_err(&func->dev, "kzalloc error\n");
- return -ENOMEM;
- }
- priv->func = func;
- sdio_set_drvdata(func, priv);
-
- INIT_WORK(&priv->bus_rescan_worker, iwmct_rescan_worker);
- INIT_WORK(&priv->isr_worker, iwmct_irq_read_worker);
-
- init_waitqueue_head(&priv->wait_q);
-
- sdio_claim_host(func);
- /* FIXME: Remove after it is fixed in the Boot ROM upgrade */
- func->enable_timeout = 10;
-
- /* In our HW, setting the block size also wakes up the boot rom. */
- ret = sdio_set_block_size(func, priv->dbg.block_size);
- if (ret) {
- LOG_ERROR(priv, INIT,
- "sdio_set_block_size() failure: %d\n", ret);
- goto error_sdio_enable;
- }
-
- ret = sdio_enable_func(func);
- if (ret) {
- LOG_ERROR(priv, INIT, "sdio_enable_func() failure: %d\n", ret);
- goto error_sdio_enable;
- }
-
- /* init reset and dev_sync states */
- atomic_set(&priv->reset, 0);
- atomic_set(&priv->dev_sync, 0);
-
- /* init read req queue */
- INIT_LIST_HEAD(&priv->read_req_list);
-
- /* process configurable parameters */
- iwmct_dbg_init_params(priv);
- ret = sysfs_create_group(&func->dev.kobj, &iwmct_attribute_group);
- if (ret) {
- LOG_ERROR(priv, INIT, "Failed to register attributes and "
- "initialize module_params\n");
- goto error_dev_attrs;
- }
-
- iwmct_dbgfs_register(priv, DRV_NAME);
-
- if (!priv->dbg.direct && priv->dbg.download_trans_blks > 8) {
- LOG_INFO(priv, INIT,
- "Reducing transaction to 8 blocks = 2K (from %d)\n",
- priv->dbg.download_trans_blks);
- priv->dbg.download_trans_blks = 8;
- }
- priv->trans_len = priv->dbg.download_trans_blks * priv->dbg.block_size;
- LOG_INFO(priv, INIT, "Transaction length = %d\n", priv->trans_len);
-
- ret = sdio_claim_irq(func, iwmct_irq);
- if (ret) {
- LOG_ERROR(priv, INIT, "sdio_claim_irq() failure: %d\n", ret);
- goto error_claim_irq;
- }
-
-
- /* Enable function's interrupt */
- sdio_writeb(priv->func, val, addr, &ret);
- if (ret) {
- LOG_ERROR(priv, INIT, "Failure writing to "
- "Interrupt Enable Register (%d): %d\n", addr, ret);
- goto error_enable_int;
- }
-
- sdio_release_host(func);
-
- LOG_INFO(priv, INIT, "exit iwmct_probe\n");
-
- return ret;
-
-error_enable_int:
- sdio_release_irq(func);
-error_claim_irq:
- sdio_disable_func(func);
-error_dev_attrs:
- iwmct_dbgfs_unregister(priv->dbgfs);
- sysfs_remove_group(&func->dev.kobj, &iwmct_attribute_group);
-error_sdio_enable:
- sdio_release_host(func);
- return ret;
-}
-
-static void iwmct_remove(struct sdio_func *func)
-{
- struct iwmct_work_struct *read_req;
- struct iwmct_priv *priv = sdio_get_drvdata(func);
-
- LOG_INFO(priv, INIT, "enter\n");
-
- sdio_claim_host(func);
- sdio_release_irq(func);
- sdio_release_host(func);
-
- /* Make sure works are finished */
- flush_work_sync(&priv->bus_rescan_worker);
- flush_work_sync(&priv->isr_worker);
-
- sdio_claim_host(func);
- sdio_disable_func(func);
- sysfs_remove_group(&func->dev.kobj, &iwmct_attribute_group);
- iwmct_dbgfs_unregister(priv->dbgfs);
- sdio_release_host(func);
-
- /* free read requests */
- while (!list_empty(&priv->read_req_list)) {
- read_req = list_entry(priv->read_req_list.next,
- struct iwmct_work_struct, list);
-
- list_del(&read_req->list);
- kfree(read_req);
- }
-
- kfree(priv);
-}
-
-
-static const struct sdio_device_id iwmct_ids[] = {
- /* Intel Wireless MultiCom 3200 Top Driver */
- { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 0x1404)},
- { }, /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(sdio, iwmct_ids);
-
-static struct sdio_driver iwmct_driver = {
- .probe = iwmct_probe,
- .remove = iwmct_remove,
- .name = DRV_NAME,
- .id_table = iwmct_ids,
-};
-
-static int __init iwmct_init(void)
-{
- int rc;
-
- /* Default log filter settings */
- iwmct_log_set_filter(LOG_SRC_ALL, LOG_SEV_FILTER_RUNTIME);
- iwmct_log_set_filter(LOG_SRC_FW_MSG, LOG_SEV_FW_FILTER_ALL);
- iwmct_log_set_fw_filter(LOG_SRC_ALL, FW_LOG_SEV_FILTER_RUNTIME);
-
- rc = sdio_register_driver(&iwmct_driver);
-
- return rc;
-}
-
-static void __exit iwmct_exit(void)
-{
- sdio_unregister_driver(&iwmct_driver);
-}
-
-module_init(iwmct_init);
-module_exit(iwmct_exit);
-
diff --git a/drivers/net/wimax/i2400m/Kconfig b/drivers/net/wimax/i2400m/Kconfig
index 672de18a776c..71453db14258 100644
--- a/drivers/net/wimax/i2400m/Kconfig
+++ b/drivers/net/wimax/i2400m/Kconfig
@@ -7,9 +7,6 @@ config WIMAX_I2400M
comment "Enable USB support to see WiMAX USB drivers"
depends on USB = n
-comment "Enable MMC support to see WiMAX SDIO drivers"
- depends on MMC = n
-
config WIMAX_I2400M_USB
tristate "Intel Wireless WiMAX Connection 2400 over USB (including 5x50)"
depends on WIMAX && USB
@@ -21,25 +18,6 @@ config WIMAX_I2400M_USB
If unsure, it is safe to select M (module).
-config WIMAX_I2400M_SDIO
- tristate "Intel Wireless WiMAX Connection 2400 over SDIO"
- depends on WIMAX && MMC
- select WIMAX_I2400M
- help
- Select if you have a device based on the Intel WiMAX
- Connection 2400 over SDIO.
-
- If unsure, it is safe to select M (module).
-
-config WIMAX_IWMC3200_SDIO
- bool "Intel Wireless Multicom WiMAX Connection 3200 over SDIO (EXPERIMENTAL)"
- depends on WIMAX_I2400M_SDIO
- depends on EXPERIMENTAL
- select IWMC3200TOP
- help
- Select if you have a device based on the Intel Multicom WiMAX
- Connection 3200 over SDIO.
-
config WIMAX_I2400M_DEBUG_LEVEL
int "WiMAX i2400m debug level"
depends on WIMAX_I2400M
diff --git a/drivers/net/wimax/i2400m/Makefile b/drivers/net/wimax/i2400m/Makefile
index 5d9e018d31af..f6d19c348082 100644
--- a/drivers/net/wimax/i2400m/Makefile
+++ b/drivers/net/wimax/i2400m/Makefile
@@ -1,7 +1,6 @@
obj-$(CONFIG_WIMAX_I2400M) += i2400m.o
obj-$(CONFIG_WIMAX_I2400M_USB) += i2400m-usb.o
-obj-$(CONFIG_WIMAX_I2400M_SDIO) += i2400m-sdio.o
i2400m-y := \
control.o \
@@ -21,10 +20,3 @@ i2400m-usb-y := \
usb-tx.o \
usb-rx.o \
usb.o
-
-
-i2400m-sdio-y := \
- sdio.o \
- sdio-tx.o \
- sdio-fw.o \
- sdio-rx.o
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c
index 47cae7150bc1..850b8bc38bee 100644
--- a/drivers/net/wimax/i2400m/driver.c
+++ b/drivers/net/wimax/i2400m/driver.c
@@ -754,8 +754,7 @@ EXPORT_SYMBOL_GPL(i2400m_error_recovery);
/*
* Alloc the command and ack buffers for boot mode
*
- * Get the buffers needed to deal with boot mode messages. These
- * buffers need to be allocated before the sdio receive irq is setup.
+ * Get the buffers needed to deal with boot mode messages.
*/
static
int i2400m_bm_buf_alloc(struct i2400m *i2400m)
diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c
index 7cbd7d231e11..7632f8cf09df 100644
--- a/drivers/net/wimax/i2400m/fw.c
+++ b/drivers/net/wimax/i2400m/fw.c
@@ -51,8 +51,7 @@
* firmware. Normal hardware takes only signed firmware.
*
* On boot mode, in USB, we write to the device using the bulk out
- * endpoint and read from it in the notification endpoint. In SDIO we
- * talk to it via the write address and read from the read address.
+ * endpoint and read from it in the notification endpoint.
*
* Upon entrance to boot mode, the device sends (preceded with a few
* zero length packets (ZLPs) on the notification endpoint in USB) a
diff --git a/drivers/net/wimax/i2400m/i2400m-sdio.h b/drivers/net/wimax/i2400m/i2400m-sdio.h
deleted file mode 100644
index 1d63ffdedfde..000000000000
--- a/drivers/net/wimax/i2400m/i2400m-sdio.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Intel Wireless WiMAX Connection 2400m
- * SDIO-specific i2400m driver definitions
- *
- *
- * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <linux-wimax@intel.com>
- * Brian Bian <brian.bian@intel.com>
- * Dirk Brandewie <dirk.j.brandewie@intel.com>
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- * Yanir Lubetkin <yanirx.lubetkin@intel.com>
- * - Initial implementation
- *
- *
- * This driver implements the bus-specific part of the i2400m for
- * SDIO. Check i2400m.h for a generic driver description.
- *
- * ARCHITECTURE
- *
- * This driver sits under the bus-generic i2400m driver, providing the
- * connection to the device.
- *
- * When probed, all the function pointers are setup and then the
- * bus-generic code called. The generic driver will then use the
- * provided pointers for uploading firmware (i2400ms_bus_bm*() in
- * sdio-fw.c) and then setting up the device (i2400ms_dev_*() in
- * sdio.c).
- *
- * Once firmware is uploaded, TX functions (sdio-tx.c) are called when
- * data is ready for transmission in the TX fifo; then the SDIO IRQ is
- * fired and data is available (sdio-rx.c), it is sent to the generic
- * driver for processing with i2400m_rx.
- */
-
-#ifndef __I2400M_SDIO_H__
-#define __I2400M_SDIO_H__
-
-#include "i2400m.h"
-
-/* Host-Device interface for SDIO */
-enum {
- I2400M_SDIO_BOOT_RETRIES = 3,
- I2400MS_BLK_SIZE = 256,
- I2400MS_PL_SIZE_MAX = 0x3E00,
-
- I2400MS_DATA_ADDR = 0x0,
- I2400MS_INTR_STATUS_ADDR = 0x13,
- I2400MS_INTR_CLEAR_ADDR = 0x13,
- I2400MS_INTR_ENABLE_ADDR = 0x14,
- I2400MS_INTR_GET_SIZE_ADDR = 0x2C,
- /* The number of ticks to wait for the device to signal that
- * it is ready */
- I2400MS_INIT_SLEEP_INTERVAL = 100,
- /* How long to wait for the device to settle after reset */
- I2400MS_SETTLE_TIME = 40,
- /* The number of msec to wait for IOR after sending IOE */
- IWMC3200_IOR_TIMEOUT = 10,
-};
-
-
-/**
- * struct i2400ms - descriptor for a SDIO connected i2400m
- *
- * @i2400m: bus-generic i2400m implementation; has to be first (see
- * it's documentation in i2400m.h).
- *
- * @func: pointer to our SDIO function
- *
- * @tx_worker: workqueue struct used to TX data when the bus-generic
- * code signals packets are pending for transmission to the device.
- *
- * @tx_workqueue: workqeueue used for data TX; we don't use the
- * system's workqueue as that might cause deadlocks with code in
- * the bus-generic driver. The read/write operation to the queue
- * is protected with spinlock (tx_lock in struct i2400m) to avoid
- * the queue being destroyed in the middle of a the queue read/write
- * operation.
- *
- * @debugfs_dentry: dentry for the SDIO specific debugfs files
- *
- * Note this value is set to NULL upon destruction; this is
- * because some routinges use it to determine if we are inside the
- * probe() path or some other path. When debugfs is disabled,
- * creation sets the dentry to '(void*) -ENODEV', which is valid
- * for the test.
- */
-struct i2400ms {
- struct i2400m i2400m; /* FIRST! See doc */
- struct sdio_func *func;
-
- struct work_struct tx_worker;
- struct workqueue_struct *tx_workqueue;
- char tx_wq_name[32];
-
- struct dentry *debugfs_dentry;
-
- wait_queue_head_t bm_wfa_wq;
- int bm_wait_result;
- size_t bm_ack_size;
-
- /* Device is any of the iwmc3200 SKUs */
- unsigned iwmc3200:1;
-};
-
-
-static inline
-void i2400ms_init(struct i2400ms *i2400ms)
-{
- i2400m_init(&i2400ms->i2400m);
-}
-
-
-extern int i2400ms_rx_setup(struct i2400ms *);
-extern void i2400ms_rx_release(struct i2400ms *);
-
-extern int i2400ms_tx_setup(struct i2400ms *);
-extern void i2400ms_tx_release(struct i2400ms *);
-extern void i2400ms_bus_tx_kick(struct i2400m *);
-
-extern ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *,
- const struct i2400m_bootrom_header *,
- size_t, int);
-extern ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *,
- struct i2400m_bootrom_header *,
- size_t);
-extern void i2400ms_bus_bm_release(struct i2400m *);
-extern int i2400ms_bus_bm_setup(struct i2400m *);
-
-#endif /* #ifndef __I2400M_SDIO_H__ */
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
index c806d4550212..79c6505b5c20 100644
--- a/drivers/net/wimax/i2400m/i2400m.h
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -46,7 +46,7 @@
* - bus generic driver (this part)
*
* The bus specific driver sets up stuff specific to the bus the
- * device is connected to (USB, SDIO, PCI, tam-tam...non-authoritative
+ * device is connected to (USB, PCI, tam-tam...non-authoritative
* nor binding list) which is basically the device-model management
* (probe/disconnect, etc), moving data from device to kernel and
* back, doing the power saving details and reseting the device.
@@ -238,14 +238,13 @@ struct i2400m_barker_db;
* amount needed for loading firmware, where us dev_start/stop setup
* the rest needed to do full data/control traffic.
*
- * @bus_tx_block_size: [fill] SDIO imposes a 256 block size, USB 16,
- * so we have a tx_blk_size variable that the bus layer sets to
- * tell the engine how much of that we need.
+ * @bus_tx_block_size: [fill] USB imposes a 16 block size, but other
+ * busses will differ. So we have a tx_blk_size variable that the
+ * bus layer sets to tell the engine how much of that we need.
*
* @bus_tx_room_min: [fill] Minimum room required while allocating
- * TX queue's buffer space for message header. SDIO requires
- * 224 bytes and USB 16 bytes. Refer bus specific driver code
- * for details.
+ * TX queue's buffer space for message header. USB requires
+ * 16 bytes. Refer to bus specific driver code for details.
*
* @bus_pl_size_max: [fill] Maximum payload size.
*
diff --git a/drivers/net/wimax/i2400m/sdio-debug-levels.h b/drivers/net/wimax/i2400m/sdio-debug-levels.h
deleted file mode 100644
index c51998741301..000000000000
--- a/drivers/net/wimax/i2400m/sdio-debug-levels.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * debug levels control file for the i2400m module's
- */
-#ifndef __debug_levels__h__
-#define __debug_levels__h__
-
-/* Maximum compile and run time debug level for all submodules */
-#define D_MODULENAME i2400m_sdio
-#define D_MASTER CONFIG_WIMAX_I2400M_DEBUG_LEVEL
-
-#include <linux/wimax/debug.h>
-
-/* List of all the enabled modules */
-enum d_module {
- D_SUBMODULE_DECLARE(main),
- D_SUBMODULE_DECLARE(tx),
- D_SUBMODULE_DECLARE(rx),
- D_SUBMODULE_DECLARE(fw)
-};
-
-
-#endif /* #ifndef __debug_levels__h__ */
diff --git a/drivers/net/wimax/i2400m/sdio-fw.c b/drivers/net/wimax/i2400m/sdio-fw.c
deleted file mode 100644
index 8e025418f5be..000000000000
--- a/drivers/net/wimax/i2400m/sdio-fw.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Intel Wireless WiMAX Connection 2400m
- * Firmware uploader's SDIO specifics
- *
- *
- * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <linux-wimax@intel.com>
- * Yanir Lubetkin <yanirx.lubetkin@intel.com>
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- * - Initial implementation
- *
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- * - Bus generic/specific split for USB
- *
- * Dirk Brandewie <dirk.j.brandewie@intel.com>
- * - Initial implementation for SDIO
- *
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- * - SDIO rehash for changes in the bus-driver model
- *
- * Dirk Brandewie <dirk.j.brandewie@intel.com>
- * - Make it IRQ based, not polling
- *
- * THE PROCEDURE
- *
- * See fw.c for the generic description of this procedure.
- *
- * This file implements only the SDIO specifics. It boils down to how
- * to send a command and waiting for an acknowledgement from the
- * device.
- *
- * All this code is sequential -- all i2400ms_bus_bm_*() functions are
- * executed in the same thread, except i2400ms_bm_irq() [on its own by
- * the SDIO driver]. This makes it possible to avoid locking.
- *
- * COMMAND EXECUTION
- *
- * The generic firmware upload code will call i2400m_bus_bm_cmd_send()
- * to send commands.
- *
- * The SDIO devices expects things in 256 byte blocks, so it will pad
- * it, compute the checksum (if needed) and pass it to SDIO.
- *
- * ACK RECEPTION
- *
- * This works in IRQ mode -- the fw loader says when to wait for data
- * and for that it calls i2400ms_bus_bm_wait_for_ack().
- *
- * This checks if there is any data available (RX size > 0); if not,
- * waits for the IRQ handler to notify about it. Once there is data,
- * it is read and passed to the caller. Doing it this way we don't
- * need much coordination/locking, and it makes it much more difficult
- * for an interrupt to be lost and the wait_for_ack() function getting
- * stuck even when data is pending.
- */
-#include <linux/mmc/sdio_func.h>
-#include "i2400m-sdio.h"
-
-
-#define D_SUBMODULE fw
-#include "sdio-debug-levels.h"
-
-
-/*
- * Send a boot-mode command to the SDIO function
- *
- * We use a bounce buffer (i2400m->bm_cmd_buf) because we need to
- * touch the header if the RAW flag is not set.
- *
- * @flags: pass thru from i2400m_bm_cmd()
- * @return: cmd_size if ok, < 0 errno code on error.
- *
- * Note the command is padded to the SDIO block size for the device.
- */
-ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *i2400m,
- const struct i2400m_bootrom_header *_cmd,
- size_t cmd_size, int flags)
-{
- ssize_t result;
- struct device *dev = i2400m_dev(i2400m);
- struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
- int opcode = _cmd == NULL ? -1 : i2400m_brh_get_opcode(_cmd);
- struct i2400m_bootrom_header *cmd;
- /* SDIO restriction */
- size_t cmd_size_a = ALIGN(cmd_size, I2400MS_BLK_SIZE);
-
- d_fnstart(5, dev, "(i2400m %p cmd %p size %zu)\n",
- i2400m, _cmd, cmd_size);
- result = -E2BIG;
- if (cmd_size > I2400M_BM_CMD_BUF_SIZE)
- goto error_too_big;
-
- if (_cmd != i2400m->bm_cmd_buf)
- memmove(i2400m->bm_cmd_buf, _cmd, cmd_size);
- cmd = i2400m->bm_cmd_buf;
- if (cmd_size_a > cmd_size) /* Zero pad space */
- memset(i2400m->bm_cmd_buf + cmd_size, 0, cmd_size_a - cmd_size);
- if ((flags & I2400M_BM_CMD_RAW) == 0) {
- if (WARN_ON(i2400m_brh_get_response_required(cmd) == 0))
- dev_warn(dev, "SW BUG: response_required == 0\n");
- i2400m_bm_cmd_prepare(cmd);
- }
- d_printf(4, dev, "BM cmd %d: %zu bytes (%zu padded)\n",
- opcode, cmd_size, cmd_size_a);
- d_dump(5, dev, cmd, cmd_size);
-
- sdio_claim_host(i2400ms->func); /* Send & check */
- result = sdio_memcpy_toio(i2400ms->func, I2400MS_DATA_ADDR,
- i2400m->bm_cmd_buf, cmd_size_a);
- sdio_release_host(i2400ms->func);
- if (result < 0) {
- dev_err(dev, "BM cmd %d: cannot send: %ld\n",
- opcode, (long) result);
- goto error_cmd_send;
- }
- result = cmd_size;
-error_cmd_send:
-error_too_big:
- d_fnend(5, dev, "(i2400m %p cmd %p size %zu) = %d\n",
- i2400m, _cmd, cmd_size, (int) result);
- return result;
-}
-
-
-/*
- * Read an ack from the device's boot-mode
- *
- * @i2400m:
- * @_ack: pointer to where to store the read data
- * @ack_size: how many bytes we should read
- *
- * Returns: < 0 errno code on error; otherwise, amount of received bytes.
- *
- * The ACK for a BM command is always at least sizeof(*ack) bytes, so
- * check for that. We don't need to check for device reboots
- *
- */
-ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *i2400m,
- struct i2400m_bootrom_header *ack,
- size_t ack_size)
-{
- ssize_t result;
- struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
- struct sdio_func *func = i2400ms->func;
- struct device *dev = &func->dev;
- int size;
-
- BUG_ON(sizeof(*ack) > ack_size);
-
- d_fnstart(5, dev, "(i2400m %p ack %p size %zu)\n",
- i2400m, ack, ack_size);
-
- result = wait_event_timeout(i2400ms->bm_wfa_wq,
- i2400ms->bm_ack_size != -EINPROGRESS,
- 2 * HZ);
- if (result == 0) {
- result = -ETIMEDOUT;
- dev_err(dev, "BM: error waiting for an ack\n");
- goto error_timeout;
- }
-
- spin_lock(&i2400m->rx_lock);
- result = i2400ms->bm_ack_size;
- BUG_ON(result == -EINPROGRESS);
- if (result < 0) /* so we exit when rx_release() is called */
- dev_err(dev, "BM: %s failed: %zd\n", __func__, result);
- else {
- size = min(ack_size, i2400ms->bm_ack_size);
- memcpy(ack, i2400m->bm_ack_buf, size);
- }
- /*
- * Remember always to clear the bm_ack_size to -EINPROGRESS
- * after the RX data is processed
- */
- i2400ms->bm_ack_size = -EINPROGRESS;
- spin_unlock(&i2400m->rx_lock);
-
-error_timeout:
- d_fnend(5, dev, "(i2400m %p ack %p size %zu) = %zd\n",
- i2400m, ack, ack_size, result);
- return result;
-}
diff --git a/drivers/net/wimax/i2400m/sdio-rx.c b/drivers/net/wimax/i2400m/sdio-rx.c
deleted file mode 100644
index fb6396dd115f..000000000000
--- a/drivers/net/wimax/i2400m/sdio-rx.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Intel Wireless WiMAX Connection 2400m
- * SDIO RX handling
- *
- *
- * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <linux-wimax@intel.com>
- * Dirk Brandewie <dirk.j.brandewie@intel.com>
- * - Initial implementation
- *
- *
- * This handles the RX path on SDIO.
- *
- * The SDIO bus driver calls the "irq" routine when data is available.
- * This is not a traditional interrupt routine since the SDIO bus
- * driver calls us from its irq thread context. Because of this
- * sleeping in the SDIO RX IRQ routine is okay.
- *
- * From there on, we obtain the size of the data that is available,
- * allocate an skb, copy it and then pass it to the generic driver's
- * RX routine [i2400m_rx()].
- *
- * ROADMAP
- *
- * i2400ms_irq()
- * i2400ms_rx()
- * __i2400ms_rx_get_size()
- * i2400m_is_boot_barker()
- * i2400m_rx()
- *
- * i2400ms_rx_setup()
- *
- * i2400ms_rx_release()
- */
-#include <linux/workqueue.h>
-#include <linux/wait.h>
-#include <linux/skbuff.h>
-#include <linux/mmc/sdio.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/slab.h>
-#include "i2400m-sdio.h"
-
-#define D_SUBMODULE rx
-#include "sdio-debug-levels.h"
-
-static const __le32 i2400m_ACK_BARKER[4] = {
- __constant_cpu_to_le32(I2400M_ACK_BARKER),
- __constant_cpu_to_le32(I2400M_ACK_BARKER),
- __constant_cpu_to_le32(I2400M_ACK_BARKER),
- __constant_cpu_to_le32(I2400M_ACK_BARKER)
-};
-
-
-/*
- * Read and return the amount of bytes available for RX
- *
- * The RX size has to be read like this: byte reads of three
- * sequential locations; then glue'em together.
- *
- * sdio_readl() doesn't work.
- */
-static ssize_t __i2400ms_rx_get_size(struct i2400ms *i2400ms)
-{
- int ret, cnt, val;
- ssize_t rx_size;
- unsigned xfer_size_addr;
- struct sdio_func *func = i2400ms->func;
- struct device *dev = &i2400ms->func->dev;
-
- d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms);
- xfer_size_addr = I2400MS_INTR_GET_SIZE_ADDR;
- rx_size = 0;
- for (cnt = 0; cnt < 3; cnt++) {
- val = sdio_readb(func, xfer_size_addr + cnt, &ret);
- if (ret < 0) {
- dev_err(dev, "RX: Can't read byte %d of RX size from "
- "0x%08x: %d\n", cnt, xfer_size_addr + cnt, ret);
- rx_size = ret;
- goto error_read;
- }
- rx_size = rx_size << 8 | (val & 0xff);
- }
- d_printf(6, dev, "RX: rx_size is %ld\n", (long) rx_size);
-error_read:
- d_fnend(7, dev, "(i2400ms %p) = %ld\n", i2400ms, (long) rx_size);
- return rx_size;
-}
-
-
-/*
- * Read data from the device (when in normal)
- *
- * Allocate an SKB of the right size, read the data in and then
- * deliver it to the generic layer.
- *
- * We also check for a reboot barker. That means the device died and
- * we have to reboot it.
- */
-static
-void i2400ms_rx(struct i2400ms *i2400ms)
-{
- int ret;
- struct sdio_func *func = i2400ms->func;
- struct device *dev = &func->dev;
- struct i2400m *i2400m = &i2400ms->i2400m;
- struct sk_buff *skb;
- ssize_t rx_size;
-
- d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms);
- rx_size = __i2400ms_rx_get_size(i2400ms);
- if (rx_size < 0) {
- ret = rx_size;
- goto error_get_size;
- }
- /*
- * Hardware quirk: make sure to clear the INTR status register
- * AFTER getting the data transfer size.
- */
- sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret);
-
- ret = -ENOMEM;
- skb = alloc_skb(rx_size, GFP_ATOMIC);
- if (NULL == skb) {
- dev_err(dev, "RX: unable to alloc skb\n");
- goto error_alloc_skb;
- }
- ret = sdio_memcpy_fromio(func, skb->data,
- I2400MS_DATA_ADDR, rx_size);
- if (ret < 0) {
- dev_err(dev, "RX: SDIO data read failed: %d\n", ret);
- goto error_memcpy_fromio;
- }
-
- rmb(); /* make sure we get boot_mode from dev_reset_handle */
- if (unlikely(i2400m->boot_mode == 1)) {
- spin_lock(&i2400m->rx_lock);
- i2400ms->bm_ack_size = rx_size;
- spin_unlock(&i2400m->rx_lock);
- memcpy(i2400m->bm_ack_buf, skb->data, rx_size);
- wake_up(&i2400ms->bm_wfa_wq);
- d_printf(5, dev, "RX: SDIO boot mode message\n");
- kfree_skb(skb);
- goto out;
- }
- ret = -EIO;
- if (unlikely(rx_size < sizeof(__le32))) {
- dev_err(dev, "HW BUG? only %zu bytes received\n", rx_size);
- goto error_bad_size;
- }
- if (likely(i2400m_is_d2h_barker(skb->data))) {
- skb_put(skb, rx_size);
- i2400m_rx(i2400m, skb);
- } else if (unlikely(i2400m_is_boot_barker(i2400m,
- skb->data, rx_size))) {
- ret = i2400m_dev_reset_handle(i2400m, "device rebooted");
- dev_err(dev, "RX: SDIO reboot barker\n");
- kfree_skb(skb);
- } else {
- i2400m_unknown_barker(i2400m, skb->data, rx_size);
- kfree_skb(skb);
- }
-out:
- d_fnend(7, dev, "(i2400ms %p) = void\n", i2400ms);
- return;
-
-error_memcpy_fromio:
- kfree_skb(skb);
-error_alloc_skb:
-error_get_size:
-error_bad_size:
- d_fnend(7, dev, "(i2400ms %p) = %d\n", i2400ms, ret);
-}
-
-
-/*
- * Process an interrupt from the SDIO card
- *
- * FIXME: need to process other events that are not just ready-to-read
- *
- * Checks there is data ready and then proceeds to read it.
- */
-static
-void i2400ms_irq(struct sdio_func *func)
-{
- int ret;
- struct i2400ms *i2400ms = sdio_get_drvdata(func);
- struct device *dev = &func->dev;
- int val;
-
- d_fnstart(6, dev, "(i2400ms %p)\n", i2400ms);
- val = sdio_readb(func, I2400MS_INTR_STATUS_ADDR, &ret);
- if (ret < 0) {
- dev_err(dev, "RX: Can't read interrupt status: %d\n", ret);
- goto error_no_irq;
- }
- if (!val) {
- dev_err(dev, "RX: BUG? got IRQ but no interrupt ready?\n");
- goto error_no_irq;
- }
- i2400ms_rx(i2400ms);
-error_no_irq:
- d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms);
-}
-
-
-/*
- * Setup SDIO RX
- *
- * Hooks up the IRQ handler and then enables IRQs.
- */
-int i2400ms_rx_setup(struct i2400ms *i2400ms)
-{
- int result;
- struct sdio_func *func = i2400ms->func;
- struct device *dev = &func->dev;
- struct i2400m *i2400m = &i2400ms->i2400m;
-
- d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
-
- init_waitqueue_head(&i2400ms->bm_wfa_wq);
- spin_lock(&i2400m->rx_lock);
- i2400ms->bm_wait_result = -EINPROGRESS;
- /*
- * Before we are about to enable the RX interrupt, make sure
- * bm_ack_size is cleared to -EINPROGRESS which indicates
- * no RX interrupt happened yet or the previous interrupt
- * has been handled, we are ready to take the new interrupt
- */
- i2400ms->bm_ack_size = -EINPROGRESS;
- spin_unlock(&i2400m->rx_lock);
-
- sdio_claim_host(func);
- result = sdio_claim_irq(func, i2400ms_irq);
- if (result < 0) {
- dev_err(dev, "Cannot claim IRQ: %d\n", result);
- goto error_irq_claim;
- }
- result = 0;
- sdio_writeb(func, 1, I2400MS_INTR_ENABLE_ADDR, &result);
- if (result < 0) {
- sdio_release_irq(func);
- dev_err(dev, "Failed to enable interrupts %d\n", result);
- }
-error_irq_claim:
- sdio_release_host(func);
- d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
- return result;
-}
-
-
-/*
- * Tear down SDIO RX
- *
- * Disables IRQs in the device and removes the IRQ handler.
- */
-void i2400ms_rx_release(struct i2400ms *i2400ms)
-{
- int result;
- struct sdio_func *func = i2400ms->func;
- struct device *dev = &func->dev;
- struct i2400m *i2400m = &i2400ms->i2400m;
-
- d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
- spin_lock(&i2400m->rx_lock);
- i2400ms->bm_ack_size = -EINTR;
- spin_unlock(&i2400m->rx_lock);
- wake_up_all(&i2400ms->bm_wfa_wq);
- sdio_claim_host(func);
- sdio_writeb(func, 0, I2400MS_INTR_ENABLE_ADDR, &result);
- sdio_release_irq(func);
- sdio_release_host(func);
- d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
-}
diff --git a/drivers/net/wimax/i2400m/sdio-tx.c b/drivers/net/wimax/i2400m/sdio-tx.c
deleted file mode 100644
index b53cd1c80e3e..000000000000
--- a/drivers/net/wimax/i2400m/sdio-tx.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Intel Wireless WiMAX Connection 2400m
- * SDIO TX transaction backends
- *
- *
- * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <linux-wimax@intel.com>
- * Dirk Brandewie <dirk.j.brandewie@intel.com>
- * - Initial implementation
- *
- *
- * Takes the TX messages in the i2400m's driver TX FIFO and sends them
- * to the device until there are no more.
- *
- * If we fail sending the message, we just drop it. There isn't much
- * we can do at this point. Most of the traffic is network, which has
- * recovery methods for dropped packets.
- *
- * The SDIO functions are not atomic, so we can't run from the context
- * where i2400m->bus_tx_kick() [i2400ms_bus_tx_kick()] is being called
- * (some times atomic). Thus, the actual TX work is deferred to a
- * workqueue.
- *
- * ROADMAP
- *
- * i2400ms_bus_tx_kick()
- * i2400ms_tx_submit() [through workqueue]
- *
- * i2400m_tx_setup()
- *
- * i2400m_tx_release()
- */
-#include <linux/mmc/sdio_func.h>
-#include "i2400m-sdio.h"
-
-#define D_SUBMODULE tx
-#include "sdio-debug-levels.h"
-
-
-/*
- * Pull TX transations from the TX FIFO and send them to the device
- * until there are no more.
- */
-static
-void i2400ms_tx_submit(struct work_struct *ws)
-{
- int result;
- struct i2400ms *i2400ms = container_of(ws, struct i2400ms, tx_worker);
- struct i2400m *i2400m = &i2400ms->i2400m;
- struct sdio_func *func = i2400ms->func;
- struct device *dev = &func->dev;
- struct i2400m_msg_hdr *tx_msg;
- size_t tx_msg_size;
-
- d_fnstart(4, dev, "(i2400ms %p, i2400m %p)\n", i2400ms, i2400ms);
-
- while (NULL != (tx_msg = i2400m_tx_msg_get(i2400m, &tx_msg_size))) {
- d_printf(2, dev, "TX: submitting %zu bytes\n", tx_msg_size);
- d_dump(5, dev, tx_msg, tx_msg_size);
-
- sdio_claim_host(func);
- result = sdio_memcpy_toio(func, 0, tx_msg, tx_msg_size);
- sdio_release_host(func);
-
- i2400m_tx_msg_sent(i2400m);
-
- if (result < 0) {
- dev_err(dev, "TX: cannot submit TX; tx_msg @%zu %zu B:"
- " %d\n", (void *) tx_msg - i2400m->tx_buf,
- tx_msg_size, result);
- }
-
- if (result == -ETIMEDOUT) {
- i2400m_error_recovery(i2400m);
- break;
- }
- d_printf(2, dev, "TX: %zub submitted\n", tx_msg_size);
- }
-
- d_fnend(4, dev, "(i2400ms %p) = void\n", i2400ms);
-}
-
-
-/*
- * The generic driver notifies us that there is data ready for TX
- *
- * Schedule a run of i2400ms_tx_submit() to handle it.
- */
-void i2400ms_bus_tx_kick(struct i2400m *i2400m)
-{
- struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
- struct device *dev = &i2400ms->func->dev;
- unsigned long flags;
-
- d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m);
-
- /* schedule tx work, this is because tx may block, therefore
- * it has to run in a thread context.
- */
- spin_lock_irqsave(&i2400m->tx_lock, flags);
- if (i2400ms->tx_workqueue != NULL)
- queue_work(i2400ms->tx_workqueue, &i2400ms->tx_worker);
- spin_unlock_irqrestore(&i2400m->tx_lock, flags);
-
- d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
-}
-
-int i2400ms_tx_setup(struct i2400ms *i2400ms)
-{
- int result;
- struct device *dev = &i2400ms->func->dev;
- struct i2400m *i2400m = &i2400ms->i2400m;
- struct workqueue_struct *tx_workqueue;
- unsigned long flags;
-
- d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
-
- INIT_WORK(&i2400ms->tx_worker, i2400ms_tx_submit);
- snprintf(i2400ms->tx_wq_name, sizeof(i2400ms->tx_wq_name),
- "%s-tx", i2400m->wimax_dev.name);
- tx_workqueue =
- create_singlethread_workqueue(i2400ms->tx_wq_name);
- if (tx_workqueue == NULL) {
- dev_err(dev, "TX: failed to create workqueue\n");
- result = -ENOMEM;
- } else
- result = 0;
- spin_lock_irqsave(&i2400m->tx_lock, flags);
- i2400ms->tx_workqueue = tx_workqueue;
- spin_unlock_irqrestore(&i2400m->tx_lock, flags);
- d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
- return result;
-}
-
-void i2400ms_tx_release(struct i2400ms *i2400ms)
-{
- struct i2400m *i2400m = &i2400ms->i2400m;
- struct workqueue_struct *tx_workqueue;
- unsigned long flags;
-
- tx_workqueue = i2400ms->tx_workqueue;
-
- spin_lock_irqsave(&i2400m->tx_lock, flags);
- i2400ms->tx_workqueue = NULL;
- spin_unlock_irqrestore(&i2400m->tx_lock, flags);
-
- if (tx_workqueue)
- destroy_workqueue(tx_workqueue);
-}
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c
deleted file mode 100644
index 21a9edd6e75d..000000000000
--- a/drivers/net/wimax/i2400m/sdio.c
+++ /dev/null
@@ -1,602 +0,0 @@
-/*
- * Intel Wireless WiMAX Connection 2400m
- * Linux driver model glue for the SDIO device, reset & fw upload
- *
- *
- * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com>
- * Dirk Brandewie <dirk.j.brandewie@intel.com>
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- * Yanir Lubetkin <yanirx.lubetkin@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * See i2400m-sdio.h for a general description of this driver.
- *
- * This file implements driver model glue, and hook ups for the
- * generic driver to implement the bus-specific functions (device
- * communication setup/tear down, firmware upload and resetting).
- *
- * ROADMAP
- *
- * i2400m_probe()
- * alloc_netdev()
- * i2400ms_netdev_setup()
- * i2400ms_init()
- * i2400m_netdev_setup()
- * i2400ms_enable_function()
- * i2400m_setup()
- *
- * i2400m_remove()
- * i2400m_release()
- * free_netdev(net_dev)
- *
- * i2400ms_bus_reset() Called by i2400m_reset
- * __i2400ms_reset()
- * __i2400ms_send_barker()
- */
-
-#include <linux/slab.h>
-#include <linux/debugfs.h>
-#include <linux/mmc/sdio_ids.h>
-#include <linux/mmc/sdio.h>
-#include <linux/mmc/sdio_func.h>
-#include "i2400m-sdio.h"
-#include <linux/wimax/i2400m.h>
-#include <linux/module.h>
-
-#define D_SUBMODULE main
-#include "sdio-debug-levels.h"
-
-/* IOE WiMAX function timeout in seconds */
-static int ioe_timeout = 2;
-module_param(ioe_timeout, int, 0);
-
-static char i2400ms_debug_params[128];
-module_param_string(debug, i2400ms_debug_params, sizeof(i2400ms_debug_params),
- 0644);
-MODULE_PARM_DESC(debug,
- "String of space-separated NAME:VALUE pairs, where NAMEs "
- "are the different debug submodules and VALUE are the "
- "initial debug value to set.");
-
-/* Our firmware file name list */
-static const char *i2400ms_bus_fw_names[] = {
-#define I2400MS_FW_FILE_NAME "i2400m-fw-sdio-1.3.sbcf"
- I2400MS_FW_FILE_NAME,
- NULL
-};
-
-
-static const struct i2400m_poke_table i2400ms_pokes[] = {
- I2400M_FW_POKE(0x6BE260, 0x00000088),
- I2400M_FW_POKE(0x080550, 0x00000005),
- I2400M_FW_POKE(0xAE0000, 0x00000000),
- I2400M_FW_POKE(0x000000, 0x00000000), /* MUST be 0 terminated or bad
- * things will happen */
-};
-
-/*
- * Enable the SDIO function
- *
- * Tries to enable the SDIO function; might fail if it is still not
- * ready (in some hardware, the SDIO WiMAX function is only enabled
- * when we ask it to explicitly doing). Tries until a timeout is
- * reached.
- *
- * The @maxtries argument indicates how many times (at most) it should
- * be tried to enable the function. 0 means forever. This acts along
- * with the timeout (ie: it'll stop trying as soon as the maximum
- * number of tries is reached _or_ as soon as the timeout is reached).
- *
- * The reverse of this is...sdio_disable_function()
- *
- * Returns: 0 if the SDIO function was enabled, < 0 errno code on
- * error (-ENODEV when it was unable to enable the function).
- */
-static
-int i2400ms_enable_function(struct i2400ms *i2400ms, unsigned maxtries)
-{
- struct sdio_func *func = i2400ms->func;
- u64 timeout;
- int err;
- struct device *dev = &func->dev;
- unsigned tries = 0;
-
- d_fnstart(3, dev, "(func %p)\n", func);
- /* Setup timeout (FIXME: This needs to read the CIS table to
- * get a real timeout) and then wait for the device to signal
- * it is ready */
- timeout = get_jiffies_64() + ioe_timeout * HZ;
- err = -ENODEV;
- while (err != 0 && time_before64(get_jiffies_64(), timeout)) {
- sdio_claim_host(func);
- /*
- * There is a sillicon bug on the IWMC3200, where the
- * IOE timeout will cause problems on Moorestown
- * platforms (system hang). We explicitly overwrite
- * func->enable_timeout here to work around the issue.
- */
- if (i2400ms->iwmc3200)
- func->enable_timeout = IWMC3200_IOR_TIMEOUT;
- err = sdio_enable_func(func);
- if (0 == err) {
- sdio_release_host(func);
- d_printf(2, dev, "SDIO function enabled\n");
- goto function_enabled;
- }
- d_printf(2, dev, "SDIO function failed to enable: %d\n", err);
- sdio_release_host(func);
- if (maxtries > 0 && ++tries >= maxtries) {
- err = -ETIME;
- break;
- }
- msleep(I2400MS_INIT_SLEEP_INTERVAL);
- }
- /* If timed out, device is not there yet -- get -ENODEV so
- * the device driver core will retry later on. */
- if (err == -ETIME) {
- dev_err(dev, "Can't enable WiMAX function; "
- " has the function been enabled?\n");
- err = -ENODEV;
- }
-function_enabled:
- d_fnend(3, dev, "(func %p) = %d\n", func, err);
- return err;
-}
-
-
-/*
- * Setup minimal device communication infrastructure needed to at
- * least be able to update the firmware.
- *
- * Note the ugly trick: if we are in the probe path
- * (i2400ms->debugfs_dentry == NULL), we only retry function
- * enablement one, to avoid racing with the iwmc3200 top controller.
- */
-static
-int i2400ms_bus_setup(struct i2400m *i2400m)
-{
- int result;
- struct i2400ms *i2400ms =
- container_of(i2400m, struct i2400ms, i2400m);
- struct device *dev = i2400m_dev(i2400m);
- struct sdio_func *func = i2400ms->func;
- int retries;
-
- sdio_claim_host(func);
- result = sdio_set_block_size(func, I2400MS_BLK_SIZE);
- sdio_release_host(func);
- if (result < 0) {
- dev_err(dev, "Failed to set block size: %d\n", result);
- goto error_set_blk_size;
- }
-
- if (i2400ms->iwmc3200 && i2400ms->debugfs_dentry == NULL)
- retries = 1;
- else
- retries = 0;
- result = i2400ms_enable_function(i2400ms, retries);
- if (result < 0) {
- dev_err(dev, "Cannot enable SDIO function: %d\n", result);
- goto error_func_enable;
- }
-
- result = i2400ms_tx_setup(i2400ms);
- if (result < 0)
- goto error_tx_setup;
- result = i2400ms_rx_setup(i2400ms);
- if (result < 0)
- goto error_rx_setup;
- return 0;
-
-error_rx_setup:
- i2400ms_tx_release(i2400ms);
-error_tx_setup:
- sdio_claim_host(func);
- sdio_disable_func(func);
- sdio_release_host(func);
-error_func_enable:
-error_set_blk_size:
- return result;
-}
-
-
-/*
- * Tear down minimal device communication infrastructure needed to at
- * least be able to update the firmware.
- */
-static
-void i2400ms_bus_release(struct i2400m *i2400m)
-{
- struct i2400ms *i2400ms =
- container_of(i2400m, struct i2400ms, i2400m);
- struct sdio_func *func = i2400ms->func;
-
- i2400ms_rx_release(i2400ms);
- i2400ms_tx_release(i2400ms);
- sdio_claim_host(func);
- sdio_disable_func(func);
- sdio_release_host(func);
-}
-
-
-/*
- * Setup driver resources needed to communicate with the device
- *
- * The fw needs some time to settle, and it was just uploaded,
- * so give it a break first. I'd prefer to just wait for the device to
- * send something, but seems the poking we do to enable SDIO stuff
- * interferes with it, so just give it a break before starting...
- */
-static
-int i2400ms_bus_dev_start(struct i2400m *i2400m)
-{
- struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
- struct sdio_func *func = i2400ms->func;
- struct device *dev = &func->dev;
-
- d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
- msleep(200);
- d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, 0);
- return 0;
-}
-
-
-/*
- * Sends a barker buffer to the device
- *
- * This helper will allocate a kmalloced buffer and use it to transmit
- * (then free it). Reason for this is that the SDIO host controller
- * expects alignment (unknown exactly which) which the stack won't
- * really provide and certain arches/host-controller combinations
- * cannot use stack/vmalloc/text areas for DMA transfers.
- */
-static
-int __i2400ms_send_barker(struct i2400ms *i2400ms,
- const __le32 *barker, size_t barker_size)
-{
- int ret;
- struct sdio_func *func = i2400ms->func;
- struct device *dev = &func->dev;
- void *buffer;
-
- ret = -ENOMEM;
- buffer = kmalloc(I2400MS_BLK_SIZE, GFP_KERNEL);
- if (buffer == NULL)
- goto error_kzalloc;
-
- memcpy(buffer, barker, barker_size);
- sdio_claim_host(func);
- ret = sdio_memcpy_toio(func, 0, buffer, I2400MS_BLK_SIZE);
- sdio_release_host(func);
-
- if (ret < 0)
- d_printf(0, dev, "E: barker error: %d\n", ret);
-
- kfree(buffer);
-error_kzalloc:
- return ret;
-}
-
-
-/*
- * Reset a device at different levels (warm, cold or bus)
- *
- * @i2400ms: device descriptor
- * @reset_type: soft, warm or bus reset (I2400M_RT_WARM/SOFT/BUS)
- *
- * FIXME: not tested -- need to confirm expected effects
- *
- * Warm and cold resets get an SDIO reset if they fail (unimplemented)
- *
- * Warm reset:
- *
- * The device will be fully reset internally, but won't be
- * disconnected from the bus (so no reenumeration will
- * happen). Firmware upload will be necessary.
- *
- * The device will send a reboot barker that will trigger the driver
- * to reinitialize the state via __i2400m_dev_reset_handle.
- *
- *
- * Cold and bus reset:
- *
- * The device will be fully reset internally, disconnected from the
- * bus an a reenumeration will happen. Firmware upload will be
- * necessary. Thus, we don't do any locking or struct
- * reinitialization, as we are going to be fully disconnected and
- * reenumerated.
- *
- * Note we need to return -ENODEV if a warm reset was requested and we
- * had to resort to a bus reset. See i2400m_op_reset(), wimax_reset()
- * and wimax_dev->op_reset.
- *
- * WARNING: no driver state saved/fixed
- */
-static
-int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt)
-{
- int result = 0;
- struct i2400ms *i2400ms =
- container_of(i2400m, struct i2400ms, i2400m);
- struct device *dev = i2400m_dev(i2400m);
- static const __le32 i2400m_WARM_BOOT_BARKER[4] = {
- cpu_to_le32(I2400M_WARM_RESET_BARKER),
- cpu_to_le32(I2400M_WARM_RESET_BARKER),
- cpu_to_le32(I2400M_WARM_RESET_BARKER),
- cpu_to_le32(I2400M_WARM_RESET_BARKER),
- };
- static const __le32 i2400m_COLD_BOOT_BARKER[4] = {
- cpu_to_le32(I2400M_COLD_RESET_BARKER),
- cpu_to_le32(I2400M_COLD_RESET_BARKER),
- cpu_to_le32(I2400M_COLD_RESET_BARKER),
- cpu_to_le32(I2400M_COLD_RESET_BARKER),
- };
-
- if (rt == I2400M_RT_WARM)
- result = __i2400ms_send_barker(i2400ms, i2400m_WARM_BOOT_BARKER,
- sizeof(i2400m_WARM_BOOT_BARKER));
- else if (rt == I2400M_RT_COLD)
- result = __i2400ms_send_barker(i2400ms, i2400m_COLD_BOOT_BARKER,
- sizeof(i2400m_COLD_BOOT_BARKER));
- else if (rt == I2400M_RT_BUS) {
-do_bus_reset:
-
- i2400ms_bus_release(i2400m);
-
- /* Wait for the device to settle */
- msleep(40);
-
- result = i2400ms_bus_setup(i2400m);
- } else
- BUG();
- if (result < 0 && rt != I2400M_RT_BUS) {
- dev_err(dev, "%s reset failed (%d); trying SDIO reset\n",
- rt == I2400M_RT_WARM ? "warm" : "cold", result);
- rt = I2400M_RT_BUS;
- goto do_bus_reset;
- }
- return result;
-}
-
-
-static
-void i2400ms_netdev_setup(struct net_device *net_dev)
-{
- struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
- struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
- i2400ms_init(i2400ms);
- i2400m_netdev_setup(net_dev);
-}
-
-
-/*
- * Debug levels control; see debug.h
- */
-struct d_level D_LEVEL[] = {
- D_SUBMODULE_DEFINE(main),
- D_SUBMODULE_DEFINE(tx),
- D_SUBMODULE_DEFINE(rx),
- D_SUBMODULE_DEFINE(fw),
-};
-size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);
-
-
-#define __debugfs_register(prefix, name, parent) \
-do { \
- result = d_level_register_debugfs(prefix, name, parent); \
- if (result < 0) \
- goto error; \
-} while (0)
-
-
-static
-int i2400ms_debugfs_add(struct i2400ms *i2400ms)
-{
- int result;
- struct dentry *dentry = i2400ms->i2400m.wimax_dev.debugfs_dentry;
-
- dentry = debugfs_create_dir("i2400m-sdio", dentry);
- result = PTR_ERR(dentry);
- if (IS_ERR(dentry)) {
- if (result == -ENODEV)
- result = 0; /* No debugfs support */
- goto error;
- }
- i2400ms->debugfs_dentry = dentry;
- __debugfs_register("dl_", main, dentry);
- __debugfs_register("dl_", tx, dentry);
- __debugfs_register("dl_", rx, dentry);
- __debugfs_register("dl_", fw, dentry);
-
- return 0;
-
-error:
- debugfs_remove_recursive(i2400ms->debugfs_dentry);
- i2400ms->debugfs_dentry = NULL;
- return result;
-}
-
-
-static struct device_type i2400ms_type = {
- .name = "wimax",
-};
-
-/*
- * Probe a i2400m interface and register it
- *
- * @func: SDIO function
- * @id: SDIO device ID
- * @returns: 0 if ok, < 0 errno code on error.
- *
- * Alloc a net device, initialize the bus-specific details and then
- * calls the bus-generic initialization routine. That will register
- * the wimax and netdev devices, upload the firmware [using
- * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the
- * communication with the device and then will start to talk to it to
- * finnish setting it up.
- *
- * Initialization is tricky; some instances of the hw are packed with
- * others in a way that requires a third driver that enables the WiMAX
- * function. In those cases, we can't enable the SDIO function and
- * we'll return with -ENODEV. When the driver that enables the WiMAX
- * function does its thing, it has to do a bus_rescan_devices() on the
- * SDIO bus so this driver is called again to enumerate the WiMAX
- * function.
- */
-static
-int i2400ms_probe(struct sdio_func *func,
- const struct sdio_device_id *id)
-{
- int result;
- struct net_device *net_dev;
- struct device *dev = &func->dev;
- struct i2400m *i2400m;
- struct i2400ms *i2400ms;
-
- /* Allocate instance [calls i2400m_netdev_setup() on it]. */
- result = -ENOMEM;
- net_dev = alloc_netdev(sizeof(*i2400ms), "wmx%d",
- i2400ms_netdev_setup);
- if (net_dev == NULL) {
- dev_err(dev, "no memory for network device instance\n");
- goto error_alloc_netdev;
- }
- SET_NETDEV_DEV(net_dev, dev);
- SET_NETDEV_DEVTYPE(net_dev, &i2400ms_type);
- i2400m = net_dev_to_i2400m(net_dev);
- i2400ms = container_of(i2400m, struct i2400ms, i2400m);
- i2400m->wimax_dev.net_dev = net_dev;
- i2400ms->func = func;
- sdio_set_drvdata(func, i2400ms);
-
- i2400m->bus_tx_block_size = I2400MS_BLK_SIZE;
- /*
- * Room required in the TX queue for SDIO message to accommodate
- * a smallest payload while allocating header space is 224 bytes,
- * which is the smallest message size(the block size 256 bytes)
- * minus the smallest message header size(32 bytes).
- */
- i2400m->bus_tx_room_min = I2400MS_BLK_SIZE - I2400M_PL_ALIGN * 2;
- i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX;
- i2400m->bus_setup = i2400ms_bus_setup;
- i2400m->bus_dev_start = i2400ms_bus_dev_start;
- i2400m->bus_dev_stop = NULL;
- i2400m->bus_release = i2400ms_bus_release;
- i2400m->bus_tx_kick = i2400ms_bus_tx_kick;
- i2400m->bus_reset = i2400ms_bus_reset;
- /* The iwmc3200-wimax sometimes requires the driver to try
- * hard when we paint it into a corner. */
- i2400m->bus_bm_retries = I2400M_SDIO_BOOT_RETRIES;
- i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send;
- i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack;
- i2400m->bus_fw_names = i2400ms_bus_fw_names;
- i2400m->bus_bm_mac_addr_impaired = 1;
- i2400m->bus_bm_pokes_table = &i2400ms_pokes[0];
-
- switch (func->device) {
- case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX:
- case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5:
- i2400ms->iwmc3200 = 1;
- break;
- default:
- i2400ms->iwmc3200 = 0;
- }
-
- result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT);
- if (result < 0) {
- dev_err(dev, "cannot setup device: %d\n", result);
- goto error_setup;
- }
-
- result = i2400ms_debugfs_add(i2400ms);
- if (result < 0) {
- dev_err(dev, "cannot create SDIO debugfs: %d\n",
- result);
- goto error_debugfs_add;
- }
- return 0;
-
-error_debugfs_add:
- i2400m_release(i2400m);
-error_setup:
- sdio_set_drvdata(func, NULL);
- free_netdev(net_dev);
-error_alloc_netdev:
- return result;
-}
-
-
-static
-void i2400ms_remove(struct sdio_func *func)
-{
- struct device *dev = &func->dev;
- struct i2400ms *i2400ms = sdio_get_drvdata(func);
- struct i2400m *i2400m = &i2400ms->i2400m;
- struct net_device *net_dev = i2400m->wimax_dev.net_dev;
-
- d_fnstart(3, dev, "SDIO func %p\n", func);
- debugfs_remove_recursive(i2400ms->debugfs_dentry);
- i2400ms->debugfs_dentry = NULL;
- i2400m_release(i2400m);
- sdio_set_drvdata(func, NULL);
- free_netdev(net_dev);
- d_fnend(3, dev, "SDIO func %p\n", func);
-}
-
-static
-const struct sdio_device_id i2400ms_sdio_ids[] = {
- /* Intel: i2400m WiMAX (iwmc3200) over SDIO */
- { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL,
- SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX) },
- { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL,
- SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5) },
- { /* end: all zeroes */ },
-};
-MODULE_DEVICE_TABLE(sdio, i2400ms_sdio_ids);
-
-
-static
-struct sdio_driver i2400m_sdio_driver = {
- .name = KBUILD_MODNAME,
- .probe = i2400ms_probe,
- .remove = i2400ms_remove,
- .id_table = i2400ms_sdio_ids,
-};
-
-
-static
-int __init i2400ms_driver_init(void)
-{
- d_parse_params(D_LEVEL, D_LEVEL_SIZE, i2400ms_debug_params,
- "i2400m_sdio.debug");
- return sdio_register_driver(&i2400m_sdio_driver);
-}
-module_init(i2400ms_driver_init);
-
-
-static
-void __exit i2400ms_driver_exit(void)
-{
- sdio_unregister_driver(&i2400m_sdio_driver);
-}
-module_exit(i2400ms_driver_exit);
-
-
-MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>");
-MODULE_DESCRIPTION("Intel 2400M WiMAX networking for SDIO");
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(I2400MS_FW_FILE_NAME);
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 5f58fa53238c..6deaae18db57 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -276,7 +276,6 @@ source "drivers/net/wireless/hostap/Kconfig"
source "drivers/net/wireless/ipw2x00/Kconfig"
source "drivers/net/wireless/iwlwifi/Kconfig"
source "drivers/net/wireless/iwlegacy/Kconfig"
-source "drivers/net/wireless/iwmc3200wifi/Kconfig"
source "drivers/net/wireless/libertas/Kconfig"
source "drivers/net/wireless/orinoco/Kconfig"
source "drivers/net/wireless/p54/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 0ce218b931d4..062dfdff6364 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -53,8 +53,6 @@ obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
obj-$(CONFIG_WL_TI) += ti/
-obj-$(CONFIG_IWM) += iwmc3200wifi/
-
obj-$(CONFIG_MWIFIEX) += mwifiex/
obj-$(CONFIG_BRCMFMAC) += brcm80211/
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 520a4b2eb9cc..a747c632597a 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -7233,8 +7233,8 @@ static int airo_get_aplist(struct net_device *dev,
}
} else {
dwrq->flags = 1; /* Should be define'd */
- memcpy(extra + sizeof(struct sockaddr)*i,
- &qual, sizeof(struct iw_quality)*i);
+ memcpy(extra + sizeof(struct sockaddr) * i, qual,
+ sizeof(struct iw_quality) * i);
}
dwrq->length = i;
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index c54b7d37bff1..420d69b2674c 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -143,6 +143,7 @@ struct ath_common {
u32 keymax;
DECLARE_BITMAP(keymap, ATH_KEYMAX);
DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX);
+ DECLARE_BITMAP(ccmp_keymap, ATH_KEYMAX);
enum ath_crypt_caps crypt_caps;
unsigned int clockrate;
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig
index e18a9aa7b6ca..338c5c42357d 100644
--- a/drivers/net/wireless/ath/ath5k/Kconfig
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
@@ -64,3 +64,11 @@ config ATH5K_PCI
---help---
This adds support for PCI type chipsets of the 5xxx Atheros
family.
+
+config ATH5K_TEST_CHANNELS
+ bool "Enables testing channels on ath5k"
+ depends on ATH5K && CFG80211_CERTIFICATION_ONUS
+ ---help---
+ This enables non-standard IEEE 802.11 channels on ath5k, which
+ can be used for research purposes. This option should be disabled
+ unless doing research.
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index fbaa30930076..8c4c040a47b8 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -74,10 +74,6 @@ bool ath5k_modparam_nohwcrypt;
module_param_named(nohwcrypt, ath5k_modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
-static bool modparam_all_channels;
-module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO);
-MODULE_PARM_DESC(all_channels, "Expose all channels the device can use.");
-
static bool modparam_fastchanswitch;
module_param_named(fastchanswitch, modparam_fastchanswitch, bool, S_IRUGO);
MODULE_PARM_DESC(fastchanswitch, "Enable fast channel switching for AR2413/AR5413 radios.");
@@ -258,8 +254,15 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re
\********************/
/*
- * Returns true for the channel numbers used without all_channels modparam.
+ * Returns true for the channel numbers used.
*/
+#ifdef CONFIG_ATH5K_TEST_CHANNELS
+static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band)
+{
+ return true;
+}
+
+#else
static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band)
{
if (band == IEEE80211_BAND_2GHZ && chan <= 14)
@@ -276,6 +279,7 @@ static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band)
/* 802.11j 4.9GHz (20MHz) */
(chan == 184 || chan == 188 || chan == 192 || chan == 196));
}
+#endif
static unsigned int
ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
@@ -316,8 +320,7 @@ ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
if (!ath5k_channel_ok(ah, &channels[count]))
continue;
- if (!modparam_all_channels &&
- !ath5k_is_standard_channel(ch, band))
+ if (!ath5k_is_standard_channel(ch, band))
continue;
count++;
@@ -1045,11 +1048,11 @@ ath5k_drain_tx_buffs(struct ath5k_hw *ah)
ath5k_txbuf_free_skb(ah, bf);
- spin_lock_bh(&ah->txbuflock);
+ spin_lock(&ah->txbuflock);
list_move_tail(&bf->list, &ah->txbuf);
ah->txbuf_len++;
txq->txq_len--;
- spin_unlock_bh(&ah->txbuflock);
+ spin_unlock(&ah->txbuflock);
}
txq->link = NULL;
txq->txq_poll_mark = false;
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index f27e9732951d..86aeef4b9d7e 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -53,6 +53,11 @@
#define DEFAULT_BG_SCAN_PERIOD 60
+struct ath6kl_cfg80211_match_probe_ssid {
+ struct cfg80211_ssid ssid;
+ u8 flag;
+};
+
static struct ieee80211_rate ath6kl_rates[] = {
RATETAB_ENT(10, 0x1, 0),
RATETAB_ENT(20, 0x2, 0),
@@ -576,6 +581,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
vif->nw_type = vif->next_mode;
+ /* enable enhanced bmiss detection if applicable */
+ ath6kl_cfg80211_sta_bmiss_enhance(vif, true);
+
if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)
nw_subtype = SUBTYPE_P2PCLIENT;
@@ -852,20 +860,6 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
}
}
- /*
- * Send a disconnect command to target when a disconnect event is
- * received with reason code other than 3 (DISCONNECT_CMD - disconnect
- * request from host) to make the firmware stop trying to connect even
- * after giving disconnect event. There will be one more disconnect
- * event for this disconnect command with reason code DISCONNECT_CMD
- * which will be notified to cfg80211.
- */
-
- if (reason != DISCONNECT_CMD) {
- ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
- return;
- }
-
clear_bit(CONNECT_PEND, &vif->flags);
if (vif->sme_state == SME_CONNECTING) {
@@ -875,32 +869,96 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
} else if (vif->sme_state == SME_CONNECTED) {
- cfg80211_disconnected(vif->ndev, reason,
+ cfg80211_disconnected(vif->ndev, proto_reason,
NULL, 0, GFP_KERNEL);
}
vif->sme_state = SME_DISCONNECTED;
+
+ /*
+ * Send a disconnect command to target when a disconnect event is
+ * received with reason code other than 3 (DISCONNECT_CMD - disconnect
+ * request from host) to make the firmware stop trying to connect even
+ * after giving disconnect event. There will be one more disconnect
+ * event for this disconnect command with reason code DISCONNECT_CMD
+ * which won't be notified to cfg80211.
+ */
+ if (reason != DISCONNECT_CMD)
+ ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
}
static int ath6kl_set_probed_ssids(struct ath6kl *ar,
struct ath6kl_vif *vif,
- struct cfg80211_ssid *ssids, int n_ssids)
+ struct cfg80211_ssid *ssids, int n_ssids,
+ struct cfg80211_match_set *match_set,
+ int n_match_ssid)
{
- u8 i;
+ u8 i, j, index_to_add, ssid_found = false;
+ struct ath6kl_cfg80211_match_probe_ssid ssid_list[MAX_PROBED_SSIDS];
+
+ memset(ssid_list, 0, sizeof(ssid_list));
- if (n_ssids > MAX_PROBED_SSID_INDEX)
+ if (n_ssids > MAX_PROBED_SSIDS ||
+ n_match_ssid > MAX_PROBED_SSIDS)
return -EINVAL;
for (i = 0; i < n_ssids; i++) {
+ memcpy(ssid_list[i].ssid.ssid,
+ ssids[i].ssid,
+ ssids[i].ssid_len);
+ ssid_list[i].ssid.ssid_len = ssids[i].ssid_len;
+
+ if (ssids[i].ssid_len)
+ ssid_list[i].flag = SPECIFIC_SSID_FLAG;
+ else
+ ssid_list[i].flag = ANY_SSID_FLAG;
+
+ if (n_match_ssid == 0)
+ ssid_list[i].flag |= MATCH_SSID_FLAG;
+ }
+
+ index_to_add = i;
+
+ for (i = 0; i < n_match_ssid; i++) {
+ ssid_found = false;
+
+ for (j = 0; j < n_ssids; j++) {
+ if ((match_set[i].ssid.ssid_len ==
+ ssid_list[j].ssid.ssid_len) &&
+ (!memcmp(ssid_list[j].ssid.ssid,
+ match_set[i].ssid.ssid,
+ match_set[i].ssid.ssid_len))) {
+ ssid_list[j].flag |= MATCH_SSID_FLAG;
+ ssid_found = true;
+ break;
+ }
+ }
+
+ if (ssid_found)
+ continue;
+
+ if (index_to_add >= MAX_PROBED_SSIDS)
+ continue;
+
+ ssid_list[index_to_add].ssid.ssid_len =
+ match_set[i].ssid.ssid_len;
+ memcpy(ssid_list[index_to_add].ssid.ssid,
+ match_set[i].ssid.ssid,
+ match_set[i].ssid.ssid_len);
+ ssid_list[index_to_add].flag |= MATCH_SSID_FLAG;
+ index_to_add++;
+ }
+
+ for (i = 0; i < index_to_add; i++) {
ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i,
- ssids[i].ssid_len ?
- SPECIFIC_SSID_FLAG : ANY_SSID_FLAG,
- ssids[i].ssid_len,
- ssids[i].ssid);
+ ssid_list[i].flag,
+ ssid_list[i].ssid.ssid_len,
+ ssid_list[i].ssid.ssid);
+
}
/* Make sure no old entries are left behind */
- for (i = n_ssids; i < MAX_PROBED_SSID_INDEX; i++) {
+ for (i = index_to_add; i < MAX_PROBED_SSIDS; i++) {
ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i,
DISABLE_SSID_FLAG, 0, NULL);
}
@@ -908,11 +966,11 @@ static int ath6kl_set_probed_ssids(struct ath6kl *ar,
return 0;
}
-static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+static int ath6kl_cfg80211_scan(struct wiphy *wiphy,
struct cfg80211_scan_request *request)
{
- struct ath6kl *ar = ath6kl_priv(ndev);
- struct ath6kl_vif *vif = netdev_priv(ndev);
+ struct ath6kl_vif *vif = ath6kl_vif_from_wdev(request->wdev);
+ struct ath6kl *ar = ath6kl_priv(vif->ndev);
s8 n_channels = 0;
u16 *channels = NULL;
int ret = 0;
@@ -934,7 +992,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
}
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
- request->n_ssids);
+ request->n_ssids, NULL, 0);
if (ret < 0)
return ret;
@@ -943,7 +1001,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
WMI_FRAME_PROBE_REQ,
request->ie, request->ie_len);
if (ret) {
- ath6kl_err("failed to set Probe Request appie for scan");
+ ath6kl_err("failed to set Probe Request appie for scan\n");
return ret;
}
@@ -1429,14 +1487,14 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
return 0;
}
-static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
- char *name,
- enum nl80211_iftype type,
- u32 *flags,
- struct vif_params *params)
+static struct wireless_dev *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
+ char *name,
+ enum nl80211_iftype type,
+ u32 *flags,
+ struct vif_params *params)
{
struct ath6kl *ar = wiphy_priv(wiphy);
- struct net_device *ndev;
+ struct wireless_dev *wdev;
u8 if_idx, nw_type;
if (ar->num_vif == ar->vif_max) {
@@ -1449,20 +1507,20 @@ static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
return ERR_PTR(-EINVAL);
}
- ndev = ath6kl_interface_add(ar, name, type, if_idx, nw_type);
- if (!ndev)
+ wdev = ath6kl_interface_add(ar, name, type, if_idx, nw_type);
+ if (!wdev)
return ERR_PTR(-ENOMEM);
ar->num_vif++;
- return ndev;
+ return wdev;
}
static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
- struct net_device *ndev)
+ struct wireless_dev *wdev)
{
struct ath6kl *ar = wiphy_priv(wiphy);
- struct ath6kl_vif *vif = netdev_priv(ndev);
+ struct ath6kl_vif *vif = netdev_priv(wdev->netdev);
spin_lock_bh(&ar->list_lock);
list_del(&vif->list);
@@ -1512,6 +1570,9 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
}
}
+ /* need to clean up enhanced bmiss detection fw state */
+ ath6kl_cfg80211_sta_bmiss_enhance(vif, false);
+
set_iface_type:
switch (type) {
case NL80211_IFTYPE_STATION:
@@ -2074,7 +2135,9 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
return -EINVAL;
- if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) {
+ if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags) &&
+ test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
+ ar->fw_capabilities)) {
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
vif->fw_vif_idx, false);
if (ret)
@@ -2209,7 +2272,9 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
ar->state = ATH6KL_STATE_ON;
- if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) {
+ if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags) &&
+ test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
+ ar->fw_capabilities)) {
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
vif->fw_vif_idx, true);
if (ret)
@@ -2475,7 +2540,7 @@ void ath6kl_check_wow_status(struct ath6kl *ar)
static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band,
bool ht_enable)
{
- struct ath6kl_htcap *htcap = &vif->htcap;
+ struct ath6kl_htcap *htcap = &vif->htcap[band];
if (htcap->ht_enable == ht_enable)
return 0;
@@ -2585,6 +2650,30 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif,
return 0;
}
+void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable)
+{
+ int err;
+
+ if (WARN_ON(!test_bit(WMI_READY, &vif->ar->flag)))
+ return;
+
+ if (vif->nw_type != INFRA_NETWORK)
+ return;
+
+ if (!test_bit(ATH6KL_FW_CAPABILITY_BMISS_ENHANCE,
+ vif->ar->fw_capabilities))
+ return;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s fw bmiss enhance\n",
+ enable ? "enable" : "disable");
+
+ err = ath6kl_wmi_sta_bmiss_enhance_cmd(vif->ar->wmi,
+ vif->fw_vif_idx, enable);
+ if (err)
+ ath6kl_err("failed to %s enhanced bmiss detection: %d\n",
+ enable ? "enable" : "disable", err);
+}
+
static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon,
u8 *rsn_capab)
{
@@ -2665,9 +2754,15 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
/* TODO:
* info->interval
- * info->dtim_period
*/
+ ret = ath6kl_wmi_ap_set_dtim_cmd(ar->wmi, vif->fw_vif_idx,
+ info->dtim_period);
+
+ /* ignore error, just print a warning and continue normally */
+ if (ret)
+ ath6kl_warn("Failed to set dtim_period in beacon: %d\n", ret);
+
if (info->beacon.head == NULL)
return -EINVAL;
mgmt = (struct ieee80211_mgmt *) info->beacon.head;
@@ -2880,14 +2975,14 @@ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
}
static int ath6kl_remain_on_channel(struct wiphy *wiphy,
- struct net_device *dev,
+ struct wireless_dev *wdev,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration,
u64 *cookie)
{
- struct ath6kl *ar = ath6kl_priv(dev);
- struct ath6kl_vif *vif = netdev_priv(dev);
+ struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
+ struct ath6kl *ar = ath6kl_priv(vif->ndev);
u32 id;
/* TODO: if already pending or ongoing remain-on-channel,
@@ -2904,11 +2999,11 @@ static int ath6kl_remain_on_channel(struct wiphy *wiphy,
}
static int ath6kl_cancel_remain_on_channel(struct wiphy *wiphy,
- struct net_device *dev,
+ struct wireless_dev *wdev,
u64 cookie)
{
- struct ath6kl *ar = ath6kl_priv(dev);
- struct ath6kl_vif *vif = netdev_priv(dev);
+ struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
+ struct ath6kl *ar = ath6kl_priv(vif->ndev);
if (cookie != vif->last_roc_id)
return -ENOENT;
@@ -3039,15 +3134,15 @@ static bool ath6kl_is_p2p_go_ssid(const u8 *buf, size_t len)
return false;
}
-static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
+static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type,
bool channel_type_valid, unsigned int wait,
const u8 *buf, size_t len, bool no_cck,
bool dont_wait_for_ack, u64 *cookie)
{
- struct ath6kl *ar = ath6kl_priv(dev);
- struct ath6kl_vif *vif = netdev_priv(dev);
+ struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
+ struct ath6kl *ar = ath6kl_priv(vif->ndev);
u32 id;
const struct ieee80211_mgmt *mgmt;
bool more_data, queued;
@@ -3092,10 +3187,10 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
}
static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
- struct net_device *dev,
+ struct wireless_dev *wdev,
u16 frame_type, bool reg)
{
- struct ath6kl_vif *vif = netdev_priv(dev);
+ struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n",
__func__, frame_type, reg);
@@ -3131,10 +3226,24 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
ath6kl_cfg80211_scan_complete_event(vif, true);
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
- request->n_ssids);
+ request->n_ssids,
+ request->match_sets,
+ request->n_match_sets);
if (ret < 0)
return ret;
+ if (!request->n_match_sets) {
+ ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
+ ALL_BSS_FILTER, 0);
+ if (ret < 0)
+ return ret;
+ } else {
+ ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
+ MATCHED_SSID_FILTER, 0);
+ if (ret < 0)
+ return ret;
+ }
+
/* fw uses seconds, also make sure that it's >0 */
interval = max_t(u16, 1, request->interval / 1000);
@@ -3156,7 +3265,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
WMI_FRAME_PROBE_REQ,
request->ie, request->ie_len);
if (ret) {
- ath6kl_warn("Failed to set probe request IE for scheduled scan: %d",
+ ath6kl_warn("Failed to set probe request IE for scheduled scan: %d\n",
ret);
return ret;
}
@@ -3188,6 +3297,18 @@ static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
return 0;
}
+static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *addr,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+ struct ath6kl_vif *vif = netdev_priv(dev);
+
+ return ath6kl_wmi_set_bitrate_mask(ar->wmi, vif->fw_vif_idx,
+ mask);
+}
+
static const struct ieee80211_txrx_stypes
ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
[NL80211_IFTYPE_STATION] = {
@@ -3253,6 +3374,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
.mgmt_frame_register = ath6kl_mgmt_frame_register,
.sched_scan_start = ath6kl_cfg80211_sscan_start,
.sched_scan_stop = ath6kl_cfg80211_sscan_stop,
+ .set_bitrate_mask = ath6kl_cfg80211_set_bitrate,
};
void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
@@ -3355,9 +3477,9 @@ void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif)
ar->num_vif--;
}
-struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
- enum nl80211_iftype type, u8 fw_vif_idx,
- u8 nw_type)
+struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, char *name,
+ enum nl80211_iftype type,
+ u8 fw_vif_idx, u8 nw_type)
{
struct net_device *ndev;
struct ath6kl_vif *vif;
@@ -3380,7 +3502,8 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
vif->bg_scan_period = 0;
- vif->htcap.ht_enable = true;
+ vif->htcap[IEEE80211_BAND_2GHZ].ht_enable = true;
+ vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true;
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
if (fw_vif_idx != 0)
@@ -3410,7 +3533,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
list_add_tail(&vif->list, &ar->vif_list);
spin_unlock_bh(&ar->list_lock);
- return ndev;
+ return &vif->wdev;
err:
aggr_module_destroy(vif->aggr_cntxt);
@@ -3440,7 +3563,13 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
}
/* max num of ssids that can be probed during scanning */
- wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
+ wiphy->max_scan_ssids = MAX_PROBED_SSIDS;
+
+ /* max num of ssids that can be matched after scan */
+ if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
+ ar->fw_capabilities))
+ wiphy->max_match_sets = MAX_PROBED_SSIDS;
+
wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
switch (ar->hw.cap) {
case WMI_11AN_CAP:
@@ -3477,6 +3606,17 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
ath6kl_band_5ghz.ht_cap.cap = 0;
ath6kl_band_5ghz.ht_cap.ht_supported = false;
}
+
+ if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) {
+ ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
+ ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
+ ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
+ ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff;
+ } else {
+ ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
+ ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
+ }
+
if (band_2gig)
wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
if (band_5gig)
@@ -3487,6 +3627,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
wiphy->cipher_suites = cipher_suites;
wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+#ifdef CONFIG_PM
wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT |
WIPHY_WOWLAN_GTK_REKEY_FAILURE |
@@ -3496,8 +3637,9 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST;
wiphy->wowlan.pattern_min_len = 1;
wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE;
+#endif
- wiphy->max_sched_scan_ssids = MAX_PROBED_SSID_INDEX;
+ wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS;
ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
WIPHY_FLAG_HAVE_AP_SME |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h
index 5ea8cbb79f43..56b1ebe79812 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.h
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h
@@ -25,9 +25,9 @@ enum ath6kl_cfg_suspend_mode {
ATH6KL_CFG_SUSPEND_SCHED_SCAN,
};
-struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
- enum nl80211_iftype type,
- u8 fw_vif_idx, u8 nw_type);
+struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, char *name,
+ enum nl80211_iftype type,
+ u8 fw_vif_idx, u8 nw_type);
void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
enum wmi_phy_mode mode);
void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted);
@@ -62,5 +62,7 @@ void ath6kl_cfg80211_cleanup(struct ath6kl *ar);
struct ath6kl *ath6kl_cfg80211_create(void);
void ath6kl_cfg80211_destroy(struct ath6kl *ar);
+/* TODO: remove this once ath6kl_vif_cleanup() is moved to cfg80211.c */
+void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable);
#endif /* ATH6KL_CFG80211_H */
diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c
index fdb3b1decc76..82c4dd2a960e 100644
--- a/drivers/net/wireless/ath/ath6kl/core.c
+++ b/drivers/net/wireless/ath/ath6kl/core.c
@@ -56,7 +56,7 @@ EXPORT_SYMBOL(ath6kl_core_rx_complete);
int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
{
struct ath6kl_bmi_target_info targ_info;
- struct net_device *ndev;
+ struct wireless_dev *wdev;
int ret = 0, i;
switch (htc_type) {
@@ -187,12 +187,12 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
rtnl_lock();
/* Add an initial station interface */
- ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0,
+ wdev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0,
INFRA_NETWORK);
rtnl_unlock();
- if (!ndev) {
+ if (!wdev) {
ath6kl_err("Failed to instantiate a network device\n");
ret = -ENOMEM;
wiphy_unregister(ar->wiphy);
@@ -200,7 +200,7 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
}
ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
- __func__, ndev->name, ndev, ar);
+ __func__, wdev->netdev->name, wdev->netdev, ar);
return ret;
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 8443b2a4133e..cec49a31029a 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -100,6 +100,21 @@ enum ath6kl_fw_capability {
/* Firmware has support to override rsn cap of rsn ie */
ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
+ /*
+ * Multicast support in WOW and host awake mode.
+ * Allow all multicast in host awake mode.
+ * Apply multicast filter in WOW mode.
+ */
+ ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
+
+ /* Firmware supports enhanced bmiss detection */
+ ATH6KL_FW_CAPABILITY_BMISS_ENHANCE,
+
+ /*
+ * FW supports matching of ssid in schedule scan
+ */
+ ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
+
/* this needs to be last */
ATH6KL_FW_CAPABILITY_MAX,
};
@@ -112,6 +127,10 @@ struct ath6kl_fw_ie {
u8 data[0];
};
+enum ath6kl_hw_flags {
+ ATH6KL_HW_FLAG_64BIT_RATES = BIT(0),
+};
+
#define ATH6KL_FW_API2_FILE "fw-2.bin"
#define ATH6KL_FW_API3_FILE "fw-3.bin"
@@ -196,7 +215,7 @@ struct ath6kl_fw_ie {
#define AGGR_NUM_OF_FREE_NETBUFS 16
-#define AGGR_RX_TIMEOUT 400 /* in ms */
+#define AGGR_RX_TIMEOUT 100 /* in ms */
#define WMI_TIMEOUT (2 * HZ)
@@ -245,7 +264,6 @@ struct skb_hold_q {
struct rxtid {
bool aggr;
- bool progress;
bool timer_mon;
u16 win_sz;
u16 seq_next;
@@ -254,9 +272,15 @@ struct rxtid {
struct sk_buff_head q;
/*
- * FIXME: No clue what this should protect. Apparently it should
- * protect some of the fields above but they are also accessed
- * without taking the lock.
+ * lock mainly protects seq_next and hold_q. Movement of seq_next
+ * needs to be protected between aggr_timeout() and
+ * aggr_process_recv_frm(). hold_q will be holding the pending
+ * reorder frames and it's access should also be protected.
+ * Some of the other fields like hold_q_sz, win_sz and aggr are
+ * initialized/reset when receiving addba/delba req, also while
+ * deleting aggr state all the pending buffers are flushed before
+ * resetting these fields, so there should not be any race in accessing
+ * these fields.
*/
spinlock_t lock;
};
@@ -541,7 +565,7 @@ struct ath6kl_vif {
struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1];
struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1];
struct aggr_info *aggr_cntxt;
- struct ath6kl_htcap htcap;
+ struct ath6kl_htcap htcap[IEEE80211_NUM_BANDS];
struct timer_list disconnect_timer;
struct timer_list sched_scan_timer;
@@ -565,6 +589,11 @@ struct ath6kl_vif {
struct list_head mc_filter;
};
+static inline struct ath6kl_vif *ath6kl_vif_from_wdev(struct wireless_dev *wdev)
+{
+ return container_of(wdev, struct ath6kl_vif, wdev);
+}
+
#define WOW_LIST_ID 0
#define WOW_HOST_REQ_DELAY 500 /* ms */
@@ -684,6 +713,8 @@ struct ath6kl {
u32 testscript_addr;
enum wmi_phy_cap cap;
+ u32 flags;
+
struct ath6kl_hw_fw {
const char *dir;
const char *otp;
diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c
index 2798624d3a9d..cd0e1ba410d6 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c
@@ -1309,7 +1309,7 @@ static int ath6kl_htc_rx_packet(struct htc_target *target,
}
ath6kl_dbg(ATH6KL_DBG_HTC,
- "htc rx 0x%p hdr x%x len %d mbox 0x%x\n",
+ "htc rx 0x%p hdr 0x%x len %d mbox 0x%x\n",
packet, packet->info.rx.exp_hdr,
padded_len, dev->ar->mbox_info.htc_addr);
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 7eb0515f458a..f90b5db741cf 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -42,6 +42,7 @@ static const struct ath6kl_hw hw_list[] = {
.reserved_ram_size = 6912,
.refclk_hz = 26000000,
.uarttx_pin = 8,
+ .flags = 0,
/* hw2.0 needs override address hardcoded */
.app_start_override_addr = 0x944C00,
@@ -67,6 +68,7 @@ static const struct ath6kl_hw hw_list[] = {
.refclk_hz = 26000000,
.uarttx_pin = 8,
.testscript_addr = 0x57ef74,
+ .flags = 0,
.fw = {
.dir = AR6003_HW_2_1_1_FW_DIR,
@@ -91,6 +93,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x433900,
.refclk_hz = 26000000,
.uarttx_pin = 11,
+ .flags = ATH6KL_HW_FLAG_64BIT_RATES,
.fw = {
.dir = AR6004_HW_1_0_FW_DIR,
@@ -110,6 +113,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x43d400,
.refclk_hz = 40000000,
.uarttx_pin = 11,
+ .flags = ATH6KL_HW_FLAG_64BIT_RATES,
.fw = {
.dir = AR6004_HW_1_1_FW_DIR,
@@ -129,6 +133,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x435c00,
.refclk_hz = 40000000,
.uarttx_pin = 11,
+ .flags = ATH6KL_HW_FLAG_64BIT_RATES,
.fw = {
.dir = AR6004_HW_1_2_FW_DIR,
@@ -938,6 +943,14 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
}
switch (ie_id) {
+ case ATH6KL_FW_IE_FW_VERSION:
+ strlcpy(ar->wiphy->fw_version, data,
+ sizeof(ar->wiphy->fw_version));
+
+ ath6kl_dbg(ATH6KL_DBG_BOOT,
+ "found fw version %s\n",
+ ar->wiphy->fw_version);
+ break;
case ATH6KL_FW_IE_OTP_IMAGE:
ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n",
ie_len);
@@ -991,9 +1004,6 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
ar->hw.reserved_ram_size);
break;
case ATH6KL_FW_IE_CAPABILITIES:
- if (ie_len < DIV_ROUND_UP(ATH6KL_FW_CAPABILITY_MAX, 8))
- break;
-
ath6kl_dbg(ATH6KL_DBG_BOOT,
"found firmware capabilities ie (%zd B)\n",
ie_len);
@@ -1002,6 +1012,9 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
index = i / 8;
bit = i % 8;
+ if (index == ie_len)
+ break;
+
if (data[index] & (1 << bit))
__set_bit(i, ar->fw_capabilities);
}
@@ -1392,6 +1405,12 @@ static int ath6kl_init_upload(struct ath6kl *ar)
ar->version.target_ver == AR6003_HW_2_1_1_VERSION) {
ath6kl_err("temporary war to avoid sdio crc error\n");
+ param = 0x28;
+ address = GPIO_BASE_ADDRESS + GPIO_PIN9_ADDRESS;
+ status = ath6kl_bmi_reg_write(ar, address, param);
+ if (status)
+ return status;
+
param = 0x20;
address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
@@ -1659,6 +1678,9 @@ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
cfg80211_scan_done(vif->scan_req, true);
vif->scan_req = NULL;
}
+
+ /* need to clean up enhanced bmiss detection fw state */
+ ath6kl_cfg80211_sta_bmiss_enhance(vif, false);
}
void ath6kl_stop_txrx(struct ath6kl *ar)
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index b836f2795114..c189e28e86a9 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -554,20 +554,24 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver,
struct ath6kl *ar = devt;
memcpy(ar->mac_addr, datap, ETH_ALEN);
- ath6kl_dbg(ATH6KL_DBG_TRC, "%s: mac addr = %pM\n",
- __func__, ar->mac_addr);
+
+ ath6kl_dbg(ATH6KL_DBG_BOOT,
+ "ready event mac addr %pM sw_ver 0x%x abi_ver 0x%x cap 0x%x\n",
+ ar->mac_addr, sw_ver, abi_ver, cap);
ar->version.wlan_ver = sw_ver;
ar->version.abi_ver = abi_ver;
ar->hw.cap = cap;
- snprintf(ar->wiphy->fw_version,
- sizeof(ar->wiphy->fw_version),
- "%u.%u.%u.%u",
- (ar->version.wlan_ver & 0xf0000000) >> 28,
- (ar->version.wlan_ver & 0x0f000000) >> 24,
- (ar->version.wlan_ver & 0x00ff0000) >> 16,
- (ar->version.wlan_ver & 0x0000ffff));
+ if (strlen(ar->wiphy->fw_version) == 0) {
+ snprintf(ar->wiphy->fw_version,
+ sizeof(ar->wiphy->fw_version),
+ "%u.%u.%u.%u",
+ (ar->version.wlan_ver & 0xf0000000) >> 28,
+ (ar->version.wlan_ver & 0x0f000000) >> 24,
+ (ar->version.wlan_ver & 0x00ff0000) >> 16,
+ (ar->version.wlan_ver & 0x0000ffff));
+ }
/* indicate to the waiting thread that the ready event was received */
set_bit(WMI_READY, &ar->flag);
@@ -1166,7 +1170,10 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
else
clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags);
- mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON);
+ if (test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
+ vif->ar->fw_capabilities)) {
+ mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON);
+ }
if (!(ndev->flags & IFF_MULTICAST)) {
mc_all_on = false;
diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h
index 78e0ef4567a5..a98c12ba70c1 100644
--- a/drivers/net/wireless/ath/ath6kl/target.h
+++ b/drivers/net/wireless/ath/ath6kl/target.h
@@ -45,6 +45,7 @@
#define LPO_CAL_ENABLE_S 20
#define LPO_CAL_ENABLE 0x00100000
+#define GPIO_PIN9_ADDRESS 0x0000004c
#define GPIO_PIN10_ADDRESS 0x00000050
#define GPIO_PIN11_ADDRESS 0x00000054
#define GPIO_PIN12_ADDRESS 0x00000058
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
index 67206aedea6c..7dfa0fd86d7b 100644
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -1036,6 +1036,7 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid,
rxtid = &agg_conn->rx_tid[tid];
stats = &agg_conn->stat[tid];
+ spin_lock_bh(&rxtid->lock);
idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz);
/*
@@ -1054,8 +1055,6 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid,
seq_end = seq_no ? seq_no : rxtid->seq_next;
idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz);
- spin_lock_bh(&rxtid->lock);
-
do {
node = &rxtid->hold_q[idx];
if ((order == 1) && (!node->skb))
@@ -1127,11 +1126,13 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid,
((end > extended_end) && (cur > extended_end) &&
(cur < end))) {
aggr_deque_frms(agg_conn, tid, 0, 0);
+ spin_lock_bh(&rxtid->lock);
if (cur >= rxtid->hold_q_sz - 1)
rxtid->seq_next = cur - (rxtid->hold_q_sz - 1);
else
rxtid->seq_next = ATH6KL_MAX_SEQ_NO -
(rxtid->hold_q_sz - 2 - cur);
+ spin_unlock_bh(&rxtid->lock);
} else {
/*
* Dequeue only those frames that are outside the
@@ -1185,25 +1186,25 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid,
aggr_deque_frms(agg_conn, tid, 0, 1);
if (agg_conn->timer_scheduled)
- rxtid->progress = true;
- else
- for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) {
- if (rxtid->hold_q[idx].skb) {
- /*
- * There is a frame in the queue and no
- * timer so start a timer to ensure that
- * the frame doesn't remain stuck
- * forever.
- */
- agg_conn->timer_scheduled = true;
- mod_timer(&agg_conn->timer,
- (jiffies +
- HZ * (AGGR_RX_TIMEOUT) / 1000));
- rxtid->progress = false;
- rxtid->timer_mon = true;
- break;
- }
+ return is_queued;
+
+ spin_lock_bh(&rxtid->lock);
+ for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) {
+ if (rxtid->hold_q[idx].skb) {
+ /*
+ * There is a frame in the queue and no
+ * timer so start a timer to ensure that
+ * the frame doesn't remain stuck
+ * forever.
+ */
+ agg_conn->timer_scheduled = true;
+ mod_timer(&agg_conn->timer,
+ (jiffies + (HZ * AGGR_RX_TIMEOUT) / 1000));
+ rxtid->timer_mon = true;
+ break;
}
+ }
+ spin_unlock_bh(&rxtid->lock);
return is_queued;
}
@@ -1608,7 +1609,7 @@ static void aggr_timeout(unsigned long arg)
rxtid = &aggr_conn->rx_tid[i];
stats = &aggr_conn->stat[i];
- if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress)
+ if (!rxtid->aggr || !rxtid->timer_mon)
continue;
stats->num_timeouts++;
@@ -1626,14 +1627,15 @@ static void aggr_timeout(unsigned long arg)
rxtid = &aggr_conn->rx_tid[i];
if (rxtid->aggr && rxtid->hold_q) {
+ spin_lock_bh(&rxtid->lock);
for (j = 0; j < rxtid->hold_q_sz; j++) {
if (rxtid->hold_q[j].skb) {
aggr_conn->timer_scheduled = true;
rxtid->timer_mon = true;
- rxtid->progress = false;
break;
}
}
+ spin_unlock_bh(&rxtid->lock);
if (j >= rxtid->hold_q_sz)
rxtid->timer_mon = false;
@@ -1660,7 +1662,6 @@ static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid)
aggr_deque_frms(aggr_conn, tid, 0, 0);
rxtid->aggr = false;
- rxtid->progress = false;
rxtid->timer_mon = false;
rxtid->win_sz = 0;
rxtid->seq_next = 0;
@@ -1739,7 +1740,6 @@ void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info *aggr_info,
for (i = 0; i < NUM_OF_TIDS; i++) {
rxtid = &aggr_conn->rx_tid[i];
rxtid->aggr = false;
- rxtid->progress = false;
rxtid->timer_mon = false;
skb_queue_head_init(&rxtid->q);
spin_lock_init(&rxtid->lock);
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index ee8ec2394c2c..c30ab4b11d61 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -474,7 +474,7 @@ static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap,
return -EINVAL;
}
id = vif->last_roc_id;
- cfg80211_ready_on_channel(vif->ndev, id, chan, NL80211_CHAN_NO_HT,
+ cfg80211_ready_on_channel(&vif->wdev, id, chan, NL80211_CHAN_NO_HT,
dur, GFP_ATOMIC);
return 0;
@@ -513,7 +513,7 @@ static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi,
else
id = vif->last_roc_id; /* timeout on uncanceled r-o-c */
vif->last_cancel_roc_id = 0;
- cfg80211_remain_on_channel_expired(vif->ndev, id, chan,
+ cfg80211_remain_on_channel_expired(&vif->wdev, id, chan,
NL80211_CHAN_NO_HT, GFP_ATOMIC);
return 0;
@@ -533,7 +533,7 @@ static int ath6kl_wmi_tx_status_event_rx(struct wmi *wmi, u8 *datap, int len,
ath6kl_dbg(ATH6KL_DBG_WMI, "tx_status: id=%x ack_status=%u\n",
id, ev->ack_status);
if (wmi->last_mgmt_tx_frame) {
- cfg80211_mgmt_tx_status(vif->ndev, id,
+ cfg80211_mgmt_tx_status(&vif->wdev, id,
wmi->last_mgmt_tx_frame,
wmi->last_mgmt_tx_frame_len,
!!ev->ack_status, GFP_ATOMIC);
@@ -568,7 +568,7 @@ static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len,
dlen, freq, vif->probe_req_report);
if (vif->probe_req_report || vif->nw_type == AP_NETWORK)
- cfg80211_rx_mgmt(vif->ndev, freq, 0,
+ cfg80211_rx_mgmt(&vif->wdev, freq, 0,
ev->data, dlen, GFP_ATOMIC);
return 0;
@@ -608,7 +608,7 @@ static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len,
return -EINVAL;
}
ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq);
- cfg80211_rx_mgmt(vif->ndev, freq, 0,
+ cfg80211_rx_mgmt(&vif->wdev, freq, 0,
ev->data, dlen, GFP_ATOMIC);
return 0;
@@ -743,7 +743,6 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
return -ENOMEM;
cmd = (struct roam_ctrl_cmd *) skb->data;
- memset(cmd, 0, sizeof(*cmd));
memcpy(cmd->info.bssid, bssid, ETH_ALEN);
cmd->roam_ctrl = WMI_FORCE_ROAM;
@@ -753,6 +752,22 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
NO_SYNC_WMIFLAG);
}
+int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period)
+{
+ struct sk_buff *skb;
+ struct set_dtim_cmd *cmd;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct set_dtim_cmd *) skb->data;
+
+ cmd->dtim_period = cpu_to_le32(dtim_period);
+ return ath6kl_wmi_cmd_send(wmi, if_idx, skb,
+ WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG);
+}
+
int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode)
{
struct sk_buff *skb;
@@ -763,7 +778,6 @@ int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode)
return -ENOMEM;
cmd = (struct roam_ctrl_cmd *) skb->data;
- memset(cmd, 0, sizeof(*cmd));
cmd->info.roam_mode = mode;
cmd->roam_ctrl = WMI_SET_ROAM_MODE;
@@ -1995,7 +2009,7 @@ int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag,
struct wmi_probed_ssid_cmd *cmd;
int ret;
- if (index > MAX_PROBED_SSID_INDEX)
+ if (index >= MAX_PROBED_SSIDS)
return -EINVAL;
if (ssid_len > sizeof(cmd->ssid))
@@ -2599,6 +2613,115 @@ static void ath6kl_wmi_relinquish_implicit_pstream_credits(struct wmi *wmi)
spin_unlock_bh(&wmi->lock);
}
+static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ struct sk_buff *skb;
+ int ret, mode, band;
+ u64 mcsrate, ratemask[IEEE80211_NUM_BANDS];
+ struct wmi_set_tx_select_rates64_cmd *cmd;
+
+ memset(&ratemask, 0, sizeof(ratemask));
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ /* copy legacy rate mask */
+ ratemask[band] = mask->control[band].legacy;
+ if (band == IEEE80211_BAND_5GHZ)
+ ratemask[band] =
+ mask->control[band].legacy << 4;
+
+ /* copy mcs rate mask */
+ mcsrate = mask->control[band].mcs[1];
+ mcsrate <<= 8;
+ mcsrate |= mask->control[band].mcs[0];
+ ratemask[band] |= mcsrate << 12;
+ ratemask[band] |= mcsrate << 28;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "Ratemask 64 bit: 2.4:%llx 5:%llx\n",
+ ratemask[0], ratemask[1]);
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_set_tx_select_rates64_cmd *) skb->data;
+ for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
+ /* A mode operate in 5GHZ band */
+ if (mode == WMI_RATES_MODE_11A ||
+ mode == WMI_RATES_MODE_11A_HT20 ||
+ mode == WMI_RATES_MODE_11A_HT40)
+ band = IEEE80211_BAND_5GHZ;
+ else
+ band = IEEE80211_BAND_2GHZ;
+ cmd->ratemask[mode] = cpu_to_le64(ratemask[band]);
+ }
+
+ ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
+ WMI_SET_TX_SELECT_RATES_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ struct sk_buff *skb;
+ int ret, mode, band;
+ u32 mcsrate, ratemask[IEEE80211_NUM_BANDS];
+ struct wmi_set_tx_select_rates32_cmd *cmd;
+
+ memset(&ratemask, 0, sizeof(ratemask));
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ /* copy legacy rate mask */
+ ratemask[band] = mask->control[band].legacy;
+ if (band == IEEE80211_BAND_5GHZ)
+ ratemask[band] =
+ mask->control[band].legacy << 4;
+
+ /* copy mcs rate mask */
+ mcsrate = mask->control[band].mcs[0];
+ ratemask[band] |= mcsrate << 12;
+ ratemask[band] |= mcsrate << 20;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "Ratemask 32 bit: 2.4:%x 5:%x\n",
+ ratemask[0], ratemask[1]);
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_set_tx_select_rates32_cmd *) skb->data;
+ for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
+ /* A mode operate in 5GHZ band */
+ if (mode == WMI_RATES_MODE_11A ||
+ mode == WMI_RATES_MODE_11A_HT20 ||
+ mode == WMI_RATES_MODE_11A_HT40)
+ band = IEEE80211_BAND_5GHZ;
+ else
+ band = IEEE80211_BAND_2GHZ;
+ cmd->ratemask[mode] = cpu_to_le32(ratemask[band]);
+ }
+
+ ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
+ WMI_SET_TX_SELECT_RATES_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ struct ath6kl *ar = wmi->parent_dev;
+
+ if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES)
+ return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
+ else
+ return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
+}
+
int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
enum ath6kl_host_mode host_mode)
{
@@ -2997,6 +3120,25 @@ int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
return ret;
}
+int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enhance)
+{
+ struct sk_buff *skb;
+ struct wmi_sta_bmiss_enhance_cmd *cmd;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_sta_bmiss_enhance_cmd *) skb->data;
+ cmd->enable = enhance ? 1 : 0;
+
+ ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
+ WMI_STA_BMISS_ENHANCE_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
s32 ath6kl_wmi_get_rate(s8 rate_index)
{
if (rate_index == RATE_AUTO)
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index 9076bec3a2ba..43339aca585d 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -624,6 +624,10 @@ enum wmi_cmd_id {
WMI_SEND_MGMT_CMDID,
WMI_BEGIN_SCAN_CMDID,
+ WMI_SET_BLACK_LIST,
+ WMI_SET_MCASTRATE,
+
+ WMI_STA_BMISS_ENHANCE_CMDID,
};
enum wmi_mgmt_frame_type {
@@ -960,6 +964,9 @@ enum wmi_bss_filter {
/* beacons matching probed ssid */
PROBED_SSID_FILTER,
+ /* beacons matching matched ssid */
+ MATCHED_SSID_FILTER,
+
/* marker only */
LAST_BSS_FILTER,
};
@@ -978,7 +985,7 @@ struct wmi_bss_filter_cmd {
} __packed;
/* WMI_SET_PROBED_SSID_CMDID */
-#define MAX_PROBED_SSID_INDEX 9
+#define MAX_PROBED_SSIDS 16
enum wmi_ssid_flag {
/* disables entry */
@@ -989,10 +996,13 @@ enum wmi_ssid_flag {
/* probes for any ssid */
ANY_SSID_FLAG = 0x02,
+
+ /* match for ssid */
+ MATCH_SSID_FLAG = 0x08,
};
struct wmi_probed_ssid_cmd {
- /* 0 to MAX_PROBED_SSID_INDEX */
+ /* 0 to MAX_PROBED_SSIDS - 1 */
u8 entry_index;
/* see, enum wmi_ssid_flg */
@@ -1017,6 +1027,11 @@ struct wmi_bmiss_time_cmd {
__le16 num_beacons;
};
+/* WMI_STA_ENHANCE_BMISS_CMDID */
+struct wmi_sta_bmiss_enhance_cmd {
+ u8 enable;
+} __packed;
+
/* WMI_SET_POWER_MODE_CMDID */
enum wmi_power_mode {
REC_POWER = 0x01,
@@ -1048,6 +1063,36 @@ struct wmi_power_params_cmd {
__le16 ps_fail_event_policy;
} __packed;
+/*
+ * Ratemask for below modes should be passed
+ * to WMI_SET_TX_SELECT_RATES_CMDID.
+ * AR6003 has 32 bit mask for each modes.
+ * First 12 bits for legacy rates, 13 to 20
+ * bits for HT 20 rates and 21 to 28 bits for
+ * HT 40 rates
+ */
+enum wmi_mode_phy {
+ WMI_RATES_MODE_11A = 0,
+ WMI_RATES_MODE_11G,
+ WMI_RATES_MODE_11B,
+ WMI_RATES_MODE_11GONLY,
+ WMI_RATES_MODE_11A_HT20,
+ WMI_RATES_MODE_11G_HT20,
+ WMI_RATES_MODE_11A_HT40,
+ WMI_RATES_MODE_11G_HT40,
+ WMI_RATES_MODE_MAX
+};
+
+/* WMI_SET_TX_SELECT_RATES_CMDID */
+struct wmi_set_tx_select_rates32_cmd {
+ __le32 ratemask[WMI_RATES_MODE_MAX];
+} __packed;
+
+/* WMI_SET_TX_SELECT_RATES_CMDID */
+struct wmi_set_tx_select_rates64_cmd {
+ __le64 ratemask[WMI_RATES_MODE_MAX];
+} __packed;
+
/* WMI_SET_DISC_TIMEOUT_CMDID */
struct wmi_disc_timeout_cmd {
/* seconds */
@@ -1572,6 +1617,10 @@ struct roam_ctrl_cmd {
u8 roam_ctrl;
} __packed;
+struct set_dtim_cmd {
+ __le32 dtim_period;
+} __packed;
+
/* BSS INFO HDR version 2.0 */
struct wmi_bss_info_hdr2 {
__le16 ch; /* frequency in MHz */
@@ -2532,6 +2581,8 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
__be32 ips0, __be32 ips1);
int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
enum ath6kl_host_mode host_mode);
+int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
+ const struct cfg80211_bitrate_mask *mask);
int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
enum ath6kl_wow_mode wow_mode,
u32 filter, u16 host_req_delay);
@@ -2542,11 +2593,14 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
u16 list_id, u16 filter_id);
int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
+int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period);
int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid);
int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode);
int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on);
int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
u8 *filter, bool add_filter);
+int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enable);
+
/* AP mode uAPSD */
int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable);
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 4a4e8a2b9d2c..3a69804f4c16 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -35,6 +35,10 @@ static const struct platform_device_id ath9k_platform_id_table[] = {
.name = "ar934x_wmac",
.driver_data = AR9300_DEVID_AR9340,
},
+ {
+ .name = "qca955x_wmac",
+ .driver_data = AR9300_DEVID_QCA955X,
+ },
{},
};
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index b4c77f9d7470..ff007f500feb 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -104,11 +104,6 @@ static const struct ani_cck_level_entry cck_level_table[] = {
#define ATH9K_ANI_CCK_DEF_LEVEL \
2 /* default level - matches the INI settings */
-static bool use_new_ani(struct ath_hw *ah)
-{
- return AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani;
-}
-
static void ath9k_hw_update_mibstats(struct ath_hw *ah,
struct ath9k_mib_stats *stats)
{
@@ -122,8 +117,6 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah,
static void ath9k_ani_restart(struct ath_hw *ah)
{
struct ar5416AniState *aniState;
- struct ath_common *common = ath9k_hw_common(ah);
- u32 ofdm_base = 0, cck_base = 0;
if (!DO_ANI(ah))
return;
@@ -131,18 +124,10 @@ static void ath9k_ani_restart(struct ath_hw *ah)
aniState = &ah->curchan->ani;
aniState->listenTime = 0;
- if (!use_new_ani(ah)) {
- ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
- cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
- }
-
- ath_dbg(common, ANI, "Writing ofdmbase=%u cckbase=%u\n",
- ofdm_base, cck_base);
-
ENABLE_REGWRITE_BUFFER(ah);
- REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
- REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
+ REG_WRITE(ah, AR_PHY_ERR_1, 0);
+ REG_WRITE(ah, AR_PHY_ERR_2, 0);
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
@@ -154,129 +139,23 @@ static void ath9k_ani_restart(struct ath_hw *ah)
aniState->cckPhyErrCount = 0;
}
-static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah)
-{
- struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
- struct ar5416AniState *aniState;
- int32_t rssi;
-
- aniState = &ah->curchan->ani;
-
- if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
- if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
- aniState->noiseImmunityLevel + 1)) {
- return;
- }
- }
-
- if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
- if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
- aniState->spurImmunityLevel + 1)) {
- return;
- }
- }
-
- if (ah->opmode == NL80211_IFTYPE_AP) {
- if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
- ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel + 1);
- }
- return;
- }
- rssi = BEACON_RSSI(ah);
- if (rssi > aniState->rssiThrHigh) {
- if (!aniState->ofdmWeakSigDetectOff) {
- if (ath9k_hw_ani_control(ah,
- ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
- false)) {
- ath9k_hw_ani_control(ah,
- ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
- return;
- }
- }
- if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
- ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel + 1);
- return;
- }
- } else if (rssi > aniState->rssiThrLow) {
- if (aniState->ofdmWeakSigDetectOff)
- ath9k_hw_ani_control(ah,
- ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
- true);
- if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
- ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel + 1);
- return;
- } else {
- if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
- !conf_is_ht(conf)) {
- if (!aniState->ofdmWeakSigDetectOff)
- ath9k_hw_ani_control(ah,
- ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
- false);
- if (aniState->firstepLevel > 0)
- ath9k_hw_ani_control(ah,
- ATH9K_ANI_FIRSTEP_LEVEL, 0);
- return;
- }
- }
-}
-
-static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
-{
- struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
- struct ar5416AniState *aniState;
- int32_t rssi;
-
- aniState = &ah->curchan->ani;
- if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
- if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
- aniState->noiseImmunityLevel + 1)) {
- return;
- }
- }
- if (ah->opmode == NL80211_IFTYPE_AP) {
- if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
- ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel + 1);
- }
- return;
- }
- rssi = BEACON_RSSI(ah);
- if (rssi > aniState->rssiThrLow) {
- if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
- ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel + 1);
- } else {
- if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
- !conf_is_ht(conf)) {
- if (aniState->firstepLevel > 0)
- ath9k_hw_ani_control(ah,
- ATH9K_ANI_FIRSTEP_LEVEL, 0);
- }
- }
-}
-
/* Adjust the OFDM Noise Immunity Level */
-static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
+static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel,
+ bool scan)
{
struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath_common *common = ath9k_hw_common(ah);
const struct ani_ofdm_level_entry *entry_ofdm;
const struct ani_cck_level_entry *entry_cck;
-
- aniState->noiseFloor = BEACON_RSSI(ah);
+ bool weak_sig;
ath_dbg(common, ANI, "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
aniState->ofdmNoiseImmunityLevel,
- immunityLevel, aniState->noiseFloor,
+ immunityLevel, BEACON_RSSI(ah),
aniState->rssiThrLow, aniState->rssiThrHigh);
- if (aniState->update_ani)
- aniState->ofdmNoiseImmunityLevel =
- (immunityLevel > ATH9K_ANI_OFDM_DEF_LEVEL) ?
- immunityLevel : ATH9K_ANI_OFDM_DEF_LEVEL;
+ if (!scan)
+ aniState->ofdmNoiseImmunityLevel = immunityLevel;
entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
@@ -292,12 +171,22 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
ATH9K_ANI_FIRSTEP_LEVEL,
entry_ofdm->fir_step_level);
- if ((aniState->noiseFloor >= aniState->rssiThrHigh) &&
- (!aniState->ofdmWeakSigDetectOff !=
- entry_ofdm->ofdm_weak_signal_on)) {
+ weak_sig = entry_ofdm->ofdm_weak_signal_on;
+ if (ah->opmode == NL80211_IFTYPE_STATION &&
+ BEACON_RSSI(ah) <= aniState->rssiThrHigh)
+ weak_sig = true;
+
+ if (aniState->ofdmWeakSigDetect != weak_sig)
ath9k_hw_ani_control(ah,
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
entry_ofdm->ofdm_weak_signal_on);
+
+ if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) {
+ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
+ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI;
+ } else {
+ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI;
+ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
}
}
@@ -308,43 +197,35 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
if (!DO_ANI(ah))
return;
- if (!use_new_ani(ah)) {
- ath9k_hw_ani_ofdm_err_trigger_old(ah);
- return;
- }
-
aniState = &ah->curchan->ani;
if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
- ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1);
+ ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1, false);
}
/*
* Set the ANI settings to match an CCK level.
*/
-static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
+static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel,
+ bool scan)
{
struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath_common *common = ath9k_hw_common(ah);
const struct ani_ofdm_level_entry *entry_ofdm;
const struct ani_cck_level_entry *entry_cck;
- aniState->noiseFloor = BEACON_RSSI(ah);
ath_dbg(common, ANI, "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
aniState->cckNoiseImmunityLevel, immunityLevel,
- aniState->noiseFloor, aniState->rssiThrLow,
+ BEACON_RSSI(ah), aniState->rssiThrLow,
aniState->rssiThrHigh);
- if ((ah->opmode == NL80211_IFTYPE_STATION ||
- ah->opmode == NL80211_IFTYPE_ADHOC) &&
- aniState->noiseFloor <= aniState->rssiThrLow &&
+ if (ah->opmode == NL80211_IFTYPE_STATION &&
+ BEACON_RSSI(ah) <= aniState->rssiThrLow &&
immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
- if (aniState->update_ani)
- aniState->cckNoiseImmunityLevel =
- (immunityLevel > ATH9K_ANI_CCK_DEF_LEVEL) ?
- immunityLevel : ATH9K_ANI_CCK_DEF_LEVEL;
+ if (!scan)
+ aniState->cckNoiseImmunityLevel = immunityLevel;
entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
@@ -359,7 +240,7 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah))
return;
- if (aniState->mrcCCKOff == entry_cck->mrc_cck_on)
+ if (aniState->mrcCCK != entry_cck->mrc_cck_on)
ath9k_hw_ani_control(ah,
ATH9K_ANI_MRC_CCK,
entry_cck->mrc_cck_on);
@@ -372,68 +253,11 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
if (!DO_ANI(ah))
return;
- if (!use_new_ani(ah)) {
- ath9k_hw_ani_cck_err_trigger_old(ah);
- return;
- }
-
aniState = &ah->curchan->ani;
if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
- ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1);
-}
-
-static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
-{
- struct ar5416AniState *aniState;
- int32_t rssi;
-
- aniState = &ah->curchan->ani;
-
- if (ah->opmode == NL80211_IFTYPE_AP) {
- if (aniState->firstepLevel > 0) {
- if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel - 1))
- return;
- }
- } else {
- rssi = BEACON_RSSI(ah);
- if (rssi > aniState->rssiThrHigh) {
- /* XXX: Handle me */
- } else if (rssi > aniState->rssiThrLow) {
- if (aniState->ofdmWeakSigDetectOff) {
- if (ath9k_hw_ani_control(ah,
- ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
- true))
- return;
- }
- if (aniState->firstepLevel > 0) {
- if (ath9k_hw_ani_control(ah,
- ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel - 1))
- return;
- }
- } else {
- if (aniState->firstepLevel > 0) {
- if (ath9k_hw_ani_control(ah,
- ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel - 1))
- return;
- }
- }
- }
-
- if (aniState->spurImmunityLevel > 0) {
- if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
- aniState->spurImmunityLevel - 1))
- return;
- }
-
- if (aniState->noiseImmunityLevel > 0) {
- ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
- aniState->noiseImmunityLevel - 1);
- return;
- }
+ ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1,
+ false);
}
/*
@@ -446,87 +270,18 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
aniState = &ah->curchan->ani;
- if (!use_new_ani(ah)) {
- ath9k_hw_ani_lower_immunity_old(ah);
- return;
- }
-
/* lower OFDM noise immunity */
if (aniState->ofdmNoiseImmunityLevel > 0 &&
(aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) {
- ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1);
+ ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1,
+ false);
return;
}
/* lower CCK noise immunity */
if (aniState->cckNoiseImmunityLevel > 0)
- ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
-}
-
-static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
-{
- struct ar5416AniState *aniState;
- struct ath9k_channel *chan = ah->curchan;
- struct ath_common *common = ath9k_hw_common(ah);
-
- if (!DO_ANI(ah))
- return;
-
- aniState = &ah->curchan->ani;
-
- if (ah->opmode != NL80211_IFTYPE_STATION
- && ah->opmode != NL80211_IFTYPE_ADHOC) {
- ath_dbg(common, ANI, "Reset ANI state opmode %u\n", ah->opmode);
- ah->stats.ast_ani_reset++;
-
- if (ah->opmode == NL80211_IFTYPE_AP) {
- /*
- * ath9k_hw_ani_control() will only process items set on
- * ah->ani_function
- */
- if (IS_CHAN_2GHZ(chan))
- ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
- ATH9K_ANI_FIRSTEP_LEVEL);
- else
- ah->ani_function = 0;
- }
-
- ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
- ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
- ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
- ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
- !ATH9K_ANI_USE_OFDM_WEAK_SIG);
- ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
- ATH9K_ANI_CCK_WEAK_SIG_THR);
-
- ath9k_ani_restart(ah);
- return;
- }
-
- if (aniState->noiseImmunityLevel != 0)
- ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
- aniState->noiseImmunityLevel);
- if (aniState->spurImmunityLevel != 0)
- ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
- aniState->spurImmunityLevel);
- if (aniState->ofdmWeakSigDetectOff)
- ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
- !aniState->ofdmWeakSigDetectOff);
- if (aniState->cckWeakSigThreshold)
- ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
- aniState->cckWeakSigThreshold);
- if (aniState->firstepLevel != 0)
- ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel);
-
- ath9k_ani_restart(ah);
-
- ENABLE_REGWRITE_BUFFER(ah);
-
- REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-
- REGWRITE_BUFFER_FLUSH(ah);
+ ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1,
+ false);
}
/*
@@ -539,13 +294,11 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath9k_channel *chan = ah->curchan;
struct ath_common *common = ath9k_hw_common(ah);
+ int ofdm_nil, cck_nil;
if (!DO_ANI(ah))
return;
- if (!use_new_ani(ah))
- return ath9k_ani_reset_old(ah, is_scanning);
-
BUG_ON(aniState == NULL);
ah->stats.ast_ani_reset++;
@@ -563,6 +316,11 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
/* always allow mode (on/off) to be controlled */
ah->ani_function |= ATH9K_ANI_MODE;
+ ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL,
+ aniState->ofdmNoiseImmunityLevel);
+ cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL,
+ aniState->cckNoiseImmunityLevel);
+
if (is_scanning ||
(ah->opmode != NL80211_IFTYPE_STATION &&
ah->opmode != NL80211_IFTYPE_ADHOC)) {
@@ -585,9 +343,8 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
aniState->ofdmNoiseImmunityLevel,
aniState->cckNoiseImmunityLevel);
- aniState->update_ani = false;
- ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
- ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
+ ofdm_nil = ATH9K_ANI_OFDM_DEF_LEVEL;
+ cck_nil = ATH9K_ANI_CCK_DEF_LEVEL;
}
} else {
/*
@@ -601,13 +358,9 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
is_scanning,
aniState->ofdmNoiseImmunityLevel,
aniState->cckNoiseImmunityLevel);
-
- aniState->update_ani = true;
- ath9k_hw_set_ofdm_nil(ah,
- aniState->ofdmNoiseImmunityLevel);
- ath9k_hw_set_cck_nil(ah,
- aniState->cckNoiseImmunityLevel);
}
+ ath9k_hw_set_ofdm_nil(ah, ofdm_nil, is_scanning);
+ ath9k_hw_set_cck_nil(ah, cck_nil, is_scanning);
/*
* enable phy counters if hw supports or if not, enable phy
@@ -627,9 +380,6 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
struct ar5416AniState *aniState = &ah->curchan->ani;
- u32 ofdm_base = 0;
- u32 cck_base = 0;
- u32 ofdmPhyErrCnt, cckPhyErrCnt;
u32 phyCnt1, phyCnt2;
int32_t listenTime;
@@ -642,11 +392,6 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
return false;
}
- if (!use_new_ani(ah)) {
- ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
- cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
- }
-
aniState->listenTime += listenTime;
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
@@ -654,35 +399,12 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
- if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
- if (phyCnt1 < ofdm_base) {
- ath_dbg(common, ANI,
- "phyCnt1 0x%x, resetting counter value to 0x%x\n",
- phyCnt1, ofdm_base);
- REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
- REG_WRITE(ah, AR_PHY_ERR_MASK_1,
- AR_PHY_ERR_OFDM_TIMING);
- }
- if (phyCnt2 < cck_base) {
- ath_dbg(common, ANI,
- "phyCnt2 0x%x, resetting counter value to 0x%x\n",
- phyCnt2, cck_base);
- REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2,
- AR_PHY_ERR_CCK_TIMING);
- }
- return false;
- }
+ ah->stats.ast_ani_ofdmerrs += phyCnt1 - aniState->ofdmPhyErrCount;
+ aniState->ofdmPhyErrCount = phyCnt1;
- ofdmPhyErrCnt = phyCnt1 - ofdm_base;
- ah->stats.ast_ani_ofdmerrs +=
- ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
- aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+ ah->stats.ast_ani_cckerrs += phyCnt2 - aniState->cckPhyErrCount;
+ aniState->cckPhyErrCount = phyCnt2;
- cckPhyErrCnt = phyCnt2 - cck_base;
- ah->stats.ast_ani_cckerrs +=
- cckPhyErrCnt - aniState->cckPhyErrCount;
- aniState->cckPhyErrCount = cckPhyErrCnt;
return true;
}
@@ -716,21 +438,10 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
if (aniState->listenTime > ah->aniperiod) {
if (cckPhyErrRate < ah->config.cck_trig_low &&
- ((ofdmPhyErrRate < ah->config.ofdm_trig_low &&
- aniState->ofdmNoiseImmunityLevel <
- ATH9K_ANI_OFDM_DEF_LEVEL) ||
- (ofdmPhyErrRate < ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI &&
- aniState->ofdmNoiseImmunityLevel >=
- ATH9K_ANI_OFDM_DEF_LEVEL))) {
+ ofdmPhyErrRate < ah->config.ofdm_trig_low) {
ath9k_hw_ani_lower_immunity(ah);
aniState->ofdmsTurn = !aniState->ofdmsTurn;
- } else if ((ofdmPhyErrRate > ah->config.ofdm_trig_high &&
- aniState->ofdmNoiseImmunityLevel >=
- ATH9K_ANI_OFDM_DEF_LEVEL) ||
- (ofdmPhyErrRate >
- ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI &&
- aniState->ofdmNoiseImmunityLevel <
- ATH9K_ANI_OFDM_DEF_LEVEL)) {
+ } else if (ofdmPhyErrRate > ah->config.ofdm_trig_high) {
ath9k_hw_ani_ofdm_err_trigger(ah);
aniState->ofdmsTurn = false;
} else if (cckPhyErrRate > ah->config.cck_trig_high) {
@@ -778,49 +489,6 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
-/*
- * Process a MIB interrupt. We may potentially be invoked because
- * any of the MIB counters overflow/trigger so don't assume we're
- * here because a PHY error counter triggered.
- */
-void ath9k_hw_proc_mib_event(struct ath_hw *ah)
-{
- u32 phyCnt1, phyCnt2;
-
- /* Reset these counters regardless */
- REG_WRITE(ah, AR_FILT_OFDM, 0);
- REG_WRITE(ah, AR_FILT_CCK, 0);
- if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
- REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
-
- /* Clear the mib counters and save them in the stats */
- ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-
- if (!DO_ANI(ah)) {
- /*
- * We must always clear the interrupt cause by
- * resetting the phy error regs.
- */
- REG_WRITE(ah, AR_PHY_ERR_1, 0);
- REG_WRITE(ah, AR_PHY_ERR_2, 0);
- return;
- }
-
- /* NB: these are not reset-on-read */
- phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
- phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
- if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
- ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
-
- if (!use_new_ani(ah))
- ath9k_hw_ani_read_counters(ah);
-
- /* NB: always restart to insure the h/w counters are reset */
- ath9k_ani_restart(ah);
- }
-}
-EXPORT_SYMBOL(ath9k_hw_proc_mib_event);
-
void ath9k_hw_ani_setup(struct ath_hw *ah)
{
int i;
@@ -845,66 +513,37 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
ath_dbg(common, ANI, "Initialize ANI\n");
- if (use_new_ani(ah)) {
- ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
- ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
+ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
+ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
- ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
- ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_NEW;
- } else {
- ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
- ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
-
- ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
- ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
- }
+ ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH;
+ ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW;
for (i = 0; i < ARRAY_SIZE(ah->channels); i++) {
struct ath9k_channel *chan = &ah->channels[i];
struct ar5416AniState *ani = &chan->ani;
- if (use_new_ani(ah)) {
- ani->spurImmunityLevel =
- ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
+ ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
- ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
+ ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
- if (AR_SREV_9300_20_OR_LATER(ah))
- ani->mrcCCKOff =
- !ATH9K_ANI_ENABLE_MRC_CCK;
- else
- ani->mrcCCKOff = true;
-
- ani->ofdmsTurn = true;
- } else {
- ani->spurImmunityLevel =
- ATH9K_ANI_SPUR_IMMUNE_LVL_OLD;
- ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
-
- ani->cckWeakSigThreshold =
- ATH9K_ANI_CCK_WEAK_SIG_THR;
- }
+ ani->mrcCCK = AR_SREV_9300_20_OR_LATER(ah) ? true : false;
+
+ ani->ofdmsTurn = true;
ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
- ani->ofdmWeakSigDetectOff =
- !ATH9K_ANI_USE_OFDM_WEAK_SIG;
+ ani->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
- ani->update_ani = false;
}
/*
* since we expect some ongoing maintenance on the tables, let's sanity
* check here default level should not modify INI setting.
*/
- if (use_new_ani(ah)) {
- ah->aniperiod = ATH9K_ANI_PERIOD_NEW;
- ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW;
- } else {
- ah->aniperiod = ATH9K_ANI_PERIOD_OLD;
- ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD;
- }
+ ah->aniperiod = ATH9K_ANI_PERIOD;
+ ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL;
if (ah->config.enable_ani)
ah->proc_phyerr |= HAL_PROCESS_ANI;
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h
index 72e2b874e179..1485bf5e3518 100644
--- a/drivers/net/wireless/ath/ath9k/ani.h
+++ b/drivers/net/wireless/ath/ath9k/ani.h
@@ -24,42 +24,34 @@
#define BEACON_RSSI(ahp) (ahp->stats.avgbrssi)
/* units are errors per second */
-#define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500
-#define ATH9K_ANI_OFDM_TRIG_HIGH_NEW 3500
+#define ATH9K_ANI_OFDM_TRIG_HIGH 3500
#define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000
/* units are errors per second */
-#define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200
-#define ATH9K_ANI_OFDM_TRIG_LOW_NEW 400
+#define ATH9K_ANI_OFDM_TRIG_LOW 400
#define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900
/* units are errors per second */
-#define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200
-#define ATH9K_ANI_CCK_TRIG_HIGH_NEW 600
+#define ATH9K_ANI_CCK_TRIG_HIGH 600
/* units are errors per second */
-#define ATH9K_ANI_CCK_TRIG_LOW_OLD 100
-#define ATH9K_ANI_CCK_TRIG_LOW_NEW 300
+#define ATH9K_ANI_CCK_TRIG_LOW 300
#define ATH9K_ANI_NOISE_IMMUNE_LVL 4
#define ATH9K_ANI_USE_OFDM_WEAK_SIG true
#define ATH9K_ANI_CCK_WEAK_SIG_THR false
-#define ATH9K_ANI_SPUR_IMMUNE_LVL_OLD 7
-#define ATH9K_ANI_SPUR_IMMUNE_LVL_NEW 3
+#define ATH9K_ANI_SPUR_IMMUNE_LVL 3
-#define ATH9K_ANI_FIRSTEP_LVL_OLD 0
-#define ATH9K_ANI_FIRSTEP_LVL_NEW 2
+#define ATH9K_ANI_FIRSTEP_LVL 2
#define ATH9K_ANI_RSSI_THR_HIGH 40
#define ATH9K_ANI_RSSI_THR_LOW 7
-#define ATH9K_ANI_PERIOD_OLD 100
-#define ATH9K_ANI_PERIOD_NEW 300
+#define ATH9K_ANI_PERIOD 300
/* in ms */
-#define ATH9K_ANI_POLLINTERVAL_OLD 100
-#define ATH9K_ANI_POLLINTERVAL_NEW 1000
+#define ATH9K_ANI_POLLINTERVAL 1000
#define HAL_NOISE_IMMUNE_MAX 4
#define HAL_SPUR_IMMUNE_MAX 7
@@ -70,8 +62,6 @@
#define ATH9K_SIG_SPUR_IMM_SETTING_MIN 0
#define ATH9K_SIG_SPUR_IMM_SETTING_MAX 22
-#define ATH9K_ANI_ENABLE_MRC_CCK true
-
/* values here are relative to the INI */
enum ath9k_ani_cmd {
@@ -119,16 +109,14 @@ struct ar5416AniState {
u8 ofdmNoiseImmunityLevel;
u8 cckNoiseImmunityLevel;
bool ofdmsTurn;
- u8 mrcCCKOff;
+ u8 mrcCCK;
u8 spurImmunityLevel;
u8 firstepLevel;
- u8 ofdmWeakSigDetectOff;
+ u8 ofdmWeakSigDetect;
u8 cckWeakSigThreshold;
- bool update_ani;
u32 listenTime;
int32_t rssiThrLow;
int32_t rssiThrHigh;
- u32 noiseFloor;
u32 ofdmPhyErrCount;
u32 cckPhyErrCount;
int16_t pktRssi[2];
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index c7492c6a2519..874186bfda41 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -995,141 +995,6 @@ static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah,
return pll;
}
-static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
- enum ath9k_ani_cmd cmd,
- int param)
-{
- struct ar5416AniState *aniState = &ah->curchan->ani;
- struct ath_common *common = ath9k_hw_common(ah);
-
- switch (cmd & ah->ani_function) {
- case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
- u32 level = param;
-
- if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
- ath_dbg(common, ANI, "level out of range (%u > %zu)\n",
- level, ARRAY_SIZE(ah->totalSizeDesired));
- return false;
- }
-
- REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
- AR_PHY_DESIRED_SZ_TOT_DES,
- ah->totalSizeDesired[level]);
- REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
- AR_PHY_AGC_CTL1_COARSE_LOW,
- ah->coarse_low[level]);
- REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
- AR_PHY_AGC_CTL1_COARSE_HIGH,
- ah->coarse_high[level]);
- REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
- AR_PHY_FIND_SIG_FIRPWR,
- ah->firpwr[level]);
-
- if (level > aniState->noiseImmunityLevel)
- ah->stats.ast_ani_niup++;
- else if (level < aniState->noiseImmunityLevel)
- ah->stats.ast_ani_nidown++;
- aniState->noiseImmunityLevel = level;
- break;
- }
- case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
- u32 on = param ? 1 : 0;
-
- if (on)
- REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
- AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
- else
- REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
- AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
-
- if (!on != aniState->ofdmWeakSigDetectOff) {
- if (on)
- ah->stats.ast_ani_ofdmon++;
- else
- ah->stats.ast_ani_ofdmoff++;
- aniState->ofdmWeakSigDetectOff = !on;
- }
- break;
- }
- case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
- static const int weakSigThrCck[] = { 8, 6 };
- u32 high = param ? 1 : 0;
-
- REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
- AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
- weakSigThrCck[high]);
- if (high != aniState->cckWeakSigThreshold) {
- if (high)
- ah->stats.ast_ani_cckhigh++;
- else
- ah->stats.ast_ani_ccklow++;
- aniState->cckWeakSigThreshold = high;
- }
- break;
- }
- case ATH9K_ANI_FIRSTEP_LEVEL:{
- static const int firstep[] = { 0, 4, 8 };
- u32 level = param;
-
- if (level >= ARRAY_SIZE(firstep)) {
- ath_dbg(common, ANI, "level out of range (%u > %zu)\n",
- level, ARRAY_SIZE(firstep));
- return false;
- }
- REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
- AR_PHY_FIND_SIG_FIRSTEP,
- firstep[level]);
- if (level > aniState->firstepLevel)
- ah->stats.ast_ani_stepup++;
- else if (level < aniState->firstepLevel)
- ah->stats.ast_ani_stepdown++;
- aniState->firstepLevel = level;
- break;
- }
- case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
- static const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
- u32 level = param;
-
- if (level >= ARRAY_SIZE(cycpwrThr1)) {
- ath_dbg(common, ANI, "level out of range (%u > %zu)\n",
- level, ARRAY_SIZE(cycpwrThr1));
- return false;
- }
- REG_RMW_FIELD(ah, AR_PHY_TIMING5,
- AR_PHY_TIMING5_CYCPWR_THR1,
- cycpwrThr1[level]);
- if (level > aniState->spurImmunityLevel)
- ah->stats.ast_ani_spurup++;
- else if (level < aniState->spurImmunityLevel)
- ah->stats.ast_ani_spurdown++;
- aniState->spurImmunityLevel = level;
- break;
- }
- case ATH9K_ANI_PRESENT:
- break;
- default:
- ath_dbg(common, ANI, "invalid cmd %u\n", cmd);
- return false;
- }
-
- ath_dbg(common, ANI, "ANI parameters:\n");
- ath_dbg(common, ANI,
- "noiseImmunityLevel=%d, spurImmunityLevel=%d, ofdmWeakSigDetectOff=%d\n",
- aniState->noiseImmunityLevel,
- aniState->spurImmunityLevel,
- !aniState->ofdmWeakSigDetectOff);
- ath_dbg(common, ANI,
- "cckWeakSigThreshold=%d, firstepLevel=%d, listenTime=%d\n",
- aniState->cckWeakSigThreshold,
- aniState->firstepLevel,
- aniState->listenTime);
- ath_dbg(common, ANI, "ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
- aniState->ofdmPhyErrCount,
- aniState->cckPhyErrCount);
-
- return true;
-}
-
static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
enum ath9k_ani_cmd cmd,
int param)
@@ -1206,18 +1071,18 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
- if (!on != aniState->ofdmWeakSigDetectOff) {
+ if (on != aniState->ofdmWeakSigDetect) {
ath_dbg(common, ANI,
"** ch %d: ofdm weak signal: %s=>%s\n",
chan->channel,
- !aniState->ofdmWeakSigDetectOff ?
+ aniState->ofdmWeakSigDetect ?
"on" : "off",
on ? "on" : "off");
if (on)
ah->stats.ast_ani_ofdmon++;
else
ah->stats.ast_ani_ofdmoff++;
- aniState->ofdmWeakSigDetectOff = !on;
+ aniState->ofdmWeakSigDetect = on;
}
break;
}
@@ -1236,7 +1101,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
* from INI file & cap value
*/
value = firstep_table[level] -
- firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
+ firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
aniState->iniDef.firstep;
if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
@@ -1251,7 +1116,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
* from INI file & cap value
*/
value2 = firstep_table[level] -
- firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
+ firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
aniState->iniDef.firstepLow;
if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
@@ -1267,7 +1132,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
chan->channel,
aniState->firstepLevel,
level,
- ATH9K_ANI_FIRSTEP_LVL_NEW,
+ ATH9K_ANI_FIRSTEP_LVL,
value,
aniState->iniDef.firstep);
ath_dbg(common, ANI,
@@ -1275,7 +1140,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
chan->channel,
aniState->firstepLevel,
level,
- ATH9K_ANI_FIRSTEP_LVL_NEW,
+ ATH9K_ANI_FIRSTEP_LVL,
value2,
aniState->iniDef.firstepLow);
if (level > aniState->firstepLevel)
@@ -1300,7 +1165,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
* from INI file & cap value
*/
value = cycpwrThr1_table[level] -
- cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
+ cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
aniState->iniDef.cycpwrThr1;
if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
@@ -1316,7 +1181,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
* from INI file & cap value
*/
value2 = cycpwrThr1_table[level] -
- cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
+ cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
aniState->iniDef.cycpwrThr1Ext;
if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
@@ -1331,7 +1196,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
chan->channel,
aniState->spurImmunityLevel,
level,
- ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
+ ATH9K_ANI_SPUR_IMMUNE_LVL,
value,
aniState->iniDef.cycpwrThr1);
ath_dbg(common, ANI,
@@ -1339,7 +1204,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
chan->channel,
aniState->spurImmunityLevel,
level,
- ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
+ ATH9K_ANI_SPUR_IMMUNE_LVL,
value2,
aniState->iniDef.cycpwrThr1Ext);
if (level > aniState->spurImmunityLevel)
@@ -1367,9 +1232,9 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
ath_dbg(common, ANI,
"ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
aniState->spurImmunityLevel,
- !aniState->ofdmWeakSigDetectOff ? "on" : "off",
+ aniState->ofdmWeakSigDetect ? "on" : "off",
aniState->firstepLevel,
- !aniState->mrcCCKOff ? "on" : "off",
+ aniState->mrcCCK ? "on" : "off",
aniState->listenTime,
aniState->ofdmPhyErrCount,
aniState->cckPhyErrCount);
@@ -1454,10 +1319,10 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah)
AR_PHY_EXT_TIMING5_CYCPWR_THR1);
/* these levels just got reset to defaults by the INI */
- aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
- aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
- aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
- aniState->mrcCCKOff = true; /* not available on pre AR9003 */
+ aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
+ aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
+ aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
+ aniState->mrcCCK = false; /* not available on pre AR9003 */
}
static void ar5008_hw_set_nf_limits(struct ath_hw *ah)
@@ -1545,11 +1410,8 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->do_getnf = ar5008_hw_do_getnf;
priv_ops->set_radar_params = ar5008_hw_set_radar_params;
- if (modparam_force_new_ani) {
- priv_ops->ani_control = ar5008_hw_ani_control_new;
- priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs;
- } else
- priv_ops->ani_control = ar5008_hw_ani_control_old;
+ priv_ops->ani_control = ar5008_hw_ani_control_new;
+ priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs;
if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
priv_ops->compute_pll_control = ar9160_hw_compute_pll_control;
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index d9a69fc470cd..edf21ea4fe93 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -21,10 +21,6 @@
#include "ar9002_initvals.h"
#include "ar9002_phy.h"
-int modparam_force_new_ani;
-module_param_named(force_new_ani, modparam_force_new_ani, int, 0444);
-MODULE_PARM_DESC(force_new_ani, "Force new ANI for AR5008, AR9001, AR9002");
-
/* General hardware code for the A5008/AR9001/AR9002 hadware families */
static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
index 952cb2b4656b..89bf94d4d8a1 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2010-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index d7deb8c9f299..84b558d126ca 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -159,14 +159,11 @@ static bool ar9003_hw_calibrate(struct ath_hw *ah,
}
}
- /* Do NF cal only at longer intervals */
- if (longcal) {
- /*
- * Get the value from the previous NF cal and update
- * history buffer.
- */
- ath9k_hw_getnf(ah, chan);
-
+ /*
+ * Do NF cal only at longer intervals. Get the value from
+ * the previous NF cal and update history buffer.
+ */
+ if (longcal && ath9k_hw_getnf(ah, chan)) {
/*
* Load the NF from history buffer of the current channel.
* NF is slow time-variant, so it is OK to use a historical
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 2cdf82bdb11d..25de6f9a9778 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -3509,7 +3509,7 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
- else if (AR_SREV_9462(ah))
+ else if (AR_SREV_9462(ah) || AR_SREV_9550(ah))
REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
else {
REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
@@ -3591,6 +3591,9 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
if (AR_SREV_9462(ah)) {
REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
AR_SWITCH_TABLE_COM_AR9462_ALL, value);
+ } else if (AR_SREV_9550(ah)) {
+ REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
+ AR_SWITCH_TABLE_COM_AR9550_ALL, value);
} else
REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
AR_SWITCH_TABLE_COM_ALL, value);
@@ -3957,7 +3960,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
ar9003_hw_drive_strength_apply(ah);
ar9003_hw_atten_apply(ah, chan);
ar9003_hw_quick_drop_apply(ah, chan->channel);
- if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))
+ if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9550(ah))
ar9003_hw_internal_regulator_apply(ah);
if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
ar9003_hw_apply_tuning_caps(ah);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index a0e3394b10dc..41e88c660e48 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -21,6 +21,7 @@
#include "ar9340_initvals.h"
#include "ar9330_1p1_initvals.h"
#include "ar9330_1p2_initvals.h"
+#include "ar955x_1p0_initvals.h"
#include "ar9580_1p0_initvals.h"
#include "ar9462_2p0_initvals.h"
@@ -327,7 +328,61 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->ini_japan2484, AR9462_BBC_TXIFR_COEFFJ,
ARRAY_SIZE(AR9462_BBC_TXIFR_COEFFJ), 2);
+ } else if (AR_SREV_9550(ah)) {
+ /* mac */
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+ ar955x_1p0_mac_core,
+ ARRAY_SIZE(ar955x_1p0_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar955x_1p0_mac_postamble,
+ ARRAY_SIZE(ar955x_1p0_mac_postamble), 5);
+
+ /* bb */
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar955x_1p0_baseband_core,
+ ARRAY_SIZE(ar955x_1p0_baseband_core), 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar955x_1p0_baseband_postamble,
+ ARRAY_SIZE(ar955x_1p0_baseband_postamble), 5);
+
+ /* radio */
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar955x_1p0_radio_core,
+ ARRAY_SIZE(ar955x_1p0_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+ ar955x_1p0_radio_postamble,
+ ARRAY_SIZE(ar955x_1p0_radio_postamble), 5);
+
+ /* soc */
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar955x_1p0_soc_preamble,
+ ARRAY_SIZE(ar955x_1p0_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+ ar955x_1p0_soc_postamble,
+ ARRAY_SIZE(ar955x_1p0_soc_postamble), 5);
+ /* rx/tx gain */
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar955x_1p0_common_wo_xlna_rx_gain_table,
+ ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_table),
+ 2);
+ INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
+ ar955x_1p0_common_wo_xlna_rx_gain_bounds,
+ ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_bounds),
+ 5);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar955x_1p0_modes_xpa_tx_gain_table,
+ ARRAY_SIZE(ar955x_1p0_modes_xpa_tx_gain_table),
+ 9);
+
+ /* Fast clock modal settings */
+ INIT_INI_ARRAY(&ah->iniModesFastClock,
+ ar955x_1p0_modes_fast_clock,
+ ARRAY_SIZE(ar955x_1p0_modes_fast_clock), 3);
} else if (AR_SREV_9580(ah)) {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
@@ -470,6 +525,11 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah)
ar9485_modes_lowest_ob_db_tx_gain_1_1,
ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
5);
+ else if (AR_SREV_9550(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar955x_1p0_modes_xpa_tx_gain_table,
+ ARRAY_SIZE(ar955x_1p0_modes_xpa_tx_gain_table),
+ 9);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_lowest_ob_db_tx_gain_table,
@@ -514,6 +574,11 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah)
ar9580_1p0_high_ob_db_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table),
5);
+ else if (AR_SREV_9550(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar955x_1p0_modes_no_xpa_tx_gain_table,
+ ARRAY_SIZE(ar955x_1p0_modes_no_xpa_tx_gain_table),
+ 9);
else if (AR_SREV_9462_20(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9462_modes_high_ob_db_tx_gain_table_2p0,
@@ -635,7 +700,16 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
ar9485Common_wo_xlna_rx_gain_1_1,
ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
2);
- else if (AR_SREV_9580(ah))
+ else if (AR_SREV_9550(ah)) {
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar955x_1p0_common_rx_gain_table,
+ ARRAY_SIZE(ar955x_1p0_common_rx_gain_table),
+ 2);
+ INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
+ ar955x_1p0_common_rx_gain_bounds,
+ ARRAY_SIZE(ar955x_1p0_common_rx_gain_bounds),
+ 5);
+ } else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_rx_gain_table,
ARRAY_SIZE(ar9580_1p0_rx_gain_table),
@@ -679,7 +753,16 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah)
ar9462_common_wo_xlna_rx_gain_table_2p0,
ARRAY_SIZE(ar9462_common_wo_xlna_rx_gain_table_2p0),
2);
- else if (AR_SREV_9580(ah))
+ else if (AR_SREV_9550(ah)) {
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar955x_1p0_common_wo_xlna_rx_gain_table,
+ ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_table),
+ 2);
+ INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
+ ar955x_1p0_common_wo_xlna_rx_gain_bounds,
+ ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_bounds),
+ 5);
+ } else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_wo_xlna_rx_gain_table,
ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table),
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index d9e0824af093..78816b8b2173 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -181,11 +181,14 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
u32 mask2 = 0;
struct ath9k_hw_capabilities *pCap = &ah->caps;
struct ath_common *common = ath9k_hw_common(ah);
- u32 sync_cause = 0, async_cause;
+ u32 sync_cause = 0, async_cause, async_mask = AR_INTR_MAC_IRQ;
+
+ if (ath9k_hw_mci_is_enabled(ah))
+ async_mask |= AR_INTR_ASYNC_MASK_MCI;
async_cause = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
- if (async_cause & (AR_INTR_MAC_IRQ | AR_INTR_ASYNC_MASK_MCI)) {
+ if (async_cause & async_mask) {
if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
== AR_RTC_STATUS_ON)
isr = REG_READ(ah, AR_ISR);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
index b1ced2a76da3..9a34fcaae3ff 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
@@ -321,7 +321,7 @@ void ar9003_mci_set_full_sleep(struct ath_hw *ah)
{
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
- if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) &&
+ if (ar9003_mci_state(ah, MCI_STATE_ENABLE) &&
(mci->bt_state != MCI_BT_SLEEP) &&
!mci->halted_bt_gpm) {
ar9003_mci_send_coex_halt_bt_gpm(ah, true, true);
@@ -484,7 +484,7 @@ static void ar9003_mci_sync_bt_state(struct ath_hw *ah)
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
u32 cur_bt_state;
- cur_bt_state = ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL);
+ cur_bt_state = ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP);
if (mci->bt_state != cur_bt_state)
mci->bt_state = cur_bt_state;
@@ -593,8 +593,7 @@ static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
if (!time_out)
break;
- offset = ar9003_mci_state(ah, MCI_STATE_NEXT_GPM_OFFSET,
- &more_data);
+ offset = ar9003_mci_get_next_gpm_offset(ah, false, &more_data);
if (offset == MCI_GPM_INVALID)
continue;
@@ -658,8 +657,7 @@ static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
time_out = 0;
while (more_data == MCI_GPM_MORE) {
- offset = ar9003_mci_state(ah, MCI_STATE_NEXT_GPM_OFFSET,
- &more_data);
+ offset = ar9003_mci_get_next_gpm_offset(ah, false, &more_data);
if (offset == MCI_GPM_INVALID)
break;
@@ -769,10 +767,6 @@ static void ar9003_mci_mute_bt(struct ath_hw *ah)
{
/* disable all MCI messages */
REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000);
- REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xffffffff);
- REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xffffffff);
- REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xffffffff);
- REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xffffffff);
REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
/* wait pending HW messages to flush out */
@@ -893,13 +887,16 @@ void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
udelay(100);
}
+ /* Check pending GPM msg before MCI Reset Rx */
+ ar9003_mci_check_gpm_offset(ah);
+
regval |= SM(1, AR_MCI_COMMAND2_RESET_RX);
REG_WRITE(ah, AR_MCI_COMMAND2, regval);
udelay(1);
regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX);
REG_WRITE(ah, AR_MCI_COMMAND2, regval);
- ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET, NULL);
+ ar9003_mci_get_next_gpm_offset(ah, true, NULL);
REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE,
(SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) |
@@ -1010,11 +1007,11 @@ static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header,
}
}
-void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done)
+void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
{
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
- if (!mci->update_2g5g)
+ if (!mci->update_2g5g && !force)
return;
if (mci->is_2g) {
@@ -1028,8 +1025,7 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done)
AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
- REG_SET_BIT(ah, AR_BTCOEX_CTRL,
- AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
+ ar9003_mci_osla_setup(ah, true);
} else {
ar9003_mci_send_lna_take(ah, true);
udelay(5);
@@ -1038,9 +1034,8 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done)
AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
REG_SET_BIT(ah, AR_PHY_GLB_CONTROL,
AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
- REG_CLR_BIT(ah, AR_BTCOEX_CTRL,
- AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
+ ar9003_mci_osla_setup(ah, false);
ar9003_mci_send_2g5g_status(ah, true);
}
}
@@ -1169,11 +1164,10 @@ void ar9003_mci_cleanup(struct ath_hw *ah)
}
EXPORT_SYMBOL(ar9003_mci_cleanup);
-u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
+u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type)
{
- struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
- u32 value = 0, more_gpm = 0, gpm_ptr;
+ u32 value = 0;
u8 query_type;
switch (state_type) {
@@ -1186,81 +1180,6 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
}
value &= AR_BTCOEX_CTRL_MCI_MODE_EN;
break;
- case MCI_STATE_INIT_GPM_OFFSET:
- value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
- mci->gpm_idx = value;
- break;
- case MCI_STATE_NEXT_GPM_OFFSET:
- case MCI_STATE_LAST_GPM_OFFSET:
- /*
- * This could be useful to avoid new GPM message interrupt which
- * may lead to spurious interrupt after power sleep, or multiple
- * entry of ath_mci_intr().
- * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can
- * alleviate this effect, but clearing GPM RX interrupt bit is
- * safe, because whether this is called from hw or driver code
- * there must be an interrupt bit set/triggered initially
- */
- REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
- AR_MCI_INTERRUPT_RX_MSG_GPM);
-
- gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
- value = gpm_ptr;
-
- if (value == 0)
- value = mci->gpm_len - 1;
- else if (value >= mci->gpm_len) {
- if (value != 0xFFFF)
- value = 0;
- } else {
- value--;
- }
-
- if (value == 0xFFFF) {
- value = MCI_GPM_INVALID;
- more_gpm = MCI_GPM_NOMORE;
- } else if (state_type == MCI_STATE_NEXT_GPM_OFFSET) {
- if (gpm_ptr == mci->gpm_idx) {
- value = MCI_GPM_INVALID;
- more_gpm = MCI_GPM_NOMORE;
- } else {
- for (;;) {
- u32 temp_index;
-
- /* skip reserved GPM if any */
-
- if (value != mci->gpm_idx)
- more_gpm = MCI_GPM_MORE;
- else
- more_gpm = MCI_GPM_NOMORE;
-
- temp_index = mci->gpm_idx;
- mci->gpm_idx++;
-
- if (mci->gpm_idx >=
- mci->gpm_len)
- mci->gpm_idx = 0;
-
- if (ar9003_mci_is_gpm_valid(ah,
- temp_index)) {
- value = temp_index;
- break;
- }
-
- if (more_gpm == MCI_GPM_NOMORE) {
- value = MCI_GPM_INVALID;
- break;
- }
- }
- }
- if (p_data)
- *p_data = more_gpm;
- }
-
- if (value != MCI_GPM_INVALID)
- value <<= 4;
-
- break;
case MCI_STATE_LAST_SCHD_MSG_OFFSET:
value = MS(REG_READ(ah, AR_MCI_RX_STATUS),
AR_MCI_RX_LAST_SCHD_MSG_INDEX);
@@ -1272,21 +1191,6 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
AR_MCI_RX_REMOTE_SLEEP) ?
MCI_BT_SLEEP : MCI_BT_AWAKE;
break;
- case MCI_STATE_CONT_RSSI_POWER:
- value = MS(mci->cont_status, AR_MCI_CONT_RSSI_POWER);
- break;
- case MCI_STATE_CONT_PRIORITY:
- value = MS(mci->cont_status, AR_MCI_CONT_RRIORITY);
- break;
- case MCI_STATE_CONT_TXRX:
- value = MS(mci->cont_status, AR_MCI_CONT_TXRX);
- break;
- case MCI_STATE_BT:
- value = mci->bt_state;
- break;
- case MCI_STATE_SET_BT_SLEEP:
- mci->bt_state = MCI_BT_SLEEP;
- break;
case MCI_STATE_SET_BT_AWAKE:
mci->bt_state = MCI_BT_AWAKE;
ar9003_mci_send_coex_version_query(ah, true);
@@ -1295,7 +1199,7 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
if (mci->unhalt_bt_gpm)
ar9003_mci_send_coex_halt_bt_gpm(ah, false, true);
- ar9003_mci_2g5g_switch(ah, true);
+ ar9003_mci_2g5g_switch(ah, false);
break;
case MCI_STATE_SET_BT_CAL_START:
mci->bt_state = MCI_BT_CAL_START;
@@ -1319,34 +1223,6 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
case MCI_STATE_SEND_WLAN_COEX_VERSION:
ar9003_mci_send_coex_version_response(ah, true);
break;
- case MCI_STATE_SET_BT_COEX_VERSION:
- if (!p_data)
- ath_dbg(common, MCI,
- "MCI Set BT Coex version with NULL data!!\n");
- else {
- mci->bt_ver_major = (*p_data >> 8) & 0xff;
- mci->bt_ver_minor = (*p_data) & 0xff;
- mci->bt_version_known = true;
- ath_dbg(common, MCI, "MCI BT version set: %d.%d\n",
- mci->bt_ver_major, mci->bt_ver_minor);
- }
- break;
- case MCI_STATE_SEND_WLAN_CHANNELS:
- if (p_data) {
- if (((mci->wlan_channels[1] & 0xffff0000) ==
- (*(p_data + 1) & 0xffff0000)) &&
- (mci->wlan_channels[2] == *(p_data + 2)) &&
- (mci->wlan_channels[3] == *(p_data + 3)))
- break;
-
- mci->wlan_channels[0] = *p_data++;
- mci->wlan_channels[1] = *p_data++;
- mci->wlan_channels[2] = *p_data++;
- mci->wlan_channels[3] = *p_data++;
- }
- mci->wlan_channels_update = true;
- ar9003_mci_send_coex_wlan_channels(ah, true);
- break;
case MCI_STATE_SEND_VERSION_QUERY:
ar9003_mci_send_coex_version_query(ah, true);
break;
@@ -1354,29 +1230,12 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
query_type = MCI_GPM_COEX_QUERY_BT_TOPOLOGY;
ar9003_mci_send_coex_bt_status_query(ah, true, query_type);
break;
- case MCI_STATE_NEED_FLUSH_BT_INFO:
- /*
- * btcoex_hw.mci.unhalt_bt_gpm means whether it's
- * needed to send UNHALT message. It's set whenever
- * there's a request to send HALT message.
- * mci_halted_bt_gpm means whether HALT message is sent
- * out successfully.
- *
- * Checking (mci_unhalt_bt_gpm == false) instead of
- * checking (ah->mci_halted_bt_gpm == false) will make
- * sure currently is in UNHALT-ed mode and BT can
- * respond to status query.
- */
- value = (!mci->unhalt_bt_gpm && mci->need_flush_btinfo) ? 1 : 0;
- if (p_data)
- mci->need_flush_btinfo = (*p_data != 0) ? true : false;
- break;
case MCI_STATE_RECOVER_RX:
ar9003_mci_prep_interface(ah);
mci->query_bt = true;
mci->need_flush_btinfo = true;
ar9003_mci_send_coex_wlan_channels(ah, true);
- ar9003_mci_2g5g_switch(ah, true);
+ ar9003_mci_2g5g_switch(ah, false);
break;
case MCI_STATE_NEED_FTP_STOMP:
value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP);
@@ -1396,6 +1255,9 @@ void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n");
+ ar9003_mci_send_lna_take(ah, true);
+ udelay(50);
+
REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
mci->is_2g = false;
mci->update_2g5g = true;
@@ -1404,3 +1266,154 @@ void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
/* Force another 2g5g update at next scanning */
mci->update_2g5g = true;
}
+
+void ar9003_mci_set_power_awake(struct ath_hw *ah)
+{
+ u32 btcoex_ctrl2, diag_sw;
+ int i;
+ u8 lna_ctrl, bt_sleep;
+
+ for (i = 0; i < AH_WAIT_TIMEOUT; i++) {
+ btcoex_ctrl2 = REG_READ(ah, AR_BTCOEX_CTRL2);
+ if (btcoex_ctrl2 != 0xdeadbeef)
+ break;
+ udelay(AH_TIME_QUANTUM);
+ }
+ REG_WRITE(ah, AR_BTCOEX_CTRL2, (btcoex_ctrl2 | BIT(23)));
+
+ for (i = 0; i < AH_WAIT_TIMEOUT; i++) {
+ diag_sw = REG_READ(ah, AR_DIAG_SW);
+ if (diag_sw != 0xdeadbeef)
+ break;
+ udelay(AH_TIME_QUANTUM);
+ }
+ REG_WRITE(ah, AR_DIAG_SW, (diag_sw | BIT(27) | BIT(19) | BIT(18)));
+ lna_ctrl = REG_READ(ah, AR_OBS_BUS_CTRL) & 0x3;
+ bt_sleep = REG_READ(ah, AR_MCI_RX_STATUS) & AR_MCI_RX_REMOTE_SLEEP;
+
+ REG_WRITE(ah, AR_BTCOEX_CTRL2, btcoex_ctrl2);
+ REG_WRITE(ah, AR_DIAG_SW, diag_sw);
+
+ if (bt_sleep && (lna_ctrl == 2)) {
+ REG_SET_BIT(ah, AR_BTCOEX_RC, 0x1);
+ REG_CLR_BIT(ah, AR_BTCOEX_RC, 0x1);
+ udelay(50);
+ }
+}
+
+void ar9003_mci_check_gpm_offset(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+ u32 offset;
+
+ /*
+ * This should only be called before "MAC Warm Reset" or "MCI Reset Rx".
+ */
+ offset = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
+ if (mci->gpm_idx == offset)
+ return;
+ ath_dbg(common, MCI, "GPM cached write pointer mismatch %d %d\n",
+ mci->gpm_idx, offset);
+ mci->query_bt = true;
+ mci->need_flush_btinfo = true;
+ mci->gpm_idx = 0;
+}
+
+u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, bool first, u32 *more)
+{
+ struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+ u32 offset, more_gpm = 0, gpm_ptr;
+
+ if (first) {
+ gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
+ mci->gpm_idx = gpm_ptr;
+ return gpm_ptr;
+ }
+
+ /*
+ * This could be useful to avoid new GPM message interrupt which
+ * may lead to spurious interrupt after power sleep, or multiple
+ * entry of ath_mci_intr().
+ * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can
+ * alleviate this effect, but clearing GPM RX interrupt bit is
+ * safe, because whether this is called from hw or driver code
+ * there must be an interrupt bit set/triggered initially
+ */
+ REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
+ AR_MCI_INTERRUPT_RX_MSG_GPM);
+
+ gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
+ offset = gpm_ptr;
+
+ if (!offset)
+ offset = mci->gpm_len - 1;
+ else if (offset >= mci->gpm_len) {
+ if (offset != 0xFFFF)
+ offset = 0;
+ } else {
+ offset--;
+ }
+
+ if ((offset == 0xFFFF) || (gpm_ptr == mci->gpm_idx)) {
+ offset = MCI_GPM_INVALID;
+ more_gpm = MCI_GPM_NOMORE;
+ goto out;
+ }
+ for (;;) {
+ u32 temp_index;
+
+ /* skip reserved GPM if any */
+
+ if (offset != mci->gpm_idx)
+ more_gpm = MCI_GPM_MORE;
+ else
+ more_gpm = MCI_GPM_NOMORE;
+
+ temp_index = mci->gpm_idx;
+ mci->gpm_idx++;
+
+ if (mci->gpm_idx >= mci->gpm_len)
+ mci->gpm_idx = 0;
+
+ if (ar9003_mci_is_gpm_valid(ah, temp_index)) {
+ offset = temp_index;
+ break;
+ }
+
+ if (more_gpm == MCI_GPM_NOMORE) {
+ offset = MCI_GPM_INVALID;
+ break;
+ }
+ }
+
+ if (offset != MCI_GPM_INVALID)
+ offset <<= 4;
+out:
+ if (more)
+ *more = more_gpm;
+
+ return offset;
+}
+EXPORT_SYMBOL(ar9003_mci_get_next_gpm_offset);
+
+void ar9003_mci_set_bt_version(struct ath_hw *ah, u8 major, u8 minor)
+{
+ struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+
+ mci->bt_ver_major = major;
+ mci->bt_ver_minor = minor;
+ mci->bt_version_known = true;
+ ath_dbg(ath9k_hw_common(ah), MCI, "MCI BT version set: %d.%d\n",
+ mci->bt_ver_major, mci->bt_ver_minor);
+}
+EXPORT_SYMBOL(ar9003_mci_set_bt_version);
+
+void ar9003_mci_send_wlan_channels(struct ath_hw *ah)
+{
+ struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+
+ mci->wlan_channels_update = true;
+ ar9003_mci_send_coex_wlan_channels(ah, true);
+}
+EXPORT_SYMBOL(ar9003_mci_send_wlan_channels);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/drivers/net/wireless/ath/ath9k/ar9003_mci.h
index 10282e2bcdc9..d33b8e128855 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mci.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.h
@@ -189,26 +189,15 @@ enum mci_bt_state {
/* Type of state query */
enum mci_state_type {
MCI_STATE_ENABLE,
- MCI_STATE_INIT_GPM_OFFSET,
- MCI_STATE_NEXT_GPM_OFFSET,
- MCI_STATE_LAST_GPM_OFFSET,
- MCI_STATE_BT,
- MCI_STATE_SET_BT_SLEEP,
MCI_STATE_SET_BT_AWAKE,
MCI_STATE_SET_BT_CAL_START,
MCI_STATE_SET_BT_CAL,
MCI_STATE_LAST_SCHD_MSG_OFFSET,
MCI_STATE_REMOTE_SLEEP,
- MCI_STATE_CONT_RSSI_POWER,
- MCI_STATE_CONT_PRIORITY,
- MCI_STATE_CONT_TXRX,
MCI_STATE_RESET_REQ_WAKE,
MCI_STATE_SEND_WLAN_COEX_VERSION,
- MCI_STATE_SET_BT_COEX_VERSION,
- MCI_STATE_SEND_WLAN_CHANNELS,
MCI_STATE_SEND_VERSION_QUERY,
MCI_STATE_SEND_STATUS_QUERY,
- MCI_STATE_NEED_FLUSH_BT_INFO,
MCI_STATE_SET_CONCUR_TX_PRI,
MCI_STATE_RECOVER_RX,
MCI_STATE_NEED_FTP_STOMP,
@@ -259,14 +248,15 @@ enum mci_gpm_coex_opcode {
bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag,
u32 *payload, u8 len, bool wait_done,
bool check_bt);
-u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data);
+u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type);
void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf,
u16 len, u32 sched_addr);
void ar9003_mci_cleanup(struct ath_hw *ah);
void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr,
u32 *rx_msg_intr);
-void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah);
-
+u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, bool first, u32 *more);
+void ar9003_mci_set_bt_version(struct ath_hw *ah, u8 major, u8 minor);
+void ar9003_mci_send_wlan_channels(struct ath_hw *ah);
/*
* These functions are used by ath9k_hw.
*/
@@ -277,7 +267,7 @@ void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep);
void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable);
void ar9003_mci_init_cal_done(struct ath_hw *ah);
void ar9003_mci_set_full_sleep(struct ath_hw *ah);
-void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done);
+void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force);
void ar9003_mci_check_bt(struct ath_hw *ah);
bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan);
int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
@@ -285,6 +275,9 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
bool is_full_sleep);
void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked);
+void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah);
+void ar9003_mci_set_power_awake(struct ath_hw *ah);
+void ar9003_mci_check_gpm_offset(struct ath_hw *ah);
#else
@@ -322,6 +315,15 @@ static inline void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
static inline void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
{
}
+static inline void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
+{
+}
+static inline void ar9003_mci_set_power_awake(struct ath_hw *ah)
+{
+}
+static inline void ar9003_mci_check_gpm_offset(struct ath_hw *ah)
+{
+}
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
#endif
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
index 3d400e8d6535..2c9f7d7ed4cc 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -211,7 +211,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1);
- if (AR_SREV_9485(ah) || AR_SREV_9462(ah))
+ if (AR_SREV_9485(ah) || AR_SREV_9462(ah) || AR_SREV_9550(ah))
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
-3);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index d6baf69cdc14..d2346dbad6cd 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -99,7 +99,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
channelSel = (freq * 4) / 120;
chan_frac = (((freq * 4) % 120) * 0x20000) / 120;
channelSel = (channelSel << 17) | chan_frac;
- } else if (AR_SREV_9340(ah)) {
+ } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) {
if (ah->is_clk_25mhz) {
u32 chan_frac;
@@ -113,7 +113,8 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
/* Set to 2G mode */
bMode = 1;
} else {
- if (AR_SREV_9340(ah) && ah->is_clk_25mhz) {
+ if ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) &&
+ ah->is_clk_25mhz) {
u32 chan_frac;
channelSel = (freq * 2) / 75;
@@ -173,16 +174,15 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
int cur_bb_spur, negative = 0, cck_spur_freq;
int i;
int range, max_spur_cnts, synth_freq;
- u8 *spur_fbin_ptr = NULL;
+ u8 *spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah, IS_CHAN_2GHZ(chan));
/*
* Need to verify range +/- 10 MHz in control channel, otherwise spur
* is out-of-band and can be ignored.
*/
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) {
- spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah,
- IS_CHAN_2GHZ(chan));
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) ||
+ AR_SREV_9550(ah)) {
if (spur_fbin_ptr[0] == 0) /* No spur */
return;
max_spur_cnts = 5;
@@ -207,7 +207,8 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
if (AR_SREV_9462(ah) && (i == 0 || i == 3))
continue;
negative = 0;
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) ||
+ AR_SREV_9550(ah))
cur_bb_spur = ath9k_hw_fbin2freq(spur_fbin_ptr[i],
IS_CHAN_2GHZ(chan));
else
@@ -620,6 +621,50 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah,
}
}
+static int ar9550_hw_get_modes_txgain_index(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ int ret;
+
+ switch (chan->chanmode) {
+ case CHANNEL_A:
+ case CHANNEL_A_HT20:
+ if (chan->channel <= 5350)
+ ret = 1;
+ else if ((chan->channel > 5350) && (chan->channel <= 5600))
+ ret = 3;
+ else
+ ret = 5;
+ break;
+
+ case CHANNEL_A_HT40PLUS:
+ case CHANNEL_A_HT40MINUS:
+ if (chan->channel <= 5350)
+ ret = 2;
+ else if ((chan->channel > 5350) && (chan->channel <= 5600))
+ ret = 4;
+ else
+ ret = 6;
+ break;
+
+ case CHANNEL_G:
+ case CHANNEL_G_HT20:
+ case CHANNEL_B:
+ ret = 8;
+ break;
+
+ case CHANNEL_G_HT40PLUS:
+ case CHANNEL_G_HT40MINUS:
+ ret = 7;
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
static int ar9003_hw_process_ini(struct ath_hw *ah,
struct ath9k_channel *chan)
{
@@ -661,7 +706,22 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
}
REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites);
- REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
+ if (AR_SREV_9550(ah))
+ REG_WRITE_ARRAY(&ah->ini_modes_rx_gain_bounds, modesIndex,
+ regWrites);
+
+ if (AR_SREV_9550(ah)) {
+ int modes_txgain_index;
+
+ modes_txgain_index = ar9550_hw_get_modes_txgain_index(ah, chan);
+ if (modes_txgain_index < 0)
+ return -EINVAL;
+
+ REG_WRITE_ARRAY(&ah->iniModesTxGain, modes_txgain_index,
+ regWrites);
+ } else {
+ REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
+ }
/*
* For 5GHz channels requiring Fast Clock, apply
@@ -825,18 +885,18 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
- if (!on != aniState->ofdmWeakSigDetectOff) {
+ if (on != aniState->ofdmWeakSigDetect) {
ath_dbg(common, ANI,
"** ch %d: ofdm weak signal: %s=>%s\n",
chan->channel,
- !aniState->ofdmWeakSigDetectOff ?
+ aniState->ofdmWeakSigDetect ?
"on" : "off",
on ? "on" : "off");
if (on)
ah->stats.ast_ani_ofdmon++;
else
ah->stats.ast_ani_ofdmoff++;
- aniState->ofdmWeakSigDetectOff = !on;
+ aniState->ofdmWeakSigDetect = on;
}
break;
}
@@ -855,7 +915,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
* from INI file & cap value
*/
value = firstep_table[level] -
- firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
+ firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
aniState->iniDef.firstep;
if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
@@ -870,7 +930,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
* from INI file & cap value
*/
value2 = firstep_table[level] -
- firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
+ firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
aniState->iniDef.firstepLow;
if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
@@ -886,7 +946,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
chan->channel,
aniState->firstepLevel,
level,
- ATH9K_ANI_FIRSTEP_LVL_NEW,
+ ATH9K_ANI_FIRSTEP_LVL,
value,
aniState->iniDef.firstep);
ath_dbg(common, ANI,
@@ -894,7 +954,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
chan->channel,
aniState->firstepLevel,
level,
- ATH9K_ANI_FIRSTEP_LVL_NEW,
+ ATH9K_ANI_FIRSTEP_LVL,
value2,
aniState->iniDef.firstepLow);
if (level > aniState->firstepLevel)
@@ -919,7 +979,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
* from INI file & cap value
*/
value = cycpwrThr1_table[level] -
- cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
+ cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
aniState->iniDef.cycpwrThr1;
if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
@@ -935,7 +995,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
* from INI file & cap value
*/
value2 = cycpwrThr1_table[level] -
- cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
+ cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
aniState->iniDef.cycpwrThr1Ext;
if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
@@ -950,7 +1010,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
chan->channel,
aniState->spurImmunityLevel,
level,
- ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
+ ATH9K_ANI_SPUR_IMMUNE_LVL,
value,
aniState->iniDef.cycpwrThr1);
ath_dbg(common, ANI,
@@ -958,7 +1018,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
chan->channel,
aniState->spurImmunityLevel,
level,
- ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
+ ATH9K_ANI_SPUR_IMMUNE_LVL,
value2,
aniState->iniDef.cycpwrThr1Ext);
if (level > aniState->spurImmunityLevel)
@@ -979,16 +1039,16 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
AR_PHY_MRC_CCK_ENABLE, is_on);
REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
AR_PHY_MRC_CCK_MUX_REG, is_on);
- if (!is_on != aniState->mrcCCKOff) {
+ if (is_on != aniState->mrcCCK) {
ath_dbg(common, ANI, "** ch %d: MRC CCK: %s=>%s\n",
chan->channel,
- !aniState->mrcCCKOff ? "on" : "off",
+ aniState->mrcCCK ? "on" : "off",
is_on ? "on" : "off");
if (is_on)
ah->stats.ast_ani_ccklow++;
else
ah->stats.ast_ani_cckhigh++;
- aniState->mrcCCKOff = !is_on;
+ aniState->mrcCCK = is_on;
}
break;
}
@@ -1002,9 +1062,9 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
ath_dbg(common, ANI,
"ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
aniState->spurImmunityLevel,
- !aniState->ofdmWeakSigDetectOff ? "on" : "off",
+ aniState->ofdmWeakSigDetect ? "on" : "off",
aniState->firstepLevel,
- !aniState->mrcCCKOff ? "on" : "off",
+ aniState->mrcCCK ? "on" : "off",
aniState->listenTime,
aniState->ofdmPhyErrCount,
aniState->cckPhyErrCount);
@@ -1111,10 +1171,10 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
AR_PHY_EXT_CYCPWR_THR1);
/* these levels just got reset to defaults by the INI */
- aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
- aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
- aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
- aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK;
+ aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
+ aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
+ aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
+ aniState->mrcCCK = true;
}
static void ar9003_hw_set_radar_params(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index ed662c3bae5b..751c83b21493 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -636,8 +636,8 @@
#define AR_CH0_TOP (AR_SREV_9300(ah) ? 0x16288 : \
((AR_SREV_9462(ah) ? 0x1628c : 0x16280)))
-#define AR_CH0_TOP_XPABIASLVL (0x300)
-#define AR_CH0_TOP_XPABIASLVL_S (8)
+#define AR_CH0_TOP_XPABIASLVL (AR_SREV_9550(ah) ? 0x3c0 : 0x300)
+#define AR_CH0_TOP_XPABIASLVL_S (AR_SREV_9550(ah) ? 6 : 8)
#define AR_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : \
((AR_SREV_9485(ah) ? 0x1628c : 0x16294)))
@@ -650,6 +650,8 @@
#define AR_SWITCH_TABLE_COM_ALL_S (0)
#define AR_SWITCH_TABLE_COM_AR9462_ALL (0xffffff)
#define AR_SWITCH_TABLE_COM_AR9462_ALL_S (0)
+#define AR_SWITCH_TABLE_COM_AR9550_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM_AR9550_ALL_S (0)
#define AR_SWITCH_TABLE_COM_SPDT (0x00f00000)
#define AR_SWITCH_TABLE_COM_SPDT_ALL (0x0000fff0)
#define AR_SWITCH_TABLE_COM_SPDT_ALL_S (4)
diff --git a/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
index 1bd3a3d22101..6e1756bc3833 100644
--- a/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
@@ -337,12 +337,7 @@ static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = {
{0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
};
-static const u32 ar9331_1p1_baseband_core_txfir_coeff_japan_2484[][2] = {
- /* Addr allmodes */
- {0x0000a398, 0x00000000},
- {0x0000a39c, 0x6f7f0301},
- {0x0000a3a0, 0xca9228ee},
-};
+#define ar9331_1p1_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
static const u32 ar9331_1p1_xtal_25M[][2] = {
/* Addr allmodes */
@@ -783,17 +778,7 @@ static const u32 ar9331_modes_high_power_tx_gain_1p1[][5] = {
{0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
};
-static const u32 ar9331_1p1_mac_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
- {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
- {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
-};
+#define ar9331_1p1_mac_postamble ar9300_2p2_mac_postamble
static const u32 ar9331_1p1_soc_preamble[][2] = {
/* Addr allmodes */
@@ -1112,38 +1097,4 @@ static const u32 ar9331_common_tx_gain_offset1_1[][1] = {
{0x00000000},
};
-static const u32 ar9331_1p1_chansel_xtal_25M[] = {
- 0x0101479e,
- 0x0101d027,
- 0x010258af,
- 0x0102e138,
- 0x010369c0,
- 0x0103f249,
- 0x01047ad1,
- 0x0105035a,
- 0x01058be2,
- 0x0106146b,
- 0x01069cf3,
- 0x0107257c,
- 0x0107ae04,
- 0x0108f5b2,
-};
-
-static const u32 ar9331_1p1_chansel_xtal_40M[] = {
- 0x00a0ccbe,
- 0x00a12213,
- 0x00a17769,
- 0x00a1ccbe,
- 0x00a22213,
- 0x00a27769,
- 0x00a2ccbe,
- 0x00a32213,
- 0x00a37769,
- 0x00a3ccbe,
- 0x00a42213,
- 0x00a47769,
- 0x00a4ccbe,
- 0x00a5998b,
-};
-
#endif /* INITVALS_9330_1P1_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
index 0e6ca0834b34..57ed8a112173 100644
--- a/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2011 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,8 +18,8 @@
#ifndef INITVALS_9330_1P2_H
#define INITVALS_9330_1P2_H
-static const u32 ar9331_modes_lowest_ob_db_tx_gain_1p2[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
@@ -102,8 +103,14 @@ static const u32 ar9331_modes_lowest_ob_db_tx_gain_1p2[][5] = {
{0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
};
+#define ar9331_modes_high_power_tx_gain_1p2 ar9331_modes_high_ob_db_tx_gain_1p2
+
+#define ar9331_modes_low_ob_db_tx_gain_1p2 ar9331_modes_high_power_tx_gain_1p2
+
+#define ar9331_modes_lowest_ob_db_tx_gain_1p2 ar9331_modes_low_ob_db_tx_gain_1p2
+
static const u32 ar9331_1p2_baseband_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
{0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
@@ -147,191 +154,6 @@ static const u32 ar9331_1p2_baseband_postamble[][5] = {
{0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
};
-static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
- {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
- {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
- {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
- {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
- {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
- {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
- {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
- {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
- {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
- {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
- {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
- {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
- {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
- {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
- {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
- {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
- {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
- {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
- {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
- {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
- {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
- {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
- {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
- {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
- {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
- {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
- {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
- {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
- {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
- {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
- {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
- {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
- {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
- {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
- {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
- {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
- {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
- {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
- {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
- {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
- {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
- {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
- {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
- {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
- {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
- {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
- {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
- {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
- {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
- {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
- {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
- {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
- {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
- {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
- {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
- {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
- {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
- {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
- {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
- {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
- {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
- {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
- {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
-};
-
-static const u32 ar9331_modes_low_ob_db_tx_gain_1p2[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
- {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
- {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
- {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
- {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
- {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
- {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
- {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
- {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
- {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
- {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
- {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
- {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
- {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
- {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
- {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
- {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
- {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
- {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
- {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
- {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
- {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
- {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
- {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
- {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
- {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
- {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
- {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
- {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
- {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
- {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
- {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
- {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
- {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
- {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
- {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
- {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
- {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
- {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
- {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
- {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
- {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
- {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
- {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
- {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
- {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
- {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
- {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
- {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
- {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
- {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
- {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
- {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
- {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
- {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
- {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
- {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
- {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
- {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
- {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
- {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
- {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
- {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
- {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
-};
-
-static const u32 ar9331_1p2_baseband_core_txfir_coeff_japan_2484[][2] = {
- /* Addr allmodes */
- {0x0000a398, 0x00000000},
- {0x0000a39c, 0x6f7f0301},
- {0x0000a3a0, 0xca9228ee},
-};
-
-static const u32 ar9331_1p2_xtal_25M[][2] = {
- /* Addr allmodes */
- {0x00007038, 0x000002f8},
- {0x00008244, 0x0010f3d7},
- {0x0000824c, 0x0001e7ae},
- {0x0001609c, 0x0f508f29},
-};
-
static const u32 ar9331_1p2_radio_core[][2] = {
/* Addr allmodes */
{0x00016000, 0x36db6db6},
@@ -397,684 +219,24 @@ static const u32 ar9331_1p2_radio_core[][2] = {
{0x000163d4, 0x00000000},
};
-static const u32 ar9331_1p2_soc_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x00007010, 0x00000022, 0x00000022, 0x00000022, 0x00000022},
-};
+#define ar9331_1p2_baseband_core_txfir_coeff_japan_2484 ar9331_1p1_baseband_core_txfir_coeff_japan_2484
-static const u32 ar9331_common_wo_xlna_rx_gain_1p2[][2] = {
- /* Addr allmodes */
- {0x0000a000, 0x00060005},
- {0x0000a004, 0x00810080},
- {0x0000a008, 0x00830082},
- {0x0000a00c, 0x00850084},
- {0x0000a010, 0x01820181},
- {0x0000a014, 0x01840183},
- {0x0000a018, 0x01880185},
- {0x0000a01c, 0x018a0189},
- {0x0000a020, 0x02850284},
- {0x0000a024, 0x02890288},
- {0x0000a028, 0x028b028a},
- {0x0000a02c, 0x03850384},
- {0x0000a030, 0x03890388},
- {0x0000a034, 0x038b038a},
- {0x0000a038, 0x038d038c},
- {0x0000a03c, 0x03910390},
- {0x0000a040, 0x03930392},
- {0x0000a044, 0x03950394},
- {0x0000a048, 0x00000396},
- {0x0000a04c, 0x00000000},
- {0x0000a050, 0x00000000},
- {0x0000a054, 0x00000000},
- {0x0000a058, 0x00000000},
- {0x0000a05c, 0x00000000},
- {0x0000a060, 0x00000000},
- {0x0000a064, 0x00000000},
- {0x0000a068, 0x00000000},
- {0x0000a06c, 0x00000000},
- {0x0000a070, 0x00000000},
- {0x0000a074, 0x00000000},
- {0x0000a078, 0x00000000},
- {0x0000a07c, 0x00000000},
- {0x0000a080, 0x28282828},
- {0x0000a084, 0x28282828},
- {0x0000a088, 0x28282828},
- {0x0000a08c, 0x28282828},
- {0x0000a090, 0x28282828},
- {0x0000a094, 0x24242428},
- {0x0000a098, 0x171e1e1e},
- {0x0000a09c, 0x02020b0b},
- {0x0000a0a0, 0x02020202},
- {0x0000a0a4, 0x00000000},
- {0x0000a0a8, 0x00000000},
- {0x0000a0ac, 0x00000000},
- {0x0000a0b0, 0x00000000},
- {0x0000a0b4, 0x00000000},
- {0x0000a0b8, 0x00000000},
- {0x0000a0bc, 0x00000000},
- {0x0000a0c0, 0x22072208},
- {0x0000a0c4, 0x22052206},
- {0x0000a0c8, 0x22032204},
- {0x0000a0cc, 0x22012202},
- {0x0000a0d0, 0x221f2200},
- {0x0000a0d4, 0x221d221e},
- {0x0000a0d8, 0x33023303},
- {0x0000a0dc, 0x33003301},
- {0x0000a0e0, 0x331e331f},
- {0x0000a0e4, 0x4402331d},
- {0x0000a0e8, 0x44004401},
- {0x0000a0ec, 0x441e441f},
- {0x0000a0f0, 0x55025503},
- {0x0000a0f4, 0x55005501},
- {0x0000a0f8, 0x551e551f},
- {0x0000a0fc, 0x6602551d},
- {0x0000a100, 0x66006601},
- {0x0000a104, 0x661e661f},
- {0x0000a108, 0x7703661d},
- {0x0000a10c, 0x77017702},
- {0x0000a110, 0x00007700},
- {0x0000a114, 0x00000000},
- {0x0000a118, 0x00000000},
- {0x0000a11c, 0x00000000},
- {0x0000a120, 0x00000000},
- {0x0000a124, 0x00000000},
- {0x0000a128, 0x00000000},
- {0x0000a12c, 0x00000000},
- {0x0000a130, 0x00000000},
- {0x0000a134, 0x00000000},
- {0x0000a138, 0x00000000},
- {0x0000a13c, 0x00000000},
- {0x0000a140, 0x001f0000},
- {0x0000a144, 0x111f1100},
- {0x0000a148, 0x111d111e},
- {0x0000a14c, 0x111b111c},
- {0x0000a150, 0x22032204},
- {0x0000a154, 0x22012202},
- {0x0000a158, 0x221f2200},
- {0x0000a15c, 0x221d221e},
- {0x0000a160, 0x33013302},
- {0x0000a164, 0x331f3300},
- {0x0000a168, 0x4402331e},
- {0x0000a16c, 0x44004401},
- {0x0000a170, 0x441e441f},
- {0x0000a174, 0x55015502},
- {0x0000a178, 0x551f5500},
- {0x0000a17c, 0x6602551e},
- {0x0000a180, 0x66006601},
- {0x0000a184, 0x661e661f},
- {0x0000a188, 0x7703661d},
- {0x0000a18c, 0x77017702},
- {0x0000a190, 0x00007700},
- {0x0000a194, 0x00000000},
- {0x0000a198, 0x00000000},
- {0x0000a19c, 0x00000000},
- {0x0000a1a0, 0x00000000},
- {0x0000a1a4, 0x00000000},
- {0x0000a1a8, 0x00000000},
- {0x0000a1ac, 0x00000000},
- {0x0000a1b0, 0x00000000},
- {0x0000a1b4, 0x00000000},
- {0x0000a1b8, 0x00000000},
- {0x0000a1bc, 0x00000000},
- {0x0000a1c0, 0x00000000},
- {0x0000a1c4, 0x00000000},
- {0x0000a1c8, 0x00000000},
- {0x0000a1cc, 0x00000000},
- {0x0000a1d0, 0x00000000},
- {0x0000a1d4, 0x00000000},
- {0x0000a1d8, 0x00000000},
- {0x0000a1dc, 0x00000000},
- {0x0000a1e0, 0x00000000},
- {0x0000a1e4, 0x00000000},
- {0x0000a1e8, 0x00000000},
- {0x0000a1ec, 0x00000000},
- {0x0000a1f0, 0x00000396},
- {0x0000a1f4, 0x00000396},
- {0x0000a1f8, 0x00000396},
- {0x0000a1fc, 0x00000296},
-};
+#define ar9331_1p2_xtal_25M ar9331_1p1_xtal_25M
-static const u32 ar9331_1p2_baseband_core[][2] = {
- /* Addr allmodes */
- {0x00009800, 0xafe68e30},
- {0x00009804, 0xfd14e000},
- {0x00009808, 0x9c0a8f6b},
- {0x0000980c, 0x04800000},
- {0x00009814, 0x9280c00a},
- {0x00009818, 0x00000000},
- {0x0000981c, 0x00020028},
- {0x00009834, 0x5f3ca3de},
- {0x00009838, 0x0108ecff},
- {0x0000983c, 0x14750600},
- {0x00009880, 0x201fff00},
- {0x00009884, 0x00001042},
- {0x000098a4, 0x00200400},
- {0x000098b0, 0x32840bbe},
- {0x000098d0, 0x004b6a8e},
- {0x000098d4, 0x00000820},
- {0x000098dc, 0x00000000},
- {0x000098f0, 0x00000000},
- {0x000098f4, 0x00000000},
- {0x00009c04, 0x00000000},
- {0x00009c08, 0x03200000},
- {0x00009c0c, 0x00000000},
- {0x00009c10, 0x00000000},
- {0x00009c14, 0x00046384},
- {0x00009c18, 0x05b6b440},
- {0x00009c1c, 0x00b6b440},
- {0x00009d00, 0xc080a333},
- {0x00009d04, 0x40206c10},
- {0x00009d08, 0x009c4060},
- {0x00009d0c, 0x1883800a},
- {0x00009d10, 0x01834061},
- {0x00009d14, 0x00c00400},
- {0x00009d18, 0x00000000},
- {0x00009e08, 0x0038233c},
- {0x00009e24, 0x9927b515},
- {0x00009e28, 0x12ef0200},
- {0x00009e30, 0x06336f77},
- {0x00009e34, 0x6af6532f},
- {0x00009e38, 0x0cc80c00},
- {0x00009e40, 0x0d261820},
- {0x00009e4c, 0x00001004},
- {0x00009e50, 0x00ff03f1},
- {0x00009fc0, 0x803e4788},
- {0x00009fc4, 0x0001efb5},
- {0x00009fcc, 0x40000014},
- {0x0000a20c, 0x00000000},
- {0x0000a220, 0x00000000},
- {0x0000a224, 0x00000000},
- {0x0000a228, 0x10002310},
- {0x0000a23c, 0x00000000},
- {0x0000a244, 0x0c000000},
- {0x0000a2a0, 0x00000001},
- {0x0000a2c0, 0x00000001},
- {0x0000a2c8, 0x00000000},
- {0x0000a2cc, 0x18c43433},
- {0x0000a2d4, 0x00000000},
- {0x0000a2dc, 0x00000000},
- {0x0000a2e0, 0x00000000},
- {0x0000a2e4, 0x00000000},
- {0x0000a2e8, 0x00000000},
- {0x0000a2ec, 0x00000000},
- {0x0000a2f0, 0x00000000},
- {0x0000a2f4, 0x00000000},
- {0x0000a2f8, 0x00000000},
- {0x0000a344, 0x00000000},
- {0x0000a34c, 0x00000000},
- {0x0000a350, 0x0000a000},
- {0x0000a364, 0x00000000},
- {0x0000a370, 0x00000000},
- {0x0000a390, 0x00000001},
- {0x0000a394, 0x00000444},
- {0x0000a398, 0x001f0e0f},
- {0x0000a39c, 0x0075393f},
- {0x0000a3a0, 0xb79f6427},
- {0x0000a3a4, 0x00000000},
- {0x0000a3a8, 0xaaaaaaaa},
- {0x0000a3ac, 0x3c466478},
- {0x0000a3c0, 0x20202020},
- {0x0000a3c4, 0x22222220},
- {0x0000a3c8, 0x20200020},
- {0x0000a3cc, 0x20202020},
- {0x0000a3d0, 0x20202020},
- {0x0000a3d4, 0x20202020},
- {0x0000a3d8, 0x20202020},
- {0x0000a3dc, 0x20202020},
- {0x0000a3e0, 0x20202020},
- {0x0000a3e4, 0x20202020},
- {0x0000a3e8, 0x20202020},
- {0x0000a3ec, 0x20202020},
- {0x0000a3f0, 0x00000000},
- {0x0000a3f4, 0x00000006},
- {0x0000a3f8, 0x0cdbd380},
- {0x0000a3fc, 0x000f0f01},
- {0x0000a400, 0x8fa91f01},
- {0x0000a404, 0x00000000},
- {0x0000a408, 0x0e79e5c6},
- {0x0000a40c, 0x00820820},
- {0x0000a414, 0x1ce739ce},
- {0x0000a418, 0x2d001dce},
- {0x0000a41c, 0x1ce739ce},
- {0x0000a420, 0x000001ce},
- {0x0000a424, 0x1ce739ce},
- {0x0000a428, 0x000001ce},
- {0x0000a42c, 0x1ce739ce},
- {0x0000a430, 0x1ce739ce},
- {0x0000a434, 0x00000000},
- {0x0000a438, 0x00001801},
- {0x0000a43c, 0x00000000},
- {0x0000a440, 0x00000000},
- {0x0000a444, 0x00000000},
- {0x0000a448, 0x04000000},
- {0x0000a44c, 0x00000001},
- {0x0000a450, 0x00010000},
- {0x0000a458, 0x00000000},
- {0x0000a640, 0x00000000},
- {0x0000a644, 0x3fad9d74},
- {0x0000a648, 0x0048060a},
- {0x0000a64c, 0x00003c37},
- {0x0000a670, 0x03020100},
- {0x0000a674, 0x09080504},
- {0x0000a678, 0x0d0c0b0a},
- {0x0000a67c, 0x13121110},
- {0x0000a680, 0x31301514},
- {0x0000a684, 0x35343332},
- {0x0000a688, 0x00000036},
- {0x0000a690, 0x00000838},
- {0x0000a7c0, 0x00000000},
- {0x0000a7c4, 0xfffffffc},
- {0x0000a7c8, 0x00000000},
- {0x0000a7cc, 0x00000000},
- {0x0000a7d0, 0x00000000},
- {0x0000a7d4, 0x00000004},
- {0x0000a7dc, 0x00000001},
-};
+#define ar9331_1p2_xtal_40M ar9331_1p1_xtal_40M
-static const u32 ar9331_modes_high_power_tx_gain_1p2[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
- {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
- {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
- {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
- {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
- {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
- {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
- {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
- {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
- {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
- {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
- {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
- {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
- {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
- {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
- {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
- {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
- {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
- {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
- {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
- {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
- {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
- {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
- {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
- {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
- {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
- {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
- {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
- {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
- {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
- {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
- {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
- {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
- {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
- {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
- {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
- {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
- {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
- {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
- {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
- {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
- {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
- {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
- {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
- {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
- {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
- {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
- {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
- {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
- {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
- {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
- {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
- {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
- {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
- {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
- {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
- {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
- {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
- {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
- {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
- {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
- {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
- {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
- {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
- {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
- {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
-};
+#define ar9331_1p2_baseband_core ar9331_1p1_baseband_core
-static const u32 ar9331_1p2_mac_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
- {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
- {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
-};
+#define ar9331_1p2_soc_postamble ar9331_1p1_soc_postamble
-static const u32 ar9331_1p2_soc_preamble[][2] = {
- /* Addr allmodes */
- {0x00007020, 0x00000000},
- {0x00007034, 0x00000002},
- {0x00007038, 0x000002f8},
-};
+#define ar9331_1p2_mac_postamble ar9331_1p1_mac_postamble
-static const u32 ar9331_1p2_xtal_40M[][2] = {
- /* Addr allmodes */
- {0x00007038, 0x000004c2},
- {0x00008244, 0x0010f400},
- {0x0000824c, 0x0001e800},
- {0x0001609c, 0x0b283f31},
-};
+#define ar9331_1p2_soc_preamble ar9331_1p1_soc_preamble
-static const u32 ar9331_1p2_mac_core[][2] = {
- /* Addr allmodes */
- {0x00000008, 0x00000000},
- {0x00000030, 0x00020085},
- {0x00000034, 0x00000005},
- {0x00000040, 0x00000000},
- {0x00000044, 0x00000000},
- {0x00000048, 0x00000008},
- {0x0000004c, 0x00000010},
- {0x00000050, 0x00000000},
- {0x00001040, 0x002ffc0f},
- {0x00001044, 0x002ffc0f},
- {0x00001048, 0x002ffc0f},
- {0x0000104c, 0x002ffc0f},
- {0x00001050, 0x002ffc0f},
- {0x00001054, 0x002ffc0f},
- {0x00001058, 0x002ffc0f},
- {0x0000105c, 0x002ffc0f},
- {0x00001060, 0x002ffc0f},
- {0x00001064, 0x002ffc0f},
- {0x000010f0, 0x00000100},
- {0x00001270, 0x00000000},
- {0x000012b0, 0x00000000},
- {0x000012f0, 0x00000000},
- {0x0000143c, 0x00000000},
- {0x0000147c, 0x00000000},
- {0x00008000, 0x00000000},
- {0x00008004, 0x00000000},
- {0x00008008, 0x00000000},
- {0x0000800c, 0x00000000},
- {0x00008018, 0x00000000},
- {0x00008020, 0x00000000},
- {0x00008038, 0x00000000},
- {0x0000803c, 0x00000000},
- {0x00008040, 0x00000000},
- {0x00008044, 0x00000000},
- {0x00008048, 0x00000000},
- {0x0000804c, 0xffffffff},
- {0x00008054, 0x00000000},
- {0x00008058, 0x00000000},
- {0x0000805c, 0x000fc78f},
- {0x00008060, 0x0000000f},
- {0x00008064, 0x00000000},
- {0x00008070, 0x00000310},
- {0x00008074, 0x00000020},
- {0x00008078, 0x00000000},
- {0x0000809c, 0x0000000f},
- {0x000080a0, 0x00000000},
- {0x000080a4, 0x02ff0000},
- {0x000080a8, 0x0e070605},
- {0x000080ac, 0x0000000d},
- {0x000080b0, 0x00000000},
- {0x000080b4, 0x00000000},
- {0x000080b8, 0x00000000},
- {0x000080bc, 0x00000000},
- {0x000080c0, 0x2a800000},
- {0x000080c4, 0x06900168},
- {0x000080c8, 0x13881c20},
- {0x000080cc, 0x01f40000},
- {0x000080d0, 0x00252500},
- {0x000080d4, 0x00a00000},
- {0x000080d8, 0x00400000},
- {0x000080dc, 0x00000000},
- {0x000080e0, 0xffffffff},
- {0x000080e4, 0x0000ffff},
- {0x000080e8, 0x3f3f3f3f},
- {0x000080ec, 0x00000000},
- {0x000080f0, 0x00000000},
- {0x000080f4, 0x00000000},
- {0x000080fc, 0x00020000},
- {0x00008100, 0x00000000},
- {0x00008108, 0x00000052},
- {0x0000810c, 0x00000000},
- {0x00008110, 0x00000000},
- {0x00008114, 0x000007ff},
- {0x00008118, 0x000000aa},
- {0x0000811c, 0x00003210},
- {0x00008124, 0x00000000},
- {0x00008128, 0x00000000},
- {0x0000812c, 0x00000000},
- {0x00008130, 0x00000000},
- {0x00008134, 0x00000000},
- {0x00008138, 0x00000000},
- {0x0000813c, 0x0000ffff},
- {0x00008144, 0xffffffff},
- {0x00008168, 0x00000000},
- {0x0000816c, 0x00000000},
- {0x00008170, 0x18486200},
- {0x00008174, 0x33332210},
- {0x00008178, 0x00000000},
- {0x0000817c, 0x00020000},
- {0x000081c0, 0x00000000},
- {0x000081c4, 0x33332210},
- {0x000081c8, 0x00000000},
- {0x000081cc, 0x00000000},
- {0x000081d4, 0x00000000},
- {0x000081ec, 0x00000000},
- {0x000081f0, 0x00000000},
- {0x000081f4, 0x00000000},
- {0x000081f8, 0x00000000},
- {0x000081fc, 0x00000000},
- {0x00008240, 0x00100000},
- {0x00008248, 0x00000800},
- {0x00008250, 0x00000000},
- {0x00008254, 0x00000000},
- {0x00008258, 0x00000000},
- {0x0000825c, 0x40000000},
- {0x00008260, 0x00080922},
- {0x00008264, 0x9d400010},
- {0x00008268, 0xffffffff},
- {0x0000826c, 0x0000ffff},
- {0x00008270, 0x00000000},
- {0x00008274, 0x40000000},
- {0x00008278, 0x003e4180},
- {0x0000827c, 0x00000004},
- {0x00008284, 0x0000002c},
- {0x00008288, 0x0000002c},
- {0x0000828c, 0x000000ff},
- {0x00008294, 0x00000000},
- {0x00008298, 0x00000000},
- {0x0000829c, 0x00000000},
- {0x00008300, 0x00000140},
- {0x00008314, 0x00000000},
- {0x0000831c, 0x0000010d},
- {0x00008328, 0x00000000},
- {0x0000832c, 0x00000007},
- {0x00008330, 0x00000302},
- {0x00008334, 0x00000700},
- {0x00008338, 0x00ff0000},
- {0x0000833c, 0x02400000},
- {0x00008340, 0x000107ff},
- {0x00008344, 0xaa48105b},
- {0x00008348, 0x008f0000},
- {0x0000835c, 0x00000000},
- {0x00008360, 0xffffffff},
- {0x00008364, 0xffffffff},
- {0x00008368, 0x00000000},
- {0x00008370, 0x00000000},
- {0x00008374, 0x000000ff},
- {0x00008378, 0x00000000},
- {0x0000837c, 0x00000000},
- {0x00008380, 0xffffffff},
- {0x00008384, 0xffffffff},
- {0x00008390, 0xffffffff},
- {0x00008394, 0xffffffff},
- {0x00008398, 0x00000000},
- {0x0000839c, 0x00000000},
- {0x000083a0, 0x00000000},
- {0x000083a4, 0x0000fa14},
- {0x000083a8, 0x000f0c00},
- {0x000083ac, 0x33332210},
- {0x000083b0, 0x33332210},
- {0x000083b4, 0x33332210},
- {0x000083b8, 0x33332210},
- {0x000083bc, 0x00000000},
- {0x000083c0, 0x00000000},
- {0x000083c4, 0x00000000},
- {0x000083c8, 0x00000000},
- {0x000083cc, 0x00000200},
- {0x000083d0, 0x000301ff},
-};
+#define ar9331_1p2_mac_core ar9331_1p1_mac_core
-static const u32 ar9331_common_rx_gain_1p2[][2] = {
- /* Addr allmodes */
- {0x0000a000, 0x00010000},
- {0x0000a004, 0x00030002},
- {0x0000a008, 0x00050004},
- {0x0000a00c, 0x00810080},
- {0x0000a010, 0x01800082},
- {0x0000a014, 0x01820181},
- {0x0000a018, 0x01840183},
- {0x0000a01c, 0x01880185},
- {0x0000a020, 0x018a0189},
- {0x0000a024, 0x02850284},
- {0x0000a028, 0x02890288},
- {0x0000a02c, 0x03850384},
- {0x0000a030, 0x03890388},
- {0x0000a034, 0x038b038a},
- {0x0000a038, 0x038d038c},
- {0x0000a03c, 0x03910390},
- {0x0000a040, 0x03930392},
- {0x0000a044, 0x03950394},
- {0x0000a048, 0x00000396},
- {0x0000a04c, 0x00000000},
- {0x0000a050, 0x00000000},
- {0x0000a054, 0x00000000},
- {0x0000a058, 0x00000000},
- {0x0000a05c, 0x00000000},
- {0x0000a060, 0x00000000},
- {0x0000a064, 0x00000000},
- {0x0000a068, 0x00000000},
- {0x0000a06c, 0x00000000},
- {0x0000a070, 0x00000000},
- {0x0000a074, 0x00000000},
- {0x0000a078, 0x00000000},
- {0x0000a07c, 0x00000000},
- {0x0000a080, 0x28282828},
- {0x0000a084, 0x28282828},
- {0x0000a088, 0x28282828},
- {0x0000a08c, 0x28282828},
- {0x0000a090, 0x28282828},
- {0x0000a094, 0x21212128},
- {0x0000a098, 0x171c1c1c},
- {0x0000a09c, 0x02020212},
- {0x0000a0a0, 0x00000202},
- {0x0000a0a4, 0x00000000},
- {0x0000a0a8, 0x00000000},
- {0x0000a0ac, 0x00000000},
- {0x0000a0b0, 0x00000000},
- {0x0000a0b4, 0x00000000},
- {0x0000a0b8, 0x00000000},
- {0x0000a0bc, 0x00000000},
- {0x0000a0c0, 0x001f0000},
- {0x0000a0c4, 0x111f1100},
- {0x0000a0c8, 0x111d111e},
- {0x0000a0cc, 0x111b111c},
- {0x0000a0d0, 0x22032204},
- {0x0000a0d4, 0x22012202},
- {0x0000a0d8, 0x221f2200},
- {0x0000a0dc, 0x221d221e},
- {0x0000a0e0, 0x33013302},
- {0x0000a0e4, 0x331f3300},
- {0x0000a0e8, 0x4402331e},
- {0x0000a0ec, 0x44004401},
- {0x0000a0f0, 0x441e441f},
- {0x0000a0f4, 0x55015502},
- {0x0000a0f8, 0x551f5500},
- {0x0000a0fc, 0x6602551e},
- {0x0000a100, 0x66006601},
- {0x0000a104, 0x661e661f},
- {0x0000a108, 0x7703661d},
- {0x0000a10c, 0x77017702},
- {0x0000a110, 0x00007700},
- {0x0000a114, 0x00000000},
- {0x0000a118, 0x00000000},
- {0x0000a11c, 0x00000000},
- {0x0000a120, 0x00000000},
- {0x0000a124, 0x00000000},
- {0x0000a128, 0x00000000},
- {0x0000a12c, 0x00000000},
- {0x0000a130, 0x00000000},
- {0x0000a134, 0x00000000},
- {0x0000a138, 0x00000000},
- {0x0000a13c, 0x00000000},
- {0x0000a140, 0x001f0000},
- {0x0000a144, 0x111f1100},
- {0x0000a148, 0x111d111e},
- {0x0000a14c, 0x111b111c},
- {0x0000a150, 0x22032204},
- {0x0000a154, 0x22012202},
- {0x0000a158, 0x221f2200},
- {0x0000a15c, 0x221d221e},
- {0x0000a160, 0x33013302},
- {0x0000a164, 0x331f3300},
- {0x0000a168, 0x4402331e},
- {0x0000a16c, 0x44004401},
- {0x0000a170, 0x441e441f},
- {0x0000a174, 0x55015502},
- {0x0000a178, 0x551f5500},
- {0x0000a17c, 0x6602551e},
- {0x0000a180, 0x66006601},
- {0x0000a184, 0x661e661f},
- {0x0000a188, 0x7703661d},
- {0x0000a18c, 0x77017702},
- {0x0000a190, 0x00007700},
- {0x0000a194, 0x00000000},
- {0x0000a198, 0x00000000},
- {0x0000a19c, 0x00000000},
- {0x0000a1a0, 0x00000000},
- {0x0000a1a4, 0x00000000},
- {0x0000a1a8, 0x00000000},
- {0x0000a1ac, 0x00000000},
- {0x0000a1b0, 0x00000000},
- {0x0000a1b4, 0x00000000},
- {0x0000a1b8, 0x00000000},
- {0x0000a1bc, 0x00000000},
- {0x0000a1c0, 0x00000000},
- {0x0000a1c4, 0x00000000},
- {0x0000a1c8, 0x00000000},
- {0x0000a1cc, 0x00000000},
- {0x0000a1d0, 0x00000000},
- {0x0000a1d4, 0x00000000},
- {0x0000a1d8, 0x00000000},
- {0x0000a1dc, 0x00000000},
- {0x0000a1e0, 0x00000000},
- {0x0000a1e4, 0x00000000},
- {0x0000a1e8, 0x00000000},
- {0x0000a1ec, 0x00000000},
- {0x0000a1f0, 0x00000396},
- {0x0000a1f4, 0x00000396},
- {0x0000a1f8, 0x00000396},
- {0x0000a1fc, 0x00000296},
-};
+#define ar9331_common_wo_xlna_rx_gain_1p2 ar9331_common_wo_xlna_rx_gain_1p1
+
+#define ar9331_common_rx_gain_1p2 ar9485_common_rx_gain_1_1
#endif /* INITVALS_9330_1P2_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h
index 815a8af1beef..1d8235e19f0f 100644
--- a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2011 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -18,16 +19,16 @@
#define INITVALS_9340_H
static const u32 ar9340_1p0_radio_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x000160ac, 0xa4646800, 0xa4646800, 0xa4646800, 0xa4646800},
- {0x0001610c, 0x08000000, 0x08000000, 0x00000000, 0x00000000},
+ {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
{0x00016140, 0x10804000, 0x10804000, 0x50804000, 0x50804000},
- {0x0001650c, 0x08000000, 0x08000000, 0x00000000, 0x00000000},
+ {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
{0x00016540, 0x10804000, 0x10804000, 0x50804000, 0x50804000},
};
static const u32 ar9340Modes_lowest_ob_db_tx_gain_table_1p0[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
@@ -99,21 +100,10 @@ static const u32 ar9340Modes_lowest_ob_db_tx_gain_table_1p0[][5] = {
{0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
};
-static const u32 ar9340Modes_fast_clock_1p0[][3] = {
- /* Addr 5G_HT20 5G_HT40 */
- {0x00001030, 0x00000268, 0x000004d0},
- {0x00001070, 0x0000018c, 0x00000318},
- {0x000010b0, 0x00000fd0, 0x00001fa0},
- {0x00008014, 0x044c044c, 0x08980898},
- {0x0000801c, 0x148ec02b, 0x148ec057},
- {0x00008318, 0x000044c0, 0x00008980},
- {0x00009e00, 0x03721821, 0x03721821},
- {0x0000a230, 0x0000000b, 0x00000016},
- {0x0000a254, 0x00000898, 0x00001130},
-};
+#define ar9340Modes_fast_clock_1p0 ar9300Modes_fast_clock_2p2
static const u32 ar9340_1p0_radio_core[][2] = {
- /* Addr allmodes */
+ /* Addr allmodes */
{0x00016000, 0x36db6db6},
{0x00016004, 0x6db6db40},
{0x00016008, 0x73f00000},
@@ -146,15 +136,13 @@ static const u32 ar9340_1p0_radio_core[][2] = {
{0x00016100, 0x04cb0001},
{0x00016104, 0xfff80000},
{0x00016108, 0x00080010},
- {0x0001610c, 0x00000000},
{0x00016140, 0x50804008},
{0x00016144, 0x01884080},
{0x00016148, 0x000080c0},
{0x00016280, 0x01000015},
- {0x00016284, 0x05530000},
+ {0x00016284, 0x15530000},
{0x00016288, 0x00318000},
{0x0001628c, 0x50000000},
- {0x00016290, 0x4080294f},
{0x00016380, 0x00000000},
{0x00016384, 0x00000000},
{0x00016388, 0x00800700},
@@ -219,52 +207,43 @@ static const u32 ar9340_1p0_radio_core[][2] = {
};
static const u32 ar9340_1p0_radio_core_40M[][2] = {
+ /* Addr allmodes */
{0x0001609c, 0x02566f3a},
{0x000160ac, 0xa4647c00},
{0x000160b0, 0x01885f5a},
};
-static const u32 ar9340_1p0_mac_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
- {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
- {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
-};
+#define ar9340_1p0_mac_postamble ar9300_2p2_mac_postamble
-static const u32 ar9340_1p0_soc_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
-};
+#define ar9340_1p0_soc_postamble ar9300_2p2_soc_postamble
static const u32 ar9340_1p0_baseband_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
{0x00009820, 0x206a022e, 0x206a022e, 0x206a022e, 0x206a022e},
{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
{0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
- {0x00009c00, 0x00000044, 0x000000c4, 0x000000c4, 0x00000044},
- {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
- {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+ {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+ {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+ {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e},
- {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+ {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
{0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
- {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
+ {0x0000a204, 0x00003ec0, 0x00003ec4, 0x00003ec4, 0x00003ec0},
{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+ {0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f},
{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
{0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
{0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
{0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
@@ -277,11 +256,11 @@ static const u32 ar9340_1p0_baseband_postamble[][5] = {
{0x0000a288, 0x00000220, 0x00000220, 0x00000110, 0x00000110},
{0x0000a28c, 0x00011111, 0x00011111, 0x00022222, 0x00022222},
{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
- {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982},
- {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+ {0x0000a2d0, 0x00041983, 0x00041983, 0x00041982, 0x00041982},
+ {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
- {0x0000ae04, 0x00180000, 0x00180000, 0x00180000, 0x00180000},
+ {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
{0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
{0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
@@ -289,21 +268,21 @@ static const u32 ar9340_1p0_baseband_postamble[][5] = {
};
static const u32 ar9340_1p0_baseband_core[][2] = {
- /* Addr allmodes */
+ /* Addr allmodes */
{0x00009800, 0xafe68e30},
{0x00009804, 0xfd14e000},
{0x00009808, 0x9c0a9f6b},
{0x0000980c, 0x04900000},
- {0x00009814, 0xb280c00a},
+ {0x00009814, 0x3280c00a},
{0x00009818, 0x00000000},
{0x0000981c, 0x00020028},
- {0x00009834, 0x5f3ca3de},
+ {0x00009834, 0x6400a190},
{0x00009838, 0x0108ecff},
- {0x0000983c, 0x14750600},
+ {0x0000983c, 0x14000600},
{0x00009880, 0x201fff00},
{0x00009884, 0x00001042},
{0x000098a4, 0x00200400},
- {0x000098b0, 0x52440bbe},
+ {0x000098b0, 0x32840bbe},
{0x000098d0, 0x004b6a8e},
{0x000098d4, 0x00000820},
{0x000098dc, 0x00000000},
@@ -329,7 +308,6 @@ static const u32 ar9340_1p0_baseband_core[][2] = {
{0x00009e30, 0x06336f77},
{0x00009e34, 0x6af6532f},
{0x00009e38, 0x0cc80c00},
- {0x00009e3c, 0xcf946222},
{0x00009e40, 0x0d261820},
{0x00009e4c, 0x00001004},
{0x00009e50, 0x00ff03f1},
@@ -342,8 +320,6 @@ static const u32 ar9340_1p0_baseband_core[][2] = {
{0x0000a220, 0x00000000},
{0x0000a224, 0x00000000},
{0x0000a228, 0x10002310},
- {0x0000a22c, 0x01036a1e},
- {0x0000a234, 0x10000fff},
{0x0000a23c, 0x00000000},
{0x0000a244, 0x0c000000},
{0x0000a2a0, 0x00000001},
@@ -351,10 +327,6 @@ static const u32 ar9340_1p0_baseband_core[][2] = {
{0x0000a2c8, 0x00000000},
{0x0000a2cc, 0x18c43433},
{0x0000a2d4, 0x00000000},
- {0x0000a2dc, 0x00000000},
- {0x0000a2e0, 0x00000000},
- {0x0000a2e4, 0x00000000},
- {0x0000a2e8, 0x00000000},
{0x0000a2ec, 0x00000000},
{0x0000a2f0, 0x00000000},
{0x0000a2f4, 0x00000000},
@@ -385,7 +357,7 @@ static const u32 ar9340_1p0_baseband_core[][2] = {
{0x0000a3e8, 0x20202020},
{0x0000a3ec, 0x20202020},
{0x0000a3f0, 0x00000000},
- {0x0000a3f4, 0x00000246},
+ {0x0000a3f4, 0x00000000},
{0x0000a3f8, 0x0cdbd380},
{0x0000a3fc, 0x000f0f01},
{0x0000a400, 0x8fa91f01},
@@ -402,33 +374,17 @@ static const u32 ar9340_1p0_baseband_core[][2] = {
{0x0000a430, 0x1ce739ce},
{0x0000a434, 0x00000000},
{0x0000a438, 0x00001801},
- {0x0000a43c, 0x00000000},
+ {0x0000a43c, 0x00100000},
{0x0000a440, 0x00000000},
{0x0000a444, 0x00000000},
- {0x0000a448, 0x04000080},
+ {0x0000a448, 0x05000080},
{0x0000a44c, 0x00000001},
{0x0000a450, 0x00010000},
{0x0000a458, 0x00000000},
- {0x0000a600, 0x00000000},
- {0x0000a604, 0x00000000},
- {0x0000a608, 0x00000000},
- {0x0000a60c, 0x00000000},
- {0x0000a610, 0x00000000},
- {0x0000a614, 0x00000000},
- {0x0000a618, 0x00000000},
- {0x0000a61c, 0x00000000},
- {0x0000a620, 0x00000000},
- {0x0000a624, 0x00000000},
- {0x0000a628, 0x00000000},
- {0x0000a62c, 0x00000000},
- {0x0000a630, 0x00000000},
- {0x0000a634, 0x00000000},
- {0x0000a638, 0x00000000},
- {0x0000a63c, 0x00000000},
{0x0000a640, 0x00000000},
{0x0000a644, 0x3fad9d74},
{0x0000a648, 0x0048060a},
- {0x0000a64c, 0x00000637},
+ {0x0000a64c, 0x00003c37},
{0x0000a670, 0x03020100},
{0x0000a674, 0x09080504},
{0x0000a678, 0x0d0c0b0a},
@@ -451,10 +407,6 @@ static const u32 ar9340_1p0_baseband_core[][2] = {
{0x0000a8f4, 0x00000000},
{0x0000b2d0, 0x00000080},
{0x0000b2d4, 0x00000000},
- {0x0000b2dc, 0x00000000},
- {0x0000b2e0, 0x00000000},
- {0x0000b2e4, 0x00000000},
- {0x0000b2e8, 0x00000000},
{0x0000b2ec, 0x00000000},
{0x0000b2f0, 0x00000000},
{0x0000b2f4, 0x00000000},
@@ -465,80 +417,108 @@ static const u32 ar9340_1p0_baseband_core[][2] = {
};
static const u32 ar9340Modes_high_power_tx_gain_table_1p0[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+ {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+ {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
{0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
- {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
- {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
- {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
- {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
- {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
- {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
- {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
- {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
- {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
- {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
- {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
- {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
- {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
- {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
- {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
- {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
- {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
- {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
- {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83},
- {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
- {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
- {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
- {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
- {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
- {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a504, 0x04002222, 0x04002222, 0x02000001, 0x02000001},
+ {0x0000a508, 0x09002421, 0x09002421, 0x05000003, 0x05000003},
+ {0x0000a50c, 0x0d002621, 0x0d002621, 0x0a000005, 0x0a000005},
+ {0x0000a510, 0x13004620, 0x13004620, 0x0e000201, 0x0e000201},
+ {0x0000a514, 0x19004a20, 0x19004a20, 0x11000203, 0x11000203},
+ {0x0000a518, 0x1d004e20, 0x1d004e20, 0x14000401, 0x14000401},
+ {0x0000a51c, 0x21005420, 0x21005420, 0x18000403, 0x18000403},
+ {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000602, 0x1b000602},
+ {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000802, 0x1f000802},
+ {0x0000a528, 0x2f005e42, 0x2f005e42, 0x21000620, 0x21000620},
+ {0x0000a52c, 0x33005e44, 0x33005e44, 0x25000820, 0x25000820},
+ {0x0000a530, 0x38005e65, 0x38005e65, 0x29000822, 0x29000822},
+ {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2d000824, 0x2d000824},
+ {0x0000a538, 0x40005e6b, 0x40005e6b, 0x30000828, 0x30000828},
+ {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x3400082a, 0x3400082a},
+ {0x0000a540, 0x49005e72, 0x49005e72, 0x38000849, 0x38000849},
+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b000a2c, 0x3b000a2c},
+ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e000e2b, 0x3e000e2b},
+ {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42000e2d, 0x42000e2d},
+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x4500124a, 0x4500124a},
+ {0x0000a554, 0x61027f12, 0x61027f12, 0x4900124c, 0x4900124c},
+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c00126c, 0x4c00126c},
+ {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x4f00128c, 0x4f00128c},
+ {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x52001290, 0x52001290},
+ {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001292, 0x56001292},
+ {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001292, 0x56001292},
+ {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001292, 0x56001292},
+ {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001292, 0x56001292},
+ {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001292, 0x56001292},
+ {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001292, 0x56001292},
+ {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001292, 0x56001292},
{0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
- {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
- {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
- {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
- {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
- {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
- {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
- {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
- {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
- {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
- {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
- {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
- {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
- {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
- {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
- {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
- {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
- {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
- {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
- {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
- {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
- {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
- {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
- {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
- {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
- {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db},
+ {0x0000a584, 0x04802222, 0x04802222, 0x02800001, 0x02800001},
+ {0x0000a588, 0x09802421, 0x09802421, 0x05800003, 0x05800003},
+ {0x0000a58c, 0x0d802621, 0x0d802621, 0x0a800005, 0x0a800005},
+ {0x0000a590, 0x13804620, 0x13804620, 0x0e800201, 0x0e800201},
+ {0x0000a594, 0x19804a20, 0x19804a20, 0x11800203, 0x11800203},
+ {0x0000a598, 0x1d804e20, 0x1d804e20, 0x14800401, 0x14800401},
+ {0x0000a59c, 0x21805420, 0x21805420, 0x18800403, 0x18800403},
+ {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800602, 0x1b800602},
+ {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800802, 0x1f800802},
+ {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x21800620, 0x21800620},
+ {0x0000a5ac, 0x33805e44, 0x33805e44, 0x25800820, 0x25800820},
+ {0x0000a5b0, 0x38805e65, 0x38805e65, 0x29800822, 0x29800822},
+ {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2d800824, 0x2d800824},
+ {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x30800828, 0x30800828},
+ {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x3480082a, 0x3480082a},
+ {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38800849, 0x38800849},
+ {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b800a2c, 0x3b800a2c},
+ {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e800e2b, 0x3e800e2b},
+ {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42800e2d, 0x42800e2d},
+ {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x4580124a, 0x4580124a},
+ {0x0000a5d4, 0x61827f12, 0x61827f12, 0x4980124c, 0x4980124c},
+ {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c80126c, 0x4c80126c},
+ {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x4f80128c, 0x4f80128c},
+ {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x52801290, 0x52801290},
+ {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801292, 0x56801292},
+ {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801292, 0x56801292},
+ {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801292, 0x56801292},
+ {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801292, 0x56801292},
+ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801292, 0x56801292},
+ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801292, 0x56801292},
+ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801292, 0x56801292},
+ {0x00016044, 0x056db2db, 0x056db2db, 0x022492db, 0x022492db},
{0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
- {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db},
+ {0x00016444, 0x056db2db, 0x056db2db, 0x022492db, 0x022492db},
{0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
};
static const u32 ar9340Modes_high_ob_db_tx_gain_table_1p0[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
{0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
{0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
@@ -559,7 +539,7 @@ static const u32 ar9340Modes_high_ob_db_tx_gain_table_1p0[][5] = {
{0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
{0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
{0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
- {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83},
+ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
{0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
{0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
{0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
@@ -604,13 +584,43 @@ static const u32 ar9340Modes_high_ob_db_tx_gain_table_1p0[][5] = {
{0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
{0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
{0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
{0x00016044, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4},
- {0x00016048, 0x8e481266, 0x8e481266, 0x8e481266, 0x8e481266},
+ {0x00016048, 0x8e481666, 0x8e481666, 0x8e481266, 0x8e481266},
+ {0x00016280, 0x01000015, 0x01000015, 0x01001015, 0x01001015},
{0x00016444, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4},
- {0x00016448, 0x8e481266, 0x8e481266, 0x8e481266, 0x8e481266},
+ {0x00016448, 0x8e481666, 0x8e481666, 0x8e481266, 0x8e481266},
};
+
static const u32 ar9340Modes_ub124_tx_gain_table_1p0[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+ {0x00009820, 0x206a022e, 0x206a022e, 0x206a00ae, 0x206a00ae},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+ {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec82d2e, 0x7ec82d2e},
+ {0x0000a2dc, 0xfef5d402, 0xfef5d402, 0xfdab5b52, 0xfdab5b52},
+ {0x0000a2e0, 0xfe896600, 0xfe896600, 0xfd339c84, 0xfd339c84},
+ {0x0000a2e4, 0xff01f800, 0xff01f800, 0xfec3e000, 0xfec3e000},
+ {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffc0000, 0xfffc0000},
{0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
{0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
@@ -676,15 +686,34 @@ static const u32 ar9340Modes_ub124_tx_gain_table_1p0[][5] = {
{0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
{0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
{0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x00016044, 0x036db2db, 0x036db2db, 0x036db2db, 0x036db2db},
- {0x00016048, 0x69b65266, 0x69b65266, 0x69b65266, 0x69b65266},
- {0x00016444, 0x036db2db, 0x036db2db, 0x036db2db, 0x036db2db},
- {0x00016448, 0x69b65266, 0x69b65266, 0x69b65266, 0x69b65266},
+ {0x00016044, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4},
+ {0x00016048, 0x8e480086, 0x8e480086, 0x8e480086, 0x8e480086},
+ {0x00016444, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4},
+ {0x00016448, 0x8e480086, 0x8e480086, 0x8e480086, 0x8e480086},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0xfef5d402, 0xfef5d402, 0xfdab5b52, 0xfdab5b52},
+ {0x0000b2e0, 0xfe896600, 0xfe896600, 0xfd339c84, 0xfd339c84},
+ {0x0000b2e4, 0xff01f800, 0xff01f800, 0xfec3e000, 0xfec3e000},
+ {0x0000b2e8, 0xfffe0000, 0xfffe0000, 0xfffc0000, 0xfffc0000},
};
-
static const u32 ar9340Common_rx_gain_table_1p0[][2] = {
- /* Addr allmodes */
+ /* Addr allmodes */
{0x0000a000, 0x00010000},
{0x0000a004, 0x00030002},
{0x0000a008, 0x00050004},
@@ -845,14 +874,14 @@ static const u32 ar9340Common_rx_gain_table_1p0[][2] = {
{0x0000b074, 0x00000000},
{0x0000b078, 0x00000000},
{0x0000b07c, 0x00000000},
- {0x0000b080, 0x32323232},
- {0x0000b084, 0x2f2f3232},
- {0x0000b088, 0x23282a2d},
- {0x0000b08c, 0x1c1e2123},
- {0x0000b090, 0x14171919},
- {0x0000b094, 0x0e0e1214},
- {0x0000b098, 0x03050707},
- {0x0000b09c, 0x00030303},
+ {0x0000b080, 0x23232323},
+ {0x0000b084, 0x21232323},
+ {0x0000b088, 0x19191c1e},
+ {0x0000b08c, 0x12141417},
+ {0x0000b090, 0x07070e0e},
+ {0x0000b094, 0x03030305},
+ {0x0000b098, 0x00000003},
+ {0x0000b09c, 0x00000000},
{0x0000b0a0, 0x00000000},
{0x0000b0a4, 0x00000000},
{0x0000b0a8, 0x00000000},
@@ -944,7 +973,11 @@ static const u32 ar9340Common_rx_gain_table_1p0[][2] = {
};
static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
@@ -952,8 +985,8 @@ static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = {
{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
{0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
{0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
- {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
- {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
+ {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
+ {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
{0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
{0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
{0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
@@ -965,19 +998,19 @@ static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = {
{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
{0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
{0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
- {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
- {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
- {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
- {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
- {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
- {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
- {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83},
+ {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84},
+ {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3},
+ {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5},
+ {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9},
+ {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
@@ -1010,14 +1043,40 @@ static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = {
{0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
{0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
{0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+ {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+ {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
{0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db},
- {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
+ {0x00016048, 0x24925666, 0x24925666, 0x24925266, 0x24925266},
+ {0x00016280, 0x01000015, 0x01000015, 0x01001015, 0x01001015},
+ {0x00016288, 0xf0318000, 0xf0318000, 0xf0318000, 0xf0318000},
{0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db},
- {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
+ {0x00016448, 0x24925666, 0x24925666, 0x24925266, 0x24925266},
};
static const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
@@ -1025,8 +1084,8 @@ static const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = {
{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
{0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
{0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400},
- {0x0000a518, 0x21020220, 0x21020220, 0x15000402, 0x15000402},
- {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
+ {0x0000a518, 0x21002220, 0x21002220, 0x15000402, 0x15000402},
+ {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
{0x0000a520, 0x2b022220, 0x2b022220, 0x1b000603, 0x1b000603},
{0x0000a524, 0x2f022222, 0x2f022222, 0x1f000a02, 0x1f000a02},
{0x0000a528, 0x34022225, 0x34022225, 0x23000a04, 0x23000a04},
@@ -1038,19 +1097,19 @@ static const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = {
{0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660},
{0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861},
{0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81},
- {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x42001a83, 0x42001a83},
- {0x0000a550, 0x61042a6c, 0x61042a6c, 0x44001c84, 0x44001c84},
- {0x0000a554, 0x66062a6c, 0x66062a6c, 0x48001ce3, 0x48001ce3},
- {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x4c001ce5, 0x4c001ce5},
- {0x0000a55c, 0x7006308c, 0x7006308c, 0x50001ce9, 0x50001ce9},
- {0x0000a560, 0x730a308a, 0x730a308a, 0x54001ceb, 0x54001ceb},
- {0x0000a564, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec},
- {0x0000a568, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec},
- {0x0000a56c, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec},
- {0x0000a570, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec},
- {0x0000a574, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec},
- {0x0000a578, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec},
- {0x0000a57c, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec},
+ {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x61024a6c, 0x61024a6c, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x66026a6c, 0x66026a6c, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a55c, 0x7002708c, 0x7002708c, 0x50001ce9, 0x50001ce9},
+ {0x0000a560, 0x7302b08a, 0x7302b08a, 0x54001ceb, 0x54001ceb},
+ {0x0000a564, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+ {0x0000a568, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+ {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+ {0x0000a570, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+ {0x0000a574, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+ {0x0000a578, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+ {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
@@ -1083,14 +1142,36 @@ static const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = {
{0x0000a5f4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
{0x0000a5f8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
{0x0000a5fc, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+ {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+ {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
{0x00016044, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4},
- {0x00016048, 0x24927266, 0x24927266, 0x8e483266, 0x8e483266},
+ {0x00016048, 0x24925666, 0x24925666, 0x8e481266, 0x8e481266},
+ {0x00016280, 0x01000015, 0x01000015, 0x01001015, 0x01001015},
+ {0x00016288, 0x30318000, 0x30318000, 0x00318000, 0x00318000},
{0x00016444, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4},
- {0x00016448, 0x24927266, 0x24927266, 0x8e482266, 0x8e482266},
+ {0x00016448, 0x24925666, 0x24925666, 0x8e481266, 0x8e481266},
};
static const u32 ar9340_1p0_mac_core[][2] = {
- /* Addr allmodes */
+ /* Addr allmodes */
{0x00000008, 0x00000000},
{0x00000030, 0x00020085},
{0x00000034, 0x00000005},
@@ -1119,6 +1200,7 @@ static const u32 ar9340_1p0_mac_core[][2] = {
{0x00008004, 0x00000000},
{0x00008008, 0x00000000},
{0x0000800c, 0x00000000},
+ {0x00008010, 0x00080800},
{0x00008018, 0x00000000},
{0x00008020, 0x00000000},
{0x00008038, 0x00000000},
@@ -1146,7 +1228,7 @@ static const u32 ar9340_1p0_mac_core[][2] = {
{0x000080bc, 0x00000000},
{0x000080c0, 0x2a800000},
{0x000080c4, 0x06900168},
- {0x000080c8, 0x13881c20},
+ {0x000080c8, 0x13881c22},
{0x000080cc, 0x01f40000},
{0x000080d0, 0x00252500},
{0x000080d4, 0x00a00000},
@@ -1250,276 +1332,17 @@ static const u32 ar9340_1p0_mac_core[][2] = {
{0x000083c4, 0x00000000},
{0x000083c8, 0x00000000},
{0x000083cc, 0x00000200},
- {0x000083d0, 0x000301ff},
+ {0x000083d0, 0x000101ff},
};
-static const u32 ar9340Common_wo_xlna_rx_gain_table_1p0[][2] = {
- /* Addr allmodes */
- {0x0000a000, 0x00010000},
- {0x0000a004, 0x00030002},
- {0x0000a008, 0x00050004},
- {0x0000a00c, 0x00810080},
- {0x0000a010, 0x00830082},
- {0x0000a014, 0x01810180},
- {0x0000a018, 0x01830182},
- {0x0000a01c, 0x01850184},
- {0x0000a020, 0x01890188},
- {0x0000a024, 0x018b018a},
- {0x0000a028, 0x018d018c},
- {0x0000a02c, 0x03820190},
- {0x0000a030, 0x03840383},
- {0x0000a034, 0x03880385},
- {0x0000a038, 0x038a0389},
- {0x0000a03c, 0x038c038b},
- {0x0000a040, 0x0390038d},
- {0x0000a044, 0x03920391},
- {0x0000a048, 0x03940393},
- {0x0000a04c, 0x03960395},
- {0x0000a050, 0x00000000},
- {0x0000a054, 0x00000000},
- {0x0000a058, 0x00000000},
- {0x0000a05c, 0x00000000},
- {0x0000a060, 0x00000000},
- {0x0000a064, 0x00000000},
- {0x0000a068, 0x00000000},
- {0x0000a06c, 0x00000000},
- {0x0000a070, 0x00000000},
- {0x0000a074, 0x00000000},
- {0x0000a078, 0x00000000},
- {0x0000a07c, 0x00000000},
- {0x0000a080, 0x29292929},
- {0x0000a084, 0x29292929},
- {0x0000a088, 0x29292929},
- {0x0000a08c, 0x29292929},
- {0x0000a090, 0x22292929},
- {0x0000a094, 0x1d1d2222},
- {0x0000a098, 0x0c111117},
- {0x0000a09c, 0x00030303},
- {0x0000a0a0, 0x00000000},
- {0x0000a0a4, 0x00000000},
- {0x0000a0a8, 0x00000000},
- {0x0000a0ac, 0x00000000},
- {0x0000a0b0, 0x00000000},
- {0x0000a0b4, 0x00000000},
- {0x0000a0b8, 0x00000000},
- {0x0000a0bc, 0x00000000},
- {0x0000a0c0, 0x001f0000},
- {0x0000a0c4, 0x01000101},
- {0x0000a0c8, 0x011e011f},
- {0x0000a0cc, 0x011c011d},
- {0x0000a0d0, 0x02030204},
- {0x0000a0d4, 0x02010202},
- {0x0000a0d8, 0x021f0200},
- {0x0000a0dc, 0x0302021e},
- {0x0000a0e0, 0x03000301},
- {0x0000a0e4, 0x031e031f},
- {0x0000a0e8, 0x0402031d},
- {0x0000a0ec, 0x04000401},
- {0x0000a0f0, 0x041e041f},
- {0x0000a0f4, 0x0502041d},
- {0x0000a0f8, 0x05000501},
- {0x0000a0fc, 0x051e051f},
- {0x0000a100, 0x06010602},
- {0x0000a104, 0x061f0600},
- {0x0000a108, 0x061d061e},
- {0x0000a10c, 0x07020703},
- {0x0000a110, 0x07000701},
- {0x0000a114, 0x00000000},
- {0x0000a118, 0x00000000},
- {0x0000a11c, 0x00000000},
- {0x0000a120, 0x00000000},
- {0x0000a124, 0x00000000},
- {0x0000a128, 0x00000000},
- {0x0000a12c, 0x00000000},
- {0x0000a130, 0x00000000},
- {0x0000a134, 0x00000000},
- {0x0000a138, 0x00000000},
- {0x0000a13c, 0x00000000},
- {0x0000a140, 0x001f0000},
- {0x0000a144, 0x01000101},
- {0x0000a148, 0x011e011f},
- {0x0000a14c, 0x011c011d},
- {0x0000a150, 0x02030204},
- {0x0000a154, 0x02010202},
- {0x0000a158, 0x021f0200},
- {0x0000a15c, 0x0302021e},
- {0x0000a160, 0x03000301},
- {0x0000a164, 0x031e031f},
- {0x0000a168, 0x0402031d},
- {0x0000a16c, 0x04000401},
- {0x0000a170, 0x041e041f},
- {0x0000a174, 0x0502041d},
- {0x0000a178, 0x05000501},
- {0x0000a17c, 0x051e051f},
- {0x0000a180, 0x06010602},
- {0x0000a184, 0x061f0600},
- {0x0000a188, 0x061d061e},
- {0x0000a18c, 0x07020703},
- {0x0000a190, 0x07000701},
- {0x0000a194, 0x00000000},
- {0x0000a198, 0x00000000},
- {0x0000a19c, 0x00000000},
- {0x0000a1a0, 0x00000000},
- {0x0000a1a4, 0x00000000},
- {0x0000a1a8, 0x00000000},
- {0x0000a1ac, 0x00000000},
- {0x0000a1b0, 0x00000000},
- {0x0000a1b4, 0x00000000},
- {0x0000a1b8, 0x00000000},
- {0x0000a1bc, 0x00000000},
- {0x0000a1c0, 0x00000000},
- {0x0000a1c4, 0x00000000},
- {0x0000a1c8, 0x00000000},
- {0x0000a1cc, 0x00000000},
- {0x0000a1d0, 0x00000000},
- {0x0000a1d4, 0x00000000},
- {0x0000a1d8, 0x00000000},
- {0x0000a1dc, 0x00000000},
- {0x0000a1e0, 0x00000000},
- {0x0000a1e4, 0x00000000},
- {0x0000a1e8, 0x00000000},
- {0x0000a1ec, 0x00000000},
- {0x0000a1f0, 0x00000396},
- {0x0000a1f4, 0x00000396},
- {0x0000a1f8, 0x00000396},
- {0x0000a1fc, 0x00000196},
- {0x0000b000, 0x00010000},
- {0x0000b004, 0x00030002},
- {0x0000b008, 0x00050004},
- {0x0000b00c, 0x00810080},
- {0x0000b010, 0x00830082},
- {0x0000b014, 0x01810180},
- {0x0000b018, 0x01830182},
- {0x0000b01c, 0x01850184},
- {0x0000b020, 0x02810280},
- {0x0000b024, 0x02830282},
- {0x0000b028, 0x02850284},
- {0x0000b02c, 0x02890288},
- {0x0000b030, 0x028b028a},
- {0x0000b034, 0x0388028c},
- {0x0000b038, 0x038a0389},
- {0x0000b03c, 0x038c038b},
- {0x0000b040, 0x0390038d},
- {0x0000b044, 0x03920391},
- {0x0000b048, 0x03940393},
- {0x0000b04c, 0x03960395},
- {0x0000b050, 0x00000000},
- {0x0000b054, 0x00000000},
- {0x0000b058, 0x00000000},
- {0x0000b05c, 0x00000000},
- {0x0000b060, 0x00000000},
- {0x0000b064, 0x00000000},
- {0x0000b068, 0x00000000},
- {0x0000b06c, 0x00000000},
- {0x0000b070, 0x00000000},
- {0x0000b074, 0x00000000},
- {0x0000b078, 0x00000000},
- {0x0000b07c, 0x00000000},
- {0x0000b080, 0x32323232},
- {0x0000b084, 0x2f2f3232},
- {0x0000b088, 0x23282a2d},
- {0x0000b08c, 0x1c1e2123},
- {0x0000b090, 0x14171919},
- {0x0000b094, 0x0e0e1214},
- {0x0000b098, 0x03050707},
- {0x0000b09c, 0x00030303},
- {0x0000b0a0, 0x00000000},
- {0x0000b0a4, 0x00000000},
- {0x0000b0a8, 0x00000000},
- {0x0000b0ac, 0x00000000},
- {0x0000b0b0, 0x00000000},
- {0x0000b0b4, 0x00000000},
- {0x0000b0b8, 0x00000000},
- {0x0000b0bc, 0x00000000},
- {0x0000b0c0, 0x003f0020},
- {0x0000b0c4, 0x00400041},
- {0x0000b0c8, 0x0140005f},
- {0x0000b0cc, 0x0160015f},
- {0x0000b0d0, 0x017e017f},
- {0x0000b0d4, 0x02410242},
- {0x0000b0d8, 0x025f0240},
- {0x0000b0dc, 0x027f0260},
- {0x0000b0e0, 0x0341027e},
- {0x0000b0e4, 0x035f0340},
- {0x0000b0e8, 0x037f0360},
- {0x0000b0ec, 0x04400441},
- {0x0000b0f0, 0x0460045f},
- {0x0000b0f4, 0x0541047f},
- {0x0000b0f8, 0x055f0540},
- {0x0000b0fc, 0x057f0560},
- {0x0000b100, 0x06400641},
- {0x0000b104, 0x0660065f},
- {0x0000b108, 0x067e067f},
- {0x0000b10c, 0x07410742},
- {0x0000b110, 0x075f0740},
- {0x0000b114, 0x077f0760},
- {0x0000b118, 0x07800781},
- {0x0000b11c, 0x07a0079f},
- {0x0000b120, 0x07c107bf},
- {0x0000b124, 0x000007c0},
- {0x0000b128, 0x00000000},
- {0x0000b12c, 0x00000000},
- {0x0000b130, 0x00000000},
- {0x0000b134, 0x00000000},
- {0x0000b138, 0x00000000},
- {0x0000b13c, 0x00000000},
- {0x0000b140, 0x003f0020},
- {0x0000b144, 0x00400041},
- {0x0000b148, 0x0140005f},
- {0x0000b14c, 0x0160015f},
- {0x0000b150, 0x017e017f},
- {0x0000b154, 0x02410242},
- {0x0000b158, 0x025f0240},
- {0x0000b15c, 0x027f0260},
- {0x0000b160, 0x0341027e},
- {0x0000b164, 0x035f0340},
- {0x0000b168, 0x037f0360},
- {0x0000b16c, 0x04400441},
- {0x0000b170, 0x0460045f},
- {0x0000b174, 0x0541047f},
- {0x0000b178, 0x055f0540},
- {0x0000b17c, 0x057f0560},
- {0x0000b180, 0x06400641},
- {0x0000b184, 0x0660065f},
- {0x0000b188, 0x067e067f},
- {0x0000b18c, 0x07410742},
- {0x0000b190, 0x075f0740},
- {0x0000b194, 0x077f0760},
- {0x0000b198, 0x07800781},
- {0x0000b19c, 0x07a0079f},
- {0x0000b1a0, 0x07c107bf},
- {0x0000b1a4, 0x000007c0},
- {0x0000b1a8, 0x00000000},
- {0x0000b1ac, 0x00000000},
- {0x0000b1b0, 0x00000000},
- {0x0000b1b4, 0x00000000},
- {0x0000b1b8, 0x00000000},
- {0x0000b1bc, 0x00000000},
- {0x0000b1c0, 0x00000000},
- {0x0000b1c4, 0x00000000},
- {0x0000b1c8, 0x00000000},
- {0x0000b1cc, 0x00000000},
- {0x0000b1d0, 0x00000000},
- {0x0000b1d4, 0x00000000},
- {0x0000b1d8, 0x00000000},
- {0x0000b1dc, 0x00000000},
- {0x0000b1e0, 0x00000000},
- {0x0000b1e4, 0x00000000},
- {0x0000b1e8, 0x00000000},
- {0x0000b1ec, 0x00000000},
- {0x0000b1f0, 0x00000396},
- {0x0000b1f4, 0x00000396},
- {0x0000b1f8, 0x00000396},
- {0x0000b1fc, 0x00000196},
-};
+#define ar9340Common_wo_xlna_rx_gain_table_1p0 ar9300Common_wo_xlna_rx_gain_table_2p2
static const u32 ar9340_1p0_soc_preamble[][2] = {
- /* Addr allmodes */
- {0x000040a4, 0x00a0c1c9},
+ /* Addr allmodes */
{0x00007008, 0x00000000},
{0x00007020, 0x00000000},
{0x00007034, 0x00000002},
{0x00007038, 0x000004c2},
};
-#endif
+#endif /* INITVALS_9340_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
index 4a93e1534c1d..4ef7dcccaa2f 100644
--- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -52,7 +53,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
{0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8},
{0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e},
- {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x33795d5e},
+ {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x32395d5e},
{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
@@ -61,7 +62,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
{0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
- {0x0000a204, 0x013187c0, 0x013187c4, 0x013187c4, 0x013187c0},
+ {0x0000a204, 0x01318fc0, 0x01318fc4, 0x01318fc4, 0x01318fc0},
{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
{0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f},
{0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
@@ -1007,7 +1008,7 @@ static const u32 ar9462_2p0_radio_core[][2] = {
static const u32 ar9462_2p0_soc_preamble[][2] = {
/* Addr allmodes */
- {0x000040a4 ,0x00a0c1c9},
+ {0x000040a4, 0x00a0c1c9},
{0x00007020, 0x00000000},
{0x00007034, 0x00000002},
{0x00007038, 0x000004c2},
diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
index d16d029f81a9..fb4497fc7a3d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2010-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,360 +18,151 @@
#ifndef INITVALS_9485_H
#define INITVALS_9485_H
-static const u32 ar9485_1_1_mac_core[][2] = {
- /* Addr allmodes */
- {0x00000008, 0x00000000},
- {0x00000030, 0x00020085},
- {0x00000034, 0x00000005},
- {0x00000040, 0x00000000},
- {0x00000044, 0x00000000},
- {0x00000048, 0x00000008},
- {0x0000004c, 0x00000010},
- {0x00000050, 0x00000000},
- {0x00001040, 0x002ffc0f},
- {0x00001044, 0x002ffc0f},
- {0x00001048, 0x002ffc0f},
- {0x0000104c, 0x002ffc0f},
- {0x00001050, 0x002ffc0f},
- {0x00001054, 0x002ffc0f},
- {0x00001058, 0x002ffc0f},
- {0x0000105c, 0x002ffc0f},
- {0x00001060, 0x002ffc0f},
- {0x00001064, 0x002ffc0f},
- {0x000010f0, 0x00000100},
- {0x00001270, 0x00000000},
- {0x000012b0, 0x00000000},
- {0x000012f0, 0x00000000},
- {0x0000143c, 0x00000000},
- {0x0000147c, 0x00000000},
- {0x00008000, 0x00000000},
- {0x00008004, 0x00000000},
- {0x00008008, 0x00000000},
- {0x0000800c, 0x00000000},
- {0x00008018, 0x00000000},
- {0x00008020, 0x00000000},
- {0x00008038, 0x00000000},
- {0x0000803c, 0x00000000},
- {0x00008040, 0x00000000},
- {0x00008044, 0x00000000},
- {0x00008048, 0x00000000},
- {0x0000804c, 0xffffffff},
- {0x00008054, 0x00000000},
- {0x00008058, 0x00000000},
- {0x0000805c, 0x000fc78f},
- {0x00008060, 0x0000000f},
- {0x00008064, 0x00000000},
- {0x00008070, 0x00000310},
- {0x00008074, 0x00000020},
- {0x00008078, 0x00000000},
- {0x0000809c, 0x0000000f},
- {0x000080a0, 0x00000000},
- {0x000080a4, 0x02ff0000},
- {0x000080a8, 0x0e070605},
- {0x000080ac, 0x0000000d},
- {0x000080b0, 0x00000000},
- {0x000080b4, 0x00000000},
- {0x000080b8, 0x00000000},
- {0x000080bc, 0x00000000},
- {0x000080c0, 0x2a800000},
- {0x000080c4, 0x06900168},
- {0x000080c8, 0x13881c22},
- {0x000080cc, 0x01f40000},
- {0x000080d0, 0x00252500},
- {0x000080d4, 0x00a00000},
- {0x000080d8, 0x00400000},
- {0x000080dc, 0x00000000},
- {0x000080e0, 0xffffffff},
- {0x000080e4, 0x0000ffff},
- {0x000080e8, 0x3f3f3f3f},
- {0x000080ec, 0x00000000},
- {0x000080f0, 0x00000000},
- {0x000080f4, 0x00000000},
- {0x000080fc, 0x00020000},
- {0x00008100, 0x00000000},
- {0x00008108, 0x00000052},
- {0x0000810c, 0x00000000},
- {0x00008110, 0x00000000},
- {0x00008114, 0x000007ff},
- {0x00008118, 0x000000aa},
- {0x0000811c, 0x00003210},
- {0x00008124, 0x00000000},
- {0x00008128, 0x00000000},
- {0x0000812c, 0x00000000},
- {0x00008130, 0x00000000},
- {0x00008134, 0x00000000},
- {0x00008138, 0x00000000},
- {0x0000813c, 0x0000ffff},
- {0x00008144, 0xffffffff},
- {0x00008168, 0x00000000},
- {0x0000816c, 0x00000000},
- {0x00008170, 0x18486200},
- {0x00008174, 0x33332210},
- {0x00008178, 0x00000000},
- {0x0000817c, 0x00020000},
- {0x000081c0, 0x00000000},
- {0x000081c4, 0x33332210},
- {0x000081d4, 0x00000000},
- {0x000081ec, 0x00000000},
- {0x000081f0, 0x00000000},
- {0x000081f4, 0x00000000},
- {0x000081f8, 0x00000000},
- {0x000081fc, 0x00000000},
- {0x00008240, 0x00100000},
- {0x00008244, 0x0010f400},
- {0x00008248, 0x00000800},
- {0x0000824c, 0x0001e800},
- {0x00008250, 0x00000000},
- {0x00008254, 0x00000000},
- {0x00008258, 0x00000000},
- {0x0000825c, 0x40000000},
- {0x00008260, 0x00080922},
- {0x00008264, 0x9ca00010},
- {0x00008268, 0xffffffff},
- {0x0000826c, 0x0000ffff},
- {0x00008270, 0x00000000},
- {0x00008274, 0x40000000},
- {0x00008278, 0x003e4180},
- {0x0000827c, 0x00000004},
- {0x00008284, 0x0000002c},
- {0x00008288, 0x0000002c},
- {0x0000828c, 0x000000ff},
- {0x00008294, 0x00000000},
- {0x00008298, 0x00000000},
- {0x0000829c, 0x00000000},
- {0x00008300, 0x00000140},
- {0x00008314, 0x00000000},
- {0x0000831c, 0x0000010d},
- {0x00008328, 0x00000000},
- {0x0000832c, 0x00000007},
- {0x00008330, 0x00000302},
- {0x00008334, 0x00000700},
- {0x00008338, 0x00ff0000},
- {0x0000833c, 0x02400000},
- {0x00008340, 0x000107ff},
- {0x00008344, 0xa248105b},
- {0x00008348, 0x008f0000},
- {0x0000835c, 0x00000000},
- {0x00008360, 0xffffffff},
- {0x00008364, 0xffffffff},
- {0x00008368, 0x00000000},
- {0x00008370, 0x00000000},
- {0x00008374, 0x000000ff},
- {0x00008378, 0x00000000},
- {0x0000837c, 0x00000000},
- {0x00008380, 0xffffffff},
- {0x00008384, 0xffffffff},
- {0x00008390, 0xffffffff},
- {0x00008394, 0xffffffff},
- {0x00008398, 0x00000000},
- {0x0000839c, 0x00000000},
- {0x000083a0, 0x00000000},
- {0x000083a4, 0x0000fa14},
- {0x000083a8, 0x000f0c00},
- {0x000083ac, 0x33332210},
- {0x000083b0, 0x33332210},
- {0x000083b4, 0x33332210},
- {0x000083b8, 0x33332210},
- {0x000083bc, 0x00000000},
- {0x000083c0, 0x00000000},
- {0x000083c4, 0x00000000},
- {0x000083c8, 0x00000000},
- {0x000083cc, 0x00000200},
- {0x000083d0, 0x000301ff},
-};
+/* AR9485 1.0 */
-static const u32 ar9485_1_1_baseband_core[][2] = {
- /* Addr allmodes */
- {0x00009800, 0xafe68e30},
- {0x00009804, 0xfd14e000},
- {0x00009808, 0x9c0a8f6b},
- {0x0000980c, 0x04800000},
- {0x00009814, 0x9280c00a},
- {0x00009818, 0x00000000},
- {0x0000981c, 0x00020028},
- {0x00009834, 0x5f3ca3de},
- {0x00009838, 0x0108ecff},
- {0x0000983c, 0x14750600},
- {0x00009880, 0x201fff00},
- {0x00009884, 0x00001042},
- {0x000098a4, 0x00200400},
- {0x000098b0, 0x52440bbe},
- {0x000098d0, 0x004b6a8e},
- {0x000098d4, 0x00000820},
- {0x000098dc, 0x00000000},
- {0x000098f0, 0x00000000},
- {0x000098f4, 0x00000000},
- {0x00009c04, 0x00000000},
- {0x00009c08, 0x03200000},
- {0x00009c0c, 0x00000000},
- {0x00009c10, 0x00000000},
- {0x00009c14, 0x00046384},
- {0x00009c18, 0x05b6b440},
- {0x00009c1c, 0x00b6b440},
- {0x00009d00, 0xc080a333},
- {0x00009d04, 0x40206c10},
- {0x00009d08, 0x009c4060},
- {0x00009d0c, 0x1883800a},
- {0x00009d10, 0x01834061},
- {0x00009d14, 0x00c00400},
- {0x00009d18, 0x00000000},
- {0x00009d1c, 0x00000000},
- {0x00009e08, 0x0038233c},
- {0x00009e24, 0x9927b515},
- {0x00009e28, 0x12ef0200},
- {0x00009e30, 0x06336f77},
- {0x00009e34, 0x6af6532f},
- {0x00009e38, 0x0cc80c00},
- {0x00009e40, 0x0d261820},
- {0x00009e4c, 0x00001004},
- {0x00009e50, 0x00ff03f1},
- {0x00009fc0, 0x80be4788},
- {0x00009fc4, 0x0001efb5},
- {0x00009fcc, 0x40000014},
- {0x0000a20c, 0x00000000},
- {0x0000a210, 0x00000000},
- {0x0000a220, 0x00000000},
- {0x0000a224, 0x00000000},
- {0x0000a228, 0x10002310},
- {0x0000a23c, 0x00000000},
- {0x0000a244, 0x0c000000},
- {0x0000a2a0, 0x00000001},
- {0x0000a2c0, 0x00000001},
- {0x0000a2c8, 0x00000000},
- {0x0000a2cc, 0x18c43433},
- {0x0000a2d4, 0x00000000},
- {0x0000a2dc, 0x00000000},
- {0x0000a2e0, 0x00000000},
- {0x0000a2e4, 0x00000000},
- {0x0000a2e8, 0x00000000},
- {0x0000a2ec, 0x00000000},
- {0x0000a2f0, 0x00000000},
- {0x0000a2f4, 0x00000000},
- {0x0000a2f8, 0x00000000},
- {0x0000a344, 0x00000000},
- {0x0000a34c, 0x00000000},
- {0x0000a350, 0x0000a000},
- {0x0000a364, 0x00000000},
- {0x0000a370, 0x00000000},
- {0x0000a390, 0x00000001},
- {0x0000a394, 0x00000444},
- {0x0000a398, 0x001f0e0f},
- {0x0000a39c, 0x0075393f},
- {0x0000a3a0, 0xb79f6427},
- {0x0000a3a4, 0x000000ff},
- {0x0000a3a8, 0x3b3b3b3b},
- {0x0000a3ac, 0x2f2f2f2f},
- {0x0000a3c0, 0x20202020},
- {0x0000a3c4, 0x22222220},
- {0x0000a3c8, 0x20200020},
- {0x0000a3cc, 0x20202020},
- {0x0000a3d0, 0x20202020},
- {0x0000a3d4, 0x20202020},
- {0x0000a3d8, 0x20202020},
- {0x0000a3dc, 0x20202020},
- {0x0000a3e0, 0x20202020},
- {0x0000a3e4, 0x20202020},
- {0x0000a3e8, 0x20202020},
- {0x0000a3ec, 0x20202020},
- {0x0000a3f0, 0x00000000},
- {0x0000a3f4, 0x00000006},
- {0x0000a3f8, 0x0cdbd380},
- {0x0000a3fc, 0x000f0f01},
- {0x0000a400, 0x8fa91f01},
- {0x0000a404, 0x00000000},
- {0x0000a408, 0x0e79e5c6},
- {0x0000a40c, 0x00820820},
- {0x0000a414, 0x1ce739cf},
- {0x0000a418, 0x2d0019ce},
- {0x0000a41c, 0x1ce739ce},
- {0x0000a420, 0x000001ce},
- {0x0000a424, 0x1ce739ce},
- {0x0000a428, 0x000001ce},
- {0x0000a42c, 0x1ce739ce},
- {0x0000a430, 0x1ce739ce},
- {0x0000a434, 0x00000000},
- {0x0000a438, 0x00001801},
- {0x0000a43c, 0x00000000},
- {0x0000a440, 0x00000000},
- {0x0000a444, 0x00000000},
- {0x0000a448, 0x04000000},
- {0x0000a44c, 0x00000001},
- {0x0000a450, 0x00010000},
- {0x0000a5c4, 0xbfad9d74},
- {0x0000a5c8, 0x0048060a},
- {0x0000a5cc, 0x00000637},
- {0x0000a760, 0x03020100},
- {0x0000a764, 0x09080504},
- {0x0000a768, 0x0d0c0b0a},
- {0x0000a76c, 0x13121110},
- {0x0000a770, 0x31301514},
- {0x0000a774, 0x35343332},
- {0x0000a778, 0x00000036},
- {0x0000a780, 0x00000838},
- {0x0000a7c0, 0x00000000},
- {0x0000a7c4, 0xfffffffc},
- {0x0000a7c8, 0x00000000},
- {0x0000a7cc, 0x00000000},
- {0x0000a7d0, 0x00000000},
- {0x0000a7d4, 0x00000004},
- {0x0000a7dc, 0x00000000},
-};
+#define ar9485_1_1_mac_postamble ar9300_2p2_mac_postamble
-static const u32 ar9485Common_1_1[][2] = {
- /* Addr allmodes */
- {0x00007010, 0x00000022},
- {0x00007020, 0x00000000},
- {0x00007034, 0x00000002},
- {0x00007038, 0x000004c2},
+static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = {
+ /* Addr allmodes */
+ {0x00018c00, 0x18012e5e},
+ {0x00018c04, 0x000801d8},
+ {0x00018c08, 0x0000080c},
};
-static const u32 ar9485_1_1_baseband_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
- {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
- {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
- {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
- {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
- {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
- {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
- {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
- {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
- {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
- {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e},
- {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
- {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
- {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
- {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
- {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
- {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
- {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
- {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
- {0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0},
- {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
- {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
- {0x0000a234, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff},
- {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
- {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
- {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
- {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
- {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
- {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
- {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
- {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0},
- {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
- {0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982},
- {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
- {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000be04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
- {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00060005},
+ {0x0000a004, 0x00810080},
+ {0x0000a008, 0x00830082},
+ {0x0000a00c, 0x00850084},
+ {0x0000a010, 0x01820181},
+ {0x0000a014, 0x01840183},
+ {0x0000a018, 0x01880185},
+ {0x0000a01c, 0x018a0189},
+ {0x0000a020, 0x02850284},
+ {0x0000a024, 0x02890288},
+ {0x0000a028, 0x028b028a},
+ {0x0000a02c, 0x03850384},
+ {0x0000a030, 0x03890388},
+ {0x0000a034, 0x038b038a},
+ {0x0000a038, 0x038d038c},
+ {0x0000a03c, 0x03910390},
+ {0x0000a040, 0x03930392},
+ {0x0000a044, 0x03950394},
+ {0x0000a048, 0x00000396},
+ {0x0000a04c, 0x00000000},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x28282828},
+ {0x0000a084, 0x28282828},
+ {0x0000a088, 0x28282828},
+ {0x0000a08c, 0x28282828},
+ {0x0000a090, 0x28282828},
+ {0x0000a094, 0x24242428},
+ {0x0000a098, 0x171e1e1e},
+ {0x0000a09c, 0x02020b0b},
+ {0x0000a0a0, 0x02020202},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x22072208},
+ {0x0000a0c4, 0x22052206},
+ {0x0000a0c8, 0x22032204},
+ {0x0000a0cc, 0x22012202},
+ {0x0000a0d0, 0x221f2200},
+ {0x0000a0d4, 0x221d221e},
+ {0x0000a0d8, 0x33023303},
+ {0x0000a0dc, 0x33003301},
+ {0x0000a0e0, 0x331e331f},
+ {0x0000a0e4, 0x4402331d},
+ {0x0000a0e8, 0x44004401},
+ {0x0000a0ec, 0x441e441f},
+ {0x0000a0f0, 0x55025503},
+ {0x0000a0f4, 0x55005501},
+ {0x0000a0f8, 0x551e551f},
+ {0x0000a0fc, 0x6602551d},
+ {0x0000a100, 0x66006601},
+ {0x0000a104, 0x661e661f},
+ {0x0000a108, 0x7703661d},
+ {0x0000a10c, 0x77017702},
+ {0x0000a110, 0x00007700},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x111f1100},
+ {0x0000a148, 0x111d111e},
+ {0x0000a14c, 0x111b111c},
+ {0x0000a150, 0x22032204},
+ {0x0000a154, 0x22012202},
+ {0x0000a158, 0x221f2200},
+ {0x0000a15c, 0x221d221e},
+ {0x0000a160, 0x33013302},
+ {0x0000a164, 0x331f3300},
+ {0x0000a168, 0x4402331e},
+ {0x0000a16c, 0x44004401},
+ {0x0000a170, 0x441e441f},
+ {0x0000a174, 0x55015502},
+ {0x0000a178, 0x551f5500},
+ {0x0000a17c, 0x6602551e},
+ {0x0000a180, 0x66006601},
+ {0x0000a184, 0x661e661f},
+ {0x0000a188, 0x7703661d},
+ {0x0000a18c, 0x77017702},
+ {0x0000a190, 0x00007700},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000296},
};
-static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
@@ -442,102 +234,34 @@ static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = {
{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
};
-static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
- {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
- {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
- {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
- {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
- {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
- {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
- {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
- {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
- {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
- {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
- {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
- {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
- {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
- {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
- {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
- {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
- {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
- {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
- {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
- {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
- {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
- {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
- {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
- {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
- {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
- {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
- {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
-};
+#define ar9485Modes_high_ob_db_tx_gain_1_1 ar9485Modes_high_power_tx_gain_1_1
-static const u32 ar9485_1_1_radio_postamble[][2] = {
- /* Addr allmodes */
- {0x0001609c, 0x0b283f31},
- {0x000160ac, 0x24611800},
- {0x000160b0, 0x03284f3e},
- {0x0001610c, 0x00170000},
- {0x00016140, 0x50804008},
-};
+#define ar9485Modes_low_ob_db_tx_gain_1_1 ar9485Modes_high_ob_db_tx_gain_1_1
-static const u32 ar9485_1_1_mac_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
- {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
- {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+#define ar9485_modes_lowest_ob_db_tx_gain_1_1 ar9485Modes_low_ob_db_tx_gain_1_1
+
+static const u32 ar9485_1_1[][2] = {
+ /* Addr allmodes */
+ {0x0000a580, 0x00000000},
+ {0x0000a584, 0x00000000},
+ {0x0000a588, 0x00000000},
+ {0x0000a58c, 0x00000000},
+ {0x0000a590, 0x00000000},
+ {0x0000a594, 0x00000000},
+ {0x0000a598, 0x00000000},
+ {0x0000a59c, 0x00000000},
+ {0x0000a5a0, 0x00000000},
+ {0x0000a5a4, 0x00000000},
+ {0x0000a5a8, 0x00000000},
+ {0x0000a5ac, 0x00000000},
+ {0x0000a5b0, 0x00000000},
+ {0x0000a5b4, 0x00000000},
+ {0x0000a5b8, 0x00000000},
+ {0x0000a5bc, 0x00000000},
};
static const u32 ar9485_1_1_radio_core[][2] = {
- /* Addr allmodes */
+ /* Addr allmodes */
{0x00016000, 0x36db6db6},
{0x00016004, 0x6db6db40},
{0x00016008, 0x73800000},
@@ -601,294 +325,145 @@ static const u32 ar9485_1_1_radio_core[][2] = {
{0x00016c44, 0x12000000},
};
-static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_enable_L1[][2] = {
- /* Addr allmodes */
- {0x00018c00, 0x18052e5e},
- {0x00018c04, 0x000801d8},
- {0x00018c08, 0x0000080c},
-};
-
-static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
- {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
- {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
- {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
- {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
- {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
- {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
- {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
- {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
- {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
- {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
- {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
- {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
- {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
- {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
- {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
- {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
- {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
- {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
- {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
- {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
- {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
- {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
- {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
- {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
- {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
- {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
- {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
-};
-
-static const u32 ar9485_1_1[][2] = {
- /* Addr allmodes */
- {0x0000a580, 0x00000000},
- {0x0000a584, 0x00000000},
- {0x0000a588, 0x00000000},
- {0x0000a58c, 0x00000000},
- {0x0000a590, 0x00000000},
- {0x0000a594, 0x00000000},
- {0x0000a598, 0x00000000},
- {0x0000a59c, 0x00000000},
- {0x0000a5a0, 0x00000000},
- {0x0000a5a4, 0x00000000},
- {0x0000a5a8, 0x00000000},
- {0x0000a5ac, 0x00000000},
- {0x0000a5b0, 0x00000000},
- {0x0000a5b4, 0x00000000},
- {0x0000a5b8, 0x00000000},
- {0x0000a5bc, 0x00000000},
-};
-
-static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003},
- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
- {0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
- {0x0000a500, 0x00022200, 0x00022200, 0x00000006, 0x00000006},
- {0x0000a504, 0x05062002, 0x05062002, 0x03000201, 0x03000201},
- {0x0000a508, 0x0c002e00, 0x0c002e00, 0x06000203, 0x06000203},
- {0x0000a50c, 0x11062202, 0x11062202, 0x0a000401, 0x0a000401},
- {0x0000a510, 0x17022e00, 0x17022e00, 0x0e000403, 0x0e000403},
- {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x12000405, 0x12000405},
- {0x0000a518, 0x25020ec0, 0x25020ec0, 0x15000604, 0x15000604},
- {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x18000605, 0x18000605},
- {0x0000a520, 0x2f001f04, 0x2f001f04, 0x1c000a04, 0x1c000a04},
- {0x0000a524, 0x35001fc4, 0x35001fc4, 0x21000a06, 0x21000a06},
- {0x0000a528, 0x3c022f04, 0x3c022f04, 0x29000a24, 0x29000a24},
- {0x0000a52c, 0x41023e85, 0x41023e85, 0x2f000e21, 0x2f000e21},
- {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000e20, 0x31000e20},
- {0x0000a534, 0x4d023f01, 0x4d023f01, 0x33000e20, 0x33000e20},
- {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
- {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
- {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
- {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
- {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
- {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
- {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
- {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
- {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
- {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
- {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
- {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000b500, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
- {0x0000b504, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
- {0x0000b508, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
- {0x0000b50c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
- {0x0000b510, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
- {0x0000b514, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
- {0x0000b518, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
- {0x0000b51c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
- {0x0000b520, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
- {0x0000b524, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
- {0x0000b528, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
- {0x0000b52c, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a},
- {0x0000b530, 0x0000003a, 0x0000003a, 0x0000003a, 0x0000003a},
- {0x0000b534, 0x0000004a, 0x0000004a, 0x0000004a, 0x0000004a},
- {0x0000b538, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b53c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b540, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b544, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b548, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b54c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b550, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b554, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b558, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b55c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b560, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b564, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b568, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b56c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b570, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b574, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b578, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x0000b57c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
- {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
- {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
-};
-
-static const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = {
- /* Addr allmodes */
- {0x00018c00, 0x18013e5e},
- {0x00018c04, 0x000801d8},
- {0x00018c08, 0x0000080c},
-};
-
-static const u32 ar9485_1_1_soc_preamble[][2] = {
- /* Addr allmodes */
- {0x00004014, 0xba280400},
- {0x00004090, 0x00aa10aa},
- {0x000040a4, 0x00a0c9c9},
- {0x00007010, 0x00000022},
- {0x00007020, 0x00000000},
- {0x00007034, 0x00000002},
- {0x00007038, 0x000004c2},
- {0x00007048, 0x00000002},
-};
-
-static const u32 ar9485_1_1_baseband_core_txfir_coeff_japan_2484[][2] = {
- /* Addr allmodes */
- {0x0000a398, 0x00000000},
- {0x0000a39c, 0x6f7f0301},
- {0x0000a3a0, 0xca9228ee},
-};
-
-static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
- {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
- {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
- {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
- {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
- {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
- {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
- {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
- {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
- {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
- {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
- {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
- {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
- {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
- {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
- {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
- {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
- {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
- {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
- {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
- {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
- {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
- {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
- {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
- {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
- {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
- {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
- {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
-};
-
-static const u32 ar9485_fast_clock_1_1_baseband_postamble[][3] = {
- /* Addr 5G_HT2 5G_HT40 */
- {0x00009e00, 0x03721821, 0x03721821},
- {0x0000a230, 0x0000400b, 0x00004016},
- {0x0000a254, 0x00000898, 0x00001130},
-};
-
-static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = {
- /* Addr allmodes */
- {0x00018c00, 0x18012e5e},
- {0x00018c04, 0x000801d8},
- {0x00018c08, 0x0000080c},
+static const u32 ar9485_1_1_baseband_core[][2] = {
+ /* Addr allmodes */
+ {0x00009800, 0xafe68e30},
+ {0x00009804, 0xfd14e000},
+ {0x00009808, 0x9c0a8f6b},
+ {0x0000980c, 0x04800000},
+ {0x00009814, 0x9280c00a},
+ {0x00009818, 0x00000000},
+ {0x0000981c, 0x00020028},
+ {0x00009834, 0x5f3ca3de},
+ {0x00009838, 0x0108ecff},
+ {0x0000983c, 0x14750600},
+ {0x00009880, 0x201fff00},
+ {0x00009884, 0x00001042},
+ {0x000098a4, 0x00200400},
+ {0x000098b0, 0x52440bbe},
+ {0x000098d0, 0x004b6a8e},
+ {0x000098d4, 0x00000820},
+ {0x000098dc, 0x00000000},
+ {0x000098f0, 0x00000000},
+ {0x000098f4, 0x00000000},
+ {0x00009c04, 0x00000000},
+ {0x00009c08, 0x03200000},
+ {0x00009c0c, 0x00000000},
+ {0x00009c10, 0x00000000},
+ {0x00009c14, 0x00046384},
+ {0x00009c18, 0x05b6b440},
+ {0x00009c1c, 0x00b6b440},
+ {0x00009d00, 0xc080a333},
+ {0x00009d04, 0x40206c10},
+ {0x00009d08, 0x009c4060},
+ {0x00009d0c, 0x1883800a},
+ {0x00009d10, 0x01834061},
+ {0x00009d14, 0x00c00400},
+ {0x00009d18, 0x00000000},
+ {0x00009d1c, 0x00000000},
+ {0x00009e08, 0x0038233c},
+ {0x00009e24, 0x9927b515},
+ {0x00009e28, 0x12ef0200},
+ {0x00009e30, 0x06336f77},
+ {0x00009e34, 0x6af6532f},
+ {0x00009e38, 0x0cc80c00},
+ {0x00009e40, 0x0d261820},
+ {0x00009e4c, 0x00001004},
+ {0x00009e50, 0x00ff03f1},
+ {0x00009fc0, 0x80be4788},
+ {0x00009fc4, 0x0001efb5},
+ {0x00009fcc, 0x40000014},
+ {0x0000a20c, 0x00000000},
+ {0x0000a210, 0x00000000},
+ {0x0000a220, 0x00000000},
+ {0x0000a224, 0x00000000},
+ {0x0000a228, 0x10002310},
+ {0x0000a23c, 0x00000000},
+ {0x0000a244, 0x0c000000},
+ {0x0000a2a0, 0x00000001},
+ {0x0000a2c0, 0x00000001},
+ {0x0000a2c8, 0x00000000},
+ {0x0000a2cc, 0x18c43433},
+ {0x0000a2d4, 0x00000000},
+ {0x0000a2dc, 0x00000000},
+ {0x0000a2e0, 0x00000000},
+ {0x0000a2e4, 0x00000000},
+ {0x0000a2e8, 0x00000000},
+ {0x0000a2ec, 0x00000000},
+ {0x0000a2f0, 0x00000000},
+ {0x0000a2f4, 0x00000000},
+ {0x0000a2f8, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a34c, 0x00000000},
+ {0x0000a350, 0x0000a000},
+ {0x0000a364, 0x00000000},
+ {0x0000a370, 0x00000000},
+ {0x0000a390, 0x00000001},
+ {0x0000a394, 0x00000444},
+ {0x0000a398, 0x001f0e0f},
+ {0x0000a39c, 0x0075393f},
+ {0x0000a3a0, 0xb79f6427},
+ {0x0000a3a4, 0x000000ff},
+ {0x0000a3a8, 0x3b3b3b3b},
+ {0x0000a3ac, 0x2f2f2f2f},
+ {0x0000a3c0, 0x20202020},
+ {0x0000a3c4, 0x22222220},
+ {0x0000a3c8, 0x20200020},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3d8, 0x20202020},
+ {0x0000a3dc, 0x20202020},
+ {0x0000a3e0, 0x20202020},
+ {0x0000a3e4, 0x20202020},
+ {0x0000a3e8, 0x20202020},
+ {0x0000a3ec, 0x20202020},
+ {0x0000a3f0, 0x00000000},
+ {0x0000a3f4, 0x00000006},
+ {0x0000a3f8, 0x0cdbd380},
+ {0x0000a3fc, 0x000f0f01},
+ {0x0000a400, 0x8fa91f01},
+ {0x0000a404, 0x00000000},
+ {0x0000a408, 0x0e79e5c6},
+ {0x0000a40c, 0x00820820},
+ {0x0000a414, 0x1ce739cf},
+ {0x0000a418, 0x2d0019ce},
+ {0x0000a41c, 0x1ce739ce},
+ {0x0000a420, 0x000001ce},
+ {0x0000a424, 0x1ce739ce},
+ {0x0000a428, 0x000001ce},
+ {0x0000a42c, 0x1ce739ce},
+ {0x0000a430, 0x1ce739ce},
+ {0x0000a434, 0x00000000},
+ {0x0000a438, 0x00001801},
+ {0x0000a43c, 0x00000000},
+ {0x0000a440, 0x00000000},
+ {0x0000a444, 0x00000000},
+ {0x0000a448, 0x04000000},
+ {0x0000a44c, 0x00000001},
+ {0x0000a450, 0x00010000},
+ {0x0000a5c4, 0xbfad9d74},
+ {0x0000a5c8, 0x0048060a},
+ {0x0000a5cc, 0x00000637},
+ {0x0000a760, 0x03020100},
+ {0x0000a764, 0x09080504},
+ {0x0000a768, 0x0d0c0b0a},
+ {0x0000a76c, 0x13121110},
+ {0x0000a770, 0x31301514},
+ {0x0000a774, 0x35343332},
+ {0x0000a778, 0x00000036},
+ {0x0000a780, 0x00000838},
+ {0x0000a7c0, 0x00000000},
+ {0x0000a7c4, 0xfffffffc},
+ {0x0000a7c8, 0x00000000},
+ {0x0000a7cc, 0x00000000},
+ {0x0000a7d0, 0x00000000},
+ {0x0000a7d4, 0x00000004},
+ {0x0000a7dc, 0x00000000},
};
static const u32 ar9485_common_rx_gain_1_1[][2] = {
- /* Addr allmodes */
+ /* Addr allmodes */
{0x0000a000, 0x00010000},
{0x0000a004, 0x00030002},
{0x0000a008, 0x00050004},
@@ -1019,143 +594,260 @@ static const u32 ar9485_common_rx_gain_1_1[][2] = {
{0x0000a1fc, 0x00000296},
};
+static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_enable_L1[][2] = {
+ /* Addr allmodes */
+ {0x00018c00, 0x18052e5e},
+ {0x00018c04, 0x000801d8},
+ {0x00018c08, 0x0000080c},
+};
+
static const u32 ar9485_1_1_pcie_phy_clkreq_enable_L1[][2] = {
- /* Addr allmodes */
+ /* Addr allmodes */
{0x00018c00, 0x18053e5e},
{0x00018c04, 0x000801d8},
{0x00018c08, 0x0000080c},
};
-static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = {
- /* Addr allmodes */
- {0x0000a000, 0x00060005},
- {0x0000a004, 0x00810080},
- {0x0000a008, 0x00830082},
- {0x0000a00c, 0x00850084},
- {0x0000a010, 0x01820181},
- {0x0000a014, 0x01840183},
- {0x0000a018, 0x01880185},
- {0x0000a01c, 0x018a0189},
- {0x0000a020, 0x02850284},
- {0x0000a024, 0x02890288},
- {0x0000a028, 0x028b028a},
- {0x0000a02c, 0x03850384},
- {0x0000a030, 0x03890388},
- {0x0000a034, 0x038b038a},
- {0x0000a038, 0x038d038c},
- {0x0000a03c, 0x03910390},
- {0x0000a040, 0x03930392},
- {0x0000a044, 0x03950394},
- {0x0000a048, 0x00000396},
- {0x0000a04c, 0x00000000},
- {0x0000a050, 0x00000000},
- {0x0000a054, 0x00000000},
- {0x0000a058, 0x00000000},
- {0x0000a05c, 0x00000000},
- {0x0000a060, 0x00000000},
- {0x0000a064, 0x00000000},
- {0x0000a068, 0x00000000},
- {0x0000a06c, 0x00000000},
- {0x0000a070, 0x00000000},
- {0x0000a074, 0x00000000},
- {0x0000a078, 0x00000000},
- {0x0000a07c, 0x00000000},
- {0x0000a080, 0x28282828},
- {0x0000a084, 0x28282828},
- {0x0000a088, 0x28282828},
- {0x0000a08c, 0x28282828},
- {0x0000a090, 0x28282828},
- {0x0000a094, 0x24242428},
- {0x0000a098, 0x171e1e1e},
- {0x0000a09c, 0x02020b0b},
- {0x0000a0a0, 0x02020202},
- {0x0000a0a4, 0x00000000},
- {0x0000a0a8, 0x00000000},
- {0x0000a0ac, 0x00000000},
- {0x0000a0b0, 0x00000000},
- {0x0000a0b4, 0x00000000},
- {0x0000a0b8, 0x00000000},
- {0x0000a0bc, 0x00000000},
- {0x0000a0c0, 0x22072208},
- {0x0000a0c4, 0x22052206},
- {0x0000a0c8, 0x22032204},
- {0x0000a0cc, 0x22012202},
- {0x0000a0d0, 0x221f2200},
- {0x0000a0d4, 0x221d221e},
- {0x0000a0d8, 0x33023303},
- {0x0000a0dc, 0x33003301},
- {0x0000a0e0, 0x331e331f},
- {0x0000a0e4, 0x4402331d},
- {0x0000a0e8, 0x44004401},
- {0x0000a0ec, 0x441e441f},
- {0x0000a0f0, 0x55025503},
- {0x0000a0f4, 0x55005501},
- {0x0000a0f8, 0x551e551f},
- {0x0000a0fc, 0x6602551d},
- {0x0000a100, 0x66006601},
- {0x0000a104, 0x661e661f},
- {0x0000a108, 0x7703661d},
- {0x0000a10c, 0x77017702},
- {0x0000a110, 0x00007700},
- {0x0000a114, 0x00000000},
- {0x0000a118, 0x00000000},
- {0x0000a11c, 0x00000000},
- {0x0000a120, 0x00000000},
- {0x0000a124, 0x00000000},
- {0x0000a128, 0x00000000},
- {0x0000a12c, 0x00000000},
- {0x0000a130, 0x00000000},
- {0x0000a134, 0x00000000},
- {0x0000a138, 0x00000000},
- {0x0000a13c, 0x00000000},
- {0x0000a140, 0x001f0000},
- {0x0000a144, 0x111f1100},
- {0x0000a148, 0x111d111e},
- {0x0000a14c, 0x111b111c},
- {0x0000a150, 0x22032204},
- {0x0000a154, 0x22012202},
- {0x0000a158, 0x221f2200},
- {0x0000a15c, 0x221d221e},
- {0x0000a160, 0x33013302},
- {0x0000a164, 0x331f3300},
- {0x0000a168, 0x4402331e},
- {0x0000a16c, 0x44004401},
- {0x0000a170, 0x441e441f},
- {0x0000a174, 0x55015502},
- {0x0000a178, 0x551f5500},
- {0x0000a17c, 0x6602551e},
- {0x0000a180, 0x66006601},
- {0x0000a184, 0x661e661f},
- {0x0000a188, 0x7703661d},
- {0x0000a18c, 0x77017702},
- {0x0000a190, 0x00007700},
- {0x0000a194, 0x00000000},
- {0x0000a198, 0x00000000},
- {0x0000a19c, 0x00000000},
- {0x0000a1a0, 0x00000000},
- {0x0000a1a4, 0x00000000},
- {0x0000a1a8, 0x00000000},
- {0x0000a1ac, 0x00000000},
- {0x0000a1b0, 0x00000000},
- {0x0000a1b4, 0x00000000},
- {0x0000a1b8, 0x00000000},
- {0x0000a1bc, 0x00000000},
- {0x0000a1c0, 0x00000000},
- {0x0000a1c4, 0x00000000},
- {0x0000a1c8, 0x00000000},
- {0x0000a1cc, 0x00000000},
- {0x0000a1d0, 0x00000000},
- {0x0000a1d4, 0x00000000},
- {0x0000a1d8, 0x00000000},
- {0x0000a1dc, 0x00000000},
- {0x0000a1e0, 0x00000000},
- {0x0000a1e4, 0x00000000},
- {0x0000a1e8, 0x00000000},
- {0x0000a1ec, 0x00000000},
- {0x0000a1f0, 0x00000396},
- {0x0000a1f4, 0x00000396},
- {0x0000a1f8, 0x00000396},
- {0x0000a1fc, 0x00000296},
+static const u32 ar9485_1_1_soc_preamble[][2] = {
+ /* Addr allmodes */
+ {0x00004014, 0xba280400},
+ {0x00004090, 0x00aa10aa},
+ {0x000040a4, 0x00a0c9c9},
+ {0x00007010, 0x00000022},
+ {0x00007020, 0x00000000},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000004c2},
+ {0x00007048, 0x00000002},
+};
+
+static const u32 ar9485_fast_clock_1_1_baseband_postamble[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x00009e00, 0x03721821, 0x03721821},
+ {0x0000a230, 0x0000400b, 0x00004016},
+ {0x0000a254, 0x00000898, 0x00001130},
+};
+
+static const u32 ar9485_1_1_baseband_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+ {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+ {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+ {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+ {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+ {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e},
+ {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+ {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+ {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+ {0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0},
+ {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+ {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
+ {0x0000a234, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff},
+ {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+ {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+ {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+ {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+ {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0},
+ {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982},
+ {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000be04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+ {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = {
+ /* Addr allmodes */
+ {0x00018c00, 0x18013e5e},
+ {0x00018c04, 0x000801d8},
+ {0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485_1_1_radio_postamble[][2] = {
+ /* Addr allmodes */
+ {0x0001609c, 0x0b283f31},
+ {0x000160ac, 0x24611800},
+ {0x000160b0, 0x03284f3e},
+ {0x0001610c, 0x00170000},
+ {0x00016140, 0x50804008},
+};
+
+static const u32 ar9485_1_1_mac_core[][2] = {
+ /* Addr allmodes */
+ {0x00000008, 0x00000000},
+ {0x00000030, 0x00020085},
+ {0x00000034, 0x00000005},
+ {0x00000040, 0x00000000},
+ {0x00000044, 0x00000000},
+ {0x00000048, 0x00000008},
+ {0x0000004c, 0x00000010},
+ {0x00000050, 0x00000000},
+ {0x00001040, 0x002ffc0f},
+ {0x00001044, 0x002ffc0f},
+ {0x00001048, 0x002ffc0f},
+ {0x0000104c, 0x002ffc0f},
+ {0x00001050, 0x002ffc0f},
+ {0x00001054, 0x002ffc0f},
+ {0x00001058, 0x002ffc0f},
+ {0x0000105c, 0x002ffc0f},
+ {0x00001060, 0x002ffc0f},
+ {0x00001064, 0x002ffc0f},
+ {0x000010f0, 0x00000100},
+ {0x00001270, 0x00000000},
+ {0x000012b0, 0x00000000},
+ {0x000012f0, 0x00000000},
+ {0x0000143c, 0x00000000},
+ {0x0000147c, 0x00000000},
+ {0x00008000, 0x00000000},
+ {0x00008004, 0x00000000},
+ {0x00008008, 0x00000000},
+ {0x0000800c, 0x00000000},
+ {0x00008018, 0x00000000},
+ {0x00008020, 0x00000000},
+ {0x00008038, 0x00000000},
+ {0x0000803c, 0x00000000},
+ {0x00008040, 0x00000000},
+ {0x00008044, 0x00000000},
+ {0x00008048, 0x00000000},
+ {0x0000804c, 0xffffffff},
+ {0x00008054, 0x00000000},
+ {0x00008058, 0x00000000},
+ {0x0000805c, 0x000fc78f},
+ {0x00008060, 0x0000000f},
+ {0x00008064, 0x00000000},
+ {0x00008070, 0x00000310},
+ {0x00008074, 0x00000020},
+ {0x00008078, 0x00000000},
+ {0x0000809c, 0x0000000f},
+ {0x000080a0, 0x00000000},
+ {0x000080a4, 0x02ff0000},
+ {0x000080a8, 0x0e070605},
+ {0x000080ac, 0x0000000d},
+ {0x000080b0, 0x00000000},
+ {0x000080b4, 0x00000000},
+ {0x000080b8, 0x00000000},
+ {0x000080bc, 0x00000000},
+ {0x000080c0, 0x2a800000},
+ {0x000080c4, 0x06900168},
+ {0x000080c8, 0x13881c22},
+ {0x000080cc, 0x01f40000},
+ {0x000080d0, 0x00252500},
+ {0x000080d4, 0x00a00000},
+ {0x000080d8, 0x00400000},
+ {0x000080dc, 0x00000000},
+ {0x000080e0, 0xffffffff},
+ {0x000080e4, 0x0000ffff},
+ {0x000080e8, 0x3f3f3f3f},
+ {0x000080ec, 0x00000000},
+ {0x000080f0, 0x00000000},
+ {0x000080f4, 0x00000000},
+ {0x000080fc, 0x00020000},
+ {0x00008100, 0x00000000},
+ {0x00008108, 0x00000052},
+ {0x0000810c, 0x00000000},
+ {0x00008110, 0x00000000},
+ {0x00008114, 0x000007ff},
+ {0x00008118, 0x000000aa},
+ {0x0000811c, 0x00003210},
+ {0x00008124, 0x00000000},
+ {0x00008128, 0x00000000},
+ {0x0000812c, 0x00000000},
+ {0x00008130, 0x00000000},
+ {0x00008134, 0x00000000},
+ {0x00008138, 0x00000000},
+ {0x0000813c, 0x0000ffff},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x00008170, 0x18486200},
+ {0x00008174, 0x33332210},
+ {0x00008178, 0x00000000},
+ {0x0000817c, 0x00020000},
+ {0x000081c0, 0x00000000},
+ {0x000081c4, 0x33332210},
+ {0x000081d4, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008244, 0x0010f400},
+ {0x00008248, 0x00000800},
+ {0x0000824c, 0x0001e800},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x40000000},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x9ca00010},
+ {0x00008268, 0xffffffff},
+ {0x0000826c, 0x0000ffff},
+ {0x00008270, 0x00000000},
+ {0x00008274, 0x40000000},
+ {0x00008278, 0x003e4180},
+ {0x0000827c, 0x00000004},
+ {0x00008284, 0x0000002c},
+ {0x00008288, 0x0000002c},
+ {0x0000828c, 0x000000ff},
+ {0x00008294, 0x00000000},
+ {0x00008298, 0x00000000},
+ {0x0000829c, 0x00000000},
+ {0x00008300, 0x00000140},
+ {0x00008314, 0x00000000},
+ {0x0000831c, 0x0000010d},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x00000007},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000700},
+ {0x00008338, 0x00ff0000},
+ {0x0000833c, 0x02400000},
+ {0x00008340, 0x000107ff},
+ {0x00008344, 0xa248105b},
+ {0x00008348, 0x008f0000},
+ {0x0000835c, 0x00000000},
+ {0x00008360, 0xffffffff},
+ {0x00008364, 0xffffffff},
+ {0x00008368, 0x00000000},
+ {0x00008370, 0x00000000},
+ {0x00008374, 0x000000ff},
+ {0x00008378, 0x00000000},
+ {0x0000837c, 0x00000000},
+ {0x00008380, 0xffffffff},
+ {0x00008384, 0xffffffff},
+ {0x00008390, 0xffffffff},
+ {0x00008394, 0xffffffff},
+ {0x00008398, 0x00000000},
+ {0x0000839c, 0x00000000},
+ {0x000083a0, 0x00000000},
+ {0x000083a4, 0x0000fa14},
+ {0x000083a8, 0x000f0c00},
+ {0x000083ac, 0x33332210},
+ {0x000083b0, 0x33332210},
+ {0x000083b4, 0x33332210},
+ {0x000083b8, 0x33332210},
+ {0x000083bc, 0x00000000},
+ {0x000083c0, 0x00000000},
+ {0x000083c4, 0x00000000},
+ {0x000083c8, 0x00000000},
+ {0x000083cc, 0x00000200},
+ {0x000083d0, 0x000301ff},
};
-#endif
+#endif /* INITVALS_9485_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
new file mode 100644
index 000000000000..df97f21c52dc
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
@@ -0,0 +1,1284 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_955X_1P0_H
+#define INITVALS_955X_1P0_H
+
+/* AR955X 1.0 */
+
+static const u32 ar955x_1p0_radio_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00016098, 0xd2dd5554, 0xd2dd5554, 0xd28b3330, 0xd28b3330},
+ {0x0001609c, 0x0a566f3a, 0x0a566f3a, 0x06345f2a, 0x06345f2a},
+ {0x000160ac, 0xa4647c00, 0xa4647c00, 0xa4646800, 0xa4646800},
+ {0x000160b0, 0x01885f52, 0x01885f52, 0x04accf3a, 0x04accf3a},
+ {0x00016104, 0xb7a00001, 0xb7a00001, 0xb7a00001, 0xb7a00001},
+ {0x0001610c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000},
+ {0x00016140, 0x10804008, 0x10804008, 0x10804008, 0x10804008},
+ {0x00016504, 0xb7a00001, 0xb7a00001, 0xb7a00001, 0xb7a00001},
+ {0x0001650c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000},
+ {0x00016540, 0x10804008, 0x10804008, 0x10804008, 0x10804008},
+ {0x00016904, 0xb7a00001, 0xb7a00001, 0xb7a00001, 0xb7a00001},
+ {0x0001690c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000},
+ {0x00016940, 0x10804008, 0x10804008, 0x10804008, 0x10804008},
+};
+
+static const u32 ar955x_1p0_baseband_core_txfir_coeff_japan_2484[][2] = {
+ /* Addr allmodes */
+ {0x0000a398, 0x00000000},
+ {0x0000a39c, 0x6f7f0301},
+ {0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar955x_1p0_baseband_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+ {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+ {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+ {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+ {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+ {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+ {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10822, 0xcfa10822},
+ {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+ {0x0000a204, 0x005c0ec0, 0x005c0ec4, 0x005c0ec4, 0x005c0ec0},
+ {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+ {0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f},
+ {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
+ {0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018},
+ {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+ {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
+ {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+ {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+ {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
+ {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33},
+ {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982},
+ {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+ {0x0000b284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+ {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000be04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+ {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+ {0x0000c284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+};
+
+static const u32 ar955x_1p0_radio_core[][2] = {
+ /* Addr allmodes */
+ {0x00016000, 0x36db6db6},
+ {0x00016004, 0x6db6db40},
+ {0x00016008, 0x73f00000},
+ {0x0001600c, 0x00000000},
+ {0x00016040, 0x7f80fff8},
+ {0x0001604c, 0x76d005b5},
+ {0x00016050, 0x557cf031},
+ {0x00016054, 0x13449440},
+ {0x00016058, 0x0c51c92c},
+ {0x0001605c, 0x3db7fffc},
+ {0x00016060, 0xfffffffc},
+ {0x00016064, 0x000f0278},
+ {0x00016068, 0x6db6db6c},
+ {0x0001606c, 0x6db60000},
+ {0x00016080, 0x00080000},
+ {0x00016084, 0x0e48048c},
+ {0x00016088, 0x14214514},
+ {0x0001608c, 0x119f101e},
+ {0x00016090, 0x24926490},
+ {0x00016094, 0x00000000},
+ {0x000160a0, 0x0a108ffe},
+ {0x000160a4, 0x812fc370},
+ {0x000160a8, 0x423c8000},
+ {0x000160b4, 0x92480080},
+ {0x000160c0, 0x006db6d0},
+ {0x000160c4, 0x6db6db60},
+ {0x000160c8, 0x6db6db6c},
+ {0x000160cc, 0x01e6c000},
+ {0x00016100, 0x11999601},
+ {0x00016108, 0x00080010},
+ {0x00016144, 0x02084080},
+ {0x00016148, 0x000080c0},
+ {0x00016280, 0x01800804},
+ {0x00016284, 0x00038dc5},
+ {0x00016288, 0x00000000},
+ {0x0001628c, 0x00000040},
+ {0x00016380, 0x00000000},
+ {0x00016384, 0x00000000},
+ {0x00016388, 0x00400705},
+ {0x0001638c, 0x00800700},
+ {0x00016390, 0x00800700},
+ {0x00016394, 0x00000000},
+ {0x00016398, 0x00000000},
+ {0x0001639c, 0x00000000},
+ {0x000163a0, 0x00000001},
+ {0x000163a4, 0x00000001},
+ {0x000163a8, 0x00000000},
+ {0x000163ac, 0x00000000},
+ {0x000163b0, 0x00000000},
+ {0x000163b4, 0x00000000},
+ {0x000163b8, 0x00000000},
+ {0x000163bc, 0x00000000},
+ {0x000163c0, 0x000000a0},
+ {0x000163c4, 0x000c0000},
+ {0x000163c8, 0x14021402},
+ {0x000163cc, 0x00001402},
+ {0x000163d0, 0x00000000},
+ {0x000163d4, 0x00000000},
+ {0x00016400, 0x36db6db6},
+ {0x00016404, 0x6db6db40},
+ {0x00016408, 0x73f00000},
+ {0x0001640c, 0x00000000},
+ {0x00016440, 0x7f80fff8},
+ {0x0001644c, 0x76d005b5},
+ {0x00016450, 0x557cf031},
+ {0x00016454, 0x13449440},
+ {0x00016458, 0x0c51c92c},
+ {0x0001645c, 0x3db7fffc},
+ {0x00016460, 0xfffffffc},
+ {0x00016464, 0x000f0278},
+ {0x00016468, 0x6db6db6c},
+ {0x0001646c, 0x6db60000},
+ {0x00016500, 0x11999601},
+ {0x00016508, 0x00080010},
+ {0x00016544, 0x02084080},
+ {0x00016548, 0x000080c0},
+ {0x00016780, 0x00000000},
+ {0x00016784, 0x00000000},
+ {0x00016788, 0x00400705},
+ {0x0001678c, 0x00800700},
+ {0x00016790, 0x00800700},
+ {0x00016794, 0x00000000},
+ {0x00016798, 0x00000000},
+ {0x0001679c, 0x00000000},
+ {0x000167a0, 0x00000001},
+ {0x000167a4, 0x00000001},
+ {0x000167a8, 0x00000000},
+ {0x000167ac, 0x00000000},
+ {0x000167b0, 0x00000000},
+ {0x000167b4, 0x00000000},
+ {0x000167b8, 0x00000000},
+ {0x000167bc, 0x00000000},
+ {0x000167c0, 0x000000a0},
+ {0x000167c4, 0x000c0000},
+ {0x000167c8, 0x14021402},
+ {0x000167cc, 0x00001402},
+ {0x000167d0, 0x00000000},
+ {0x000167d4, 0x00000000},
+ {0x00016800, 0x36db6db6},
+ {0x00016804, 0x6db6db40},
+ {0x00016808, 0x73f00000},
+ {0x0001680c, 0x00000000},
+ {0x00016840, 0x7f80fff8},
+ {0x0001684c, 0x76d005b5},
+ {0x00016850, 0x557cf031},
+ {0x00016854, 0x13449440},
+ {0x00016858, 0x0c51c92c},
+ {0x0001685c, 0x3db7fffc},
+ {0x00016860, 0xfffffffc},
+ {0x00016864, 0x000f0278},
+ {0x00016868, 0x6db6db6c},
+ {0x0001686c, 0x6db60000},
+ {0x00016900, 0x11999601},
+ {0x00016908, 0x00080010},
+ {0x00016944, 0x02084080},
+ {0x00016948, 0x000080c0},
+ {0x00016b80, 0x00000000},
+ {0x00016b84, 0x00000000},
+ {0x00016b88, 0x00400705},
+ {0x00016b8c, 0x00800700},
+ {0x00016b90, 0x00800700},
+ {0x00016b94, 0x00000000},
+ {0x00016b98, 0x00000000},
+ {0x00016b9c, 0x00000000},
+ {0x00016ba0, 0x00000001},
+ {0x00016ba4, 0x00000001},
+ {0x00016ba8, 0x00000000},
+ {0x00016bac, 0x00000000},
+ {0x00016bb0, 0x00000000},
+ {0x00016bb4, 0x00000000},
+ {0x00016bb8, 0x00000000},
+ {0x00016bbc, 0x00000000},
+ {0x00016bc0, 0x000000a0},
+ {0x00016bc4, 0x000c0000},
+ {0x00016bc8, 0x14021402},
+ {0x00016bcc, 0x00001402},
+ {0x00016bd0, 0x00000000},
+ {0x00016bd4, 0x00000000},
+};
+
+static const u32 ar955x_1p0_modes_xpa_tx_gain_table[][9] = {
+ /* Addr 5G_HT20_L 5G_HT40_L 5G_HT20_M 5G_HT40_M 5G_HT20_H 5G_HT40_H 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xfffd5aaa, 0xfffd5aaa},
+ {0x0000a2e0, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xfffe9ccc, 0xfffe9ccc},
+ {0x0000a2e4, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xffffe0f0, 0xffffe0f0},
+ {0x0000a2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00},
+ {0x0000a410, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050da, 0x000050da},
+ {0x0000a500, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000000, 0x00000000},
+ {0x0000a504, 0x04000005, 0x04000005, 0x04000005, 0x04000005, 0x04000005, 0x04000005, 0x04000002, 0x04000002},
+ {0x0000a508, 0x08000009, 0x08000009, 0x08000009, 0x08000009, 0x08000009, 0x08000009, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c000006, 0x0c000006},
+ {0x0000a510, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x0f00000a, 0x0f00000a},
+ {0x0000a514, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x1300000c, 0x1300000c},
+ {0x0000a518, 0x19004008, 0x19004008, 0x19004008, 0x19004008, 0x18004008, 0x18004008, 0x1700000e, 0x1700000e},
+ {0x0000a51c, 0x1d00400a, 0x1d00400a, 0x1d00400a, 0x1d00400a, 0x1c00400a, 0x1c00400a, 0x1b000064, 0x1b000064},
+ {0x0000a520, 0x230020a2, 0x230020a2, 0x210020a2, 0x210020a2, 0x200020a2, 0x200020a2, 0x1f000242, 0x1f000242},
+ {0x0000a524, 0x2500006e, 0x2500006e, 0x2500006e, 0x2500006e, 0x2400006e, 0x2400006e, 0x23000229, 0x23000229},
+ {0x0000a528, 0x29022221, 0x29022221, 0x28022221, 0x28022221, 0x27022221, 0x27022221, 0x270002a2, 0x270002a2},
+ {0x0000a52c, 0x2d00062a, 0x2d00062a, 0x2c00062a, 0x2c00062a, 0x2a00062a, 0x2a00062a, 0x2c001203, 0x2c001203},
+ {0x0000a530, 0x340220a5, 0x340220a5, 0x320220a5, 0x320220a5, 0x2f0220a5, 0x2f0220a5, 0x30001803, 0x30001803},
+ {0x0000a534, 0x380022c5, 0x380022c5, 0x350022c5, 0x350022c5, 0x320022c5, 0x320022c5, 0x33000881, 0x33000881},
+ {0x0000a538, 0x3b002486, 0x3b002486, 0x39002486, 0x39002486, 0x36002486, 0x36002486, 0x38001809, 0x38001809},
+ {0x0000a53c, 0x3f00248a, 0x3f00248a, 0x3d00248a, 0x3d00248a, 0x3a00248a, 0x3a00248a, 0x3a000814, 0x3a000814},
+ {0x0000a540, 0x4202242c, 0x4202242c, 0x4102242c, 0x4102242c, 0x3f02242c, 0x3f02242c, 0x3f001a0c, 0x3f001a0c},
+ {0x0000a544, 0x490044c6, 0x490044c6, 0x460044c6, 0x460044c6, 0x420044c6, 0x420044c6, 0x43001a0e, 0x43001a0e},
+ {0x0000a548, 0x4d024485, 0x4d024485, 0x4a024485, 0x4a024485, 0x46024485, 0x46024485, 0x46001812, 0x46001812},
+ {0x0000a54c, 0x51044483, 0x51044483, 0x4e044483, 0x4e044483, 0x4a044483, 0x4a044483, 0x49001884, 0x49001884},
+ {0x0000a550, 0x5404a40c, 0x5404a40c, 0x5204a40c, 0x5204a40c, 0x4d04a40c, 0x4d04a40c, 0x4d001e84, 0x4d001e84},
+ {0x0000a554, 0x57024632, 0x57024632, 0x55024632, 0x55024632, 0x52024632, 0x52024632, 0x50001e69, 0x50001e69},
+ {0x0000a558, 0x5c00a634, 0x5c00a634, 0x5900a634, 0x5900a634, 0x5600a634, 0x5600a634, 0x550006f4, 0x550006f4},
+ {0x0000a55c, 0x5f026832, 0x5f026832, 0x5d026832, 0x5d026832, 0x5a026832, 0x5a026832, 0x59000ad3, 0x59000ad3},
+ {0x0000a560, 0x6602b012, 0x6602b012, 0x6202b012, 0x6202b012, 0x5d02b012, 0x5d02b012, 0x5e000ad5, 0x5e000ad5},
+ {0x0000a564, 0x6e02d0e1, 0x6e02d0e1, 0x6802d0e1, 0x6802d0e1, 0x6002d0e1, 0x6002d0e1, 0x61001ced, 0x61001ced},
+ {0x0000a568, 0x7202b4c4, 0x7202b4c4, 0x6c02b4c4, 0x6c02b4c4, 0x6502b4c4, 0x6502b4c4, 0x660018d4, 0x660018d4},
+ {0x0000a56c, 0x75007894, 0x75007894, 0x70007894, 0x70007894, 0x6b007894, 0x6b007894, 0x660018d4, 0x660018d4},
+ {0x0000a570, 0x7b025c74, 0x7b025c74, 0x75025c74, 0x75025c74, 0x70025c74, 0x70025c74, 0x660018d4, 0x660018d4},
+ {0x0000a574, 0x8300bcb5, 0x8300bcb5, 0x7a00bcb5, 0x7a00bcb5, 0x7600bcb5, 0x7600bcb5, 0x660018d4, 0x660018d4},
+ {0x0000a578, 0x8a04dc74, 0x8a04dc74, 0x7f04dc74, 0x7f04dc74, 0x7c04dc74, 0x7c04dc74, 0x660018d4, 0x660018d4},
+ {0x0000a57c, 0x8a04dc74, 0x8a04dc74, 0x7f04dc74, 0x7f04dc74, 0x7c04dc74, 0x7c04dc74, 0x660018d4, 0x660018d4},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x03804000, 0x03804000},
+ {0x0000a610, 0x04c08c01, 0x04c08c01, 0x04808b01, 0x04808b01, 0x04808a01, 0x04808a01, 0x0300ca02, 0x0300ca02},
+ {0x0000a614, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00000e04, 0x00000e04},
+ {0x0000a618, 0x04010c01, 0x04010c01, 0x03c10b01, 0x03c10b01, 0x03810a01, 0x03810a01, 0x03014000, 0x03014000},
+ {0x0000a61c, 0x03814e05, 0x03814e05, 0x03414d05, 0x03414d05, 0x03414d05, 0x03414d05, 0x00000000, 0x00000000},
+ {0x0000a620, 0x04010303, 0x04010303, 0x03c10303, 0x03c10303, 0x03810303, 0x03810303, 0x00000000, 0x00000000},
+ {0x0000a624, 0x03814e05, 0x03814e05, 0x03414d05, 0x03414d05, 0x03414d05, 0x03414d05, 0x03014000, 0x03014000},
+ {0x0000a628, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x03804c05, 0x03804c05},
+ {0x0000a62c, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x0701de06, 0x0701de06},
+ {0x0000a630, 0x03418000, 0x03418000, 0x03018000, 0x03018000, 0x02c18000, 0x02c18000, 0x07819c07, 0x07819c07},
+ {0x0000a634, 0x03815004, 0x03815004, 0x03414f04, 0x03414f04, 0x03414e04, 0x03414e04, 0x0701dc07, 0x0701dc07},
+ {0x0000a638, 0x03005302, 0x03005302, 0x02c05202, 0x02c05202, 0x02805202, 0x02805202, 0x0701dc07, 0x0701dc07},
+ {0x0000a63c, 0x04c09302, 0x04c09302, 0x04809202, 0x04809202, 0x04809202, 0x04809202, 0x0701dc07, 0x0701dc07},
+ {0x0000b2dc, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xfffd5aaa, 0xfffd5aaa},
+ {0x0000b2e0, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xfffe9ccc, 0xfffe9ccc},
+ {0x0000b2e4, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xffffe0f0, 0xffffe0f0},
+ {0x0000b2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00},
+ {0x0000c2dc, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xfffd5aaa, 0xfffd5aaa},
+ {0x0000c2e0, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xfffe9ccc, 0xfffe9ccc},
+ {0x0000c2e4, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xffffe0f0, 0xffffe0f0},
+ {0x0000c2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00},
+ {0x00016044, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4},
+ {0x00016048, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x66482401, 0x66482401},
+ {0x00016280, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01808e84, 0x01808e84},
+ {0x00016444, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4},
+ {0x00016448, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x66482401, 0x66482401},
+ {0x00016844, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4},
+ {0x00016848, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x66482401, 0x66482401},
+};
+
+static const u32 ar955x_1p0_mac_core[][2] = {
+ /* Addr allmodes */
+ {0x00000008, 0x00000000},
+ {0x00000030, 0x00020085},
+ {0x00000034, 0x00000005},
+ {0x00000040, 0x00000000},
+ {0x00000044, 0x00000000},
+ {0x00000048, 0x00000008},
+ {0x0000004c, 0x00000010},
+ {0x00000050, 0x00000000},
+ {0x00001040, 0x002ffc0f},
+ {0x00001044, 0x002ffc0f},
+ {0x00001048, 0x002ffc0f},
+ {0x0000104c, 0x002ffc0f},
+ {0x00001050, 0x002ffc0f},
+ {0x00001054, 0x002ffc0f},
+ {0x00001058, 0x002ffc0f},
+ {0x0000105c, 0x002ffc0f},
+ {0x00001060, 0x002ffc0f},
+ {0x00001064, 0x002ffc0f},
+ {0x000010f0, 0x00000100},
+ {0x00001270, 0x00000000},
+ {0x000012b0, 0x00000000},
+ {0x000012f0, 0x00000000},
+ {0x0000143c, 0x00000000},
+ {0x0000147c, 0x00000000},
+ {0x00008000, 0x00000000},
+ {0x00008004, 0x00000000},
+ {0x00008008, 0x00000000},
+ {0x0000800c, 0x00000000},
+ {0x00008018, 0x00000000},
+ {0x00008020, 0x00000000},
+ {0x00008038, 0x00000000},
+ {0x0000803c, 0x00000000},
+ {0x00008040, 0x00000000},
+ {0x00008044, 0x00000000},
+ {0x00008048, 0x00000000},
+ {0x0000804c, 0xffffffff},
+ {0x00008054, 0x00000000},
+ {0x00008058, 0x00000000},
+ {0x0000805c, 0x000fc78f},
+ {0x00008060, 0x0000000f},
+ {0x00008064, 0x00000000},
+ {0x00008070, 0x00000310},
+ {0x00008074, 0x00000020},
+ {0x00008078, 0x00000000},
+ {0x0000809c, 0x0000000f},
+ {0x000080a0, 0x00000000},
+ {0x000080a4, 0x02ff0000},
+ {0x000080a8, 0x0e070605},
+ {0x000080ac, 0x0000000d},
+ {0x000080b0, 0x00000000},
+ {0x000080b4, 0x00000000},
+ {0x000080b8, 0x00000000},
+ {0x000080bc, 0x00000000},
+ {0x000080c0, 0x2a800000},
+ {0x000080c4, 0x06900168},
+ {0x000080c8, 0x13881c22},
+ {0x000080cc, 0x01f40000},
+ {0x000080d0, 0x00252500},
+ {0x000080d4, 0x00a00000},
+ {0x000080d8, 0x00400000},
+ {0x000080dc, 0x00000000},
+ {0x000080e0, 0xffffffff},
+ {0x000080e4, 0x0000ffff},
+ {0x000080e8, 0x3f3f3f3f},
+ {0x000080ec, 0x00000000},
+ {0x000080f0, 0x00000000},
+ {0x000080f4, 0x00000000},
+ {0x000080fc, 0x00020000},
+ {0x00008100, 0x00000000},
+ {0x00008108, 0x00000052},
+ {0x0000810c, 0x00000000},
+ {0x00008110, 0x00000000},
+ {0x00008114, 0x000007ff},
+ {0x00008118, 0x000000aa},
+ {0x0000811c, 0x00003210},
+ {0x00008124, 0x00000000},
+ {0x00008128, 0x00000000},
+ {0x0000812c, 0x00000000},
+ {0x00008130, 0x00000000},
+ {0x00008134, 0x00000000},
+ {0x00008138, 0x00000000},
+ {0x0000813c, 0x0000ffff},
+ {0x00008140, 0x000000fe},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x000081c0, 0x00000000},
+ {0x000081c4, 0x33332210},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008244, 0x0010f400},
+ {0x00008248, 0x00000800},
+ {0x0000824c, 0x0001e800},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x40000000},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x9d400010},
+ {0x00008268, 0xffffffff},
+ {0x0000826c, 0x0000ffff},
+ {0x00008270, 0x00000000},
+ {0x00008274, 0x40000000},
+ {0x00008278, 0x003e4180},
+ {0x0000827c, 0x00000004},
+ {0x00008284, 0x0000002c},
+ {0x00008288, 0x0000002c},
+ {0x0000828c, 0x000000ff},
+ {0x00008294, 0x00000000},
+ {0x00008298, 0x00000000},
+ {0x0000829c, 0x00000000},
+ {0x00008300, 0x00001d40},
+ {0x00008314, 0x00000000},
+ {0x0000831c, 0x0000010d},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x0000001f},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000700},
+ {0x00008338, 0xffff0000},
+ {0x0000833c, 0x02400000},
+ {0x00008340, 0x000107ff},
+ {0x00008344, 0xaa48107b},
+ {0x00008348, 0x008f0000},
+ {0x0000835c, 0x00000000},
+ {0x00008360, 0xffffffff},
+ {0x00008364, 0xffffffff},
+ {0x00008368, 0x00000000},
+ {0x00008370, 0x00000000},
+ {0x00008374, 0x000000ff},
+ {0x00008378, 0x00000000},
+ {0x0000837c, 0x00000000},
+ {0x00008380, 0xffffffff},
+ {0x00008384, 0xffffffff},
+ {0x00008390, 0xffffffff},
+ {0x00008394, 0xffffffff},
+ {0x00008398, 0x00000000},
+ {0x0000839c, 0x00000000},
+ {0x000083a0, 0x00000000},
+ {0x000083a4, 0x0000fa14},
+ {0x000083a8, 0x000f0c00},
+ {0x000083ac, 0x33332210},
+ {0x000083b0, 0x33332210},
+ {0x000083b4, 0x33332210},
+ {0x000083b8, 0x33332210},
+ {0x000083bc, 0x00000000},
+ {0x000083c0, 0x00000000},
+ {0x000083c4, 0x00000000},
+ {0x000083c8, 0x00000000},
+ {0x000083cc, 0x00000200},
+ {0x000083d0, 0x8c7901ff},
+};
+
+static const u32 ar955x_1p0_common_rx_gain_table[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x00830082},
+ {0x0000a014, 0x01810180},
+ {0x0000a018, 0x01830182},
+ {0x0000a01c, 0x01850184},
+ {0x0000a020, 0x01890188},
+ {0x0000a024, 0x018b018a},
+ {0x0000a028, 0x018d018c},
+ {0x0000a02c, 0x01910190},
+ {0x0000a030, 0x01930192},
+ {0x0000a034, 0x01950194},
+ {0x0000a038, 0x038a0196},
+ {0x0000a03c, 0x038c038b},
+ {0x0000a040, 0x0390038d},
+ {0x0000a044, 0x03920391},
+ {0x0000a048, 0x03940393},
+ {0x0000a04c, 0x03960395},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x22222229},
+ {0x0000a084, 0x1d1d1d1d},
+ {0x0000a088, 0x1d1d1d1d},
+ {0x0000a08c, 0x1d1d1d1d},
+ {0x0000a090, 0x171d1d1d},
+ {0x0000a094, 0x11111717},
+ {0x0000a098, 0x00030311},
+ {0x0000a09c, 0x00000000},
+ {0x0000a0a0, 0x00000000},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x01000101},
+ {0x0000a0c8, 0x011e011f},
+ {0x0000a0cc, 0x011c011d},
+ {0x0000a0d0, 0x02030204},
+ {0x0000a0d4, 0x02010202},
+ {0x0000a0d8, 0x021f0200},
+ {0x0000a0dc, 0x0302021e},
+ {0x0000a0e0, 0x03000301},
+ {0x0000a0e4, 0x031e031f},
+ {0x0000a0e8, 0x0402031d},
+ {0x0000a0ec, 0x04000401},
+ {0x0000a0f0, 0x041e041f},
+ {0x0000a0f4, 0x0502041d},
+ {0x0000a0f8, 0x05000501},
+ {0x0000a0fc, 0x051e051f},
+ {0x0000a100, 0x06010602},
+ {0x0000a104, 0x061f0600},
+ {0x0000a108, 0x061d061e},
+ {0x0000a10c, 0x07020703},
+ {0x0000a110, 0x07000701},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x01000101},
+ {0x0000a148, 0x011e011f},
+ {0x0000a14c, 0x011c011d},
+ {0x0000a150, 0x02030204},
+ {0x0000a154, 0x02010202},
+ {0x0000a158, 0x021f0200},
+ {0x0000a15c, 0x0302021e},
+ {0x0000a160, 0x03000301},
+ {0x0000a164, 0x031e031f},
+ {0x0000a168, 0x0402031d},
+ {0x0000a16c, 0x04000401},
+ {0x0000a170, 0x041e041f},
+ {0x0000a174, 0x0502041d},
+ {0x0000a178, 0x05000501},
+ {0x0000a17c, 0x051e051f},
+ {0x0000a180, 0x06010602},
+ {0x0000a184, 0x061f0600},
+ {0x0000a188, 0x061d061e},
+ {0x0000a18c, 0x07020703},
+ {0x0000a190, 0x07000701},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000196},
+ {0x0000b000, 0x00010000},
+ {0x0000b004, 0x00030002},
+ {0x0000b008, 0x00050004},
+ {0x0000b00c, 0x00810080},
+ {0x0000b010, 0x00830082},
+ {0x0000b014, 0x01810180},
+ {0x0000b018, 0x01830182},
+ {0x0000b01c, 0x01850184},
+ {0x0000b020, 0x02810280},
+ {0x0000b024, 0x02830282},
+ {0x0000b028, 0x02850284},
+ {0x0000b02c, 0x02890288},
+ {0x0000b030, 0x028b028a},
+ {0x0000b034, 0x0388028c},
+ {0x0000b038, 0x038a0389},
+ {0x0000b03c, 0x038c038b},
+ {0x0000b040, 0x0390038d},
+ {0x0000b044, 0x03920391},
+ {0x0000b048, 0x03940393},
+ {0x0000b04c, 0x03960395},
+ {0x0000b050, 0x00000000},
+ {0x0000b054, 0x00000000},
+ {0x0000b058, 0x00000000},
+ {0x0000b05c, 0x00000000},
+ {0x0000b060, 0x00000000},
+ {0x0000b064, 0x00000000},
+ {0x0000b068, 0x00000000},
+ {0x0000b06c, 0x00000000},
+ {0x0000b070, 0x00000000},
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+ {0x0000b080, 0x23232323},
+ {0x0000b084, 0x21232323},
+ {0x0000b088, 0x19191c1e},
+ {0x0000b08c, 0x12141417},
+ {0x0000b090, 0x07070e0e},
+ {0x0000b094, 0x03030305},
+ {0x0000b098, 0x00000003},
+ {0x0000b09c, 0x00000000},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+ {0x0000b0ac, 0x00000000},
+ {0x0000b0b0, 0x00000000},
+ {0x0000b0b4, 0x00000000},
+ {0x0000b0b8, 0x00000000},
+ {0x0000b0bc, 0x00000000},
+ {0x0000b0c0, 0x003f0020},
+ {0x0000b0c4, 0x00400041},
+ {0x0000b0c8, 0x0140005f},
+ {0x0000b0cc, 0x0160015f},
+ {0x0000b0d0, 0x017e017f},
+ {0x0000b0d4, 0x02410242},
+ {0x0000b0d8, 0x025f0240},
+ {0x0000b0dc, 0x027f0260},
+ {0x0000b0e0, 0x0341027e},
+ {0x0000b0e4, 0x035f0340},
+ {0x0000b0e8, 0x037f0360},
+ {0x0000b0ec, 0x04400441},
+ {0x0000b0f0, 0x0460045f},
+ {0x0000b0f4, 0x0541047f},
+ {0x0000b0f8, 0x055f0540},
+ {0x0000b0fc, 0x057f0560},
+ {0x0000b100, 0x06400641},
+ {0x0000b104, 0x0660065f},
+ {0x0000b108, 0x067e067f},
+ {0x0000b10c, 0x07410742},
+ {0x0000b110, 0x075f0740},
+ {0x0000b114, 0x077f0760},
+ {0x0000b118, 0x07800781},
+ {0x0000b11c, 0x07a0079f},
+ {0x0000b120, 0x07c107bf},
+ {0x0000b124, 0x000007c0},
+ {0x0000b128, 0x00000000},
+ {0x0000b12c, 0x00000000},
+ {0x0000b130, 0x00000000},
+ {0x0000b134, 0x00000000},
+ {0x0000b138, 0x00000000},
+ {0x0000b13c, 0x00000000},
+ {0x0000b140, 0x003f0020},
+ {0x0000b144, 0x00400041},
+ {0x0000b148, 0x0140005f},
+ {0x0000b14c, 0x0160015f},
+ {0x0000b150, 0x017e017f},
+ {0x0000b154, 0x02410242},
+ {0x0000b158, 0x025f0240},
+ {0x0000b15c, 0x027f0260},
+ {0x0000b160, 0x0341027e},
+ {0x0000b164, 0x035f0340},
+ {0x0000b168, 0x037f0360},
+ {0x0000b16c, 0x04400441},
+ {0x0000b170, 0x0460045f},
+ {0x0000b174, 0x0541047f},
+ {0x0000b178, 0x055f0540},
+ {0x0000b17c, 0x057f0560},
+ {0x0000b180, 0x06400641},
+ {0x0000b184, 0x0660065f},
+ {0x0000b188, 0x067e067f},
+ {0x0000b18c, 0x07410742},
+ {0x0000b190, 0x075f0740},
+ {0x0000b194, 0x077f0760},
+ {0x0000b198, 0x07800781},
+ {0x0000b19c, 0x07a0079f},
+ {0x0000b1a0, 0x07c107bf},
+ {0x0000b1a4, 0x000007c0},
+ {0x0000b1a8, 0x00000000},
+ {0x0000b1ac, 0x00000000},
+ {0x0000b1b0, 0x00000000},
+ {0x0000b1b4, 0x00000000},
+ {0x0000b1b8, 0x00000000},
+ {0x0000b1bc, 0x00000000},
+ {0x0000b1c0, 0x00000000},
+ {0x0000b1c4, 0x00000000},
+ {0x0000b1c8, 0x00000000},
+ {0x0000b1cc, 0x00000000},
+ {0x0000b1d0, 0x00000000},
+ {0x0000b1d4, 0x00000000},
+ {0x0000b1d8, 0x00000000},
+ {0x0000b1dc, 0x00000000},
+ {0x0000b1e0, 0x00000000},
+ {0x0000b1e4, 0x00000000},
+ {0x0000b1e8, 0x00000000},
+ {0x0000b1ec, 0x00000000},
+ {0x0000b1f0, 0x00000396},
+ {0x0000b1f4, 0x00000396},
+ {0x0000b1f8, 0x00000396},
+ {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar955x_1p0_baseband_core[][2] = {
+ /* Addr allmodes */
+ {0x00009800, 0xafe68e30},
+ {0x00009804, 0xfd14e000},
+ {0x00009808, 0x9c0a9f6b},
+ {0x0000980c, 0x04900000},
+ {0x00009814, 0x0280c00a},
+ {0x00009818, 0x00000000},
+ {0x0000981c, 0x00020028},
+ {0x00009834, 0x6400a190},
+ {0x00009838, 0x0108ecff},
+ {0x0000983c, 0x14000600},
+ {0x00009880, 0x201fff00},
+ {0x00009884, 0x00001042},
+ {0x000098a4, 0x00200400},
+ {0x000098b0, 0x32840bbe},
+ {0x000098bc, 0x00000002},
+ {0x000098d0, 0x004b6a8e},
+ {0x000098d4, 0x00000820},
+ {0x000098dc, 0x00000000},
+ {0x000098f0, 0x00000000},
+ {0x000098f4, 0x00000000},
+ {0x00009c04, 0xff55ff55},
+ {0x00009c08, 0x0320ff55},
+ {0x00009c0c, 0x00000000},
+ {0x00009c10, 0x00000000},
+ {0x00009c14, 0x00046384},
+ {0x00009c18, 0x05b6b440},
+ {0x00009c1c, 0x00b6b440},
+ {0x00009d00, 0xc080a333},
+ {0x00009d04, 0x40206c10},
+ {0x00009d08, 0x009c4060},
+ {0x00009d0c, 0x9883800a},
+ {0x00009d10, 0x01834061},
+ {0x00009d14, 0x00c0040b},
+ {0x00009d18, 0x00000000},
+ {0x00009e08, 0x0038230c},
+ {0x00009e24, 0x990bb515},
+ {0x00009e28, 0x0c6f0000},
+ {0x00009e30, 0x06336f77},
+ {0x00009e34, 0x6af6532f},
+ {0x00009e38, 0x0cc80c00},
+ {0x00009e40, 0x0d261820},
+ {0x00009e4c, 0x00001004},
+ {0x00009e50, 0x00ff03f1},
+ {0x00009fc0, 0x813e4788},
+ {0x00009fc4, 0x0001efb5},
+ {0x00009fcc, 0x40000014},
+ {0x00009fd0, 0x01193b93},
+ {0x0000a20c, 0x00000000},
+ {0x0000a220, 0x00000000},
+ {0x0000a224, 0x00000000},
+ {0x0000a228, 0x10002310},
+ {0x0000a23c, 0x00000000},
+ {0x0000a244, 0x0c000000},
+ {0x0000a248, 0x00000140},
+ {0x0000a2a0, 0x00000007},
+ {0x0000a2c0, 0x00000007},
+ {0x0000a2c8, 0x00000000},
+ {0x0000a2d4, 0x00000000},
+ {0x0000a2ec, 0x00000000},
+ {0x0000a2f0, 0x00000000},
+ {0x0000a2f4, 0x00000000},
+ {0x0000a2f8, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a34c, 0x00000000},
+ {0x0000a350, 0x0000a000},
+ {0x0000a364, 0x00000000},
+ {0x0000a370, 0x00000000},
+ {0x0000a390, 0x00000001},
+ {0x0000a394, 0x00000444},
+ {0x0000a398, 0x1f020503},
+ {0x0000a39c, 0x29180c03},
+ {0x0000a3a0, 0x9a8b6844},
+ {0x0000a3a4, 0x00000000},
+ {0x0000a3a8, 0xaaaaaaaa},
+ {0x0000a3ac, 0x3c466478},
+ {0x0000a3c0, 0x20202020},
+ {0x0000a3c4, 0x22222220},
+ {0x0000a3c8, 0x20200020},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3d8, 0x20202020},
+ {0x0000a3dc, 0x20202020},
+ {0x0000a3e0, 0x20202020},
+ {0x0000a3e4, 0x20202020},
+ {0x0000a3e8, 0x20202020},
+ {0x0000a3ec, 0x20202020},
+ {0x0000a3f0, 0x00000000},
+ {0x0000a3f4, 0x00000000},
+ {0x0000a3f8, 0x0c9bd380},
+ {0x0000a3fc, 0x000f0f01},
+ {0x0000a400, 0x8fa91f01},
+ {0x0000a404, 0x00000000},
+ {0x0000a408, 0x0e79e5c6},
+ {0x0000a40c, 0x00820820},
+ {0x0000a414, 0x1ce739ce},
+ {0x0000a418, 0x2d001dce},
+ {0x0000a41c, 0x1ce739ce},
+ {0x0000a420, 0x000001ce},
+ {0x0000a424, 0x1ce739ce},
+ {0x0000a428, 0x000001ce},
+ {0x0000a42c, 0x1ce739ce},
+ {0x0000a430, 0x1ce739ce},
+ {0x0000a434, 0x00000000},
+ {0x0000a438, 0x00001801},
+ {0x0000a43c, 0x00100000},
+ {0x0000a444, 0x00000000},
+ {0x0000a448, 0x05000080},
+ {0x0000a44c, 0x00000001},
+ {0x0000a450, 0x00010000},
+ {0x0000a458, 0x00000000},
+ {0x0000a644, 0x3fad9d74},
+ {0x0000a648, 0x0048060a},
+ {0x0000a64c, 0x00003c37},
+ {0x0000a670, 0x03020100},
+ {0x0000a674, 0x09080504},
+ {0x0000a678, 0x0d0c0b0a},
+ {0x0000a67c, 0x13121110},
+ {0x0000a680, 0x31301514},
+ {0x0000a684, 0x35343332},
+ {0x0000a688, 0x00000036},
+ {0x0000a690, 0x00000838},
+ {0x0000a7cc, 0x00000000},
+ {0x0000a7d0, 0x00000000},
+ {0x0000a7d4, 0x00000004},
+ {0x0000a7dc, 0x00000000},
+ {0x0000a8d0, 0x004b6a8e},
+ {0x0000a8d4, 0x00000820},
+ {0x0000a8dc, 0x00000000},
+ {0x0000a8f0, 0x00000000},
+ {0x0000a8f4, 0x00000000},
+ {0x0000b2d0, 0x00000080},
+ {0x0000b2d4, 0x00000000},
+ {0x0000b2ec, 0x00000000},
+ {0x0000b2f0, 0x00000000},
+ {0x0000b2f4, 0x00000000},
+ {0x0000b2f8, 0x00000000},
+ {0x0000b408, 0x0e79e5c0},
+ {0x0000b40c, 0x00820820},
+ {0x0000b420, 0x00000000},
+ {0x0000b8d0, 0x004b6a8e},
+ {0x0000b8d4, 0x00000820},
+ {0x0000b8dc, 0x00000000},
+ {0x0000b8f0, 0x00000000},
+ {0x0000b8f4, 0x00000000},
+ {0x0000c2d0, 0x00000080},
+ {0x0000c2d4, 0x00000000},
+ {0x0000c2ec, 0x00000000},
+ {0x0000c2f0, 0x00000000},
+ {0x0000c2f4, 0x00000000},
+ {0x0000c2f8, 0x00000000},
+ {0x0000c408, 0x0e79e5c0},
+ {0x0000c40c, 0x00820820},
+ {0x0000c420, 0x00000000},
+};
+
+static const u32 ar955x_1p0_common_wo_xlna_rx_gain_table[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x00830082},
+ {0x0000a014, 0x01810180},
+ {0x0000a018, 0x01830182},
+ {0x0000a01c, 0x01850184},
+ {0x0000a020, 0x01890188},
+ {0x0000a024, 0x018b018a},
+ {0x0000a028, 0x018d018c},
+ {0x0000a02c, 0x03820190},
+ {0x0000a030, 0x03840383},
+ {0x0000a034, 0x03880385},
+ {0x0000a038, 0x038a0389},
+ {0x0000a03c, 0x038c038b},
+ {0x0000a040, 0x0390038d},
+ {0x0000a044, 0x03920391},
+ {0x0000a048, 0x03940393},
+ {0x0000a04c, 0x03960395},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x29292929},
+ {0x0000a084, 0x29292929},
+ {0x0000a088, 0x29292929},
+ {0x0000a08c, 0x29292929},
+ {0x0000a090, 0x22292929},
+ {0x0000a094, 0x1d1d2222},
+ {0x0000a098, 0x0c111117},
+ {0x0000a09c, 0x00030303},
+ {0x0000a0a0, 0x00000000},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x01000101},
+ {0x0000a0c8, 0x011e011f},
+ {0x0000a0cc, 0x011c011d},
+ {0x0000a0d0, 0x02030204},
+ {0x0000a0d4, 0x02010202},
+ {0x0000a0d8, 0x021f0200},
+ {0x0000a0dc, 0x0302021e},
+ {0x0000a0e0, 0x03000301},
+ {0x0000a0e4, 0x031e031f},
+ {0x0000a0e8, 0x0402031d},
+ {0x0000a0ec, 0x04000401},
+ {0x0000a0f0, 0x041e041f},
+ {0x0000a0f4, 0x0502041d},
+ {0x0000a0f8, 0x05000501},
+ {0x0000a0fc, 0x051e051f},
+ {0x0000a100, 0x06010602},
+ {0x0000a104, 0x061f0600},
+ {0x0000a108, 0x061d061e},
+ {0x0000a10c, 0x07020703},
+ {0x0000a110, 0x07000701},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x01000101},
+ {0x0000a148, 0x011e011f},
+ {0x0000a14c, 0x011c011d},
+ {0x0000a150, 0x02030204},
+ {0x0000a154, 0x02010202},
+ {0x0000a158, 0x021f0200},
+ {0x0000a15c, 0x0302021e},
+ {0x0000a160, 0x03000301},
+ {0x0000a164, 0x031e031f},
+ {0x0000a168, 0x0402031d},
+ {0x0000a16c, 0x04000401},
+ {0x0000a170, 0x041e041f},
+ {0x0000a174, 0x0502041d},
+ {0x0000a178, 0x05000501},
+ {0x0000a17c, 0x051e051f},
+ {0x0000a180, 0x06010602},
+ {0x0000a184, 0x061f0600},
+ {0x0000a188, 0x061d061e},
+ {0x0000a18c, 0x07020703},
+ {0x0000a190, 0x07000701},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000196},
+ {0x0000b000, 0x00010000},
+ {0x0000b004, 0x00030002},
+ {0x0000b008, 0x00050004},
+ {0x0000b00c, 0x00810080},
+ {0x0000b010, 0x00830082},
+ {0x0000b014, 0x01810180},
+ {0x0000b018, 0x01830182},
+ {0x0000b01c, 0x01850184},
+ {0x0000b020, 0x02810280},
+ {0x0000b024, 0x02830282},
+ {0x0000b028, 0x02850284},
+ {0x0000b02c, 0x02890288},
+ {0x0000b030, 0x028b028a},
+ {0x0000b034, 0x0388028c},
+ {0x0000b038, 0x038a0389},
+ {0x0000b03c, 0x038c038b},
+ {0x0000b040, 0x0390038d},
+ {0x0000b044, 0x03920391},
+ {0x0000b048, 0x03940393},
+ {0x0000b04c, 0x03960395},
+ {0x0000b050, 0x00000000},
+ {0x0000b054, 0x00000000},
+ {0x0000b058, 0x00000000},
+ {0x0000b05c, 0x00000000},
+ {0x0000b060, 0x00000000},
+ {0x0000b064, 0x00000000},
+ {0x0000b068, 0x00000000},
+ {0x0000b06c, 0x00000000},
+ {0x0000b070, 0x00000000},
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+ {0x0000b080, 0x32323232},
+ {0x0000b084, 0x2f2f3232},
+ {0x0000b088, 0x23282a2d},
+ {0x0000b08c, 0x1c1e2123},
+ {0x0000b090, 0x14171919},
+ {0x0000b094, 0x0e0e1214},
+ {0x0000b098, 0x03050707},
+ {0x0000b09c, 0x00030303},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+ {0x0000b0ac, 0x00000000},
+ {0x0000b0b0, 0x00000000},
+ {0x0000b0b4, 0x00000000},
+ {0x0000b0b8, 0x00000000},
+ {0x0000b0bc, 0x00000000},
+ {0x0000b0c0, 0x003f0020},
+ {0x0000b0c4, 0x00400041},
+ {0x0000b0c8, 0x0140005f},
+ {0x0000b0cc, 0x0160015f},
+ {0x0000b0d0, 0x017e017f},
+ {0x0000b0d4, 0x02410242},
+ {0x0000b0d8, 0x025f0240},
+ {0x0000b0dc, 0x027f0260},
+ {0x0000b0e0, 0x0341027e},
+ {0x0000b0e4, 0x035f0340},
+ {0x0000b0e8, 0x037f0360},
+ {0x0000b0ec, 0x04400441},
+ {0x0000b0f0, 0x0460045f},
+ {0x0000b0f4, 0x0541047f},
+ {0x0000b0f8, 0x055f0540},
+ {0x0000b0fc, 0x057f0560},
+ {0x0000b100, 0x06400641},
+ {0x0000b104, 0x0660065f},
+ {0x0000b108, 0x067e067f},
+ {0x0000b10c, 0x07410742},
+ {0x0000b110, 0x075f0740},
+ {0x0000b114, 0x077f0760},
+ {0x0000b118, 0x07800781},
+ {0x0000b11c, 0x07a0079f},
+ {0x0000b120, 0x07c107bf},
+ {0x0000b124, 0x000007c0},
+ {0x0000b128, 0x00000000},
+ {0x0000b12c, 0x00000000},
+ {0x0000b130, 0x00000000},
+ {0x0000b134, 0x00000000},
+ {0x0000b138, 0x00000000},
+ {0x0000b13c, 0x00000000},
+ {0x0000b140, 0x003f0020},
+ {0x0000b144, 0x00400041},
+ {0x0000b148, 0x0140005f},
+ {0x0000b14c, 0x0160015f},
+ {0x0000b150, 0x017e017f},
+ {0x0000b154, 0x02410242},
+ {0x0000b158, 0x025f0240},
+ {0x0000b15c, 0x027f0260},
+ {0x0000b160, 0x0341027e},
+ {0x0000b164, 0x035f0340},
+ {0x0000b168, 0x037f0360},
+ {0x0000b16c, 0x04400441},
+ {0x0000b170, 0x0460045f},
+ {0x0000b174, 0x0541047f},
+ {0x0000b178, 0x055f0540},
+ {0x0000b17c, 0x057f0560},
+ {0x0000b180, 0x06400641},
+ {0x0000b184, 0x0660065f},
+ {0x0000b188, 0x067e067f},
+ {0x0000b18c, 0x07410742},
+ {0x0000b190, 0x075f0740},
+ {0x0000b194, 0x077f0760},
+ {0x0000b198, 0x07800781},
+ {0x0000b19c, 0x07a0079f},
+ {0x0000b1a0, 0x07c107bf},
+ {0x0000b1a4, 0x000007c0},
+ {0x0000b1a8, 0x00000000},
+ {0x0000b1ac, 0x00000000},
+ {0x0000b1b0, 0x00000000},
+ {0x0000b1b4, 0x00000000},
+ {0x0000b1b8, 0x00000000},
+ {0x0000b1bc, 0x00000000},
+ {0x0000b1c0, 0x00000000},
+ {0x0000b1c4, 0x00000000},
+ {0x0000b1c8, 0x00000000},
+ {0x0000b1cc, 0x00000000},
+ {0x0000b1d0, 0x00000000},
+ {0x0000b1d4, 0x00000000},
+ {0x0000b1d8, 0x00000000},
+ {0x0000b1dc, 0x00000000},
+ {0x0000b1e0, 0x00000000},
+ {0x0000b1e4, 0x00000000},
+ {0x0000b1e8, 0x00000000},
+ {0x0000b1ec, 0x00000000},
+ {0x0000b1f0, 0x00000396},
+ {0x0000b1f4, 0x00000396},
+ {0x0000b1f8, 0x00000396},
+ {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar955x_1p0_soc_preamble[][2] = {
+ /* Addr allmodes */
+ {0x00007000, 0x00000000},
+ {0x00007004, 0x00000000},
+ {0x00007008, 0x00000000},
+ {0x0000700c, 0x00000000},
+ {0x0000701c, 0x00000000},
+ {0x00007020, 0x00000000},
+ {0x00007024, 0x00000000},
+ {0x00007028, 0x00000000},
+ {0x0000702c, 0x00000000},
+ {0x00007030, 0x00000000},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000004c2},
+ {0x00007048, 0x00000000},
+};
+
+static const u32 ar955x_1p0_common_wo_xlna_rx_gain_bounds[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+};
+
+static const u32 ar955x_1p0_mac_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar955x_1p0_common_rx_gain_bounds[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302018, 0x50302018},
+};
+
+static const u32 ar955x_1p0_modes_no_xpa_tx_gain_table[][9] = {
+ /* Addr 5G_HT20_L 5G_HT40_L 5G_HT20_M 5G_HT40_M 5G_HT20_H 5G_HT40_H 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0xfffe5aaa, 0xfffe5aaa},
+ {0x0000a2e0, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0xfffe9ccc, 0xfffe9ccc},
+ {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0xffffe0f0, 0xffffe0f0},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffef00, 0xffffef00},
+ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d8, 0x000050d8, 0x000050d8, 0x000050d8, 0x000050d7, 0x000050d7},
+ {0x0000a500, 0x00002220, 0x00002220, 0x00002220, 0x00002220, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+ {0x0000a504, 0x04002222, 0x04002222, 0x04002222, 0x04002222, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+ {0x0000a508, 0x09002421, 0x09002421, 0x09002421, 0x09002421, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x0d002621, 0x0d002621, 0x0d002621, 0x0d002621, 0x0d002621, 0x0d002621, 0x0b000006, 0x0b000006},
+ {0x0000a510, 0x13004620, 0x13004620, 0x13004620, 0x13004620, 0x13004620, 0x13004620, 0x0f00000a, 0x0f00000a},
+ {0x0000a514, 0x19004a20, 0x19004a20, 0x19004a20, 0x19004a20, 0x19004a20, 0x19004a20, 0x1300000c, 0x1300000c},
+ {0x0000a518, 0x1d004e20, 0x1d004e20, 0x1d004e20, 0x1d004e20, 0x1d004e20, 0x1d004e20, 0x1700000e, 0x1700000e},
+ {0x0000a51c, 0x21005420, 0x21005420, 0x21005420, 0x21005420, 0x21005420, 0x21005420, 0x1b000012, 0x1b000012},
+ {0x0000a520, 0x26005e20, 0x26005e20, 0x26005e20, 0x26005e20, 0x26005e20, 0x26005e20, 0x1f00004a, 0x1f00004a},
+ {0x0000a524, 0x2b005e40, 0x2b005e40, 0x2b005e40, 0x2b005e40, 0x2b005e40, 0x2b005e40, 0x23000244, 0x23000244},
+ {0x0000a528, 0x2f005e42, 0x2f005e42, 0x2f005e42, 0x2f005e42, 0x2f005e42, 0x2f005e42, 0x2700022b, 0x2700022b},
+ {0x0000a52c, 0x33005e44, 0x33005e44, 0x33005e44, 0x33005e44, 0x33005e44, 0x33005e44, 0x2b000625, 0x2b000625},
+ {0x0000a530, 0x38005e65, 0x38005e65, 0x38005e65, 0x38005e65, 0x38005e65, 0x38005e65, 0x2f001006, 0x2f001006},
+ {0x0000a534, 0x3c005e69, 0x3c005e69, 0x3c005e69, 0x3c005e69, 0x3c005e69, 0x3c005e69, 0x330008a0, 0x330008a0},
+ {0x0000a538, 0x40005e6b, 0x40005e6b, 0x40005e6b, 0x40005e6b, 0x40005e6b, 0x40005e6b, 0x37000a2a, 0x37000a2a},
+ {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x44005e6d, 0x44005e6d, 0x44005e6d, 0x44005e6d, 0x3b001c23, 0x3b001c23},
+ {0x0000a540, 0x49005e72, 0x49005e72, 0x49005e72, 0x49005e72, 0x49005e72, 0x49005e72, 0x3f0014a0, 0x3f0014a0},
+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x4e005eb2, 0x4e005eb2, 0x4e005eb2, 0x4e005eb2, 0x43001882, 0x43001882},
+ {0x0000a548, 0x53005f12, 0x53005f12, 0x53005f12, 0x53005f12, 0x53005f12, 0x53005f12, 0x47001ca2, 0x47001ca2},
+ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x59025eb2, 0x59025eb2, 0x59025eb2, 0x59025eb2, 0x4b001ec3, 0x4b001ec3},
+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x5e025f12, 0x5e025f12, 0x5e025f12, 0x5e025f12, 0x4f00148c, 0x4f00148c},
+ {0x0000a554, 0x61027f12, 0x61027f12, 0x61027f12, 0x61027f12, 0x61027f12, 0x61027f12, 0x53001c6e, 0x53001c6e},
+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x6702bf12, 0x6702bf12, 0x6702bf12, 0x6702bf12, 0x57001c92, 0x57001c92},
+ {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x6b02bf14, 0x6b02bf14, 0x6b02bf14, 0x6b02bf14, 0x5c001af6, 0x5c001af6},
+ {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
+ {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
+ {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
+ {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
+ {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
+ {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
+ {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
+ {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x6f02bf16, 0x5c001af6, 0x5c001af6},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00804000, 0x00804000, 0x00804000, 0x00804000, 0x00804000, 0x00804000, 0x04005001, 0x04005001},
+ {0x0000a614, 0x00804201, 0x00804201, 0x00804201, 0x00804201, 0x00804201, 0x00804201, 0x03808e02, 0x03808e02},
+ {0x0000a618, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802, 0x0300c000, 0x0300c000},
+ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x03808e02, 0x03808e02},
+ {0x0000a620, 0x04c15104, 0x04c15104, 0x04c15104, 0x04c15104, 0x04c15104, 0x04c15104, 0x03410c03, 0x03410c03},
+ {0x0000a624, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04014c03, 0x04014c03},
+ {0x0000a628, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x05818d04, 0x05818d04},
+ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x0801cd04, 0x0801cd04},
+ {0x0000a630, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x0801e007, 0x0801e007},
+ {0x0000a634, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x0801e007, 0x0801e007},
+ {0x0000a638, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x0801e007, 0x0801e007},
+ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x04c15305, 0x0801e007, 0x0801e007},
+ {0x0000b2dc, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0xfffe5aaa, 0xfffe5aaa},
+ {0x0000b2e0, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0xfffe9ccc, 0xfffe9ccc},
+ {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0xffffe0f0, 0xffffe0f0},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffef00, 0xffffef00},
+ {0x0000c2dc, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0x01feee00, 0xfffe5aaa, 0xfffe5aaa},
+ {0x0000c2e0, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0x0000f000, 0xfffe9ccc, 0xfffe9ccc},
+ {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0x01ff0000, 0xffffe0f0, 0xffffe0f0},
+ {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffef00, 0xffffef00},
+ {0x00016044, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x054922d4, 0x054922d4},
+ {0x00016048, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401},
+ {0x00016444, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x054922d4, 0x054922d4},
+ {0x00016448, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401},
+ {0x00016844, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x054922d4, 0x054922d4},
+ {0x00016848, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401},
+};
+
+static const u32 ar955x_1p0_soc_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
+};
+
+static const u32 ar955x_1p0_modes_fast_clock[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x00001030, 0x00000268, 0x000004d0},
+ {0x00001070, 0x0000018c, 0x00000318},
+ {0x000010b0, 0x00000fd0, 0x00001fa0},
+ {0x00008014, 0x044c044c, 0x08980898},
+ {0x0000801c, 0x148ec02b, 0x148ec057},
+ {0x00008318, 0x000044c0, 0x00008980},
+ {0x00009e00, 0x0372131c, 0x0372131c},
+ {0x0000a230, 0x0000000b, 0x00000016},
+ {0x0000a254, 0x00000898, 0x00001130},
+};
+
+#endif /* INITVALS_955X_1P0_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
index 06b3f0df9fad..6e1915aee712 100644
--- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -19,18 +20,7 @@
/* AR9580 1.0 */
-static const u32 ar9580_1p0_modes_fast_clock[][3] = {
- /* Addr 5G_HT20 5G_HT40 */
- {0x00001030, 0x00000268, 0x000004d0},
- {0x00001070, 0x0000018c, 0x00000318},
- {0x000010b0, 0x00000fd0, 0x00001fa0},
- {0x00008014, 0x044c044c, 0x08980898},
- {0x0000801c, 0x148ec02b, 0x148ec057},
- {0x00008318, 0x000044c0, 0x00008980},
- {0x00009e00, 0x0372131c, 0x0372131c},
- {0x0000a230, 0x0000000b, 0x00000016},
- {0x0000a254, 0x00000898, 0x00001130},
-};
+#define ar9580_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2
static const u32 ar9580_1p0_radio_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
@@ -208,17 +198,7 @@ static const u32 ar9580_1p0_baseband_core[][2] = {
{0x0000c420, 0x00000000},
};
-static const u32 ar9580_1p0_mac_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
- {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
- {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
-};
+#define ar9580_1p0_mac_postamble ar9300_2p2_mac_postamble
static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
@@ -326,111 +306,7 @@ static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = {
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
};
-static const u32 ar9580_1p0_high_power_tx_gain_table[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
- {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
- {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
- {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
- {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
- {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
- {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
- {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
- {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
- {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
- {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
- {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
- {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
- {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
- {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
- {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
- {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
- {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
- {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
- {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
- {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
- {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
- {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83},
- {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84},
- {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3},
- {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5},
- {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9},
- {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb},
- {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
- {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
- {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
- {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
- {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
- {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
- {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
- {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
- {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
- {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
- {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
- {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
- {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
- {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
- {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
- {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
- {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
- {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
- {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
- {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
- {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
- {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
- {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
- {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
- {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
- {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
- {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83},
- {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84},
- {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3},
- {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5},
- {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9},
- {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb},
- {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
- {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
- {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
- {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
- {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
- {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
- {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
- {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
- {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
- {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
- {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
- {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
- {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
- {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
- {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
- {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
- {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
- {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
- {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
- {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
- {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
- {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
- {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
- {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
- {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
- {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
- {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
- {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
- {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
- {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
- {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
- {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
- {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
- {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
- {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
-};
+#define ar9580_1p0_high_power_tx_gain_table ar9580_1p0_low_ob_db_tx_gain_table
static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
@@ -538,12 +414,7 @@ static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = {
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
};
-static const u32 ar9580_1p0_baseband_core_txfir_coeff_japan_2484[][2] = {
- /* Addr allmodes */
- {0x0000a398, 0x00000000},
- {0x0000a39c, 0x6f7f0301},
- {0x0000a3a0, 0xca9228ee},
-};
+#define ar9580_1p0_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
static const u32 ar9580_1p0_mac_core[][2] = {
/* Addr allmodes */
@@ -808,376 +679,11 @@ static const u32 ar9580_1p0_mixed_ob_db_tx_gain_table[][5] = {
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
};
-static const u32 ar9580_1p0_wo_xlna_rx_gain_table[][2] = {
- /* Addr allmodes */
- {0x0000a000, 0x00010000},
- {0x0000a004, 0x00030002},
- {0x0000a008, 0x00050004},
- {0x0000a00c, 0x00810080},
- {0x0000a010, 0x00830082},
- {0x0000a014, 0x01810180},
- {0x0000a018, 0x01830182},
- {0x0000a01c, 0x01850184},
- {0x0000a020, 0x01890188},
- {0x0000a024, 0x018b018a},
- {0x0000a028, 0x018d018c},
- {0x0000a02c, 0x03820190},
- {0x0000a030, 0x03840383},
- {0x0000a034, 0x03880385},
- {0x0000a038, 0x038a0389},
- {0x0000a03c, 0x038c038b},
- {0x0000a040, 0x0390038d},
- {0x0000a044, 0x03920391},
- {0x0000a048, 0x03940393},
- {0x0000a04c, 0x03960395},
- {0x0000a050, 0x00000000},
- {0x0000a054, 0x00000000},
- {0x0000a058, 0x00000000},
- {0x0000a05c, 0x00000000},
- {0x0000a060, 0x00000000},
- {0x0000a064, 0x00000000},
- {0x0000a068, 0x00000000},
- {0x0000a06c, 0x00000000},
- {0x0000a070, 0x00000000},
- {0x0000a074, 0x00000000},
- {0x0000a078, 0x00000000},
- {0x0000a07c, 0x00000000},
- {0x0000a080, 0x29292929},
- {0x0000a084, 0x29292929},
- {0x0000a088, 0x29292929},
- {0x0000a08c, 0x29292929},
- {0x0000a090, 0x22292929},
- {0x0000a094, 0x1d1d2222},
- {0x0000a098, 0x0c111117},
- {0x0000a09c, 0x00030303},
- {0x0000a0a0, 0x00000000},
- {0x0000a0a4, 0x00000000},
- {0x0000a0a8, 0x00000000},
- {0x0000a0ac, 0x00000000},
- {0x0000a0b0, 0x00000000},
- {0x0000a0b4, 0x00000000},
- {0x0000a0b8, 0x00000000},
- {0x0000a0bc, 0x00000000},
- {0x0000a0c0, 0x001f0000},
- {0x0000a0c4, 0x01000101},
- {0x0000a0c8, 0x011e011f},
- {0x0000a0cc, 0x011c011d},
- {0x0000a0d0, 0x02030204},
- {0x0000a0d4, 0x02010202},
- {0x0000a0d8, 0x021f0200},
- {0x0000a0dc, 0x0302021e},
- {0x0000a0e0, 0x03000301},
- {0x0000a0e4, 0x031e031f},
- {0x0000a0e8, 0x0402031d},
- {0x0000a0ec, 0x04000401},
- {0x0000a0f0, 0x041e041f},
- {0x0000a0f4, 0x0502041d},
- {0x0000a0f8, 0x05000501},
- {0x0000a0fc, 0x051e051f},
- {0x0000a100, 0x06010602},
- {0x0000a104, 0x061f0600},
- {0x0000a108, 0x061d061e},
- {0x0000a10c, 0x07020703},
- {0x0000a110, 0x07000701},
- {0x0000a114, 0x00000000},
- {0x0000a118, 0x00000000},
- {0x0000a11c, 0x00000000},
- {0x0000a120, 0x00000000},
- {0x0000a124, 0x00000000},
- {0x0000a128, 0x00000000},
- {0x0000a12c, 0x00000000},
- {0x0000a130, 0x00000000},
- {0x0000a134, 0x00000000},
- {0x0000a138, 0x00000000},
- {0x0000a13c, 0x00000000},
- {0x0000a140, 0x001f0000},
- {0x0000a144, 0x01000101},
- {0x0000a148, 0x011e011f},
- {0x0000a14c, 0x011c011d},
- {0x0000a150, 0x02030204},
- {0x0000a154, 0x02010202},
- {0x0000a158, 0x021f0200},
- {0x0000a15c, 0x0302021e},
- {0x0000a160, 0x03000301},
- {0x0000a164, 0x031e031f},
- {0x0000a168, 0x0402031d},
- {0x0000a16c, 0x04000401},
- {0x0000a170, 0x041e041f},
- {0x0000a174, 0x0502041d},
- {0x0000a178, 0x05000501},
- {0x0000a17c, 0x051e051f},
- {0x0000a180, 0x06010602},
- {0x0000a184, 0x061f0600},
- {0x0000a188, 0x061d061e},
- {0x0000a18c, 0x07020703},
- {0x0000a190, 0x07000701},
- {0x0000a194, 0x00000000},
- {0x0000a198, 0x00000000},
- {0x0000a19c, 0x00000000},
- {0x0000a1a0, 0x00000000},
- {0x0000a1a4, 0x00000000},
- {0x0000a1a8, 0x00000000},
- {0x0000a1ac, 0x00000000},
- {0x0000a1b0, 0x00000000},
- {0x0000a1b4, 0x00000000},
- {0x0000a1b8, 0x00000000},
- {0x0000a1bc, 0x00000000},
- {0x0000a1c0, 0x00000000},
- {0x0000a1c4, 0x00000000},
- {0x0000a1c8, 0x00000000},
- {0x0000a1cc, 0x00000000},
- {0x0000a1d0, 0x00000000},
- {0x0000a1d4, 0x00000000},
- {0x0000a1d8, 0x00000000},
- {0x0000a1dc, 0x00000000},
- {0x0000a1e0, 0x00000000},
- {0x0000a1e4, 0x00000000},
- {0x0000a1e8, 0x00000000},
- {0x0000a1ec, 0x00000000},
- {0x0000a1f0, 0x00000396},
- {0x0000a1f4, 0x00000396},
- {0x0000a1f8, 0x00000396},
- {0x0000a1fc, 0x00000196},
- {0x0000b000, 0x00010000},
- {0x0000b004, 0x00030002},
- {0x0000b008, 0x00050004},
- {0x0000b00c, 0x00810080},
- {0x0000b010, 0x00830082},
- {0x0000b014, 0x01810180},
- {0x0000b018, 0x01830182},
- {0x0000b01c, 0x01850184},
- {0x0000b020, 0x02810280},
- {0x0000b024, 0x02830282},
- {0x0000b028, 0x02850284},
- {0x0000b02c, 0x02890288},
- {0x0000b030, 0x028b028a},
- {0x0000b034, 0x0388028c},
- {0x0000b038, 0x038a0389},
- {0x0000b03c, 0x038c038b},
- {0x0000b040, 0x0390038d},
- {0x0000b044, 0x03920391},
- {0x0000b048, 0x03940393},
- {0x0000b04c, 0x03960395},
- {0x0000b050, 0x00000000},
- {0x0000b054, 0x00000000},
- {0x0000b058, 0x00000000},
- {0x0000b05c, 0x00000000},
- {0x0000b060, 0x00000000},
- {0x0000b064, 0x00000000},
- {0x0000b068, 0x00000000},
- {0x0000b06c, 0x00000000},
- {0x0000b070, 0x00000000},
- {0x0000b074, 0x00000000},
- {0x0000b078, 0x00000000},
- {0x0000b07c, 0x00000000},
- {0x0000b080, 0x32323232},
- {0x0000b084, 0x2f2f3232},
- {0x0000b088, 0x23282a2d},
- {0x0000b08c, 0x1c1e2123},
- {0x0000b090, 0x14171919},
- {0x0000b094, 0x0e0e1214},
- {0x0000b098, 0x03050707},
- {0x0000b09c, 0x00030303},
- {0x0000b0a0, 0x00000000},
- {0x0000b0a4, 0x00000000},
- {0x0000b0a8, 0x00000000},
- {0x0000b0ac, 0x00000000},
- {0x0000b0b0, 0x00000000},
- {0x0000b0b4, 0x00000000},
- {0x0000b0b8, 0x00000000},
- {0x0000b0bc, 0x00000000},
- {0x0000b0c0, 0x003f0020},
- {0x0000b0c4, 0x00400041},
- {0x0000b0c8, 0x0140005f},
- {0x0000b0cc, 0x0160015f},
- {0x0000b0d0, 0x017e017f},
- {0x0000b0d4, 0x02410242},
- {0x0000b0d8, 0x025f0240},
- {0x0000b0dc, 0x027f0260},
- {0x0000b0e0, 0x0341027e},
- {0x0000b0e4, 0x035f0340},
- {0x0000b0e8, 0x037f0360},
- {0x0000b0ec, 0x04400441},
- {0x0000b0f0, 0x0460045f},
- {0x0000b0f4, 0x0541047f},
- {0x0000b0f8, 0x055f0540},
- {0x0000b0fc, 0x057f0560},
- {0x0000b100, 0x06400641},
- {0x0000b104, 0x0660065f},
- {0x0000b108, 0x067e067f},
- {0x0000b10c, 0x07410742},
- {0x0000b110, 0x075f0740},
- {0x0000b114, 0x077f0760},
- {0x0000b118, 0x07800781},
- {0x0000b11c, 0x07a0079f},
- {0x0000b120, 0x07c107bf},
- {0x0000b124, 0x000007c0},
- {0x0000b128, 0x00000000},
- {0x0000b12c, 0x00000000},
- {0x0000b130, 0x00000000},
- {0x0000b134, 0x00000000},
- {0x0000b138, 0x00000000},
- {0x0000b13c, 0x00000000},
- {0x0000b140, 0x003f0020},
- {0x0000b144, 0x00400041},
- {0x0000b148, 0x0140005f},
- {0x0000b14c, 0x0160015f},
- {0x0000b150, 0x017e017f},
- {0x0000b154, 0x02410242},
- {0x0000b158, 0x025f0240},
- {0x0000b15c, 0x027f0260},
- {0x0000b160, 0x0341027e},
- {0x0000b164, 0x035f0340},
- {0x0000b168, 0x037f0360},
- {0x0000b16c, 0x04400441},
- {0x0000b170, 0x0460045f},
- {0x0000b174, 0x0541047f},
- {0x0000b178, 0x055f0540},
- {0x0000b17c, 0x057f0560},
- {0x0000b180, 0x06400641},
- {0x0000b184, 0x0660065f},
- {0x0000b188, 0x067e067f},
- {0x0000b18c, 0x07410742},
- {0x0000b190, 0x075f0740},
- {0x0000b194, 0x077f0760},
- {0x0000b198, 0x07800781},
- {0x0000b19c, 0x07a0079f},
- {0x0000b1a0, 0x07c107bf},
- {0x0000b1a4, 0x000007c0},
- {0x0000b1a8, 0x00000000},
- {0x0000b1ac, 0x00000000},
- {0x0000b1b0, 0x00000000},
- {0x0000b1b4, 0x00000000},
- {0x0000b1b8, 0x00000000},
- {0x0000b1bc, 0x00000000},
- {0x0000b1c0, 0x00000000},
- {0x0000b1c4, 0x00000000},
- {0x0000b1c8, 0x00000000},
- {0x0000b1cc, 0x00000000},
- {0x0000b1d0, 0x00000000},
- {0x0000b1d4, 0x00000000},
- {0x0000b1d8, 0x00000000},
- {0x0000b1dc, 0x00000000},
- {0x0000b1e0, 0x00000000},
- {0x0000b1e4, 0x00000000},
- {0x0000b1e8, 0x00000000},
- {0x0000b1ec, 0x00000000},
- {0x0000b1f0, 0x00000396},
- {0x0000b1f4, 0x00000396},
- {0x0000b1f8, 0x00000396},
- {0x0000b1fc, 0x00000196},
-};
+#define ar9580_1p0_wo_xlna_rx_gain_table ar9300Common_wo_xlna_rx_gain_table_2p2
-static const u32 ar9580_1p0_soc_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
-};
+#define ar9580_1p0_soc_postamble ar9300_2p2_soc_postamble
-static const u32 ar9580_1p0_high_ob_db_tx_gain_table[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
- {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
- {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
- {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
- {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
- {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
- {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
- {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
- {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
- {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
- {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
- {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
- {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
- {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
- {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
- {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
- {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
- {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
- {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
- {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
- {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
- {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
- {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
- {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
- {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
- {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
- {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
- {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
- {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
- {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
- {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
- {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
- {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
- {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
- {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
- {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
- {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
- {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
- {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
- {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
- {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
- {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
- {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
- {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
- {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
- {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
- {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
- {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
- {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
- {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
- {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
- {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
- {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
- {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
- {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
- {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
- {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
- {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
- {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
- {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
- {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
- {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
- {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
- {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
- {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
- {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
- {0x0000c2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
- {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
- {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
- {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
- {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
- {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
- {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
- {0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
- {0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
- {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
- {0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
- {0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
- {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
-};
+#define ar9580_1p0_high_ob_db_tx_gain_table ar9300Modes_high_ob_db_tx_gain_table_2p2
static const u32 ar9580_1p0_soc_preamble[][2] = {
/* Addr allmodes */
@@ -1189,265 +695,7 @@ static const u32 ar9580_1p0_soc_preamble[][2] = {
{0x00007048, 0x00000008},
};
-static const u32 ar9580_1p0_rx_gain_table[][2] = {
- /* Addr allmodes */
- {0x0000a000, 0x00010000},
- {0x0000a004, 0x00030002},
- {0x0000a008, 0x00050004},
- {0x0000a00c, 0x00810080},
- {0x0000a010, 0x00830082},
- {0x0000a014, 0x01810180},
- {0x0000a018, 0x01830182},
- {0x0000a01c, 0x01850184},
- {0x0000a020, 0x01890188},
- {0x0000a024, 0x018b018a},
- {0x0000a028, 0x018d018c},
- {0x0000a02c, 0x01910190},
- {0x0000a030, 0x01930192},
- {0x0000a034, 0x01950194},
- {0x0000a038, 0x038a0196},
- {0x0000a03c, 0x038c038b},
- {0x0000a040, 0x0390038d},
- {0x0000a044, 0x03920391},
- {0x0000a048, 0x03940393},
- {0x0000a04c, 0x03960395},
- {0x0000a050, 0x00000000},
- {0x0000a054, 0x00000000},
- {0x0000a058, 0x00000000},
- {0x0000a05c, 0x00000000},
- {0x0000a060, 0x00000000},
- {0x0000a064, 0x00000000},
- {0x0000a068, 0x00000000},
- {0x0000a06c, 0x00000000},
- {0x0000a070, 0x00000000},
- {0x0000a074, 0x00000000},
- {0x0000a078, 0x00000000},
- {0x0000a07c, 0x00000000},
- {0x0000a080, 0x22222229},
- {0x0000a084, 0x1d1d1d1d},
- {0x0000a088, 0x1d1d1d1d},
- {0x0000a08c, 0x1d1d1d1d},
- {0x0000a090, 0x171d1d1d},
- {0x0000a094, 0x11111717},
- {0x0000a098, 0x00030311},
- {0x0000a09c, 0x00000000},
- {0x0000a0a0, 0x00000000},
- {0x0000a0a4, 0x00000000},
- {0x0000a0a8, 0x00000000},
- {0x0000a0ac, 0x00000000},
- {0x0000a0b0, 0x00000000},
- {0x0000a0b4, 0x00000000},
- {0x0000a0b8, 0x00000000},
- {0x0000a0bc, 0x00000000},
- {0x0000a0c0, 0x001f0000},
- {0x0000a0c4, 0x01000101},
- {0x0000a0c8, 0x011e011f},
- {0x0000a0cc, 0x011c011d},
- {0x0000a0d0, 0x02030204},
- {0x0000a0d4, 0x02010202},
- {0x0000a0d8, 0x021f0200},
- {0x0000a0dc, 0x0302021e},
- {0x0000a0e0, 0x03000301},
- {0x0000a0e4, 0x031e031f},
- {0x0000a0e8, 0x0402031d},
- {0x0000a0ec, 0x04000401},
- {0x0000a0f0, 0x041e041f},
- {0x0000a0f4, 0x0502041d},
- {0x0000a0f8, 0x05000501},
- {0x0000a0fc, 0x051e051f},
- {0x0000a100, 0x06010602},
- {0x0000a104, 0x061f0600},
- {0x0000a108, 0x061d061e},
- {0x0000a10c, 0x07020703},
- {0x0000a110, 0x07000701},
- {0x0000a114, 0x00000000},
- {0x0000a118, 0x00000000},
- {0x0000a11c, 0x00000000},
- {0x0000a120, 0x00000000},
- {0x0000a124, 0x00000000},
- {0x0000a128, 0x00000000},
- {0x0000a12c, 0x00000000},
- {0x0000a130, 0x00000000},
- {0x0000a134, 0x00000000},
- {0x0000a138, 0x00000000},
- {0x0000a13c, 0x00000000},
- {0x0000a140, 0x001f0000},
- {0x0000a144, 0x01000101},
- {0x0000a148, 0x011e011f},
- {0x0000a14c, 0x011c011d},
- {0x0000a150, 0x02030204},
- {0x0000a154, 0x02010202},
- {0x0000a158, 0x021f0200},
- {0x0000a15c, 0x0302021e},
- {0x0000a160, 0x03000301},
- {0x0000a164, 0x031e031f},
- {0x0000a168, 0x0402031d},
- {0x0000a16c, 0x04000401},
- {0x0000a170, 0x041e041f},
- {0x0000a174, 0x0502041d},
- {0x0000a178, 0x05000501},
- {0x0000a17c, 0x051e051f},
- {0x0000a180, 0x06010602},
- {0x0000a184, 0x061f0600},
- {0x0000a188, 0x061d061e},
- {0x0000a18c, 0x07020703},
- {0x0000a190, 0x07000701},
- {0x0000a194, 0x00000000},
- {0x0000a198, 0x00000000},
- {0x0000a19c, 0x00000000},
- {0x0000a1a0, 0x00000000},
- {0x0000a1a4, 0x00000000},
- {0x0000a1a8, 0x00000000},
- {0x0000a1ac, 0x00000000},
- {0x0000a1b0, 0x00000000},
- {0x0000a1b4, 0x00000000},
- {0x0000a1b8, 0x00000000},
- {0x0000a1bc, 0x00000000},
- {0x0000a1c0, 0x00000000},
- {0x0000a1c4, 0x00000000},
- {0x0000a1c8, 0x00000000},
- {0x0000a1cc, 0x00000000},
- {0x0000a1d0, 0x00000000},
- {0x0000a1d4, 0x00000000},
- {0x0000a1d8, 0x00000000},
- {0x0000a1dc, 0x00000000},
- {0x0000a1e0, 0x00000000},
- {0x0000a1e4, 0x00000000},
- {0x0000a1e8, 0x00000000},
- {0x0000a1ec, 0x00000000},
- {0x0000a1f0, 0x00000396},
- {0x0000a1f4, 0x00000396},
- {0x0000a1f8, 0x00000396},
- {0x0000a1fc, 0x00000196},
- {0x0000b000, 0x00010000},
- {0x0000b004, 0x00030002},
- {0x0000b008, 0x00050004},
- {0x0000b00c, 0x00810080},
- {0x0000b010, 0x00830082},
- {0x0000b014, 0x01810180},
- {0x0000b018, 0x01830182},
- {0x0000b01c, 0x01850184},
- {0x0000b020, 0x02810280},
- {0x0000b024, 0x02830282},
- {0x0000b028, 0x02850284},
- {0x0000b02c, 0x02890288},
- {0x0000b030, 0x028b028a},
- {0x0000b034, 0x0388028c},
- {0x0000b038, 0x038a0389},
- {0x0000b03c, 0x038c038b},
- {0x0000b040, 0x0390038d},
- {0x0000b044, 0x03920391},
- {0x0000b048, 0x03940393},
- {0x0000b04c, 0x03960395},
- {0x0000b050, 0x00000000},
- {0x0000b054, 0x00000000},
- {0x0000b058, 0x00000000},
- {0x0000b05c, 0x00000000},
- {0x0000b060, 0x00000000},
- {0x0000b064, 0x00000000},
- {0x0000b068, 0x00000000},
- {0x0000b06c, 0x00000000},
- {0x0000b070, 0x00000000},
- {0x0000b074, 0x00000000},
- {0x0000b078, 0x00000000},
- {0x0000b07c, 0x00000000},
- {0x0000b080, 0x2a2d2f32},
- {0x0000b084, 0x21232328},
- {0x0000b088, 0x19191c1e},
- {0x0000b08c, 0x12141417},
- {0x0000b090, 0x07070e0e},
- {0x0000b094, 0x03030305},
- {0x0000b098, 0x00000003},
- {0x0000b09c, 0x00000000},
- {0x0000b0a0, 0x00000000},
- {0x0000b0a4, 0x00000000},
- {0x0000b0a8, 0x00000000},
- {0x0000b0ac, 0x00000000},
- {0x0000b0b0, 0x00000000},
- {0x0000b0b4, 0x00000000},
- {0x0000b0b8, 0x00000000},
- {0x0000b0bc, 0x00000000},
- {0x0000b0c0, 0x003f0020},
- {0x0000b0c4, 0x00400041},
- {0x0000b0c8, 0x0140005f},
- {0x0000b0cc, 0x0160015f},
- {0x0000b0d0, 0x017e017f},
- {0x0000b0d4, 0x02410242},
- {0x0000b0d8, 0x025f0240},
- {0x0000b0dc, 0x027f0260},
- {0x0000b0e0, 0x0341027e},
- {0x0000b0e4, 0x035f0340},
- {0x0000b0e8, 0x037f0360},
- {0x0000b0ec, 0x04400441},
- {0x0000b0f0, 0x0460045f},
- {0x0000b0f4, 0x0541047f},
- {0x0000b0f8, 0x055f0540},
- {0x0000b0fc, 0x057f0560},
- {0x0000b100, 0x06400641},
- {0x0000b104, 0x0660065f},
- {0x0000b108, 0x067e067f},
- {0x0000b10c, 0x07410742},
- {0x0000b110, 0x075f0740},
- {0x0000b114, 0x077f0760},
- {0x0000b118, 0x07800781},
- {0x0000b11c, 0x07a0079f},
- {0x0000b120, 0x07c107bf},
- {0x0000b124, 0x000007c0},
- {0x0000b128, 0x00000000},
- {0x0000b12c, 0x00000000},
- {0x0000b130, 0x00000000},
- {0x0000b134, 0x00000000},
- {0x0000b138, 0x00000000},
- {0x0000b13c, 0x00000000},
- {0x0000b140, 0x003f0020},
- {0x0000b144, 0x00400041},
- {0x0000b148, 0x0140005f},
- {0x0000b14c, 0x0160015f},
- {0x0000b150, 0x017e017f},
- {0x0000b154, 0x02410242},
- {0x0000b158, 0x025f0240},
- {0x0000b15c, 0x027f0260},
- {0x0000b160, 0x0341027e},
- {0x0000b164, 0x035f0340},
- {0x0000b168, 0x037f0360},
- {0x0000b16c, 0x04400441},
- {0x0000b170, 0x0460045f},
- {0x0000b174, 0x0541047f},
- {0x0000b178, 0x055f0540},
- {0x0000b17c, 0x057f0560},
- {0x0000b180, 0x06400641},
- {0x0000b184, 0x0660065f},
- {0x0000b188, 0x067e067f},
- {0x0000b18c, 0x07410742},
- {0x0000b190, 0x075f0740},
- {0x0000b194, 0x077f0760},
- {0x0000b198, 0x07800781},
- {0x0000b19c, 0x07a0079f},
- {0x0000b1a0, 0x07c107bf},
- {0x0000b1a4, 0x000007c0},
- {0x0000b1a8, 0x00000000},
- {0x0000b1ac, 0x00000000},
- {0x0000b1b0, 0x00000000},
- {0x0000b1b4, 0x00000000},
- {0x0000b1b8, 0x00000000},
- {0x0000b1bc, 0x00000000},
- {0x0000b1c0, 0x00000000},
- {0x0000b1c4, 0x00000000},
- {0x0000b1c8, 0x00000000},
- {0x0000b1cc, 0x00000000},
- {0x0000b1d0, 0x00000000},
- {0x0000b1d4, 0x00000000},
- {0x0000b1d8, 0x00000000},
- {0x0000b1dc, 0x00000000},
- {0x0000b1e0, 0x00000000},
- {0x0000b1e4, 0x00000000},
- {0x0000b1e8, 0x00000000},
- {0x0000b1ec, 0x00000000},
- {0x0000b1f0, 0x00000396},
- {0x0000b1f4, 0x00000396},
- {0x0000b1f8, 0x00000396},
- {0x0000b1fc, 0x00000196},
-};
+#define ar9580_1p0_rx_gain_table ar9462_common_rx_gain_table_2p0
static const u32 ar9580_1p0_radio_core[][2] = {
/* Addr allmodes */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 02fc1c1e5eeb..79840d6deef2 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -214,6 +214,7 @@ struct ath_frame_info {
enum ath9k_key_type keytype;
u8 keyix;
u8 retries;
+ u8 rtscts_rate;
};
struct ath_buf_state {
@@ -480,6 +481,7 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc);
void ath9k_btcoex_timer_pause(struct ath_softc *sc);
void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status);
u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen);
+void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc);
#else
static inline int ath9k_init_btcoex(struct ath_softc *sc)
{
@@ -503,6 +505,9 @@ static inline u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc,
{
return 0;
}
+static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
+{
+}
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
/********************/
@@ -698,6 +703,7 @@ struct ath_softc {
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
struct ath_btcoex btcoex;
struct ath_mci_coex mci_coex;
+ struct work_struct mci_work;
#endif
struct ath_descdma txsdma;
@@ -720,6 +726,7 @@ extern int ath9k_modparam_nohwcrypt;
extern int led_blink;
extern bool is_ath9k_unloaded;
+u8 ath9k_parse_mpdudensity(u8 mpdudensity);
irqreturn_t ath_isr(int irq, void *dev);
int ath9k_init_device(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops);
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 2831258d9507..5c3192ffc196 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -348,8 +348,6 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
sc->debug.stats.istats.txok++;
if (status & ATH9K_INT_TXURN)
sc->debug.stats.istats.txurn++;
- if (status & ATH9K_INT_MIB)
- sc->debug.stats.istats.mib++;
if (status & ATH9K_INT_RXPHY)
sc->debug.stats.istats.rxphyerr++;
if (status & ATH9K_INT_RXKCM)
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index af6d27350291..bacdb8fb4ef4 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -194,6 +194,14 @@ static void ath_btcoex_period_timer(unsigned long data)
struct ath_mci_profile *mci = &btcoex->mci;
u32 timer_period;
bool is_btscan;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sc->sc_pm_lock, flags);
+ if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) {
+ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+ goto skip_hw_wakeup;
+ }
+ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
ath9k_ps_wakeup(sc);
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
@@ -202,7 +210,7 @@ static void ath_btcoex_period_timer(unsigned long data)
btcoex->bt_wait_time += btcoex->btcoex_period;
if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) {
- if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP, NULL) &&
+ if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) &&
(mci->num_pan || mci->num_other_acl))
ah->btcoex_hw.mci.stomp_ftp =
(sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH);
@@ -232,7 +240,8 @@ static void ath_btcoex_period_timer(unsigned long data)
}
ath9k_ps_restore(sc);
- timer_period = btcoex->btcoex_period / 1000;
+skip_hw_wakeup:
+ timer_period = btcoex->btcoex_period;
mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period));
}
@@ -267,10 +276,10 @@ static int ath_init_btcoex_timer(struct ath_softc *sc)
{
struct ath_btcoex *btcoex = &sc->btcoex;
- btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;
- btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
+ btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
+ btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * 1000 *
btcoex->btcoex_period / 100;
- btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
+ btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * 1000 *
btcoex->btcoex_period / 100;
setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
@@ -305,7 +314,8 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc)
btcoex->bt_priority_cnt = 0;
btcoex->bt_priority_time = jiffies;
- btcoex->op_flags &= ~(BT_OP_PRIORITY_DETECTED | BT_OP_SCAN);
+ clear_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags);
+ clear_bit(BT_OP_SCAN, &btcoex->op_flags);
mod_timer(&btcoex->period_timer, jiffies);
}
@@ -327,6 +337,13 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc)
btcoex->hw_timer_enabled = false;
}
+void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
+{
+ struct ath_btcoex *btcoex = &sc->btcoex;
+
+ ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
+}
+
u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)
{
struct ath_btcoex *btcoex = &sc->btcoex;
@@ -376,9 +393,9 @@ void ath9k_stop_btcoex(struct ath_softc *sc)
if (ah->btcoex_hw.enabled &&
ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
- ath9k_hw_btcoex_disable(ah);
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
ath9k_btcoex_timer_pause(sc);
+ ath9k_hw_btcoex_disable(ah);
if (AR_SREV_9462(ah))
ath_mci_flush_profile(&sc->btcoex.mci);
}
@@ -386,11 +403,13 @@ void ath9k_stop_btcoex(struct ath_softc *sc)
void ath9k_deinit_btcoex(struct ath_softc *sc)
{
+ struct ath_hw *ah = sc->sc_ah;
+
if ((sc->btcoex.no_stomp_timer) &&
ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_3WIRE)
ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
- if (AR_SREV_9462(sc->sc_ah))
+ if (ath9k_hw_mci_is_enabled(ah))
ath_mci_cleanup(sc);
}
@@ -416,7 +435,7 @@ int ath9k_init_btcoex(struct ath_softc *sc)
txq = sc->tx.txq_map[WME_AC_BE];
ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
- if (AR_SREV_9462(ah)) {
+ if (ath9k_hw_mci_is_enabled(ah)) {
sc->btcoex.duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE;
INIT_LIST_HEAD(&sc->btcoex.mci.info);
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 135795257d95..936e920fb88e 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -453,7 +453,6 @@ struct ath9k_htc_priv {
u8 num_sta_assoc_vif;
u8 num_ap_vif;
- u16 op_flags;
u16 curtxpow;
u16 txpowlimit;
u16 nvifs;
@@ -461,6 +460,7 @@ struct ath9k_htc_priv {
bool rearm_ani;
bool reconfig_beacon;
unsigned int rxfilter;
+ unsigned long op_flags;
struct ath9k_hw_cal_data caldata;
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
@@ -572,8 +572,6 @@ bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw);
-void ath9k_htc_radio_enable(struct ieee80211_hw *hw);
-void ath9k_htc_radio_disable(struct ieee80211_hw *hw);
#ifdef CONFIG_MAC80211_LEDS
void ath9k_init_leds(struct ath9k_htc_priv *priv);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index 2eadffb7971c..77d541feb910 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -207,9 +207,9 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
else
priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE;
- if (priv->op_flags & OP_TSF_RESET) {
+ if (test_bit(OP_TSF_RESET, &priv->op_flags)) {
ath9k_hw_reset_tsf(priv->ah);
- priv->op_flags &= ~OP_TSF_RESET;
+ clear_bit(OP_TSF_RESET, &priv->op_flags);
} else {
/*
* Pull nexttbtt forward to reflect the current TSF.
@@ -221,7 +221,7 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
} while (nexttbtt < tsftu);
}
- if (priv->op_flags & OP_ENABLE_BEACON)
+ if (test_bit(OP_ENABLE_BEACON, &priv->op_flags))
imask |= ATH9K_INT_SWBA;
ath_dbg(common, CONFIG,
@@ -269,7 +269,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
else
priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE;
- if (priv->op_flags & OP_ENABLE_BEACON)
+ if (test_bit(OP_ENABLE_BEACON, &priv->op_flags))
imask |= ATH9K_INT_SWBA;
ath_dbg(common, CONFIG,
@@ -365,7 +365,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
vif = priv->cur_beacon_conf.bslot[slot];
avp = (struct ath9k_htc_vif *)vif->drv_priv;
- if (unlikely(priv->op_flags & OP_SCANNING)) {
+ if (unlikely(test_bit(OP_SCANNING, &priv->op_flags))) {
spin_unlock_bh(&priv->beacon_lock);
return;
}
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
index 1c10e2e5c237..07df279c8d46 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
@@ -37,17 +37,18 @@ static void ath_detect_bt_priority(struct ath9k_htc_priv *priv)
if (time_after(jiffies, btcoex->bt_priority_time +
msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
- priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
+ clear_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
+ clear_bit(OP_BT_SCAN, &priv->op_flags);
/* Detect if colocated bt started scanning */
if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
ath_dbg(ath9k_hw_common(ah), BTCOEX,
"BT scan detected\n");
- priv->op_flags |= (OP_BT_SCAN |
- OP_BT_PRIORITY_DETECTED);
+ set_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
+ set_bit(OP_BT_SCAN, &priv->op_flags);
} else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
ath_dbg(ath9k_hw_common(ah), BTCOEX,
"BT priority traffic detected\n");
- priv->op_flags |= OP_BT_PRIORITY_DETECTED;
+ set_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
}
btcoex->bt_priority_cnt = 0;
@@ -67,26 +68,23 @@ static void ath_btcoex_period_work(struct work_struct *work)
struct ath_btcoex *btcoex = &priv->btcoex;
struct ath_common *common = ath9k_hw_common(priv->ah);
u32 timer_period;
- bool is_btscan;
int ret;
ath_detect_bt_priority(priv);
- is_btscan = !!(priv->op_flags & OP_BT_SCAN);
-
ret = ath9k_htc_update_cap_target(priv,
- !!(priv->op_flags & OP_BT_PRIORITY_DETECTED));
+ test_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags));
if (ret) {
ath_err(common, "Unable to set BTCOEX parameters\n");
return;
}
- ath9k_hw_btcoex_bt_stomp(priv->ah, is_btscan ? ATH_BTCOEX_STOMP_ALL :
- btcoex->bt_stomp_type);
+ ath9k_hw_btcoex_bt_stomp(priv->ah, test_bit(OP_BT_SCAN, &priv->op_flags) ?
+ ATH_BTCOEX_STOMP_ALL : btcoex->bt_stomp_type);
ath9k_hw_btcoex_enable(priv->ah);
- timer_period = is_btscan ? btcoex->btscan_no_stomp :
- btcoex->btcoex_no_stomp;
+ timer_period = test_bit(OP_BT_SCAN, &priv->op_flags) ?
+ btcoex->btscan_no_stomp : btcoex->btcoex_no_stomp;
ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work,
msecs_to_jiffies(timer_period));
ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work,
@@ -104,14 +102,15 @@ static void ath_btcoex_duty_cycle_work(struct work_struct *work)
struct ath_hw *ah = priv->ah;
struct ath_btcoex *btcoex = &priv->btcoex;
struct ath_common *common = ath9k_hw_common(ah);
- bool is_btscan = priv->op_flags & OP_BT_SCAN;
ath_dbg(common, BTCOEX, "time slice work for bt and wlan\n");
- if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan)
+ if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW ||
+ test_bit(OP_BT_SCAN, &priv->op_flags))
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
+
ath9k_hw_btcoex_enable(priv->ah);
}
@@ -141,7 +140,8 @@ static void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv)
btcoex->bt_priority_cnt = 0;
btcoex->bt_priority_time = jiffies;
- priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
+ clear_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
+ clear_bit(OP_BT_SCAN, &priv->op_flags);
ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0);
}
@@ -310,95 +310,3 @@ void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
wiphy_rfkill_start_polling(priv->hw->wiphy);
}
-
-void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
-{
- struct ath9k_htc_priv *priv = hw->priv;
- struct ath_hw *ah = priv->ah;
- struct ath_common *common = ath9k_hw_common(ah);
- int ret;
- u8 cmd_rsp;
-
- if (!ah->curchan)
- ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
-
- /* Reset the HW */
- ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
- if (ret) {
- ath_err(common,
- "Unable to reset hardware; reset status %d (freq %u MHz)\n",
- ret, ah->curchan->channel);
- }
-
- ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
- &priv->curtxpow);
-
- /* Start RX */
- WMI_CMD(WMI_START_RECV_CMDID);
- ath9k_host_rx_init(priv);
-
- /* Start TX */
- htc_start(priv->htc);
- spin_lock_bh(&priv->tx.tx_lock);
- priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP;
- spin_unlock_bh(&priv->tx.tx_lock);
- ieee80211_wake_queues(hw);
-
- WMI_CMD(WMI_ENABLE_INTR_CMDID);
-
- /* Enable LED */
- ath9k_hw_cfg_output(ah, ah->led_pin,
- AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
- ath9k_hw_set_gpio(ah, ah->led_pin, 0);
-}
-
-void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
-{
- struct ath9k_htc_priv *priv = hw->priv;
- struct ath_hw *ah = priv->ah;
- struct ath_common *common = ath9k_hw_common(ah);
- int ret;
- u8 cmd_rsp;
-
- ath9k_htc_ps_wakeup(priv);
-
- /* Disable LED */
- ath9k_hw_set_gpio(ah, ah->led_pin, 1);
- ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
-
- WMI_CMD(WMI_DISABLE_INTR_CMDID);
-
- /* Stop TX */
- ieee80211_stop_queues(hw);
- ath9k_htc_tx_drain(priv);
- WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
-
- /* Stop RX */
- WMI_CMD(WMI_STOP_RECV_CMDID);
-
- /* Clear the WMI event queue */
- ath9k_wmi_event_drain(priv);
-
- /*
- * The MIB counters have to be disabled here,
- * since the target doesn't do it.
- */
- ath9k_hw_disable_mib_counters(ah);
-
- if (!ah->curchan)
- ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
-
- /* Reset the HW */
- ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
- if (ret) {
- ath_err(common,
- "Unable to reset hardware; reset status %d (freq %u MHz)\n",
- ret, ah->curchan->channel);
- }
-
- /* Disable the PHY */
- ath9k_hw_phy_disable(ah);
-
- ath9k_htc_ps_restore(priv);
- ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
-}
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 25213d521bc2..a035a380d669 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -611,7 +611,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
struct ath_common *common;
int i, ret = 0, csz = 0;
- priv->op_flags |= OP_INVALID;
+ set_bit(OP_INVALID, &priv->op_flags);
ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
if (!ah)
@@ -718,7 +718,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
hw->queues = 4;
hw->channel_change_time = 5000;
- hw->max_listen_interval = 10;
+ hw->max_listen_interval = 1;
hw->vif_data_size = sizeof(struct ath9k_htc_vif);
hw->sta_data_size = sizeof(struct ath9k_htc_sta);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 2b8f61c210e1..374c32ed905a 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -75,14 +75,19 @@ unlock:
void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv)
{
+ bool reset;
+
mutex_lock(&priv->htc_pm_lock);
if (--priv->ps_usecount != 0)
goto unlock;
- if (priv->ps_idle)
+ if (priv->ps_idle) {
+ ath9k_hw_setrxabort(priv->ah, true);
+ ath9k_hw_stopdmarecv(priv->ah, &reset);
ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP);
- else if (priv->ps_enabled)
+ } else if (priv->ps_enabled) {
ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP);
+ }
unlock:
mutex_unlock(&priv->htc_pm_lock);
@@ -250,7 +255,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
u8 cmd_rsp;
int ret;
- if (priv->op_flags & OP_INVALID)
+ if (test_bit(OP_INVALID, &priv->op_flags))
return -EIO;
fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);
@@ -304,7 +309,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
htc_start(priv->htc);
- if (!(priv->op_flags & OP_SCANNING) &&
+ if (!test_bit(OP_SCANNING, &priv->op_flags) &&
!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
ath9k_htc_vif_reconfig(priv);
@@ -750,7 +755,7 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv)
common->ani.shortcal_timer = timestamp;
common->ani.checkani_timer = timestamp;
- priv->op_flags |= OP_ANI_RUNNING;
+ set_bit(OP_ANI_RUNNING, &priv->op_flags);
ieee80211_queue_delayed_work(common->hw, &priv->ani_work,
msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
@@ -759,7 +764,7 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv)
void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv)
{
cancel_delayed_work_sync(&priv->ani_work);
- priv->op_flags &= ~OP_ANI_RUNNING;
+ clear_bit(OP_ANI_RUNNING, &priv->op_flags);
}
void ath9k_htc_ani_work(struct work_struct *work)
@@ -944,7 +949,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
ath_dbg(common, CONFIG,
"Failed to update capability in target\n");
- priv->op_flags &= ~OP_INVALID;
+ clear_bit(OP_INVALID, &priv->op_flags);
htc_start(priv->htc);
spin_lock_bh(&priv->tx.tx_lock);
@@ -973,7 +978,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
mutex_lock(&priv->mutex);
- if (priv->op_flags & OP_INVALID) {
+ if (test_bit(OP_INVALID, &priv->op_flags)) {
ath_dbg(common, ANY, "Device not present\n");
mutex_unlock(&priv->mutex);
return;
@@ -1015,7 +1020,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
ath9k_htc_ps_restore(priv);
ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
- priv->op_flags |= OP_INVALID;
+ set_bit(OP_INVALID, &priv->op_flags);
ath_dbg(common, CONFIG, "Driver halt\n");
mutex_unlock(&priv->mutex);
@@ -1105,7 +1110,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
ath9k_htc_set_opmode(priv);
if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
- !(priv->op_flags & OP_ANI_RUNNING)) {
+ !test_bit(OP_ANI_RUNNING, &priv->op_flags)) {
ath9k_hw_set_tsfadjust(priv->ah, 1);
ath9k_htc_start_ani(priv);
}
@@ -1178,24 +1183,20 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
struct ath9k_htc_priv *priv = hw->priv;
struct ath_common *common = ath9k_hw_common(priv->ah);
struct ieee80211_conf *conf = &hw->conf;
+ bool chip_reset = false;
+ int ret = 0;
mutex_lock(&priv->mutex);
+ ath9k_htc_ps_wakeup(priv);
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
- bool enable_radio = false;
- bool idle = !!(conf->flags & IEEE80211_CONF_IDLE);
-
mutex_lock(&priv->htc_pm_lock);
- if (!idle && priv->ps_idle)
- enable_radio = true;
- priv->ps_idle = idle;
- mutex_unlock(&priv->htc_pm_lock);
- if (enable_radio) {
- ath_dbg(common, CONFIG, "not-idle: enabling radio\n");
- ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
- ath9k_htc_radio_enable(hw);
- }
+ priv->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
+ if (priv->ps_idle)
+ chip_reset = true;
+
+ mutex_unlock(&priv->htc_pm_lock);
}
/*
@@ -1210,7 +1211,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
ath9k_htc_remove_monitor_interface(priv);
}
- if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || chip_reset) {
struct ieee80211_channel *curchan = hw->conf.channel;
int pos = curchan->hw_value;
@@ -1223,8 +1224,8 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
ath_err(common, "Unable to set channel\n");
- mutex_unlock(&priv->mutex);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
}
@@ -1246,21 +1247,10 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
priv->txpowlimit, &priv->curtxpow);
}
- if (changed & IEEE80211_CONF_CHANGE_IDLE) {
- mutex_lock(&priv->htc_pm_lock);
- if (!priv->ps_idle) {
- mutex_unlock(&priv->htc_pm_lock);
- goto out;
- }
- mutex_unlock(&priv->htc_pm_lock);
-
- ath_dbg(common, CONFIG, "idle: disabling radio\n");
- ath9k_htc_radio_disable(hw);
- }
-
out:
+ ath9k_htc_ps_restore(priv);
mutex_unlock(&priv->mutex);
- return 0;
+ return ret;
}
#define SUPPORTED_FILTERS \
@@ -1285,7 +1275,7 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
changed_flags &= SUPPORTED_FILTERS;
*total_flags &= SUPPORTED_FILTERS;
- if (priv->op_flags & OP_INVALID) {
+ if (test_bit(OP_INVALID, &priv->op_flags)) {
ath_dbg(ath9k_hw_common(priv->ah), ANY,
"Unable to configure filter on invalid state\n");
mutex_unlock(&priv->mutex);
@@ -1496,6 +1486,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
priv->num_sta_assoc_vif++ : priv->num_sta_assoc_vif--;
if (priv->ah->opmode == NL80211_IFTYPE_STATION) {
+ ath9k_htc_choose_set_bssid(priv);
if (bss_conf->assoc && (priv->num_sta_assoc_vif == 1))
ath9k_htc_start_ani(priv);
else if (priv->num_sta_assoc_vif == 0)
@@ -1503,13 +1494,11 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
}
}
- if (changed & BSS_CHANGED_BSSID) {
+ if (changed & BSS_CHANGED_IBSS) {
if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) {
common->curaid = bss_conf->aid;
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
ath9k_htc_set_bssid(priv);
- } else if (priv->ah->opmode == NL80211_IFTYPE_STATION) {
- ath9k_htc_choose_set_bssid(priv);
}
}
@@ -1517,7 +1506,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
ath_dbg(common, CONFIG, "Beacon enabled for BSS: %pM\n",
bss_conf->bssid);
ath9k_htc_set_tsfadjust(priv, vif);
- priv->op_flags |= OP_ENABLE_BEACON;
+ set_bit(OP_ENABLE_BEACON, &priv->op_flags);
ath9k_htc_beacon_config(priv, vif);
}
@@ -1530,7 +1519,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
ath_dbg(common, CONFIG,
"Beacon disabled for BSS: %pM\n",
bss_conf->bssid);
- priv->op_flags &= ~OP_ENABLE_BEACON;
+ clear_bit(OP_ENABLE_BEACON, &priv->op_flags);
ath9k_htc_beacon_config(priv, vif);
}
}
@@ -1543,7 +1532,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
(priv->nvifs == 1) &&
(priv->num_ap_vif == 1) &&
(vif->type == NL80211_IFTYPE_AP)) {
- priv->op_flags |= OP_TSF_RESET;
+ set_bit(OP_TSF_RESET, &priv->op_flags);
}
ath_dbg(common, CONFIG,
"Beacon interval changed for BSS: %pM\n",
@@ -1655,7 +1644,7 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
mutex_lock(&priv->mutex);
spin_lock_bh(&priv->beacon_lock);
- priv->op_flags |= OP_SCANNING;
+ set_bit(OP_SCANNING, &priv->op_flags);
spin_unlock_bh(&priv->beacon_lock);
cancel_work_sync(&priv->ps_work);
ath9k_htc_stop_ani(priv);
@@ -1668,7 +1657,7 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
mutex_lock(&priv->mutex);
spin_lock_bh(&priv->beacon_lock);
- priv->op_flags &= ~OP_SCANNING;
+ clear_bit(OP_SCANNING, &priv->op_flags);
spin_unlock_bh(&priv->beacon_lock);
ath9k_htc_ps_wakeup(priv);
ath9k_htc_vif_reconfig(priv);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 3e40a6461512..47e61d0da33b 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -916,7 +916,7 @@ void ath9k_host_rx_init(struct ath9k_htc_priv *priv)
{
ath9k_hw_rxena(priv->ah);
ath9k_htc_opmode_init(priv);
- ath9k_hw_startpcureceive(priv->ah, (priv->op_flags & OP_SCANNING));
+ ath9k_hw_startpcureceive(priv->ah, test_bit(OP_SCANNING, &priv->op_flags));
priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER;
}
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 45e670087e1c..c1659d079513 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -342,6 +342,9 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
val = REG_READ(ah, AR_SREV);
ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
return;
+ case AR9300_DEVID_QCA955X:
+ ah->hw_version.macVersion = AR_SREV_VERSION_9550;
+ return;
}
val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
@@ -614,7 +617,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
- ((AR_SREV_9160(ah) || AR_SREV_9280(ah)) &&
+ ((AR_SREV_9160(ah) || AR_SREV_9280(ah) || AR_SREV_9287(ah)) &&
!ah->is_pciexpress)) {
ah->config.serialize_regmode =
SER_REG_MODE_ON;
@@ -646,6 +649,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
case AR_SREV_VERSION_9485:
case AR_SREV_VERSION_9340:
case AR_SREV_VERSION_9462:
+ case AR_SREV_VERSION_9550:
break;
default:
ath_err(common,
@@ -655,7 +659,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
}
if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) ||
- AR_SREV_9330(ah))
+ AR_SREV_9330(ah) || AR_SREV_9550(ah))
ah->is_pciexpress = false;
ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
@@ -727,6 +731,7 @@ int ath9k_hw_init(struct ath_hw *ah)
case AR9300_DEVID_AR9485_PCIE:
case AR9300_DEVID_AR9330:
case AR9300_DEVID_AR9340:
+ case AR9300_DEVID_QCA955X:
case AR9300_DEVID_AR9580:
case AR9300_DEVID_AR9462:
break;
@@ -773,13 +778,25 @@ static void ath9k_hw_init_qos(struct ath_hw *ah)
u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah)
{
+ struct ath_common *common = ath9k_hw_common(ah);
+ int i = 0;
+
REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK);
udelay(100);
REG_SET_BIT(ah, PLL3, PLL3_DO_MEAS_MASK);
- while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0)
+ while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) {
+
udelay(100);
+ if (WARN_ON_ONCE(i >= 100)) {
+ ath_err(common, "PLL4 meaurement not done\n");
+ break;
+ }
+
+ i++;
+ }
+
return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3;
}
EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc);
@@ -853,7 +870,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
/* program BB PLL phase_shift */
REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1);
- } else if (AR_SREV_9340(ah)) {
+ } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) {
u32 regval, pll2_divint, pll2_divfrac, refdiv;
REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
@@ -867,9 +884,15 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
pll2_divfrac = 0x1eb85;
refdiv = 3;
} else {
- pll2_divint = 88;
- pll2_divfrac = 0;
- refdiv = 5;
+ if (AR_SREV_9340(ah)) {
+ pll2_divint = 88;
+ pll2_divfrac = 0;
+ refdiv = 5;
+ } else {
+ pll2_divint = 0x11;
+ pll2_divfrac = 0x26666;
+ refdiv = 1;
+ }
}
regval = REG_READ(ah, AR_PHY_PLL_MODE);
@@ -882,8 +905,12 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
udelay(100);
regval = REG_READ(ah, AR_PHY_PLL_MODE);
- regval = (regval & 0x80071fff) | (0x1 << 30) | (0x1 << 13) |
- (0x4 << 26) | (0x18 << 19);
+ if (AR_SREV_9340(ah))
+ regval = (regval & 0x80071fff) | (0x1 << 30) |
+ (0x1 << 13) | (0x4 << 26) | (0x18 << 19);
+ else
+ regval = (regval & 0x80071fff) | (0x3 << 30) |
+ (0x1 << 13) | (0x4 << 26) | (0x60 << 19);
REG_WRITE(ah, AR_PHY_PLL_MODE, regval);
REG_WRITE(ah, AR_PHY_PLL_MODE,
REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff);
@@ -894,7 +921,8 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
- if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) ||
+ AR_SREV_9550(ah))
udelay(1000);
/* Switch the core clock for ar9271 to 117Mhz */
@@ -907,7 +935,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
- if (AR_SREV_9340(ah)) {
+ if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) {
if (ah->is_clk_25mhz) {
REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1);
REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7);
@@ -931,7 +959,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
AR_IMR_RXORN |
AR_IMR_BCNMISC;
- if (AR_SREV_9340(ah))
+ if (AR_SREV_9340(ah) || AR_SREV_9550(ah))
sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
if (AR_SREV_9300_20_OR_LATER(ah)) {
@@ -1348,6 +1376,9 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
}
}
+ if (ath9k_hw_mci_is_enabled(ah))
+ ar9003_mci_check_gpm_offset(ah);
+
REG_WRITE(ah, AR_RTC_RC, rst_flags);
REGWRITE_BUFFER_FLUSH(ah);
@@ -1708,7 +1739,7 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
ath9k_hw_start_nfcal(ah, true);
if (ath9k_hw_mci_is_enabled(ah))
- ar9003_mci_2g5g_switch(ah, true);
+ ar9003_mci_2g5g_switch(ah, false);
if (AR_SREV_9271(ah))
ar9002_hw_load_ani_reg(ah, chan);
@@ -1912,7 +1943,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_set_dma(ah);
- REG_WRITE(ah, AR_OBS, 8);
+ if (!ath9k_hw_mci_is_enabled(ah))
+ REG_WRITE(ah, AR_OBS, 8);
if (ah->config.rx_intr_mitigation) {
REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
@@ -1933,9 +1965,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (!ath9k_hw_init_cal(ah, chan))
return -EIO;
- ath9k_hw_loadnf(ah, chan);
- ath9k_hw_start_nfcal(ah, true);
-
if (ath9k_hw_mci_is_enabled(ah) && ar9003_mci_end_reset(ah, chan, caldata))
return -EIO;
@@ -1971,7 +2000,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
}
#ifdef __BIG_ENDIAN
- else if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
+ else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) ||
+ AR_SREV_9550(ah))
REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0);
else
REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
@@ -1984,6 +2014,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (ath9k_hw_mci_is_enabled(ah))
ar9003_mci_check_bt(ah);
+ ath9k_hw_loadnf(ah, chan);
+ ath9k_hw_start_nfcal(ah, true);
+
if (AR_SREV_9300_20_OR_LATER(ah)) {
ar9003_hw_bb_watchdog_config(ah);
@@ -2111,6 +2144,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
AR_RTC_FORCE_WAKE_EN);
udelay(50);
+ if (ath9k_hw_mci_is_enabled(ah))
+ ar9003_mci_set_power_awake(ah);
+
for (i = POWER_UP_TIME / 50; i > 0; i--) {
val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
if (val == AR_RTC_STATUS_ON)
@@ -3118,6 +3154,7 @@ static struct {
{ AR_SREV_VERSION_9340, "9340" },
{ AR_SREV_VERSION_9485, "9485" },
{ AR_SREV_VERSION_9462, "9462" },
+ { AR_SREV_VERSION_9550, "9550" },
};
/* For devices with external radios */
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 03d590924c64..26da1732978d 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -48,6 +48,7 @@
#define AR9300_DEVID_AR9580 0x0033
#define AR9300_DEVID_AR9462 0x0034
#define AR9300_DEVID_AR9330 0x0035
+#define AR9300_DEVID_QCA955X 0x0038
#define AR5416_AR9100_DEVID 0x000b
@@ -818,6 +819,7 @@ struct ath_hw {
struct ar5416IniArray iniModesFastClock;
struct ar5416IniArray iniAdditional;
struct ar5416IniArray iniModesRxGain;
+ struct ar5416IniArray ini_modes_rx_gain_bounds;
struct ar5416IniArray iniModesTxGain;
struct ar5416IniArray iniCckfirNormal;
struct ar5416IniArray iniCckfirJapan2484;
@@ -1019,16 +1021,8 @@ void ar9002_hw_attach_ops(struct ath_hw *ah);
void ar9003_hw_attach_ops(struct ath_hw *ah);
void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan);
-/*
- * ANI work can be shared between all families but a next
- * generation implementation of ANI will be used only for AR9003 only
- * for now as the other families still need to be tested with the same
- * next generation ANI. Feel free to start testing it though for the
- * older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani.
- */
-extern int modparam_force_new_ani;
+
void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning);
-void ath9k_hw_proc_mib_event(struct ath_hw *ah);
void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan);
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
@@ -1038,7 +1032,8 @@ static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah)
}
static inline bool ath9k_hw_mci_is_enabled(struct ath_hw *ah)
{
- return ah->btcoex_hw.enabled && (ah->caps.hw_caps & ATH9K_HW_CAP_MCI);
+ return ah->common.btcoex_enabled &&
+ (ah->caps.hw_caps & ATH9K_HW_CAP_MCI);
}
void ath9k_hw_btcoex_enable(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index 0cc4c70f7f0c..91650fe50461 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -136,6 +136,14 @@ void ath_hw_pll_work(struct work_struct *work)
u32 pll_sqsum;
struct ath_softc *sc = container_of(work, struct ath_softc,
hw_pll_work.work);
+ /*
+ * ensure that the PLL WAR is executed only
+ * after the STA is associated (or) if the
+ * beaconing had started in interfaces that
+ * uses beacons.
+ */
+ if (!test_bit(SC_OP_BEACONS, &sc->sc_flags))
+ return;
ath9k_ps_wakeup(sc);
pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
@@ -399,6 +407,7 @@ void ath_ani_calibrate(unsigned long data)
longcal ? "long" : "", shortcal ? "short" : "",
aniflag ? "ani" : "", common->ani.caldone ? "true" : "false");
+ ath9k_debug_samp_bb_mac(sc);
ath9k_ps_restore(sc);
set_timer:
@@ -407,7 +416,6 @@ set_timer:
* The interval must be the shortest necessary to satisfy ANI,
* short calibration and long calibration.
*/
- ath9k_debug_samp_bb_mac(sc);
cal_interval = ATH_LONG_CALINTERVAL;
if (sc->sc_ah->config.enable_ani)
cal_interval = min(cal_interval,
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 04ef775ccee1..7990cd55599c 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -810,7 +810,7 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah)
return;
}
- if (AR_SREV_9340(ah))
+ if (AR_SREV_9340(ah) || AR_SREV_9550(ah))
sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
async_mask = AR_INTR_MAC_IRQ;
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 21c955609e6c..0eba36dca6f8 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -646,6 +646,7 @@ enum ath9k_rx_filter {
ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000,
ATH9K_RX_FILTER_CONTROL_WRAPPER = 0x00080000,
+ ATH9K_RX_FILTER_4ADDRESS = 0x00100000,
};
#define ATH9K_RATESERIES_RTS_CTS 0x0001
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index c0f478b0a9a2..248e5b24acfa 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -19,7 +19,7 @@
#include "ath9k.h"
#include "btcoex.h"
-static u8 parse_mpdudensity(u8 mpdudensity)
+u8 ath9k_parse_mpdudensity(u8 mpdudensity)
{
/*
* 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
@@ -130,6 +130,8 @@ void ath9k_ps_restore(struct ath_softc *sc)
PS_WAIT_FOR_PSPOLL_DATA |
PS_WAIT_FOR_TX_ACK))) {
mode = ATH9K_PM_NETWORK_SLEEP;
+ if (ath9k_hw_btcoex_is_enabled(sc->sc_ah))
+ ath9k_btcoex_stop_gen_timer(sc);
} else {
goto unlock;
}
@@ -150,6 +152,11 @@ static void __ath_cancel_work(struct ath_softc *sc)
cancel_work_sync(&sc->hw_check_work);
cancel_delayed_work_sync(&sc->tx_complete_work);
cancel_delayed_work_sync(&sc->hw_pll_work);
+
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+ if (ath9k_hw_mci_is_enabled(sc->sc_ah))
+ cancel_work_sync(&sc->mci_work);
+#endif
}
static void ath_cancel_work(struct ath_softc *sc)
@@ -164,7 +171,8 @@ static void ath_restart_work(struct ath_softc *sc)
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
- if (AR_SREV_9485(sc->sc_ah) || AR_SREV_9340(sc->sc_ah))
+ if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9485(sc->sc_ah) ||
+ AR_SREV_9550(sc->sc_ah))
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
@@ -317,6 +325,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
{
struct ath_node *an;
+ u8 density;
an = (struct ath_node *)sta->drv_priv;
#ifdef CONFIG_ATH9K_DEBUGFS
@@ -331,7 +340,8 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
ath_tx_node_init(sc, an);
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor);
- an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
+ density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
+ an->mpdudensity = density;
}
}
@@ -513,24 +523,6 @@ irqreturn_t ath_isr(int irq, void *dev)
ath9k_hw_set_interrupts(ah);
}
- if (status & ATH9K_INT_MIB) {
- /*
- * Disable interrupts until we service the MIB
- * interrupt; otherwise it will continue to
- * fire.
- */
- ath9k_hw_disable_interrupts(ah);
- /*
- * Let the hal handle the event. We assume
- * it will clear whatever condition caused
- * the interrupt.
- */
- spin_lock(&common->cc_lock);
- ath9k_hw_proc_mib_event(ah);
- spin_unlock(&common->cc_lock);
- ath9k_hw_enable_interrupts(ah);
- }
-
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
if (status & ATH9K_INT_TIM_TIMER) {
if (ATH_DBG_WARN_ON_ONCE(sc->ps_idle))
@@ -677,8 +669,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
spin_unlock_bh(&sc->sc_pcu_lock);
- ath9k_start_btcoex(sc);
-
if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
common->bus_ops->extn_synch_en(common);
@@ -785,8 +775,6 @@ static void ath9k_stop(struct ieee80211_hw *hw)
/* Ensure HW is awake when we try to shut it down. */
ath9k_ps_wakeup(sc);
- ath9k_stop_btcoex(sc);
-
spin_lock_bh(&sc->sc_pcu_lock);
/* prevent tasklets to enable interrupts once we disable them */
@@ -956,14 +944,10 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
/*
* Enable MIB interrupts when there are hardware phy counters.
*/
- if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0) {
- if (ah->config.enable_ani)
- ah->imask |= ATH9K_INT_MIB;
+ if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0)
ah->imask |= ATH9K_INT_TSFOOR;
- } else {
- ah->imask &= ~ATH9K_INT_MIB;
+ else
ah->imask &= ~ATH9K_INT_TSFOOR;
- }
ath9k_hw_set_interrupts(ah);
@@ -1033,15 +1017,6 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
}
}
- if ((ah->opmode == NL80211_IFTYPE_ADHOC) ||
- ((vif->type == NL80211_IFTYPE_ADHOC) &&
- sc->nvifs > 0)) {
- ath_err(common, "Cannot create ADHOC interface when other"
- " interfaces already exist.\n");
- ret = -EINVAL;
- goto out;
- }
-
ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type);
sc->nvifs++;
@@ -1066,15 +1041,6 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
mutex_lock(&sc->mutex);
ath9k_ps_wakeup(sc);
- /* See if new interface type is valid. */
- if ((new_type == NL80211_IFTYPE_ADHOC) &&
- (sc->nvifs > 1)) {
- ath_err(common, "When using ADHOC, it must be the only"
- " interface.\n");
- ret = -EINVAL;
- goto out;
- }
-
if (ath9k_uses_beacons(new_type) &&
!ath9k_uses_beacons(vif->type)) {
if (sc->nbcnvifs >= ATH_BCBUF) {
@@ -1172,14 +1138,17 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
- if (sc->ps_idle)
+ if (sc->ps_idle) {
ath_cancel_work(sc);
- else
+ ath9k_stop_btcoex(sc);
+ } else {
+ ath9k_start_btcoex(sc);
/*
* The chip needs a reset to properly wake up from
* full sleep
*/
reset_channel = ah->chip_fullsleep;
+ }
}
/*
@@ -1258,6 +1227,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
ath_err(common, "Unable to set channel\n");
mutex_unlock(&sc->mutex);
+ ath9k_ps_restore(sc);
return -EINVAL;
}
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c
index 49137f477b05..87acff7fdaae 100644
--- a/drivers/net/wireless/ath/ath9k/mci.c
+++ b/drivers/net/wireless/ath/ath9k/mci.c
@@ -20,7 +20,7 @@
#include "ath9k.h"
#include "mci.h"
-static const u8 ath_mci_duty_cycle[] = { 0, 50, 60, 70, 80, 85, 90, 95, 98 };
+static const u8 ath_mci_duty_cycle[] = { 55, 50, 60, 70, 80, 85, 90, 95, 98 };
static struct ath_mci_profile_info*
ath_mci_find_profile(struct ath_mci_profile *mci,
@@ -28,11 +28,14 @@ ath_mci_find_profile(struct ath_mci_profile *mci,
{
struct ath_mci_profile_info *entry;
+ if (list_empty(&mci->info))
+ return NULL;
+
list_for_each_entry(entry, &mci->info, list) {
if (entry->conn_handle == info->conn_handle)
- break;
+ return entry;
}
- return entry;
+ return NULL;
}
static bool ath_mci_add_profile(struct ath_common *common,
@@ -49,31 +52,21 @@ static bool ath_mci_add_profile(struct ath_common *common,
(info->type != MCI_GPM_COEX_PROFILE_VOICE))
return false;
- entry = ath_mci_find_profile(mci, info);
-
- if (entry) {
- memcpy(entry, info, 10);
- } else {
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry)
- return false;
+ entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
+ if (!entry)
+ return false;
- memcpy(entry, info, 10);
- INC_PROF(mci, info);
- list_add_tail(&info->list, &mci->info);
- }
+ memcpy(entry, info, 10);
+ INC_PROF(mci, info);
+ list_add_tail(&entry->list, &mci->info);
return true;
}
static void ath_mci_del_profile(struct ath_common *common,
struct ath_mci_profile *mci,
- struct ath_mci_profile_info *info)
+ struct ath_mci_profile_info *entry)
{
- struct ath_mci_profile_info *entry;
-
- entry = ath_mci_find_profile(mci, info);
-
if (!entry)
return;
@@ -86,12 +79,16 @@ void ath_mci_flush_profile(struct ath_mci_profile *mci)
{
struct ath_mci_profile_info *info, *tinfo;
+ mci->aggr_limit = 0;
+
+ if (list_empty(&mci->info))
+ return;
+
list_for_each_entry_safe(info, tinfo, &mci->info, list) {
list_del(&info->list);
DEC_PROF(mci, info);
kfree(info);
}
- mci->aggr_limit = 0;
}
static void ath_mci_adjust_aggr_limit(struct ath_btcoex *btcoex)
@@ -123,6 +120,8 @@ static void ath_mci_update_scheme(struct ath_softc *sc)
if (mci_hw->config & ATH_MCI_CONFIG_DISABLE_TUNING)
goto skip_tuning;
+ btcoex->duty_cycle = ath_mci_duty_cycle[num_profile];
+
if (num_profile == 1) {
info = list_first_entry(&mci->info,
struct ath_mci_profile_info,
@@ -175,18 +174,17 @@ skip_tuning:
btcoex->btcoex_period >>= 1;
}
- ath9k_hw_btcoex_disable(sc->sc_ah);
ath9k_btcoex_timer_pause(sc);
+ ath9k_hw_btcoex_disable(sc->sc_ah);
if (IS_CHAN_5GHZ(sc->sc_ah->curchan))
return;
- btcoex->duty_cycle += (mci->num_bdr ? ATH_MCI_MAX_DUTY_CYCLE : 0);
+ btcoex->duty_cycle += (mci->num_bdr ? ATH_MCI_BDR_DUTY_CYCLE : 0);
if (btcoex->duty_cycle > ATH_MCI_MAX_DUTY_CYCLE)
btcoex->duty_cycle = ATH_MCI_MAX_DUTY_CYCLE;
- btcoex->btcoex_period *= 1000;
- btcoex->btcoex_no_stomp = btcoex->btcoex_period *
+ btcoex->btcoex_no_stomp = btcoex->btcoex_period * 1000 *
(100 - btcoex->duty_cycle) / 100;
ath9k_hw_btcoex_enable(sc->sc_ah);
@@ -197,20 +195,16 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
u32 payload[4] = {0, 0, 0, 0};
switch (opcode) {
case MCI_GPM_BT_CAL_REQ:
- if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_AWAKE) {
- ar9003_mci_state(ah, MCI_STATE_SET_BT_CAL_START, NULL);
+ if (mci_hw->bt_state == MCI_BT_AWAKE) {
+ ar9003_mci_state(ah, MCI_STATE_SET_BT_CAL_START);
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
- } else {
- ath_dbg(common, MCI, "MCI State mismatch: %d\n",
- ar9003_mci_state(ah, MCI_STATE_BT, NULL));
}
- break;
- case MCI_GPM_BT_CAL_DONE:
- ar9003_mci_state(ah, MCI_STATE_BT, NULL);
+ ath_dbg(common, MCI, "MCI State : %d\n", mci_hw->bt_state);
break;
case MCI_GPM_BT_CAL_GRANT:
MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_DONE);
@@ -223,32 +217,55 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
}
}
+static void ath9k_mci_work(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc, mci_work);
+
+ ath_mci_update_scheme(sc);
+}
+
static void ath_mci_process_profile(struct ath_softc *sc,
struct ath_mci_profile_info *info)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_btcoex *btcoex = &sc->btcoex;
struct ath_mci_profile *mci = &btcoex->mci;
+ struct ath_mci_profile_info *entry = NULL;
+
+ entry = ath_mci_find_profile(mci, info);
+ if (entry) {
+ /*
+ * Two MCI interrupts are generated while connecting to
+ * headset and A2DP profile, but only one MCI interrupt
+ * is generated with last added profile type while disconnecting
+ * both profiles.
+ * So while adding second profile type decrement
+ * the first one.
+ */
+ if (entry->type != info->type) {
+ DEC_PROF(mci, entry);
+ INC_PROF(mci, info);
+ }
+ memcpy(entry, info, 10);
+ }
if (info->start) {
- if (!ath_mci_add_profile(common, mci, info))
+ if (!entry && !ath_mci_add_profile(common, mci, info))
return;
} else
- ath_mci_del_profile(common, mci, info);
+ ath_mci_del_profile(common, mci, entry);
btcoex->btcoex_period = ATH_MCI_DEF_BT_PERIOD;
mci->aggr_limit = mci->num_sco ? 6 : 0;
- if (NUM_PROF(mci)) {
+ btcoex->duty_cycle = ath_mci_duty_cycle[NUM_PROF(mci)];
+ if (NUM_PROF(mci))
btcoex->bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
- btcoex->duty_cycle = ath_mci_duty_cycle[NUM_PROF(mci)];
- } else {
+ else
btcoex->bt_stomp_type = mci->num_mgmt ? ATH_BTCOEX_STOMP_ALL :
ATH_BTCOEX_STOMP_LOW;
- btcoex->duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE;
- }
- ath_mci_update_scheme(sc);
+ ieee80211_queue_work(sc->hw, &sc->mci_work);
}
static void ath_mci_process_status(struct ath_softc *sc,
@@ -263,8 +280,6 @@ static void ath_mci_process_status(struct ath_softc *sc,
if (status->is_link)
return;
- memset(&info, 0, sizeof(struct ath_mci_profile_info));
-
info.conn_handle = status->conn_handle;
if (ath_mci_find_profile(mci, &info))
return;
@@ -284,7 +299,7 @@ static void ath_mci_process_status(struct ath_softc *sc,
} while (++i < ATH_MCI_MAX_PROFILE);
if (old_num_mgmt != mci->num_mgmt)
- ath_mci_update_scheme(sc);
+ ieee80211_queue_work(sc->hw, &sc->mci_work);
}
static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
@@ -293,25 +308,20 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
struct ath_mci_profile_info profile_info;
struct ath_mci_profile_status profile_status;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- u32 version;
- u8 major;
- u8 minor;
+ u8 major, minor;
u32 seq_num;
switch (opcode) {
case MCI_GPM_COEX_VERSION_QUERY:
- version = ar9003_mci_state(ah, MCI_STATE_SEND_WLAN_COEX_VERSION,
- NULL);
+ ar9003_mci_state(ah, MCI_STATE_SEND_WLAN_COEX_VERSION);
break;
case MCI_GPM_COEX_VERSION_RESPONSE:
major = *(rx_payload + MCI_GPM_COEX_B_MAJOR_VERSION);
minor = *(rx_payload + MCI_GPM_COEX_B_MINOR_VERSION);
- version = (major << 8) + minor;
- version = ar9003_mci_state(ah, MCI_STATE_SET_BT_COEX_VERSION,
- &version);
+ ar9003_mci_set_bt_version(ah, major, minor);
break;
case MCI_GPM_COEX_STATUS_QUERY:
- ar9003_mci_state(ah, MCI_STATE_SEND_WLAN_CHANNELS, NULL);
+ ar9003_mci_send_wlan_channels(ah);
break;
case MCI_GPM_COEX_BT_PROFILE_INFO:
memcpy(&profile_info,
@@ -338,7 +348,7 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
seq_num = *((u32 *)(rx_payload + 12));
ath_dbg(common, MCI,
- "BT_Status_Update: is_link=%d, linkId=%d, state=%d, SEQ=%d\n",
+ "BT_Status_Update: is_link=%d, linkId=%d, state=%d, SEQ=%u\n",
profile_status.is_link, profile_status.conn_handle,
profile_status.is_critical, seq_num);
@@ -378,6 +388,7 @@ int ath_mci_setup(struct ath_softc *sc)
mci->gpm_buf.bf_addr, (mci->gpm_buf.bf_len >> 4),
mci->sched_buf.bf_paddr);
+ INIT_WORK(&sc->mci_work, ath9k_mci_work);
ath_dbg(common, MCI, "MCI Initialized\n");
return 0;
@@ -405,6 +416,7 @@ void ath_mci_intr(struct ath_softc *sc)
struct ath_mci_coex *mci = &sc->mci_coex;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
u32 mci_int, mci_int_rxmsg;
u32 offset, subtype, opcode;
u32 *pgpm;
@@ -413,8 +425,8 @@ void ath_mci_intr(struct ath_softc *sc)
ar9003_mci_get_interrupt(sc->sc_ah, &mci_int, &mci_int_rxmsg);
- if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) == 0) {
- ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET, NULL);
+ if (ar9003_mci_state(ah, MCI_STATE_ENABLE) == 0) {
+ ar9003_mci_get_next_gpm_offset(ah, true, NULL);
return;
}
@@ -433,46 +445,41 @@ void ath_mci_intr(struct ath_softc *sc)
NULL, 0, true, false);
mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE;
- ar9003_mci_state(ah, MCI_STATE_RESET_REQ_WAKE, NULL);
+ ar9003_mci_state(ah, MCI_STATE_RESET_REQ_WAKE);
/*
* always do this for recovery and 2G/5G toggling and LNA_TRANS
*/
- ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE, NULL);
+ ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE);
}
if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING) {
mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING;
- if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_SLEEP) {
- if (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL) !=
- MCI_BT_SLEEP)
- ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE,
- NULL);
- }
+ if ((mci_hw->bt_state == MCI_BT_SLEEP) &&
+ (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP) !=
+ MCI_BT_SLEEP))
+ ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE);
}
if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) {
mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING;
- if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_AWAKE) {
- if (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL) !=
- MCI_BT_AWAKE)
- ar9003_mci_state(ah, MCI_STATE_SET_BT_SLEEP,
- NULL);
- }
+ if ((mci_hw->bt_state == MCI_BT_AWAKE) &&
+ (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP) !=
+ MCI_BT_AWAKE))
+ mci_hw->bt_state = MCI_BT_SLEEP;
}
if ((mci_int & AR_MCI_INTERRUPT_RX_INVALID_HDR) ||
(mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) {
- ar9003_mci_state(ah, MCI_STATE_RECOVER_RX, NULL);
+ ar9003_mci_state(ah, MCI_STATE_RECOVER_RX);
skip_gpm = true;
}
if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO) {
mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO;
- offset = ar9003_mci_state(ah, MCI_STATE_LAST_SCHD_MSG_OFFSET,
- NULL);
+ offset = ar9003_mci_state(ah, MCI_STATE_LAST_SCHD_MSG_OFFSET);
}
if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_GPM) {
@@ -481,8 +488,8 @@ void ath_mci_intr(struct ath_softc *sc)
while (more_data == MCI_GPM_MORE) {
pgpm = mci->gpm_buf.bf_addr;
- offset = ar9003_mci_state(ah, MCI_STATE_NEXT_GPM_OFFSET,
- &more_data);
+ offset = ar9003_mci_get_next_gpm_offset(ah, false,
+ &more_data);
if (offset == MCI_GPM_INVALID)
break;
@@ -523,23 +530,17 @@ void ath_mci_intr(struct ath_softc *sc)
mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_LNA_INFO;
if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) {
- int value_dbm = ar9003_mci_state(ah,
- MCI_STATE_CONT_RSSI_POWER, NULL);
+ int value_dbm = MS(mci_hw->cont_status,
+ AR_MCI_CONT_RSSI_POWER);
mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_INFO;
- if (ar9003_mci_state(ah, MCI_STATE_CONT_TXRX, NULL))
- ath_dbg(common, MCI,
- "MCI CONT_INFO: (tx) pri = %d, pwr = %d dBm\n",
- ar9003_mci_state(ah,
- MCI_STATE_CONT_PRIORITY, NULL),
- value_dbm);
- else
- ath_dbg(common, MCI,
- "MCI CONT_INFO: (rx) pri = %d,pwr = %d dBm\n",
- ar9003_mci_state(ah,
- MCI_STATE_CONT_PRIORITY, NULL),
- value_dbm);
+ ath_dbg(common, MCI,
+ "MCI CONT_INFO: (%s) pri = %d pwr = %d dBm\n",
+ MS(mci_hw->cont_status, AR_MCI_CONT_TXRX) ?
+ "tx" : "rx",
+ MS(mci_hw->cont_status, AR_MCI_CONT_PRIORITY),
+ value_dbm);
}
if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_NACK)
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 92a6c0a87f89..e034add9cd5a 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -770,7 +770,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
struct ieee80211_tx_rate *rates = tx_info->control.rates;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 fc = hdr->frame_control;
- u8 try_per_rate, i = 0, rix, high_rix;
+ u8 try_per_rate, i = 0, rix;
int is_probe = 0;
if (rate_control_send_low(sta, priv_sta, txrc))
@@ -791,7 +791,6 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
rate_table = ath_rc_priv->rate_table;
rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table,
&is_probe, false);
- high_rix = rix;
/*
* If we're in HT mode and both us and our peer supports LDPC.
@@ -839,16 +838,16 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
try_per_rate = 8;
/*
- * Use a legacy rate as last retry to ensure that the frame
- * is tried in both MCS and legacy rates.
+ * If the last rate in the rate series is MCS and has
+ * more than 80% of per thresh, then use a legacy rate
+ * as last retry to ensure that the frame is tried in both
+ * MCS and legacy rate.
*/
- if ((rates[2].flags & IEEE80211_TX_RC_MCS) &&
- (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) ||
- (ath_rc_priv->per[high_rix] > 45)))
+ ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
+ if (WLAN_RC_PHY_HT(rate_table->info[rix].phy) &&
+ (ath_rc_priv->per[rix] > 45))
rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table,
&is_probe, true);
- else
- ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
/* All other rates in the series have RTS enabled */
ath_rc_rate_set_series(rate_table, &rates[i], txrc,
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index fbdcc80437fe..11f3703a420a 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -430,6 +430,9 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;
}
+ if (AR_SREV_9550(sc->sc_ah))
+ rfilt |= ATH9K_RX_FILTER_4ADDRESS;
+
return rfilt;
}
@@ -658,9 +661,9 @@ static bool ath_edma_get_buffers(struct ath_softc *sc,
__skb_unlink(skb, &rx_edma->rx_fifo);
list_add_tail(&bf->list, &sc->rx.rxbuf);
ath_rx_edma_buf_link(sc, qtype);
- } else {
- bf = NULL;
}
+
+ bf = NULL;
}
*dest = bf;
@@ -785,7 +788,8 @@ static bool ath9k_rx_accept(struct ath_common *common,
* descriptor does contain a valid key index. This has been observed
* mostly with CCMP encryption.
*/
- if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID)
+ if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID ||
+ !test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
if (!rx_stats->rs_datalen) {
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 560d6effac7a..6592c07ac646 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -798,6 +798,7 @@
#define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */
#define AR_SREV_VERSION_9462 0x280
#define AR_SREV_REVISION_9462_20 2
+#define AR_SREV_VERSION_9550 0x400
#define AR_SREV_5416(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
@@ -905,6 +906,9 @@
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20))
+#define AR_SREV_9550(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9550))
+
#define AR_SREV_9580(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10))
@@ -1643,11 +1647,11 @@ enum {
#define AR_TPC 0x80e8
#define AR_TPC_ACK 0x0000003f
-#define AR_TPC_ACK_S 0x00
+#define AR_TPC_ACK_S 0
#define AR_TPC_CTS 0x00003f00
-#define AR_TPC_CTS_S 0x08
+#define AR_TPC_CTS_S 8
#define AR_TPC_CHIRP 0x003f0000
-#define AR_TPC_CHIRP_S 0x16
+#define AR_TPC_CHIRP_S 16
#define AR_QUIET1 0x80fc
#define AR_QUIET1_NEXT_QUIET_S 0
@@ -2077,12 +2081,6 @@ enum {
AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET| \
AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING | \
AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING| \
- AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \
- AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL | \
- AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \
- AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \
- AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \
- AR_MCI_INTERRUPT_RX_MSG_CONT_RST | \
AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)
#define AR_MCI_CPU_INT 0x1840
@@ -2098,8 +2096,8 @@ enum {
#define AR_MCI_CONT_STATUS 0x1848
#define AR_MCI_CONT_RSSI_POWER 0x000000FF
#define AR_MCI_CONT_RSSI_POWER_S 0
-#define AR_MCI_CONT_RRIORITY 0x0000FF00
-#define AR_MCI_CONT_RRIORITY_S 8
+#define AR_MCI_CONT_PRIORITY 0x0000FF00
+#define AR_MCI_CONT_PRIORITY_S 8
#define AR_MCI_CONT_TXRX 0x00010000
#define AR_MCI_CONT_TXRX_S 16
@@ -2162,10 +2160,6 @@ enum {
#define AR_BTCOEX_CTRL_SPDT_POLARITY 0x80000000
#define AR_BTCOEX_CTRL_SPDT_POLARITY_S 31
-#define AR_BTCOEX_WL_WEIGHTS0 0x18b0
-#define AR_BTCOEX_WL_WEIGHTS1 0x18b4
-#define AR_BTCOEX_WL_WEIGHTS2 0x18b8
-#define AR_BTCOEX_WL_WEIGHTS3 0x18bc
#define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2))
#define AR_BTCOEX_WL_LNA 0x1940
#define AR_BTCOEX_RFGAIN_CTRL 0x1944
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index f777ddcd1172..cafb4a09729a 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -938,6 +938,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
struct ieee80211_tx_rate *rates;
const struct ieee80211_rate *rate;
struct ieee80211_hdr *hdr;
+ struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
int i;
u8 rix = 0;
@@ -948,18 +949,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
/* set dur_update_en for l-sig computation except for PS-Poll frames */
info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
-
- /*
- * We check if Short Preamble is needed for the CTS rate by
- * checking the BSS's global flag.
- * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
- */
- rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
- info->rtscts_rate = rate->hw_value;
-
- if (tx_info->control.vif &&
- tx_info->control.vif->bss_conf.use_short_preamble)
- info->rtscts_rate |= rate->hw_value_short;
+ info->rtscts_rate = fi->rtscts_rate;
for (i = 0; i < 4; i++) {
bool is_40, is_sgi, is_sp;
@@ -1001,13 +991,13 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
}
/* legacy rates */
+ rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
!(rate->flags & IEEE80211_RATE_ERP_G))
phy = WLAN_RC_PHY_CCK;
else
phy = WLAN_RC_PHY_OFDM;
- rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
info->rates[i].Rate = rate->hw_value;
if (rate->hw_value_short) {
if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
@@ -1175,6 +1165,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
{
struct ath_atx_tid *txtid;
struct ath_node *an;
+ u8 density;
an = (struct ath_node *)sta->drv_priv;
txtid = ATH_AN_2_TID(an, tid);
@@ -1182,6 +1173,17 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
return -EAGAIN;
+ /* update ampdu factor/density, they may have changed. This may happen
+ * in HT IBSS when a beacon with HT-info is received after the station
+ * has already been added.
+ */
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
+ an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
+ sta->ht_cap.ampdu_factor);
+ density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
+ an->mpdudensity = density;
+ }
+
txtid->state |= AGGR_ADDBA_PROGRESS;
txtid->paused = true;
*ssn = txtid->seq_start = txtid->seq_next;
@@ -1776,10 +1778,22 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_sta *sta = tx_info->control.sta;
struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ const struct ieee80211_rate *rate;
struct ath_frame_info *fi = get_frame_info(skb);
struct ath_node *an = NULL;
enum ath9k_key_type keytype;
+ bool short_preamble = false;
+
+ /*
+ * We check if Short Preamble is needed for the CTS rate by
+ * checking the BSS's global flag.
+ * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
+ */
+ if (tx_info->control.vif &&
+ tx_info->control.vif->bss_conf.use_short_preamble)
+ short_preamble = true;
+ rate = ieee80211_get_rts_cts_rate(hw, tx_info);
keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
if (sta)
@@ -1794,6 +1808,9 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
fi->keyix = ATH9K_TXKEYIX_INVALID;
fi->keytype = keytype;
fi->framelen = framelen;
+ fi->rtscts_rate = rate->hw_value;
+ if (short_preamble)
+ fi->rtscts_rate |= rate->hw_value_short;
}
u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index 0cea20e3e250..376be11161c0 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -289,6 +289,7 @@ struct ar9170 {
unsigned int mem_block_size;
unsigned int rx_size;
unsigned int tx_seq_table;
+ bool ba_filter;
} fw;
/* interface configuration combinations */
@@ -425,6 +426,10 @@ struct ar9170 {
struct sk_buff *rx_failover;
int rx_failover_missing;
+ /* FIFO for collecting outstanding BlockAckRequest */
+ struct list_head bar_list[__AR9170_NUM_TXQ];
+ spinlock_t bar_list_lock[__AR9170_NUM_TXQ];
+
#ifdef CONFIG_CARL9170_WPC
struct {
bool pbc_state;
@@ -468,6 +473,12 @@ enum carl9170_ps_off_override_reasons {
PS_OFF_BCN = BIT(1),
};
+struct carl9170_bar_list_entry {
+ struct list_head list;
+ struct rcu_head head;
+ struct sk_buff *skb;
+};
+
struct carl9170_ba_stats {
u8 ampdu_len;
u8 ampdu_ack_len;
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c
index 5c73c03872f3..c5ca6f1f5836 100644
--- a/drivers/net/wireless/ath/carl9170/fw.c
+++ b/drivers/net/wireless/ath/carl9170/fw.c
@@ -307,6 +307,9 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
if (SUPP(CARL9170FW_WOL))
device_set_wakeup_enable(&ar->udev->dev, true);
+ if (SUPP(CARL9170FW_RX_BA_FILTER))
+ ar->fw.ba_filter = true;
+
if_comb_types = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_P2P_CLIENT);
diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h
index 6d9c0891ce7f..66848d47c88e 100644
--- a/drivers/net/wireless/ath/carl9170/fwdesc.h
+++ b/drivers/net/wireless/ath/carl9170/fwdesc.h
@@ -78,6 +78,9 @@ enum carl9170fw_feature_list {
/* HW (ANI, CCA, MIB) tally counters */
CARL9170FW_HW_COUNTERS,
+ /* Firmware will pass BA when BARs are queued */
+ CARL9170FW_RX_BA_FILTER,
+
/* KEEP LAST */
__CARL9170FW_FEATURE_NUM
};
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 8d2523b3f722..858e58dfc4dc 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -949,6 +949,9 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw,
if (ar->fw.rx_filter && changed_flags & ar->rx_filter_caps) {
u32 rx_filter = 0;
+ if (!ar->fw.ba_filter)
+ rx_filter |= CARL9170_RX_FILTER_CTL_OTHER;
+
if (!(*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)))
rx_filter |= CARL9170_RX_FILTER_BAD;
@@ -1753,6 +1756,9 @@ void *carl9170_alloc(size_t priv_size)
for (i = 0; i < ar->hw->queues; i++) {
skb_queue_head_init(&ar->tx_status[i]);
skb_queue_head_init(&ar->tx_pending[i]);
+
+ INIT_LIST_HEAD(&ar->bar_list[i]);
+ spin_lock_init(&ar->bar_list_lock[i]);
}
INIT_WORK(&ar->ps_work, carl9170_ps_work);
INIT_WORK(&ar->ping_work, carl9170_ping_work);
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index 84b22eec7abd..25910a14e79c 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -576,6 +576,53 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len)
}
}
+static void carl9170_ba_check(struct ar9170 *ar, void *data, unsigned int len)
+{
+ struct ieee80211_bar *bar = (void *) data;
+ struct carl9170_bar_list_entry *entry;
+ unsigned int queue;
+
+ if (likely(!ieee80211_is_back(bar->frame_control)))
+ return;
+
+ if (len <= sizeof(*bar) + FCS_LEN)
+ return;
+
+ queue = TID_TO_WME_AC(((le16_to_cpu(bar->control) &
+ IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
+ IEEE80211_BAR_CTRL_TID_INFO_SHIFT) & 7);
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(entry, &ar->bar_list[queue], list) {
+ struct sk_buff *entry_skb = entry->skb;
+ struct _carl9170_tx_superframe *super = (void *)entry_skb->data;
+ struct ieee80211_bar *entry_bar = (void *)super->frame_data;
+
+#define TID_CHECK(a, b) ( \
+ ((a) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK)) == \
+ ((b) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK))) \
+
+ if (bar->start_seq_num == entry_bar->start_seq_num &&
+ TID_CHECK(bar->control, entry_bar->control) &&
+ compare_ether_addr(bar->ra, entry_bar->ta) == 0 &&
+ compare_ether_addr(bar->ta, entry_bar->ra) == 0) {
+ struct ieee80211_tx_info *tx_info;
+
+ tx_info = IEEE80211_SKB_CB(entry_skb);
+ tx_info->flags |= IEEE80211_TX_STAT_ACK;
+
+ spin_lock_bh(&ar->bar_list_lock[queue]);
+ list_del_rcu(&entry->list);
+ spin_unlock_bh(&ar->bar_list_lock[queue]);
+ kfree_rcu(entry, head);
+ break;
+ }
+ }
+ rcu_read_unlock();
+
+#undef TID_CHECK
+}
+
static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms)
{
__le16 fc;
@@ -738,6 +785,8 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
carl9170_ps_beacon(ar, buf, mpdu_len);
+ carl9170_ba_check(ar, buf, mpdu_len);
+
skb = carl9170_rx_copy_data(buf, mpdu_len);
if (!skb)
goto drop;
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index aed305177af6..6a8681407a1d 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -277,11 +277,11 @@ static void carl9170_tx_release(struct kref *ref)
return;
BUILD_BUG_ON(
- offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23);
+ offsetof(struct ieee80211_tx_info, status.ack_signal) != 20);
- memset(&txinfo->status.ampdu_ack_len, 0,
+ memset(&txinfo->status.ack_signal, 0,
sizeof(struct ieee80211_tx_info) -
- offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
+ offsetof(struct ieee80211_tx_info, status.ack_signal));
if (atomic_read(&ar->tx_total_queued))
ar->tx_schedule = true;
@@ -436,6 +436,45 @@ out_rcu:
rcu_read_unlock();
}
+static void carl9170_tx_bar_status(struct ar9170 *ar, struct sk_buff *skb,
+ struct ieee80211_tx_info *tx_info)
+{
+ struct _carl9170_tx_superframe *super = (void *) skb->data;
+ struct ieee80211_bar *bar = (void *) super->frame_data;
+
+ /*
+ * Unlike all other frames, the status report for BARs does
+ * not directly come from the hardware as it is incapable of
+ * matching a BA to a previously send BAR.
+ * Instead the RX-path will scan for incoming BAs and set the
+ * IEEE80211_TX_STAT_ACK if it sees one that was likely
+ * caused by a BAR from us.
+ */
+
+ if (unlikely(ieee80211_is_back_req(bar->frame_control)) &&
+ !(tx_info->flags & IEEE80211_TX_STAT_ACK)) {
+ struct carl9170_bar_list_entry *entry;
+ int queue = skb_get_queue_mapping(skb);
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(entry, &ar->bar_list[queue], list) {
+ if (entry->skb == skb) {
+ spin_lock_bh(&ar->bar_list_lock[queue]);
+ list_del_rcu(&entry->list);
+ spin_unlock_bh(&ar->bar_list_lock[queue]);
+ kfree_rcu(entry, head);
+ goto out;
+ }
+ }
+
+ WARN(1, "bar not found in %d - ra:%pM ta:%pM c:%x ssn:%x\n",
+ queue, bar->ra, bar->ta, bar->control,
+ bar->start_seq_num);
+out:
+ rcu_read_unlock();
+ }
+}
+
void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
const bool success)
{
@@ -445,6 +484,8 @@ void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
txinfo = IEEE80211_SKB_CB(skb);
+ carl9170_tx_bar_status(ar, skb, txinfo);
+
if (success)
txinfo->flags |= IEEE80211_TX_STAT_ACK;
else
@@ -1265,6 +1306,26 @@ out_rcu:
return false;
}
+static void carl9170_bar_check(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct _carl9170_tx_superframe *super = (void *) skb->data;
+ struct ieee80211_bar *bar = (void *) super->frame_data;
+
+ if (unlikely(ieee80211_is_back_req(bar->frame_control)) &&
+ skb->len >= sizeof(struct ieee80211_bar)) {
+ struct carl9170_bar_list_entry *entry;
+ unsigned int queue = skb_get_queue_mapping(skb);
+
+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+ if (!WARN_ON_ONCE(!entry)) {
+ entry->skb = skb;
+ spin_lock_bh(&ar->bar_list_lock[queue]);
+ list_add_tail_rcu(&entry->list, &ar->bar_list[queue]);
+ spin_unlock_bh(&ar->bar_list_lock[queue]);
+ }
+ }
+}
+
static void carl9170_tx(struct ar9170 *ar)
{
struct sk_buff *skb;
@@ -1287,6 +1348,8 @@ static void carl9170_tx(struct ar9170 *ar)
if (unlikely(carl9170_tx_ps_drop(ar, skb)))
continue;
+ carl9170_bar_check(ar, skb);
+
atomic_inc(&ar->tx_total_pending);
q = __carl9170_get_queue(ar, i);
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h
index e651db856344..2ec3e9191e4d 100644
--- a/drivers/net/wireless/ath/carl9170/version.h
+++ b/drivers/net/wireless/ath/carl9170/version.h
@@ -1,7 +1,7 @@
#ifndef __CARL9170_SHARED_VERSION_H
#define __CARL9170_SHARED_VERSION_H
-#define CARL9170FW_VERSION_YEAR 11
-#define CARL9170FW_VERSION_MONTH 8
-#define CARL9170FW_VERSION_DAY 15
-#define CARL9170FW_VERSION_GIT "1.9.4"
+#define CARL9170FW_VERSION_YEAR 12
+#define CARL9170FW_VERSION_MONTH 7
+#define CARL9170FW_VERSION_DAY 7
+#define CARL9170FW_VERSION_GIT "1.9.6"
#endif /* __CARL9170_SHARED_VERSION_H */
diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c
index 0e81904956cf..5c54aa43ca2d 100644
--- a/drivers/net/wireless/ath/key.c
+++ b/drivers/net/wireless/ath/key.c
@@ -556,6 +556,9 @@ int ath_key_config(struct ath_common *common,
return -EIO;
set_bit(idx, common->keymap);
+ if (key->cipher == WLAN_CIPHER_SUITE_CCMP)
+ set_bit(idx, common->ccmp_keymap);
+
if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
set_bit(idx + 64, common->keymap);
set_bit(idx, common->tkip_keymap);
@@ -582,6 +585,7 @@ void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key)
return;
clear_bit(key->hw_key_idx, common->keymap);
+ clear_bit(key->hw_key_idx, common->ccmp_keymap);
if (key->cipher != WLAN_CIPHER_SUITE_TKIP)
return;
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 108118820b36..b92bb9c92ad1 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -1369,7 +1369,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
i << 2);
b43_nphy_poll_rssi(dev, 2, results[i], 8);
}
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < 4; i += 2) {
s32 curr;
s32 mind = 40;
s32 minpoll = 249;
@@ -1415,14 +1415,15 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 1, i);
b43_nphy_poll_rssi(dev, i, poll_results, 8);
for (j = 0; j < 4; j++) {
- if (j / 2 == core)
+ if (j / 2 == core) {
offset[j] = 232 - poll_results[j];
- if (offset[j] < 0)
- offset[j] = -(abs(offset[j] + 4) / 8);
- else
- offset[j] = (offset[j] + 4) / 8;
- b43_nphy_scale_offset_rssi(dev, 0,
- offset[2 * core], core + 1, j % 2, i);
+ if (offset[j] < 0)
+ offset[j] = -(abs(offset[j] + 4) / 8);
+ else
+ offset[j] = (offset[j] + 4) / 8;
+ b43_nphy_scale_offset_rssi(dev, 0,
+ offset[2 * core], core + 1, j % 2, i);
+ }
}
}
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index abb48032753b..9d5170b6df50 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -34,3 +34,5 @@ brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
sdio_chip.o
brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
usb.o
+brcmfmac-$(CONFIG_BRCMDBG) += \
+ dhd_dbg.o \ No newline at end of file
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 82f51dbd0d66..49765d34b4e0 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -44,6 +44,7 @@
#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
#define SDIO_DEVICE_ID_BROADCOM_4330 0x4330
+#define SDIO_DEVICE_ID_BROADCOM_4334 0x4334
#define SDIO_FUNC1_BLOCKSIZE 64
#define SDIO_FUNC2_BLOCKSIZE 512
@@ -52,6 +53,7 @@
static const struct sdio_device_id brcmf_sdmmc_ids[] = {
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)},
{ /* end: all zeroes */ },
};
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 9f637014486e..a11fe54f5950 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -613,6 +613,9 @@ struct brcmf_pub {
struct work_struct multicast_work;
u8 macvalue[ETH_ALEN];
atomic_t pend_8021x_cnt;
+#ifdef DEBUG
+ struct dentry *dbgfs_dir;
+#endif
};
struct brcmf_if_event {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index 366916494be4..537f499cc5d2 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -36,6 +36,13 @@ struct dngl_stats {
unsigned long multicast; /* multicast packets received */
};
+struct brcmf_bus_dcmd {
+ char *name;
+ char *param;
+ int param_len;
+ struct list_head list;
+};
+
/* interface structure between common and bus layer */
struct brcmf_bus {
u8 type; /* bus type */
@@ -50,6 +57,7 @@ struct brcmf_bus {
unsigned long tx_realloc; /* Tx packets realloced for headroom */
struct dngl_stats dstats; /* Stats for dongle-based data */
u8 align; /* bus alignment requirement */
+ struct list_head dcmd_list;
/* interface functions pointers */
/* Stop bus module: clear pending frames, disable data flow */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
index 236cb9fa460c..2621dd3d7dcd 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
@@ -800,13 +800,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for
"event_msgs" + '\0' + bitvec */
char buf[128], *ptr;
- u32 dongle_align = drvr->bus_if->align;
- u32 glom = 0;
u32 roaming = 1;
uint bcn_timeout = 3;
int scan_assoc_time = 40;
int scan_unassoc_time = 40;
int i;
+ struct brcmf_bus_dcmd *cmdlst;
+ struct list_head *cur, *q;
mutex_lock(&drvr->proto_block);
@@ -827,17 +827,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
/* Print fw version info */
brcmf_dbg(ERROR, "Firmware version = %s\n", buf);
- /* Match Host and Dongle rx alignment */
- brcmf_c_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
- sizeof(iovbuf));
- brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
- sizeof(iovbuf));
-
- /* disable glom option per default */
- brcmf_c_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
- brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
- sizeof(iovbuf));
-
/* Setup timeout if Beacons are lost and roam is off to report
link down */
brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
@@ -874,6 +863,20 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
0, true);
}
+ /* set bus specific command if there is any */
+ list_for_each_safe(cur, q, &drvr->bus_if->dcmd_list) {
+ cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list);
+ if (cmdlst->name && cmdlst->param && cmdlst->param_len) {
+ brcmf_c_mkiovar(cmdlst->name, cmdlst->param,
+ cmdlst->param_len, iovbuf,
+ sizeof(iovbuf));
+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
+ iovbuf, sizeof(iovbuf));
+ }
+ list_del(cur);
+ kfree(cmdlst);
+ }
+
mutex_unlock(&drvr->proto_block);
return 0;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
new file mode 100644
index 000000000000..7f89540b56da
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/debugfs.h>
+#include <linux/if_ether.h>
+#include <linux/if.h>
+#include <linux/ieee80211.h>
+#include <linux/module.h>
+
+#include <defs.h>
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
+
+static struct dentry *root_folder;
+
+void brcmf_debugfs_init(void)
+{
+ root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL);
+ if (IS_ERR(root_folder))
+ root_folder = NULL;
+}
+
+void brcmf_debugfs_exit(void)
+{
+ if (!root_folder)
+ return;
+
+ debugfs_remove_recursive(root_folder);
+ root_folder = NULL;
+}
+
+int brcmf_debugfs_attach(struct brcmf_pub *drvr)
+{
+ if (!root_folder)
+ return -ENODEV;
+
+ drvr->dbgfs_dir = debugfs_create_dir(dev_name(drvr->dev), root_folder);
+ return PTR_RET(drvr->dbgfs_dir);
+}
+
+void brcmf_debugfs_detach(struct brcmf_pub *drvr)
+{
+ if (!IS_ERR_OR_NULL(drvr->dbgfs_dir))
+ debugfs_remove_recursive(drvr->dbgfs_dir);
+}
+
+struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr)
+{
+ return drvr->dbgfs_dir;
+}
+
+static
+ssize_t brcmf_debugfs_sdio_counter_read(struct file *f, char __user *data,
+ size_t count, loff_t *ppos)
+{
+ struct brcmf_sdio_count *sdcnt = f->private_data;
+ char buf[750];
+ int res;
+
+ /* only allow read from start */
+ if (*ppos > 0)
+ return 0;
+
+ res = scnprintf(buf, sizeof(buf),
+ "intrcount: %u\nlastintrs: %u\n"
+ "pollcnt: %u\nregfails: %u\n"
+ "tx_sderrs: %u\nfcqueued: %u\n"
+ "rxrtx: %u\nrx_toolong: %u\n"
+ "rxc_errors: %u\nrx_hdrfail: %u\n"
+ "rx_badhdr: %u\nrx_badseq: %u\n"
+ "fc_rcvd: %u\nfc_xoff: %u\n"
+ "fc_xon: %u\nrxglomfail: %u\n"
+ "rxglomframes: %u\nrxglompkts: %u\n"
+ "f2rxhdrs: %u\nf2rxdata: %u\n"
+ "f2txdata: %u\nf1regdata: %u\n"
+ "tickcnt: %u\ntx_ctlerrs: %lu\n"
+ "tx_ctlpkts: %lu\nrx_ctlerrs: %lu\n"
+ "rx_ctlpkts: %lu\nrx_readahead: %lu\n",
+ sdcnt->intrcount, sdcnt->lastintrs,
+ sdcnt->pollcnt, sdcnt->regfails,
+ sdcnt->tx_sderrs, sdcnt->fcqueued,
+ sdcnt->rxrtx, sdcnt->rx_toolong,
+ sdcnt->rxc_errors, sdcnt->rx_hdrfail,
+ sdcnt->rx_badhdr, sdcnt->rx_badseq,
+ sdcnt->fc_rcvd, sdcnt->fc_xoff,
+ sdcnt->fc_xon, sdcnt->rxglomfail,
+ sdcnt->rxglomframes, sdcnt->rxglompkts,
+ sdcnt->f2rxhdrs, sdcnt->f2rxdata,
+ sdcnt->f2txdata, sdcnt->f1regdata,
+ sdcnt->tickcnt, sdcnt->tx_ctlerrs,
+ sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs,
+ sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt);
+
+ return simple_read_from_buffer(data, count, ppos, buf, res);
+}
+
+static const struct file_operations brcmf_debugfs_sdio_counter_ops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = brcmf_debugfs_sdio_counter_read
+};
+
+void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr,
+ struct brcmf_sdio_count *sdcnt)
+{
+ struct dentry *dentry = drvr->dbgfs_dir;
+
+ if (!IS_ERR_OR_NULL(dentry))
+ debugfs_create_file("counters", S_IRUGO, dentry,
+ sdcnt, &brcmf_debugfs_sdio_counter_ops);
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
index a2c4576cf9ff..b784920532d3 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
@@ -76,4 +76,63 @@ do { \
extern int brcmf_msg_level;
+/*
+ * hold counter variables used in brcmfmac sdio driver.
+ */
+struct brcmf_sdio_count {
+ uint intrcount; /* Count of device interrupt callbacks */
+ uint lastintrs; /* Count as of last watchdog timer */
+ uint pollcnt; /* Count of active polls */
+ uint regfails; /* Count of R_REG failures */
+ uint tx_sderrs; /* Count of tx attempts with sd errors */
+ uint fcqueued; /* Tx packets that got queued */
+ uint rxrtx; /* Count of rtx requests (NAK to dongle) */
+ uint rx_toolong; /* Receive frames too long to receive */
+ uint rxc_errors; /* SDIO errors when reading control frames */
+ uint rx_hdrfail; /* SDIO errors on header reads */
+ uint rx_badhdr; /* Bad received headers (roosync?) */
+ uint rx_badseq; /* Mismatched rx sequence number */
+ uint fc_rcvd; /* Number of flow-control events received */
+ uint fc_xoff; /* Number which turned on flow-control */
+ uint fc_xon; /* Number which turned off flow-control */
+ uint rxglomfail; /* Failed deglom attempts */
+ uint rxglomframes; /* Number of glom frames (superframes) */
+ uint rxglompkts; /* Number of packets from glom frames */
+ uint f2rxhdrs; /* Number of header reads */
+ uint f2rxdata; /* Number of frame data reads */
+ uint f2txdata; /* Number of f2 frame writes */
+ uint f1regdata; /* Number of f1 register accesses */
+ uint tickcnt; /* Number of watchdog been schedule */
+ ulong tx_ctlerrs; /* Err of sending ctrl frames */
+ ulong tx_ctlpkts; /* Ctrl frames sent to dongle */
+ ulong rx_ctlerrs; /* Err of processing rx ctrl frames */
+ ulong rx_ctlpkts; /* Ctrl frames processed from dongle */
+ ulong rx_readahead_cnt; /* packets where header read-ahead was used */
+};
+
+struct brcmf_pub;
+#ifdef DEBUG
+void brcmf_debugfs_init(void);
+void brcmf_debugfs_exit(void);
+int brcmf_debugfs_attach(struct brcmf_pub *drvr);
+void brcmf_debugfs_detach(struct brcmf_pub *drvr);
+struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr);
+void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr,
+ struct brcmf_sdio_count *sdcnt);
+#else
+static inline void brcmf_debugfs_init(void)
+{
+}
+static inline void brcmf_debugfs_exit(void)
+{
+}
+static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr)
+{
+ return 0;
+}
+static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr)
+{
+}
+#endif
+
#endif /* _BRCMF_DBG_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index 8933f9b31a9a..57bf1d7ee80f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -1007,6 +1007,9 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
drvr->bus_if->drvr = drvr;
drvr->dev = dev;
+ /* create device debugfs folder */
+ brcmf_debugfs_attach(drvr);
+
/* Attach and link in the protocol */
ret = brcmf_proto_attach(drvr);
if (ret != 0) {
@@ -1017,6 +1020,8 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
INIT_WORK(&drvr->setmacaddr_work, _brcmf_set_mac_address);
INIT_WORK(&drvr->multicast_work, _brcmf_set_multicast_list);
+ INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);
+
return ret;
fail:
@@ -1123,6 +1128,7 @@ void brcmf_detach(struct device *dev)
brcmf_proto_detach(drvr);
}
+ brcmf_debugfs_detach(drvr);
bus_if->drvr = NULL;
kfree(drvr);
}
@@ -1192,6 +1198,8 @@ exit:
static void brcmf_driver_init(struct work_struct *work)
{
+ brcmf_debugfs_init();
+
#ifdef CONFIG_BRCMFMAC_SDIO
brcmf_sdio_init();
#endif
@@ -1219,6 +1227,7 @@ static void __exit brcmfmac_module_exit(void)
#ifdef CONFIG_BRCMFMAC_USB
brcmf_usb_exit();
#endif
+ brcmf_debugfs_exit();
}
module_init(brcmfmac_module_init);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 1dbf2be478c8..5c868bac1c1c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -31,6 +31,8 @@
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/bcma/bcma.h>
+#include <linux/debugfs.h>
+#include <linux/vmalloc.h>
#include <asm/unaligned.h>
#include <defs.h>
#include <brcmu_wifi.h>
@@ -48,6 +50,9 @@
#define CBUF_LEN (128)
+/* Device console log buffer state */
+#define CONSOLE_BUFFER_MAX 2024
+
struct rte_log_le {
__le32 buf; /* Can't be pointer on (64-bit) hosts */
__le32 buf_size;
@@ -281,7 +286,7 @@ struct rte_console {
* Shared structure between dongle and the host.
* The structure contains pointers to trap or assert information.
*/
-#define SDPCM_SHARED_VERSION 0x0002
+#define SDPCM_SHARED_VERSION 0x0003
#define SDPCM_SHARED_VERSION_MASK 0x00FF
#define SDPCM_SHARED_ASSERT_BUILT 0x0100
#define SDPCM_SHARED_ASSERT 0x0200
@@ -428,6 +433,29 @@ struct brcmf_console {
u8 *buf; /* Log buffer (host copy) */
uint last; /* Last buffer read index */
};
+
+struct brcmf_trap_info {
+ __le32 type;
+ __le32 epc;
+ __le32 cpsr;
+ __le32 spsr;
+ __le32 r0; /* a1 */
+ __le32 r1; /* a2 */
+ __le32 r2; /* a3 */
+ __le32 r3; /* a4 */
+ __le32 r4; /* v1 */
+ __le32 r5; /* v2 */
+ __le32 r6; /* v3 */
+ __le32 r7; /* v4 */
+ __le32 r8; /* v5 */
+ __le32 r9; /* sb/v6 */
+ __le32 r10; /* sl/v7 */
+ __le32 r11; /* fp/v8 */
+ __le32 r12; /* ip */
+ __le32 r13; /* sp */
+ __le32 r14; /* lr */
+ __le32 pc; /* r15 */
+};
#endif /* DEBUG */
struct sdpcm_shared {
@@ -439,6 +467,7 @@ struct sdpcm_shared {
u32 console_addr; /* Address of struct rte_console */
u32 msgtrace_addr;
u8 tag[32];
+ u32 brpt_addr;
};
struct sdpcm_shared_le {
@@ -450,6 +479,7 @@ struct sdpcm_shared_le {
__le32 console_addr; /* Address of struct rte_console */
__le32 msgtrace_addr;
u8 tag[32];
+ __le32 brpt_addr;
};
@@ -502,12 +532,9 @@ struct brcmf_sdio {
bool intr; /* Use interrupts */
bool poll; /* Use polling */
bool ipend; /* Device interrupt is pending */
- uint intrcount; /* Count of device interrupt callbacks */
- uint lastintrs; /* Count as of last watchdog timer */
uint spurious; /* Count of spurious interrupts */
uint pollrate; /* Ticks between device polls */
uint polltick; /* Tick counter */
- uint pollcnt; /* Count of active polls */
#ifdef DEBUG
uint console_interval;
@@ -515,8 +542,6 @@ struct brcmf_sdio {
uint console_addr; /* Console address from shared struct */
#endif /* DEBUG */
- uint regfails; /* Count of R_REG failures */
-
uint clkstate; /* State of sd and backplane clock(s) */
bool activity; /* Activity flag for clock down */
s32 idletime; /* Control for activity timeout */
@@ -531,33 +556,6 @@ struct brcmf_sdio {
/* Field to decide if rx of control frames happen in rxbuf or lb-pool */
bool usebufpool;
- /* Some additional counters */
- uint tx_sderrs; /* Count of tx attempts with sd errors */
- uint fcqueued; /* Tx packets that got queued */
- uint rxrtx; /* Count of rtx requests (NAK to dongle) */
- uint rx_toolong; /* Receive frames too long to receive */
- uint rxc_errors; /* SDIO errors when reading control frames */
- uint rx_hdrfail; /* SDIO errors on header reads */
- uint rx_badhdr; /* Bad received headers (roosync?) */
- uint rx_badseq; /* Mismatched rx sequence number */
- uint fc_rcvd; /* Number of flow-control events received */
- uint fc_xoff; /* Number which turned on flow-control */
- uint fc_xon; /* Number which turned off flow-control */
- uint rxglomfail; /* Failed deglom attempts */
- uint rxglomframes; /* Number of glom frames (superframes) */
- uint rxglompkts; /* Number of packets from glom frames */
- uint f2rxhdrs; /* Number of header reads */
- uint f2rxdata; /* Number of frame data reads */
- uint f2txdata; /* Number of f2 frame writes */
- uint f1regdata; /* Number of f1 register accesses */
- uint tickcnt; /* Number of watchdog been schedule */
- unsigned long tx_ctlerrs; /* Err of sending ctrl frames */
- unsigned long tx_ctlpkts; /* Ctrl frames sent to dongle */
- unsigned long rx_ctlerrs; /* Err of processing rx ctrl frames */
- unsigned long rx_ctlpkts; /* Ctrl frames processed from dongle */
- unsigned long rx_readahead_cnt; /* Number of packets where header
- * read-ahead was used. */
-
u8 *ctrl_frame_buf;
u32 ctrl_frame_len;
bool ctrl_frame_stat;
@@ -583,6 +581,7 @@ struct brcmf_sdio {
u32 fw_ptr;
bool txoff; /* Transmit flow-controlled */
+ struct brcmf_sdio_count sdcnt;
};
/* clkstate */
@@ -945,7 +944,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
if (ret == 0)
w_sdreg32(bus, SMB_INT_ACK,
offsetof(struct sdpcmd_regs, tosbmailbox));
- bus->f1regdata += 2;
+ bus->sdcnt.f1regdata += 2;
/* Dongle recomposed rx frames, accept them again */
if (hmb_data & HMB_DATA_NAKHANDLED) {
@@ -984,12 +983,12 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
HMB_DATA_FCDATA_SHIFT;
if (fcbits & ~bus->flowcontrol)
- bus->fc_xoff++;
+ bus->sdcnt.fc_xoff++;
if (bus->flowcontrol & ~fcbits)
- bus->fc_xon++;
+ bus->sdcnt.fc_xon++;
- bus->fc_rcvd++;
+ bus->sdcnt.fc_rcvd++;
bus->flowcontrol = fcbits;
}
@@ -1021,7 +1020,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
SFC_RF_TERM, &err);
- bus->f1regdata++;
+ bus->sdcnt.f1regdata++;
/* Wait until the packet has been flushed (device/FIFO stable) */
for (lastrbc = retries = 0xffff; retries > 0; retries--) {
@@ -1029,7 +1028,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
SBSDIO_FUNC1_RFRAMEBCHI, &err);
lo = brcmf_sdio_regrb(bus->sdiodev,
SBSDIO_FUNC1_RFRAMEBCLO, &err);
- bus->f1regdata += 2;
+ bus->sdcnt.f1regdata += 2;
if ((hi == 0) && (lo == 0))
break;
@@ -1047,11 +1046,11 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries);
if (rtx) {
- bus->rxrtx++;
+ bus->sdcnt.rxrtx++;
err = w_sdreg32(bus, SMB_NAK,
offsetof(struct sdpcmd_regs, tosbmailbox));
- bus->f1regdata++;
+ bus->sdcnt.f1regdata++;
if (err == 0)
bus->rxskip = true;
}
@@ -1243,7 +1242,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
dlen);
errcode = -1;
}
- bus->f2rxdata++;
+ bus->sdcnt.f2rxdata++;
/* On failure, kill the superframe, allow a couple retries */
if (errcode < 0) {
@@ -1256,7 +1255,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
} else {
bus->glomerr = 0;
brcmf_sdbrcm_rxfail(bus, true, false);
- bus->rxglomfail++;
+ bus->sdcnt.rxglomfail++;
brcmf_sdbrcm_free_glom(bus);
}
return 0;
@@ -1312,7 +1311,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
if (rxseq != seq) {
brcmf_dbg(INFO, "(superframe) rx_seq %d, expected %d\n",
seq, rxseq);
- bus->rx_badseq++;
+ bus->sdcnt.rx_badseq++;
rxseq = seq;
}
@@ -1376,7 +1375,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
} else {
bus->glomerr = 0;
brcmf_sdbrcm_rxfail(bus, true, false);
- bus->rxglomfail++;
+ bus->sdcnt.rxglomfail++;
brcmf_sdbrcm_free_glom(bus);
}
bus->nextlen = 0;
@@ -1402,7 +1401,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
if (rxseq != seq) {
brcmf_dbg(GLOM, "rx_seq %d, expected %d\n",
seq, rxseq);
- bus->rx_badseq++;
+ bus->sdcnt.rx_badseq++;
rxseq = seq;
}
rxseq++;
@@ -1441,8 +1440,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
down(&bus->sdsem);
}
- bus->rxglomframes++;
- bus->rxglompkts += bus->glom.qlen;
+ bus->sdcnt.rxglomframes++;
+ bus->sdcnt.rxglompkts += bus->glom.qlen;
}
return num;
}
@@ -1526,7 +1525,7 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
brcmf_dbg(ERROR, "%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
len, len - doff, bus->sdiodev->bus_if->maxctl);
bus->sdiodev->bus_if->dstats.rx_errors++;
- bus->rx_toolong++;
+ bus->sdcnt.rx_toolong++;
brcmf_sdbrcm_rxfail(bus, false, false);
goto done;
}
@@ -1536,13 +1535,13 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
bus->sdiodev->sbwad,
SDIO_FUNC_2,
F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen);
- bus->f2rxdata++;
+ bus->sdcnt.f2rxdata++;
/* Control frame failures need retransmission */
if (sdret < 0) {
brcmf_dbg(ERROR, "read %d control bytes failed: %d\n",
rdlen, sdret);
- bus->rxc_errors++;
+ bus->sdcnt.rxc_errors++;
brcmf_sdbrcm_rxfail(bus, true, true);
goto done;
}
@@ -1589,7 +1588,7 @@ brcmf_alloc_pkt_and_read(struct brcmf_sdio *bus, u16 rdlen,
/* Read the entire frame */
sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, *pkt);
- bus->f2rxdata++;
+ bus->sdcnt.f2rxdata++;
if (sdret < 0) {
brcmf_dbg(ERROR, "(nextlen): read %d bytes failed: %d\n",
@@ -1630,7 +1629,7 @@ brcmf_check_rxbuf(struct brcmf_sdio *bus, struct sk_buff *pkt, u8 *rxbuf,
if ((u16)~(*len ^ check)) {
brcmf_dbg(ERROR, "(nextlen): HW hdr error: nextlen/len/check 0x%04x/0x%04x/0x%04x\n",
nextlen, *len, check);
- bus->rx_badhdr++;
+ bus->sdcnt.rx_badhdr++;
brcmf_sdbrcm_rxfail(bus, false, false);
goto fail;
}
@@ -1746,7 +1745,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished)
bus->nextlen = 0;
}
- bus->rx_readahead_cnt++;
+ bus->sdcnt.rx_readahead_cnt++;
/* Handle Flow Control */
fcbits = SDPCM_FCMASK_VALUE(
@@ -1754,12 +1753,12 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished)
if (bus->flowcontrol != fcbits) {
if (~bus->flowcontrol & fcbits)
- bus->fc_xoff++;
+ bus->sdcnt.fc_xoff++;
if (bus->flowcontrol & ~fcbits)
- bus->fc_xon++;
+ bus->sdcnt.fc_xon++;
- bus->fc_rcvd++;
+ bus->sdcnt.fc_rcvd++;
bus->flowcontrol = fcbits;
}
@@ -1767,7 +1766,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished)
if (rxseq != seq) {
brcmf_dbg(INFO, "(nextlen): rx_seq %d, expected %d\n",
seq, rxseq);
- bus->rx_badseq++;
+ bus->sdcnt.rx_badseq++;
rxseq = seq;
}
@@ -1814,11 +1813,11 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished)
sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, bus->rxhdr,
BRCMF_FIRSTREAD);
- bus->f2rxhdrs++;
+ bus->sdcnt.f2rxhdrs++;
if (sdret < 0) {
brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n", sdret);
- bus->rx_hdrfail++;
+ bus->sdcnt.rx_hdrfail++;
brcmf_sdbrcm_rxfail(bus, true, true);
continue;
}
@@ -1840,7 +1839,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished)
if ((u16) ~(len ^ check)) {
brcmf_dbg(ERROR, "HW hdr err: len/check 0x%04x/0x%04x\n",
len, check);
- bus->rx_badhdr++;
+ bus->sdcnt.rx_badhdr++;
brcmf_sdbrcm_rxfail(bus, false, false);
continue;
}
@@ -1861,7 +1860,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished)
if ((doff < SDPCM_HDRLEN) || (doff > len)) {
brcmf_dbg(ERROR, "Bad data offset %d: HW len %d, min %d seq %d\n",
doff, len, SDPCM_HDRLEN, seq);
- bus->rx_badhdr++;
+ bus->sdcnt.rx_badhdr++;
brcmf_sdbrcm_rxfail(bus, false, false);
continue;
}
@@ -1880,19 +1879,19 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished)
if (bus->flowcontrol != fcbits) {
if (~bus->flowcontrol & fcbits)
- bus->fc_xoff++;
+ bus->sdcnt.fc_xoff++;
if (bus->flowcontrol & ~fcbits)
- bus->fc_xon++;
+ bus->sdcnt.fc_xon++;
- bus->fc_rcvd++;
+ bus->sdcnt.fc_rcvd++;
bus->flowcontrol = fcbits;
}
/* Check and update sequence number */
if (rxseq != seq) {
brcmf_dbg(INFO, "rx_seq %d, expected %d\n", seq, rxseq);
- bus->rx_badseq++;
+ bus->sdcnt.rx_badseq++;
rxseq = seq;
}
@@ -1937,7 +1936,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished)
brcmf_dbg(ERROR, "too long: len %d rdlen %d\n",
len, rdlen);
bus->sdiodev->bus_if->dstats.rx_errors++;
- bus->rx_toolong++;
+ bus->sdcnt.rx_toolong++;
brcmf_sdbrcm_rxfail(bus, false, false);
continue;
}
@@ -1960,7 +1959,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished)
/* Read the remaining frame data */
sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, pkt);
- bus->f2rxdata++;
+ bus->sdcnt.f2rxdata++;
if (sdret < 0) {
brcmf_dbg(ERROR, "read %d %s bytes failed: %d\n", rdlen,
@@ -2147,18 +2146,18 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, pkt);
- bus->f2txdata++;
+ bus->sdcnt.f2txdata++;
if (ret < 0) {
/* On failure, abort the command and terminate the frame */
brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n",
ret);
- bus->tx_sderrs++;
+ bus->sdcnt.tx_sderrs++;
brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
SFC_WF_TERM, NULL);
- bus->f1regdata++;
+ bus->sdcnt.f1regdata++;
for (i = 0; i < 3; i++) {
u8 hi, lo;
@@ -2166,7 +2165,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
SBSDIO_FUNC1_WFRAMEBCHI, NULL);
lo = brcmf_sdio_regrb(bus->sdiodev,
SBSDIO_FUNC1_WFRAMEBCLO, NULL);
- bus->f1regdata += 2;
+ bus->sdcnt.f1regdata += 2;
if ((hi == 0) && (lo == 0))
break;
}
@@ -2224,7 +2223,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
ret = r_sdreg32(bus, &intstatus,
offsetof(struct sdpcmd_regs,
intstatus));
- bus->f2txdata++;
+ bus->sdcnt.f2txdata++;
if (ret != 0)
break;
if (intstatus & bus->hostintmask)
@@ -2417,7 +2416,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
bus->ipend = false;
err = r_sdreg32(bus, &newstatus,
offsetof(struct sdpcmd_regs, intstatus));
- bus->f1regdata++;
+ bus->sdcnt.f1regdata++;
if (err != 0)
newstatus = 0;
newstatus &= bus->hostintmask;
@@ -2426,7 +2425,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
err = w_sdreg32(bus, newstatus,
offsetof(struct sdpcmd_regs,
intstatus));
- bus->f1regdata++;
+ bus->sdcnt.f1regdata++;
}
}
@@ -2445,7 +2444,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
err = r_sdreg32(bus, &newstatus,
offsetof(struct sdpcmd_regs, intstatus));
- bus->f1regdata += 2;
+ bus->sdcnt.f1regdata += 2;
bus->fcstate =
!!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
intstatus |= (newstatus & bus->hostintmask);
@@ -2510,13 +2509,13 @@ clkwait:
terminate the frame */
brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n",
ret);
- bus->tx_sderrs++;
+ bus->sdcnt.tx_sderrs++;
brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
SFC_WF_TERM, &err);
- bus->f1regdata++;
+ bus->sdcnt.f1regdata++;
for (i = 0; i < 3; i++) {
u8 hi, lo;
@@ -2526,7 +2525,7 @@ clkwait:
lo = brcmf_sdio_regrb(bus->sdiodev,
SBSDIO_FUNC1_WFRAMEBCLO,
&err);
- bus->f1regdata += 2;
+ bus->sdcnt.f1regdata += 2;
if ((hi == 0) && (lo == 0))
break;
}
@@ -2657,7 +2656,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
/* Check for existing queue, current flow-control,
pending event, or pending clock */
brcmf_dbg(TRACE, "deferring pktq len %d\n", pktq_len(&bus->txq));
- bus->fcqueued++;
+ bus->sdcnt.fcqueued++;
/* Priority based enq */
spin_lock_bh(&bus->txqlock);
@@ -2845,13 +2844,13 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len)
/* On failure, abort the command and terminate the frame */
brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n",
ret);
- bus->tx_sderrs++;
+ bus->sdcnt.tx_sderrs++;
brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
SFC_WF_TERM, NULL);
- bus->f1regdata++;
+ bus->sdcnt.f1regdata++;
for (i = 0; i < 3; i++) {
u8 hi, lo;
@@ -2859,7 +2858,7 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len)
SBSDIO_FUNC1_WFRAMEBCHI, NULL);
lo = brcmf_sdio_regrb(bus->sdiodev,
SBSDIO_FUNC1_WFRAMEBCLO, NULL);
- bus->f1regdata += 2;
+ bus->sdcnt.f1regdata += 2;
if (hi == 0 && lo == 0)
break;
}
@@ -2976,13 +2975,324 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
up(&bus->sdsem);
if (ret)
- bus->tx_ctlerrs++;
+ bus->sdcnt.tx_ctlerrs++;
else
- bus->tx_ctlpkts++;
+ bus->sdcnt.tx_ctlpkts++;
return ret ? -EIO : 0;
}
+#ifdef DEBUG
+static inline bool brcmf_sdio_valid_shared_address(u32 addr)
+{
+ return !(addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff));
+}
+
+static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
+ struct sdpcm_shared *sh)
+{
+ u32 addr;
+ int rv;
+ u32 shaddr = 0;
+ struct sdpcm_shared_le sh_le;
+ __le32 addr_le;
+
+ shaddr = bus->ramsize - 4;
+
+ /*
+ * Read last word in socram to determine
+ * address of sdpcm_shared structure
+ */
+ rv = brcmf_sdbrcm_membytes(bus, false, shaddr,
+ (u8 *)&addr_le, 4);
+ if (rv < 0)
+ return rv;
+
+ addr = le32_to_cpu(addr_le);
+
+ brcmf_dbg(INFO, "sdpcm_shared address 0x%08X\n", addr);
+
+ /*
+ * Check if addr is valid.
+ * NVRAM length at the end of memory should have been overwritten.
+ */
+ if (!brcmf_sdio_valid_shared_address(addr)) {
+ brcmf_dbg(ERROR, "invalid sdpcm_shared address 0x%08X\n",
+ addr);
+ return -EINVAL;
+ }
+
+ /* Read hndrte_shared structure */
+ rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le,
+ sizeof(struct sdpcm_shared_le));
+ if (rv < 0)
+ return rv;
+
+ /* Endianness */
+ sh->flags = le32_to_cpu(sh_le.flags);
+ sh->trap_addr = le32_to_cpu(sh_le.trap_addr);
+ sh->assert_exp_addr = le32_to_cpu(sh_le.assert_exp_addr);
+ sh->assert_file_addr = le32_to_cpu(sh_le.assert_file_addr);
+ sh->assert_line = le32_to_cpu(sh_le.assert_line);
+ sh->console_addr = le32_to_cpu(sh_le.console_addr);
+ sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr);
+
+ if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
+ brcmf_dbg(ERROR,
+ "sdpcm_shared version mismatch: dhd %d dongle %d\n",
+ SDPCM_SHARED_VERSION,
+ sh->flags & SDPCM_SHARED_VERSION_MASK);
+ return -EPROTO;
+ }
+
+ return 0;
+}
+
+static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
+ struct sdpcm_shared *sh, char __user *data,
+ size_t count)
+{
+ u32 addr, console_ptr, console_size, console_index;
+ char *conbuf = NULL;
+ __le32 sh_val;
+ int rv;
+ loff_t pos = 0;
+ int nbytes = 0;
+
+ /* obtain console information from device memory */
+ addr = sh->console_addr + offsetof(struct rte_console, log_le);
+ rv = brcmf_sdbrcm_membytes(bus, false, addr,
+ (u8 *)&sh_val, sizeof(u32));
+ if (rv < 0)
+ return rv;
+ console_ptr = le32_to_cpu(sh_val);
+
+ addr = sh->console_addr + offsetof(struct rte_console, log_le.buf_size);
+ rv = brcmf_sdbrcm_membytes(bus, false, addr,
+ (u8 *)&sh_val, sizeof(u32));
+ if (rv < 0)
+ return rv;
+ console_size = le32_to_cpu(sh_val);
+
+ addr = sh->console_addr + offsetof(struct rte_console, log_le.idx);
+ rv = brcmf_sdbrcm_membytes(bus, false, addr,
+ (u8 *)&sh_val, sizeof(u32));
+ if (rv < 0)
+ return rv;
+ console_index = le32_to_cpu(sh_val);
+
+ /* allocate buffer for console data */
+ if (console_size <= CONSOLE_BUFFER_MAX)
+ conbuf = vzalloc(console_size+1);
+
+ if (!conbuf)
+ return -ENOMEM;
+
+ /* obtain the console data from device */
+ conbuf[console_size] = '\0';
+ rv = brcmf_sdbrcm_membytes(bus, false, console_ptr, (u8 *)conbuf,
+ console_size);
+ if (rv < 0)
+ goto done;
+
+ rv = simple_read_from_buffer(data, count, &pos,
+ conbuf + console_index,
+ console_size - console_index);
+ if (rv < 0)
+ goto done;
+
+ nbytes = rv;
+ if (console_index > 0) {
+ pos = 0;
+ rv = simple_read_from_buffer(data+nbytes, count, &pos,
+ conbuf, console_index - 1);
+ if (rv < 0)
+ goto done;
+ rv += nbytes;
+ }
+done:
+ vfree(conbuf);
+ return rv;
+}
+
+static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
+ char __user *data, size_t count)
+{
+ int error, res;
+ char buf[350];
+ struct brcmf_trap_info tr;
+ int nbytes;
+ loff_t pos = 0;
+
+ if ((sh->flags & SDPCM_SHARED_TRAP) == 0)
+ return 0;
+
+ error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
+ sizeof(struct brcmf_trap_info));
+ if (error < 0)
+ return error;
+
+ nbytes = brcmf_sdio_dump_console(bus, sh, data, count);
+ if (nbytes < 0)
+ return nbytes;
+
+ res = scnprintf(buf, sizeof(buf),
+ "dongle trap info: type 0x%x @ epc 0x%08x\n"
+ " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
+ " lr 0x%08x pc 0x%08x offset 0x%x\n"
+ " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n"
+ " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n",
+ le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
+ le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
+ le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
+ le32_to_cpu(tr.pc), sh->trap_addr,
+ le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
+ le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
+ le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
+ le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
+
+ error = simple_read_from_buffer(data+nbytes, count, &pos, buf, res);
+ if (error < 0)
+ return error;
+
+ nbytes += error;
+ return nbytes;
+}
+
+static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
+ struct sdpcm_shared *sh, char __user *data,
+ size_t count)
+{
+ int error = 0;
+ char buf[200];
+ char file[80] = "?";
+ char expr[80] = "<???>";
+ int res;
+ loff_t pos = 0;
+
+ if ((sh->flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
+ brcmf_dbg(INFO, "firmware not built with -assert\n");
+ return 0;
+ } else if ((sh->flags & SDPCM_SHARED_ASSERT) == 0) {
+ brcmf_dbg(INFO, "no assert in dongle\n");
+ return 0;
+ }
+
+ if (sh->assert_file_addr != 0) {
+ error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr,
+ (u8 *)file, 80);
+ if (error < 0)
+ return error;
+ }
+ if (sh->assert_exp_addr != 0) {
+ error = brcmf_sdbrcm_membytes(bus, false, sh->assert_exp_addr,
+ (u8 *)expr, 80);
+ if (error < 0)
+ return error;
+ }
+
+ res = scnprintf(buf, sizeof(buf),
+ "dongle assert: %s:%d: assert(%s)\n",
+ file, sh->assert_line, expr);
+ return simple_read_from_buffer(data, count, &pos, buf, res);
+}
+
+static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus)
+{
+ int error;
+ struct sdpcm_shared sh;
+
+ down(&bus->sdsem);
+ error = brcmf_sdio_readshared(bus, &sh);
+ up(&bus->sdsem);
+
+ if (error < 0)
+ return error;
+
+ if ((sh.flags & SDPCM_SHARED_ASSERT_BUILT) == 0)
+ brcmf_dbg(INFO, "firmware not built with -assert\n");
+ else if (sh.flags & SDPCM_SHARED_ASSERT)
+ brcmf_dbg(ERROR, "assertion in dongle\n");
+
+ if (sh.flags & SDPCM_SHARED_TRAP)
+ brcmf_dbg(ERROR, "firmware trap in dongle\n");
+
+ return 0;
+}
+
+static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data,
+ size_t count, loff_t *ppos)
+{
+ int error = 0;
+ struct sdpcm_shared sh;
+ int nbytes = 0;
+ loff_t pos = *ppos;
+
+ if (pos != 0)
+ return 0;
+
+ down(&bus->sdsem);
+ error = brcmf_sdio_readshared(bus, &sh);
+ if (error < 0)
+ goto done;
+
+ error = brcmf_sdio_assert_info(bus, &sh, data, count);
+ if (error < 0)
+ goto done;
+
+ nbytes = error;
+ error = brcmf_sdio_trap_info(bus, &sh, data, count);
+ if (error < 0)
+ goto done;
+
+ error += nbytes;
+ *ppos += error;
+done:
+ up(&bus->sdsem);
+ return error;
+}
+
+static ssize_t brcmf_sdio_forensic_read(struct file *f, char __user *data,
+ size_t count, loff_t *ppos)
+{
+ struct brcmf_sdio *bus = f->private_data;
+ int res;
+
+ res = brcmf_sdbrcm_died_dump(bus, data, count, ppos);
+ if (res > 0)
+ *ppos += res;
+ return (ssize_t)res;
+}
+
+static const struct file_operations brcmf_sdio_forensic_ops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = brcmf_sdio_forensic_read
+};
+
+static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
+{
+ struct brcmf_pub *drvr = bus->sdiodev->bus_if->drvr;
+ struct dentry *dentry = brcmf_debugfs_get_devdir(drvr);
+
+ if (IS_ERR_OR_NULL(dentry))
+ return;
+
+ debugfs_create_file("forensics", S_IRUGO, dentry, bus,
+ &brcmf_sdio_forensic_ops);
+ brcmf_debugfs_create_sdio_count(drvr, &bus->sdcnt);
+}
+#else
+static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus)
+{
+ return 0;
+}
+
+static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
+{
+}
+#endif /* DEBUG */
+
static int
brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
{
@@ -3009,60 +3319,27 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
rxlen, msglen);
} else if (timeleft == 0) {
brcmf_dbg(ERROR, "resumed on timeout\n");
+ brcmf_sdbrcm_checkdied(bus);
} else if (pending) {
brcmf_dbg(CTL, "cancelled\n");
return -ERESTARTSYS;
} else {
brcmf_dbg(CTL, "resumed for unknown reason?\n");
+ brcmf_sdbrcm_checkdied(bus);
}
if (rxlen)
- bus->rx_ctlpkts++;
+ bus->sdcnt.rx_ctlpkts++;
else
- bus->rx_ctlerrs++;
+ bus->sdcnt.rx_ctlerrs++;
return rxlen ? (int)rxlen : -ETIMEDOUT;
}
-static int brcmf_sdbrcm_downloadvars(struct brcmf_sdio *bus, void *arg, int len)
-{
- int bcmerror = 0;
-
- brcmf_dbg(TRACE, "Enter\n");
-
- /* Basic sanity checks */
- if (bus->sdiodev->bus_if->drvr_up) {
- bcmerror = -EISCONN;
- goto err;
- }
- if (!len) {
- bcmerror = -EOVERFLOW;
- goto err;
- }
-
- /* Free the old ones and replace with passed variables */
- kfree(bus->vars);
-
- bus->vars = kmalloc(len, GFP_ATOMIC);
- bus->varsz = bus->vars ? len : 0;
- if (bus->vars == NULL) {
- bcmerror = -ENOMEM;
- goto err;
- }
-
- /* Copy the passed variables, which should include the
- terminating double-null */
- memcpy(bus->vars, arg, bus->varsz);
-err:
- return bcmerror;
-}
-
static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus)
{
int bcmerror = 0;
- u32 varsize;
u32 varaddr;
- u8 *vbuffer;
u32 varsizew;
__le32 varsizew_le;
#ifdef DEBUG
@@ -3071,56 +3348,44 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus)
/* Even if there are no vars are to be written, we still
need to set the ramsize. */
- varsize = bus->varsz ? roundup(bus->varsz, 4) : 0;
- varaddr = (bus->ramsize - 4) - varsize;
+ varaddr = (bus->ramsize - 4) - bus->varsz;
if (bus->vars) {
- vbuffer = kzalloc(varsize, GFP_ATOMIC);
- if (!vbuffer)
- return -ENOMEM;
-
- memcpy(vbuffer, bus->vars, bus->varsz);
-
/* Write the vars list */
- bcmerror =
- brcmf_sdbrcm_membytes(bus, true, varaddr, vbuffer, varsize);
+ bcmerror = brcmf_sdbrcm_membytes(bus, true, varaddr,
+ bus->vars, bus->varsz);
#ifdef DEBUG
/* Verify NVRAM bytes */
- brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", varsize);
- nvram_ularray = kmalloc(varsize, GFP_ATOMIC);
- if (!nvram_ularray) {
- kfree(vbuffer);
+ brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n",
+ bus->varsz);
+ nvram_ularray = kmalloc(bus->varsz, GFP_ATOMIC);
+ if (!nvram_ularray)
return -ENOMEM;
- }
/* Upload image to verify downloaded contents. */
- memset(nvram_ularray, 0xaa, varsize);
+ memset(nvram_ularray, 0xaa, bus->varsz);
/* Read the vars list to temp buffer for comparison */
- bcmerror =
- brcmf_sdbrcm_membytes(bus, false, varaddr, nvram_ularray,
- varsize);
+ bcmerror = brcmf_sdbrcm_membytes(bus, false, varaddr,
+ nvram_ularray, bus->varsz);
if (bcmerror) {
brcmf_dbg(ERROR, "error %d on reading %d nvram bytes at 0x%08x\n",
- bcmerror, varsize, varaddr);
+ bcmerror, bus->varsz, varaddr);
}
/* Compare the org NVRAM with the one read from RAM */
- if (memcmp(vbuffer, nvram_ularray, varsize))
+ if (memcmp(bus->vars, nvram_ularray, bus->varsz))
brcmf_dbg(ERROR, "Downloaded NVRAM image is corrupted\n");
else
brcmf_dbg(ERROR, "Download/Upload/Compare of NVRAM ok\n");
kfree(nvram_ularray);
#endif /* DEBUG */
-
- kfree(vbuffer);
}
/* adjust to the user specified RAM */
brcmf_dbg(INFO, "Physical memory size: %d\n", bus->ramsize);
brcmf_dbg(INFO, "Vars are at %d, orig varsize is %d\n",
- varaddr, varsize);
- varsize = ((bus->ramsize - 4) - varaddr);
+ varaddr, bus->varsz);
/*
* Determine the length token:
@@ -3131,13 +3396,13 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus)
varsizew = 0;
varsizew_le = cpu_to_le32(0);
} else {
- varsizew = varsize / 4;
+ varsizew = bus->varsz / 4;
varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
varsizew_le = cpu_to_le32(varsizew);
}
brcmf_dbg(INFO, "New varsize is %d, length token=0x%08x\n",
- varsize, varsizew);
+ bus->varsz, varsizew);
/* Write the length token to the last word */
bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->ramsize - 4),
@@ -3261,13 +3526,21 @@ err:
* by two NULs.
*/
-static uint brcmf_process_nvram_vars(char *varbuf, uint len)
+static int brcmf_process_nvram_vars(struct brcmf_sdio *bus)
{
+ char *varbuf;
char *dp;
bool findNewline;
int column;
- uint buf_len, n;
+ int ret = 0;
+ uint buf_len, n, len;
+ len = bus->firmware->size;
+ varbuf = vmalloc(len);
+ if (!varbuf)
+ return -ENOMEM;
+
+ memcpy(varbuf, bus->firmware->data, len);
dp = varbuf;
findNewline = false;
@@ -3296,56 +3569,44 @@ static uint brcmf_process_nvram_vars(char *varbuf, uint len)
column++;
}
buf_len = dp - varbuf;
-
while (dp < varbuf + n)
*dp++ = 0;
- return buf_len;
+ kfree(bus->vars);
+ /* roundup needed for download to device */
+ bus->varsz = roundup(buf_len + 1, 4);
+ bus->vars = kmalloc(bus->varsz, GFP_KERNEL);
+ if (bus->vars == NULL) {
+ bus->varsz = 0;
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /* copy the processed variables and add null termination */
+ memcpy(bus->vars, varbuf, buf_len);
+ bus->vars[buf_len] = 0;
+err:
+ vfree(varbuf);
+ return ret;
}
static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus)
{
- uint len;
- char *memblock = NULL;
- char *bufp;
int ret;
+ if (bus->sdiodev->bus_if->drvr_up)
+ return -EISCONN;
+
ret = request_firmware(&bus->firmware, BRCMF_SDIO_NV_NAME,
&bus->sdiodev->func[2]->dev);
if (ret) {
brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret);
return ret;
}
- bus->fw_ptr = 0;
-
- memblock = kmalloc(MEMBLOCK, GFP_ATOMIC);
- if (memblock == NULL) {
- ret = -ENOMEM;
- goto err;
- }
-
- len = brcmf_sdbrcm_get_image(memblock, MEMBLOCK, bus);
-
- if (len > 0 && len < MEMBLOCK) {
- bufp = (char *)memblock;
- bufp[len] = 0;
- len = brcmf_process_nvram_vars(bufp, len);
- bufp += len;
- *bufp++ = 0;
- if (len)
- ret = brcmf_sdbrcm_downloadvars(bus, memblock, len + 1);
- if (ret)
- brcmf_dbg(ERROR, "error downloading vars: %d\n", ret);
- } else {
- brcmf_dbg(ERROR, "error reading nvram file: %d\n", len);
- ret = -EIO;
- }
-err:
- kfree(memblock);
+ ret = brcmf_process_nvram_vars(bus);
release_firmware(bus->firmware);
- bus->fw_ptr = 0;
return ret;
}
@@ -3419,7 +3680,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
return 0;
/* Start the watchdog timer */
- bus->tickcnt = 0;
+ bus->sdcnt.tickcnt = 0;
brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
down(&bus->sdsem);
@@ -3512,7 +3773,7 @@ void brcmf_sdbrcm_isr(void *arg)
return;
}
/* Count the interrupt call */
- bus->intrcount++;
+ bus->sdcnt.intrcount++;
bus->ipend = true;
/* Shouldn't get this interrupt if we're sleeping? */
@@ -3554,7 +3815,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
bus->polltick = 0;
/* Check device if no interrupts */
- if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
+ if (!bus->intr ||
+ (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) {
if (!bus->dpc_sched) {
u8 devpend;
@@ -3569,7 +3831,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
/* If there is something, make like the ISR and
schedule the DPC */
if (intstatus) {
- bus->pollcnt++;
+ bus->sdcnt.pollcnt++;
bus->ipend = true;
bus->dpc_sched = true;
@@ -3581,7 +3843,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
}
/* Update interrupt tracking */
- bus->lastintrs = bus->intrcount;
+ bus->sdcnt.lastintrs = bus->sdcnt.intrcount;
}
#ifdef DEBUG
/* Poll for console output periodically */
@@ -3623,6 +3885,8 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid)
return true;
if (chipid == BCM4330_CHIP_ID)
return true;
+ if (chipid == BCM4334_CHIP_ID)
+ return true;
return false;
}
@@ -3793,7 +4057,7 @@ brcmf_sdbrcm_watchdog_thread(void *data)
if (!wait_for_completion_interruptible(&bus->watchdog_wait)) {
brcmf_sdbrcm_bus_watchdog(bus);
/* Count the tick for reference */
- bus->tickcnt++;
+ bus->sdcnt.tickcnt++;
} else
break;
}
@@ -3856,6 +4120,10 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
{
int ret;
struct brcmf_sdio *bus;
+ struct brcmf_bus_dcmd *dlst;
+ u32 dngl_txglom;
+ u32 dngl_txglomalign;
+ u8 idx;
brcmf_dbg(TRACE, "Enter\n");
@@ -3938,8 +4206,29 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
goto fail;
}
+ brcmf_sdio_debugfs_create(bus);
brcmf_dbg(INFO, "completed!!\n");
+ /* sdio bus core specific dcmd */
+ idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
+ dlst = kzalloc(sizeof(struct brcmf_bus_dcmd), GFP_KERNEL);
+ if (dlst) {
+ if (bus->ci->c_inf[idx].rev < 12) {
+ /* for sdio core rev < 12, disable txgloming */
+ dngl_txglom = 0;
+ dlst->name = "bus:txglom";
+ dlst->param = (char *)&dngl_txglom;
+ dlst->param_len = sizeof(u32);
+ } else {
+ /* otherwise, set txglomalign */
+ dngl_txglomalign = bus->sdiodev->bus_if->align;
+ dlst->name = "bus:txglomalign";
+ dlst->param = (char *)&dngl_txglomalign;
+ dlst->param_len = sizeof(u32);
+ }
+ list_add(&dlst->list, &bus->sdiodev->bus_if->dcmd_list);
+ }
+
/* if firmware path present try to download and bring up bus */
ret = brcmf_bus_start(bus->sdiodev->dev);
if (ret != 0) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
index f8e1f1c84d08..58155e23d220 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
@@ -403,6 +403,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
ci->c_inf[3].cib = 0x03004211;
ci->ramsize = 0x48000;
break;
+ case BCM4334_CHIP_ID:
+ ci->c_inf[0].wrapbase = 0x18100000;
+ ci->c_inf[0].cib = 0x29004211;
+ ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
+ ci->c_inf[1].base = 0x18002000;
+ ci->c_inf[1].wrapbase = 0x18102000;
+ ci->c_inf[1].cib = 0x0d004211;
+ ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
+ ci->c_inf[2].base = 0x18004000;
+ ci->c_inf[2].wrapbase = 0x18104000;
+ ci->c_inf[2].cib = 0x13080401;
+ ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
+ ci->c_inf[3].base = 0x18003000;
+ ci->c_inf[3].wrapbase = 0x18103000;
+ ci->c_inf[3].cib = 0x07004211;
+ ci->ramsize = 0x80000;
+ break;
default:
brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
return -ENODEV;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index d13ae9c299f2..c6a10caec79f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -691,9 +691,10 @@ scan_out:
}
static s32
-brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+brcmf_cfg80211_scan(struct wiphy *wiphy,
struct cfg80211_scan_request *request)
{
+ struct net_device *ndev = request->wdev->netdev;
s32 err = 0;
WL_TRACE("Enter\n");
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
index 3c6f9b1e8d05..8c9345dd37d2 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
@@ -318,10 +318,6 @@
#define IS_SIM(chippkg) \
((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
-#define PCIE(sih) (ai_get_buscoretype(sih) == PCIE_CORE_ID)
-
-#define PCI_FORCEHT(sih) (PCIE(sih) && (ai_get_chip_id(sih) == BCM4716_CHIP_ID))
-
#ifdef DEBUG
#define SI_MSG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__)
#else
@@ -473,9 +469,6 @@ ai_buscore_setup(struct si_info *sii, struct bcma_device *cc)
sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
}
- /* figure out buscore */
- sii->buscore = ai_findcore(&sii->pub, PCIE_CORE_ID, 0);
-
return true;
}
@@ -483,11 +476,7 @@ static struct si_info *ai_doattach(struct si_info *sii,
struct bcma_bus *pbus)
{
struct si_pub *sih = &sii->pub;
- u32 w, savewin;
struct bcma_device *cc;
- struct ssb_sprom *sprom = &pbus->sprom;
-
- savewin = 0;
sii->icbus = pbus;
sii->pcibus = pbus->host_pci;
@@ -510,47 +499,7 @@ static struct si_info *ai_doattach(struct si_info *sii,
/* PMU specific initializations */
if (ai_get_cccaps(sih) & CC_CAP_PMU) {
- si_pmu_init(sih);
(void)si_pmu_measure_alpclk(sih);
- si_pmu_res_init(sih);
- }
-
- /* setup the GPIO based LED powersave register */
- w = (sprom->leddc_on_time << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
- (sprom->leddc_off_time << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT);
- if (w == 0)
- w = DEFAULT_GPIOTIMERVAL;
- ai_cc_reg(sih, offsetof(struct chipcregs, gpiotimerval),
- ~0, w);
-
- if (ai_get_chip_id(sih) == BCM43224_CHIP_ID) {
- /*
- * enable 12 mA drive strenth for 43224 and
- * set chipControl register bit 15
- */
- if (ai_get_chiprev(sih) == 0) {
- SI_MSG("Applying 43224A0 WARs\n");
- ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol),
- CCTRL43224_GPIO_TOGGLE,
- CCTRL43224_GPIO_TOGGLE);
- si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE,
- CCTRL_43224A0_12MA_LED_DRIVE);
- }
- if (ai_get_chiprev(sih) >= 1) {
- SI_MSG("Applying 43224B0+ WARs\n");
- si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE,
- CCTRL_43224B0_12MA_LED_DRIVE);
- }
- }
-
- if (ai_get_chip_id(sih) == BCM4313_CHIP_ID) {
- /*
- * enable 12 mA drive strenth for 4313 and
- * set chipControl register bit 1
- */
- SI_MSG("Applying 4313 WARs\n");
- si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE,
- CCTRL_4313_12MA_LED_DRIVE);
}
return sii;
@@ -589,7 +538,7 @@ void ai_detach(struct si_pub *sih)
struct si_pub *si_local = NULL;
memcpy(&si_local, &sih, sizeof(struct si_pub **));
- sii = (struct si_info *)sih;
+ sii = container_of(sih, struct si_info, pub);
if (sii == NULL)
return;
@@ -597,27 +546,6 @@ void ai_detach(struct si_pub *sih)
kfree(sii);
}
-/* return index of coreid or BADIDX if not found */
-struct bcma_device *ai_findcore(struct si_pub *sih, u16 coreid, u16 coreunit)
-{
- struct bcma_device *core;
- struct si_info *sii;
- uint found;
-
- sii = (struct si_info *)sih;
-
- found = 0;
-
- list_for_each_entry(core, &sii->icbus->cores, list)
- if (core->id.id == coreid) {
- if (found == coreunit)
- return core;
- found++;
- }
-
- return NULL;
-}
-
/*
* read/modify chipcommon core register.
*/
@@ -627,7 +555,7 @@ uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val)
u32 w;
struct si_info *sii;
- sii = (struct si_info *)sih;
+ sii = container_of(sih, struct si_info, pub);
cc = sii->icbus->drv_cc.core;
/* mask and set */
@@ -693,12 +621,13 @@ ai_clkctl_setdelay(struct si_pub *sih, struct bcma_device *cc)
/* initialize power control delay registers */
void ai_clkctl_init(struct si_pub *sih)
{
+ struct si_info *sii = container_of(sih, struct si_info, pub);
struct bcma_device *cc;
if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL))
return;
- cc = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
+ cc = sii->icbus->drv_cc.core;
if (cc == NULL)
return;
@@ -720,7 +649,7 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih)
uint slowminfreq;
u16 fpdelay;
- sii = (struct si_info *)sih;
+ sii = container_of(sih, struct si_info, pub);
if (ai_get_cccaps(sih) & CC_CAP_PMU) {
fpdelay = si_pmu_fast_pwrup_delay(sih);
return fpdelay;
@@ -730,7 +659,7 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih)
return 0;
fpdelay = 0;
- cc = ai_findcore(sih, CC_CORE_ID, 0);
+ cc = sii->icbus->drv_cc.core;
if (cc) {
slowminfreq = ai_slowclk_freq(sih, false, cc);
fpdelay = (((bcma_read32(cc, CHIPCREGOFFS(pll_on_delay)) + 2)
@@ -752,12 +681,9 @@ bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode)
struct si_info *sii;
struct bcma_device *cc;
- sii = (struct si_info *)sih;
-
- if (PCI_FORCEHT(sih))
- return mode == BCMA_CLKMODE_FAST;
+ sii = container_of(sih, struct si_info, pub);
- cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0);
+ cc = sii->icbus->drv_cc.core;
bcma_core_set_clockmode(cc, mode);
return mode == BCMA_CLKMODE_FAST;
}
@@ -765,16 +691,10 @@ bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode)
void ai_pci_up(struct si_pub *sih)
{
struct si_info *sii;
- struct bcma_device *cc;
- sii = (struct si_info *)sih;
+ sii = container_of(sih, struct si_info, pub);
- if (PCI_FORCEHT(sih)) {
- cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0);
- bcma_core_set_clockmode(cc, BCMA_CLKMODE_FAST);
- }
-
- if (PCIE(sih))
+ if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, true);
}
@@ -782,26 +702,20 @@ void ai_pci_up(struct si_pub *sih)
void ai_pci_down(struct si_pub *sih)
{
struct si_info *sii;
- struct bcma_device *cc;
- sii = (struct si_info *)sih;
+ sii = container_of(sih, struct si_info, pub);
- /* release FORCEHT since chip is going to "down" state */
- if (PCI_FORCEHT(sih)) {
- cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0);
- bcma_core_set_clockmode(cc, BCMA_CLKMODE_DYNAMIC);
- }
-
- if (PCIE(sih))
+ if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, false);
}
/* Enable BT-COEX & Ex-PA for 4313 */
void ai_epa_4313war(struct si_pub *sih)
{
+ struct si_info *sii = container_of(sih, struct si_info, pub);
struct bcma_device *cc;
- cc = ai_findcore(sih, CC_CORE_ID, 0);
+ cc = sii->icbus->drv_cc.core;
/* EPA Fix */
bcma_set32(cc, CHIPCREGOFFS(gpiocontrol), GPIO_CTRL_EPA_EN_MASK);
@@ -813,7 +727,7 @@ bool ai_deviceremoved(struct si_pub *sih)
u32 w;
struct si_info *sii;
- sii = (struct si_info *)sih;
+ sii = container_of(sih, struct si_info, pub);
if (sii->icbus->hosttype != BCMA_HOSTTYPE_PCI)
return false;
@@ -824,15 +738,3 @@ bool ai_deviceremoved(struct si_pub *sih)
return false;
}
-
-uint ai_get_buscoretype(struct si_pub *sih)
-{
- struct si_info *sii = (struct si_info *)sih;
- return sii->buscore->id.id;
-}
-
-uint ai_get_buscorerev(struct si_pub *sih)
-{
- struct si_info *sii = (struct si_info *)sih;
- return sii->buscore->id.rev;
-}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h
index d6fa9829af9a..89562c1fbf49 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h
@@ -88,16 +88,6 @@
#define CLKD_OTP 0x000f0000
#define CLKD_OTP_SHIFT 16
-/* Package IDs */
-#define BCM4717_PKG_ID 9 /* 4717 package id */
-#define BCM4718_PKG_ID 10 /* 4718 package id */
-#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */
-
-/* these are router chips */
-#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */
-#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */
-#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */
-
/* dynamic clock control defines */
#define LPOMINFREQ 25000 /* low power oscillator min */
#define LPOMAXFREQ 43000 /* low power oscillator max */
@@ -168,7 +158,6 @@ struct si_info {
struct si_pub pub; /* back plane public state (must be first) */
struct bcma_bus *icbus; /* handle to soc interconnect bus */
struct pci_dev *pcibus; /* handle to pci bus */
- struct bcma_device *buscore;
u32 chipst; /* chip status */
};
@@ -183,8 +172,6 @@ struct si_info {
/* AMBA Interconnect exported externs */
-extern struct bcma_device *ai_findcore(struct si_pub *sih,
- u16 coreid, u16 coreunit);
extern u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val);
/* === exported functions === */
@@ -202,9 +189,6 @@ extern void ai_pci_up(struct si_pub *sih);
/* Enable Ex-PA for 4313 */
extern void ai_epa_4313war(struct si_pub *sih);
-extern uint ai_get_buscoretype(struct si_pub *sih);
-extern uint ai_get_buscorerev(struct si_pub *sih);
-
static inline u32 ai_get_cccaps(struct si_pub *sih)
{
return sih->cccaps;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
index 95b5902bc4b3..01b190a25d94 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
@@ -735,10 +735,8 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
* a candidate for aggregation
*/
p = pktq_ppeek(&qi->q, prec);
- /* tx_info must be checked with current p */
- tx_info = IEEE80211_SKB_CB(p);
-
if (p) {
+ tx_info = IEEE80211_SKB_CB(p);
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
((u8) (p->priority) == tid)) {
plen = p->len + AMPDU_MAX_MPDU_OVERHEAD;
@@ -759,6 +757,7 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
p = NULL;
continue;
}
+ /* next packet fit for aggregation so dequeue */
p = brcmu_pktq_pdeq(&qi->q, prec);
} else {
p = NULL;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index eb77ac3cfb6b..9a4c63f927cb 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -15,7 +15,9 @@
*/
#include <linux/types.h>
+#include <net/cfg80211.h>
#include <net/mac80211.h>
+#include <net/regulatory.h>
#include <defs.h>
#include "pub.h"
@@ -23,73 +25,17 @@
#include "main.h"
#include "stf.h"
#include "channel.h"
+#include "mac80211_if.h"
/* QDB() macro takes a dB value and converts to a quarter dB value */
#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
-#define LOCALE_CHAN_01_11 (1<<0)
-#define LOCALE_CHAN_12_13 (1<<1)
-#define LOCALE_CHAN_14 (1<<2)
-#define LOCALE_SET_5G_LOW_JP1 (1<<3) /* 34-48, step 2 */
-#define LOCALE_SET_5G_LOW_JP2 (1<<4) /* 34-46, step 4 */
-#define LOCALE_SET_5G_LOW1 (1<<5) /* 36-48, step 4 */
-#define LOCALE_SET_5G_LOW2 (1<<6) /* 52 */
-#define LOCALE_SET_5G_LOW3 (1<<7) /* 56-64, step 4 */
-#define LOCALE_SET_5G_MID1 (1<<8) /* 100-116, step 4 */
-#define LOCALE_SET_5G_MID2 (1<<9) /* 120-124, step 4 */
-#define LOCALE_SET_5G_MID3 (1<<10) /* 128 */
-#define LOCALE_SET_5G_HIGH1 (1<<11) /* 132-140, step 4 */
-#define LOCALE_SET_5G_HIGH2 (1<<12) /* 149-161, step 4 */
-#define LOCALE_SET_5G_HIGH3 (1<<13) /* 165 */
-#define LOCALE_CHAN_52_140_ALL (1<<14)
-#define LOCALE_SET_5G_HIGH4 (1<<15) /* 184-216 */
-
-#define LOCALE_CHAN_36_64 (LOCALE_SET_5G_LOW1 | \
- LOCALE_SET_5G_LOW2 | \
- LOCALE_SET_5G_LOW3)
-#define LOCALE_CHAN_52_64 (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
-#define LOCALE_CHAN_100_124 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2)
-#define LOCALE_CHAN_100_140 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | \
- LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1)
-#define LOCALE_CHAN_149_165 (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3)
-#define LOCALE_CHAN_184_216 LOCALE_SET_5G_HIGH4
-
-#define LOCALE_CHAN_01_14 (LOCALE_CHAN_01_11 | \
- LOCALE_CHAN_12_13 | \
- LOCALE_CHAN_14)
-
-#define LOCALE_RADAR_SET_NONE 0
-#define LOCALE_RADAR_SET_1 1
-
-#define LOCALE_RESTRICTED_NONE 0
-#define LOCALE_RESTRICTED_SET_2G_SHORT 1
-#define LOCALE_RESTRICTED_CHAN_165 2
-#define LOCALE_CHAN_ALL_5G 3
-#define LOCALE_RESTRICTED_JAPAN_LEGACY 4
-#define LOCALE_RESTRICTED_11D_2G 5
-#define LOCALE_RESTRICTED_11D_5G 6
-#define LOCALE_RESTRICTED_LOW_HI 7
-#define LOCALE_RESTRICTED_12_13_14 8
-
-#define LOCALE_2G_IDX_i 0
-#define LOCALE_5G_IDX_11 0
#define LOCALE_MIMO_IDX_bn 0
#define LOCALE_MIMO_IDX_11n 0
-/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */
-#define BRCMS_MAXPWR_TBL_SIZE 6
/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
#define BRCMS_MAXPWR_MIMO_TBL_SIZE 14
-/* power level in group of 2.4GHz band channels:
- * maxpwr[0] - CCK channels [1]
- * maxpwr[1] - CCK channels [2-10]
- * maxpwr[2] - CCK channels [11-14]
- * maxpwr[3] - OFDM channels [1]
- * maxpwr[4] - OFDM channels [2-10]
- * maxpwr[5] - OFDM channels [11-14]
- */
-
/* maxpwr mapping to 5GHz band channels:
* maxpwr[0] - channels [34-48]
* maxpwr[1] - channels [52-60]
@@ -101,16 +47,8 @@
#define LC(id) LOCALE_MIMO_IDX_ ## id
-#define LC_2G(id) LOCALE_2G_IDX_ ## id
-
-#define LC_5G(id) LOCALE_5G_IDX_ ## id
-
-#define LOCALES(band2, band5, mimo2, mimo5) \
- {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)}
-
-/* macro to get 2.4 GHz channel group index for tx power */
-#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2))
-#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5))
+#define LOCALES(mimo2, mimo5) \
+ {LC(mimo2), LC(mimo5)}
/* macro to get 5 GHz channel group index for tx power */
#define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \
@@ -118,18 +56,37 @@
(((c) < 100) ? 2 : \
(((c) < 149) ? 3 : 4))))
-#define ISDFS_EU(fl) (((fl) & BRCMS_DFS_EU) == BRCMS_DFS_EU)
-
-struct brcms_cm_band {
- /* struct locale_info flags */
- u8 locale_flags;
- /* List of valid channels in the country */
- struct brcms_chanvec valid_channels;
- /* List of restricted use channels */
- const struct brcms_chanvec *restricted_channels;
- /* List of radar sensitive channels */
- const struct brcms_chanvec *radar_channels;
- u8 PAD[8];
+#define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
+#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \
+ NL80211_RRF_PASSIVE_SCAN | \
+ NL80211_RRF_NO_IBSS)
+
+#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \
+ NL80211_RRF_PASSIVE_SCAN | \
+ NL80211_RRF_NO_IBSS)
+#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \
+ NL80211_RRF_PASSIVE_SCAN | \
+ NL80211_RRF_DFS | \
+ NL80211_RRF_NO_IBSS)
+#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \
+ NL80211_RRF_PASSIVE_SCAN | \
+ NL80211_RRF_DFS | \
+ NL80211_RRF_NO_IBSS)
+#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \
+ NL80211_RRF_PASSIVE_SCAN | \
+ NL80211_RRF_NO_IBSS)
+
+static const struct ieee80211_regdomain brcms_regdom_x2 = {
+ .n_reg_rules = 7,
+ .alpha2 = "X2",
+ .reg_rules = {
+ BRCM_2GHZ_2412_2462,
+ BRCM_2GHZ_2467_2472,
+ BRCM_5GHZ_5180_5240,
+ BRCM_5GHZ_5260_5320,
+ BRCM_5GHZ_5500_5700,
+ BRCM_5GHZ_5745_5825,
+ }
};
/* locale per-channel tx power limits for MIMO frames
@@ -141,337 +98,23 @@ struct locale_mimo_info {
s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE];
/* tx 40 MHz power limits, qdBm units */
s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE];
- u8 flags;
};
/* Country names and abbreviations with locale defined from ISO 3166 */
struct country_info {
- const u8 locale_2G; /* 2.4G band locale */
- const u8 locale_5G; /* 5G band locale */
const u8 locale_mimo_2G; /* 2.4G mimo info */
const u8 locale_mimo_5G; /* 5G mimo info */
};
+struct brcms_regd {
+ struct country_info country;
+ const struct ieee80211_regdomain *regdomain;
+};
+
struct brcms_cm_info {
struct brcms_pub *pub;
struct brcms_c_info *wlc;
- char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */
- uint srom_regrev; /* Regulatory Rev for the SROM ccode */
- const struct country_info *country; /* current country def */
- char ccode[BRCM_CNTRY_BUF_SZ]; /* current internal Country Code */
- uint regrev; /* current Regulatory Revision */
- char country_abbrev[BRCM_CNTRY_BUF_SZ]; /* current advertised ccode */
- /* per-band state (one per phy/radio) */
- struct brcms_cm_band bandstate[MAXBANDS];
- /* quiet channels currently for radar sensitivity or 11h support */
- /* channels on which we cannot transmit */
- struct brcms_chanvec quiet_channels;
-};
-
-/* locale channel and power info. */
-struct locale_info {
- u32 valid_channels;
- /* List of radar sensitive channels */
- u8 radar_channels;
- /* List of channels used only if APs are detected */
- u8 restricted_channels;
- /* Max tx pwr in qdBm for each sub-band */
- s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE];
- /* Country IE advertised max tx pwr in dBm per sub-band */
- s8 pub_maxpwr[BAND_5G_PWR_LVLS];
- u8 flags;
-};
-
-/* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */
-
-/*
- * Some common channel sets
- */
-
-/* No channels */
-static const struct brcms_chanvec chanvec_none = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-/* All 2.4 GHz HW channels */
-static const struct brcms_chanvec chanvec_all_2G = {
- {0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-/* All 5 GHz HW channels */
-static const struct brcms_chanvec chanvec_all_5G = {
- {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x11, 0x11,
- 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
- 0x11, 0x11, 0x20, 0x22, 0x22, 0x00, 0x00, 0x11,
- 0x11, 0x11, 0x11, 0x01}
-};
-
-/*
- * Radar channel sets
- */
-
-/* Channels 52 - 64, 100 - 140 */
-static const struct brcms_chanvec radar_set1 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, /* 52 - 60 */
- 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, /* 64, 100 - 124 */
- 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 - 140 */
- 0x00, 0x00, 0x00, 0x00}
-};
-
-/*
- * Restricted channel sets
- */
-
-/* Channels 34, 38, 42, 46 */
-static const struct brcms_chanvec restricted_set_japan_legacy = {
- {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Channels 12, 13 */
-static const struct brcms_chanvec restricted_set_2g_short = {
- {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Channel 165 */
-static const struct brcms_chanvec restricted_chan_165 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Channels 36 - 48 & 149 - 165 */
-static const struct brcms_chanvec restricted_low_hi = {
- {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Channels 12 - 14 */
-static const struct brcms_chanvec restricted_set_12_13_14 = {
- {0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-/* global memory to provide working buffer for expanded locale */
-
-static const struct brcms_chanvec *g_table_radar_set[] = {
- &chanvec_none,
- &radar_set1
-};
-
-static const struct brcms_chanvec *g_table_restricted_chan[] = {
- &chanvec_none, /* restricted_set_none */
- &restricted_set_2g_short,
- &restricted_chan_165,
- &chanvec_all_5G,
- &restricted_set_japan_legacy,
- &chanvec_all_2G, /* restricted_set_11d_2G */
- &chanvec_all_5G, /* restricted_set_11d_5G */
- &restricted_low_hi,
- &restricted_set_12_13_14
-};
-
-static const struct brcms_chanvec locale_2g_01_11 = {
- {0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_2g_12_13 = {
- {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_2g_14 = {
- {0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_LOW_JP1 = {
- {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_LOW_JP2 = {
- {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_LOW1 = {
- {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_LOW2 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_LOW3 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_MID1 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_MID2 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_MID3 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_HIGH1 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_HIGH2 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_HIGH3 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_52_140_ALL = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_HIGH4 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
- 0x11, 0x11, 0x11, 0x11}
-};
-
-static const struct brcms_chanvec *g_table_locale_base[] = {
- &locale_2g_01_11,
- &locale_2g_12_13,
- &locale_2g_14,
- &locale_5g_LOW_JP1,
- &locale_5g_LOW_JP2,
- &locale_5g_LOW1,
- &locale_5g_LOW2,
- &locale_5g_LOW3,
- &locale_5g_MID1,
- &locale_5g_MID2,
- &locale_5g_MID3,
- &locale_5g_HIGH1,
- &locale_5g_HIGH2,
- &locale_5g_HIGH3,
- &locale_5g_52_140_ALL,
- &locale_5g_HIGH4
-};
-
-static void brcms_c_locale_add_channels(struct brcms_chanvec *target,
- const struct brcms_chanvec *channels)
-{
- u8 i;
- for (i = 0; i < sizeof(struct brcms_chanvec); i++)
- target->vec[i] |= channels->vec[i];
-}
-
-static void brcms_c_locale_get_channels(const struct locale_info *locale,
- struct brcms_chanvec *channels)
-{
- u8 i;
-
- memset(channels, 0, sizeof(struct brcms_chanvec));
-
- for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) {
- if (locale->valid_channels & (1 << i))
- brcms_c_locale_add_channels(channels,
- g_table_locale_base[i]);
- }
-}
-
-/*
- * Locale Definitions - 2.4 GHz
- */
-static const struct locale_info locale_i = { /* locale i. channel 1 - 13 */
- LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13,
- LOCALE_RADAR_SET_NONE,
- LOCALE_RESTRICTED_SET_2G_SHORT,
- {QDB(19), QDB(19), QDB(19),
- QDB(19), QDB(19), QDB(19)},
- {20, 20, 20, 0},
- BRCMS_EIRP
-};
-
-/*
- * Locale Definitions - 5 GHz
- */
-static const struct locale_info locale_11 = {
- /* locale 11. channel 36 - 48, 52 - 64, 100 - 140, 149 - 165 */
- LOCALE_CHAN_36_64 | LOCALE_CHAN_100_140 | LOCALE_CHAN_149_165,
- LOCALE_RADAR_SET_1,
- LOCALE_RESTRICTED_NONE,
- {QDB(21), QDB(21), QDB(21), QDB(21), QDB(21)},
- {23, 23, 23, 30, 30},
- BRCMS_EIRP | BRCMS_DFS_EU
-};
-
-static const struct locale_info *g_locale_2g_table[] = {
- &locale_i
-};
-
-static const struct locale_info *g_locale_5g_table[] = {
- &locale_11
+ const struct brcms_regd *world_regd;
};
/*
@@ -484,7 +127,6 @@ static const struct locale_mimo_info locale_bn = {
{0, 0, QDB(13), QDB(13), QDB(13),
QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
QDB(13), 0, 0},
- 0
};
static const struct locale_mimo_info *g_mimo_2g_table[] = {
@@ -497,114 +139,20 @@ static const struct locale_mimo_info *g_mimo_2g_table[] = {
static const struct locale_mimo_info locale_11n = {
{ /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)},
{QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)},
- 0
};
static const struct locale_mimo_info *g_mimo_5g_table[] = {
&locale_11n
};
-static const struct {
- char abbrev[BRCM_CNTRY_BUF_SZ]; /* country abbreviation */
- struct country_info country;
-} cntry_locales[] = {
+static const struct brcms_regd cntry_locales[] = {
+ /* Worldwide RoW 2, must always be at index 0 */
{
- "X2", LOCALES(i, 11, bn, 11n)}, /* Worldwide RoW 2 */
-};
-
-#ifdef SUPPORT_40MHZ
-/* 20MHz channel info for 40MHz pairing support */
-struct chan20_info {
- u8 sb;
- u8 adj_sbs;
+ .country = LOCALES(bn, 11n),
+ .regdomain = &brcms_regdom_x2,
+ },
};
-/* indicates adjacent channels that are allowed for a 40 Mhz channel and
- * those that permitted by the HT
- */
-struct chan20_info chan20_info[] = {
- /* 11b/11g */
-/* 0 */ {1, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 1 */ {2, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 2 */ {3, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 3 */ {4, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 4 */ {5, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 5 */ {6, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 6 */ {7, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 7 */ {8, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 8 */ {9, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 9 */ {10, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 10 */ {11, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 11 */ {12, (CH_LOWER_SB)},
-/* 12 */ {13, (CH_LOWER_SB)},
-/* 13 */ {14, (CH_LOWER_SB)},
-
-/* 11a japan high */
-/* 14 */ {34, (CH_UPPER_SB)},
-/* 15 */ {38, (CH_LOWER_SB)},
-/* 16 */ {42, (CH_LOWER_SB)},
-/* 17 */ {46, (CH_LOWER_SB)},
-
-/* 11a usa low */
-/* 18 */ {36, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 19 */ {40, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 20 */ {44, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 21 */ {48, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 22 */ {52, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 23 */ {56, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 24 */ {60, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 25 */ {64, (CH_LOWER_SB | CH_EWA_VALID)},
-
-/* 11a Europe */
-/* 26 */ {100, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 27 */ {104, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 28 */ {108, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 29 */ {112, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 30 */ {116, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 31 */ {120, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 32 */ {124, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 33 */ {128, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 34 */ {132, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 35 */ {136, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 36 */ {140, (CH_LOWER_SB)},
-
-/* 11a usa high, ref5 only */
-/* The 0x80 bit in pdiv means these are REF5, other entries are REF20 */
-/* 37 */ {149, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 38 */ {153, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 39 */ {157, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 40 */ {161, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 41 */ {165, (CH_LOWER_SB)},
-
-/* 11a japan */
-/* 42 */ {184, (CH_UPPER_SB)},
-/* 43 */ {188, (CH_LOWER_SB)},
-/* 44 */ {192, (CH_UPPER_SB)},
-/* 45 */ {196, (CH_LOWER_SB)},
-/* 46 */ {200, (CH_UPPER_SB)},
-/* 47 */ {204, (CH_LOWER_SB)},
-/* 48 */ {208, (CH_UPPER_SB)},
-/* 49 */ {212, (CH_LOWER_SB)},
-/* 50 */ {216, (CH_LOWER_SB)}
-};
-#endif /* SUPPORT_40MHZ */
-
-static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx)
-{
- if (locale_idx >= ARRAY_SIZE(g_locale_2g_table))
- return NULL; /* error condition */
-
- return g_locale_2g_table[locale_idx];
-}
-
-static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx)
-{
- if (locale_idx >= ARRAY_SIZE(g_locale_5g_table))
- return NULL; /* error condition */
-
- return g_locale_5g_table[locale_idx];
-}
-
static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx)
{
if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table))
@@ -621,13 +169,6 @@ static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx)
return g_mimo_5g_table[locale_idx];
}
-static int
-brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode,
- char *mapped_ccode, uint *mapped_regrev)
-{
- return false;
-}
-
/*
* Indicates whether the country provided is valid to pass
* to cfg80211 or not.
@@ -662,155 +203,24 @@ static bool brcms_c_country_valid(const char *ccode)
return true;
}
-/* Lookup a country info structure from a null terminated country
- * abbreviation and regrev directly with no translation.
- */
-static const struct country_info *
-brcms_c_country_lookup_direct(const char *ccode, uint regrev)
+static const struct brcms_regd *brcms_world_regd(const char *regdom, int len)
{
- uint size, i;
-
- /* Should just return 0 for single locale driver. */
- /* Keep it this way in case we add more locales. (for now anyway) */
-
- /*
- * all other country def arrays are for regrev == 0, so if
- * regrev is non-zero, fail
- */
- if (regrev > 0)
- return NULL;
-
- /* find matched table entry from country code */
- size = ARRAY_SIZE(cntry_locales);
- for (i = 0; i < size; i++) {
- if (strcmp(ccode, cntry_locales[i].abbrev) == 0)
- return &cntry_locales[i].country;
- }
- return NULL;
-}
-
-static const struct country_info *
-brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode,
- char *mapped_ccode, uint *mapped_regrev)
-{
- struct brcms_c_info *wlc = wlc_cm->wlc;
- const struct country_info *country;
- uint srom_regrev = wlc_cm->srom_regrev;
- const char *srom_ccode = wlc_cm->srom_ccode;
- int mapped;
-
- /* check for currently supported ccode size */
- if (strlen(ccode) > (BRCM_CNTRY_BUF_SZ - 1)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: ccode \"%s\" too long for "
- "match\n", wlc->pub->unit, __func__, ccode);
- return NULL;
- }
-
- /* default mapping is the given ccode and regrev 0 */
- strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ);
- *mapped_regrev = 0;
-
- /* If the desired country code matches the srom country code,
- * then the mapped country is the srom regulatory rev.
- * Otherwise look for an aggregate mapping.
- */
- if (!strcmp(srom_ccode, ccode)) {
- *mapped_regrev = srom_regrev;
- mapped = 0;
- wiphy_err(wlc->wiphy, "srom_code == ccode %s\n", __func__);
- } else {
- mapped =
- brcms_c_country_aggregate_map(wlc_cm, ccode, mapped_ccode,
- mapped_regrev);
- }
-
- /* find the matching built-in country definition */
- country = brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev);
-
- /* if there is not an exact rev match, default to rev zero */
- if (country == NULL && *mapped_regrev != 0) {
- *mapped_regrev = 0;
- country =
- brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev);
- }
-
- return country;
-}
-
-/* Lookup a country info structure from a null terminated country code
- * The lookup is case sensitive.
- */
-static const struct country_info *
-brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode)
-{
- const struct country_info *country;
- char mapped_ccode[BRCM_CNTRY_BUF_SZ];
- uint mapped_regrev;
-
- /*
- * map the country code to a built-in country code, regrev, and
- * country_info struct
- */
- country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode,
- &mapped_regrev);
-
- return country;
-}
-
-/*
- * reset the quiet channels vector to the union
- * of the restricted and radar channel sets
- */
-static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm)
-{
- struct brcms_c_info *wlc = wlc_cm->wlc;
- uint i, j;
- struct brcms_band *band;
- const struct brcms_chanvec *chanvec;
-
- memset(&wlc_cm->quiet_channels, 0, sizeof(struct brcms_chanvec));
-
- band = wlc->band;
- for (i = 0; i < wlc->pub->_nbands;
- i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
-
- /* initialize quiet channels for restricted channels */
- chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels;
- for (j = 0; j < sizeof(struct brcms_chanvec); j++)
- wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j];
+ const struct brcms_regd *regd = NULL;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(cntry_locales); i++) {
+ if (!strncmp(regdom, cntry_locales[i].regdomain->alpha2, len)) {
+ regd = &cntry_locales[i];
+ break;
+ }
}
-}
-
-/* Is the channel valid for the current locale and current band? */
-static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val)
-{
- struct brcms_c_info *wlc = wlc_cm->wlc;
- return ((val < MAXCHANNEL) &&
- isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec,
- val));
+ return regd;
}
-/* Is the channel valid for the current locale and specified band? */
-static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm,
- uint bandunit, uint val)
-{
- return ((val < MAXCHANNEL)
- && isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val));
-}
-
-/* Is the channel valid for the current locale? (but don't consider channels not
- * available due to bandlocking)
- */
-static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val)
+static const struct brcms_regd *brcms_default_world_regd(void)
{
- struct brcms_c_info *wlc = wlc_cm->wlc;
-
- return brcms_c_valid_channel20(wlc->cmi, val) ||
- (!wlc->bandlocked
- && brcms_c_valid_channel20_in_band(wlc->cmi,
- OTHERBANDUNIT(wlc), val));
+ return &cntry_locales[0];
}
/* JP, J1 - J10 are Japan ccodes */
@@ -820,12 +230,6 @@ static bool brcms_c_japan_ccode(const char *ccode)
(ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
}
-/* Returns true if currently set country is Japan or variant */
-static bool brcms_c_japan(struct brcms_c_info *wlc)
-{
- return brcms_c_japan_ccode(wlc->cmi->country_abbrev);
-}
-
static void
brcms_c_channel_min_txpower_limits_with_local_constraint(
struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr,
@@ -901,140 +305,16 @@ brcms_c_channel_min_txpower_limits_with_local_constraint(
}
-/* Update the radio state (enable/disable) and tx power targets
- * based on a new set of channel/regulatory information
- */
-static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
-{
- struct brcms_c_info *wlc = wlc_cm->wlc;
- uint chan;
- struct txpwr_limits txpwr;
-
- /* search for the existence of any valid channel */
- for (chan = 0; chan < MAXCHANNEL; chan++) {
- if (brcms_c_valid_channel20_db(wlc->cmi, chan))
- break;
- }
- if (chan == MAXCHANNEL)
- chan = INVCHANNEL;
-
- /*
- * based on the channel search above, set or
- * clear WL_RADIO_COUNTRY_DISABLE.
- */
- if (chan == INVCHANNEL) {
- /*
- * country/locale with no valid channels, set
- * the radio disable bit
- */
- mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
- wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" "
- "nbands %d bandlocked %d\n", wlc->pub->unit,
- __func__, wlc_cm->country_abbrev, wlc->pub->_nbands,
- wlc->bandlocked);
- } else if (mboolisset(wlc->pub->radio_disabled,
- WL_RADIO_COUNTRY_DISABLE)) {
- /*
- * country/locale with valid channel, clear
- * the radio disable bit
- */
- mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
- }
-
- /*
- * Now that the country abbreviation is set, if the radio supports 2G,
- * then set channel 14 restrictions based on the new locale.
- */
- if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
- wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
- brcms_c_japan(wlc) ? true :
- false);
-
- if (wlc->pub->up && chan != INVCHANNEL) {
- brcms_c_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr);
- brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm,
- &txpwr, BRCMS_TXPWR_MAX);
- wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec);
- }
-}
-
-static int
-brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
- const struct country_info *country)
-{
- struct brcms_c_info *wlc = wlc_cm->wlc;
- uint i, j;
- struct brcms_band *band;
- const struct locale_info *li;
- struct brcms_chanvec sup_chan;
- const struct locale_mimo_info *li_mimo;
-
- band = wlc->band;
- for (i = 0; i < wlc->pub->_nbands;
- i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
-
- li = (band->bandtype == BRCM_BAND_5G) ?
- brcms_c_get_locale_5g(country->locale_5G) :
- brcms_c_get_locale_2g(country->locale_2G);
- wlc_cm->bandstate[band->bandunit].locale_flags = li->flags;
- li_mimo = (band->bandtype == BRCM_BAND_5G) ?
- brcms_c_get_mimo_5g(country->locale_mimo_5G) :
- brcms_c_get_mimo_2g(country->locale_mimo_2G);
-
- /* merge the mimo non-mimo locale flags */
- wlc_cm->bandstate[band->bandunit].locale_flags |=
- li_mimo->flags;
-
- wlc_cm->bandstate[band->bandunit].restricted_channels =
- g_table_restricted_chan[li->restricted_channels];
- wlc_cm->bandstate[band->bandunit].radar_channels =
- g_table_radar_set[li->radar_channels];
-
- /*
- * set the channel availability, masking out the channels
- * that may not be supported on this phy.
- */
- wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
- &sup_chan);
- brcms_c_locale_get_channels(li,
- &wlc_cm->bandstate[band->bandunit].
- valid_channels);
- for (j = 0; j < sizeof(struct brcms_chanvec); j++)
- wlc_cm->bandstate[band->bandunit].valid_channels.
- vec[j] &= sup_chan.vec[j];
- }
-
- brcms_c_quiet_channels_reset(wlc_cm);
- brcms_c_channels_commit(wlc_cm);
-
- return 0;
-}
-
/*
* set the driver's current country and regulatory information
* using a country code as the source. Look up built in country
* information found with the country code.
*/
static void
-brcms_c_set_country_common(struct brcms_cm_info *wlc_cm,
- const char *country_abbrev,
- const char *ccode, uint regrev,
- const struct country_info *country)
+brcms_c_set_country(struct brcms_cm_info *wlc_cm,
+ const struct brcms_regd *regd)
{
- const struct locale_info *locale;
struct brcms_c_info *wlc = wlc_cm->wlc;
- char prev_country_abbrev[BRCM_CNTRY_BUF_SZ];
-
- /* save current country state */
- wlc_cm->country = country;
-
- memset(&prev_country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
- strncpy(prev_country_abbrev, wlc_cm->country_abbrev,
- BRCM_CNTRY_BUF_SZ - 1);
-
- strncpy(wlc_cm->country_abbrev, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
- strncpy(wlc_cm->ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
- wlc_cm->regrev = regrev;
if ((wlc->pub->_n_enab & SUPPORT_11N) !=
wlc->protection->nmode_user)
@@ -1042,75 +322,19 @@ brcms_c_set_country_common(struct brcms_cm_info *wlc_cm,
brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
- /* set or restore gmode as required by regulatory */
- locale = brcms_c_get_locale_2g(country->locale_2G);
- if (locale && (locale->flags & BRCMS_NO_OFDM))
- brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
- else
- brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
- brcms_c_channels_init(wlc_cm, country);
+ brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
return;
}
-static int
-brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
- const char *country_abbrev,
- const char *ccode, int regrev)
-{
- const struct country_info *country;
- char mapped_ccode[BRCM_CNTRY_BUF_SZ];
- uint mapped_regrev;
-
- /* if regrev is -1, lookup the mapped country code,
- * otherwise use the ccode and regrev directly
- */
- if (regrev == -1) {
- /*
- * map the country code to a built-in country
- * code, regrev, and country_info
- */
- country =
- brcms_c_countrycode_map(wlc_cm, ccode, mapped_ccode,
- &mapped_regrev);
- } else {
- /* find the matching built-in country definition */
- country = brcms_c_country_lookup_direct(ccode, regrev);
- strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ);
- mapped_regrev = regrev;
- }
-
- if (country == NULL)
- return -EINVAL;
-
- /* set the driver state for the country */
- brcms_c_set_country_common(wlc_cm, country_abbrev, mapped_ccode,
- mapped_regrev, country);
-
- return 0;
-}
-
-/*
- * set the driver's current country and regulatory information using
- * a country code as the source. Lookup built in country information
- * found with the country code.
- */
-static int
-brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode)
-{
- char country_abbrev[BRCM_CNTRY_BUF_SZ];
- strncpy(country_abbrev, ccode, BRCM_CNTRY_BUF_SZ);
- return brcms_c_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1);
-}
-
struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
{
struct brcms_cm_info *wlc_cm;
- char country_abbrev[BRCM_CNTRY_BUF_SZ];
- const struct country_info *country;
struct brcms_pub *pub = wlc->pub;
struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom;
+ const char *ccode = sprom->alpha2;
+ int ccode_len = sizeof(sprom->alpha2);
BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
@@ -1122,24 +346,27 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
wlc->cmi = wlc_cm;
/* store the country code for passing up as a regulatory hint */
- if (sprom->alpha2 && brcms_c_country_valid(sprom->alpha2))
- strncpy(wlc->pub->srom_ccode, sprom->alpha2, sizeof(sprom->alpha2));
+ wlc_cm->world_regd = brcms_world_regd(ccode, ccode_len);
+ if (brcms_c_country_valid(ccode))
+ strncpy(wlc->pub->srom_ccode, ccode, ccode_len);
/*
- * internal country information which must match
- * regulatory constraints in firmware
+ * If no custom world domain is found in the SROM, use the
+ * default "X2" domain.
*/
- memset(country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
- strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1);
- country = brcms_c_country_lookup(wlc, country_abbrev);
+ if (!wlc_cm->world_regd) {
+ wlc_cm->world_regd = brcms_default_world_regd();
+ ccode = wlc_cm->world_regd->regdomain->alpha2;
+ ccode_len = BRCM_CNTRY_BUF_SZ - 1;
+ }
/* save default country for exiting 11d regulatory mode */
- strncpy(wlc->country_default, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
+ strncpy(wlc->country_default, ccode, ccode_len);
/* initialize autocountry_default to driver default */
- strncpy(wlc->autocountry_default, "X2", BRCM_CNTRY_BUF_SZ - 1);
+ strncpy(wlc->autocountry_default, ccode, ccode_len);
- brcms_c_set_countrycode(wlc_cm, country_abbrev);
+ brcms_c_set_country(wlc_cm, wlc_cm->world_regd);
return wlc_cm;
}
@@ -1149,31 +376,15 @@ void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
kfree(wlc_cm);
}
-u8
-brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
- uint bandunit)
-{
- return wlc_cm->bandstate[bandunit].locale_flags;
-}
-
-static bool
-brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, u16 chspec)
-{
- return (wlc_cm->wlc->pub->_n_enab & SUPPORT_11N) &&
- CHSPEC_IS40(chspec) ?
- (isset(wlc_cm->quiet_channels.vec,
- lower_20_sb(CHSPEC_CHANNEL(chspec))) ||
- isset(wlc_cm->quiet_channels.vec,
- upper_20_sb(CHSPEC_CHANNEL(chspec)))) :
- isset(wlc_cm->quiet_channels.vec, CHSPEC_CHANNEL(chspec));
-}
-
void
brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
u8 local_constraint_qdbm)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
+ struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
+ const struct ieee80211_reg_rule *reg_rule;
struct txpwr_limits txpwr;
+ int ret;
brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);
@@ -1181,8 +392,15 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
wlc_cm, &txpwr, local_constraint_qdbm
);
+ /* set or restore gmode as required by regulatory */
+ ret = freq_reg_info(wlc->wiphy, ch->center_freq, 0, &reg_rule);
+ if (!ret && (reg_rule->flags & NL80211_RRF_NO_OFDM))
+ brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
+ else
+ brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
+
brcms_b_set_chanspec(wlc->hw, chanspec,
- (brcms_c_quiet_chanspec(wlc_cm, chanspec) != 0),
+ !!(ch->flags & IEEE80211_CHAN_PASSIVE_SCAN),
&txpwr);
}
@@ -1191,15 +409,14 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
struct txpwr_limits *txpwr)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
+ struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
uint i;
uint chan;
int maxpwr;
int delta;
const struct country_info *country;
struct brcms_band *band;
- const struct locale_info *li;
int conducted_max = BRCMS_TXPWR_MAX;
- int conducted_ofdm_max = BRCMS_TXPWR_MAX;
const struct locale_mimo_info *li_mimo;
int maxpwr20, maxpwr40;
int maxpwr_idx;
@@ -1207,67 +424,35 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
memset(txpwr, 0, sizeof(struct txpwr_limits));
- if (!brcms_c_valid_chanspec_db(wlc_cm, chanspec)) {
- country = brcms_c_country_lookup(wlc, wlc->autocountry_default);
- if (country == NULL)
- return;
- } else {
- country = wlc_cm->country;
- }
+ if (WARN_ON(!ch))
+ return;
+
+ country = &wlc_cm->world_regd->country;
chan = CHSPEC_CHANNEL(chanspec);
band = wlc->bandstate[chspec_bandunit(chanspec)];
- li = (band->bandtype == BRCM_BAND_5G) ?
- brcms_c_get_locale_5g(country->locale_5G) :
- brcms_c_get_locale_2g(country->locale_2G);
-
li_mimo = (band->bandtype == BRCM_BAND_5G) ?
brcms_c_get_mimo_5g(country->locale_mimo_5G) :
brcms_c_get_mimo_2g(country->locale_mimo_2G);
- if (li->flags & BRCMS_EIRP) {
- delta = band->antgain;
- } else {
- delta = 0;
- if (band->antgain > QDB(6))
- delta = band->antgain - QDB(6); /* Excess over 6 dB */
- }
+ delta = band->antgain;
- if (li == &locale_i) {
+ if (band->bandtype == BRCM_BAND_2G)
conducted_max = QDB(22);
- conducted_ofdm_max = QDB(22);
- }
+
+ maxpwr = QDB(ch->max_power) - delta;
+ maxpwr = max(maxpwr, 0);
+ maxpwr = min(maxpwr, conducted_max);
/* CCK txpwr limits for 2.4G band */
if (band->bandtype == BRCM_BAND_2G) {
- maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)];
-
- maxpwr = maxpwr - delta;
- maxpwr = max(maxpwr, 0);
- maxpwr = min(maxpwr, conducted_max);
-
for (i = 0; i < BRCMS_NUM_RATES_CCK; i++)
txpwr->cck[i] = (u8) maxpwr;
}
- /* OFDM txpwr limits for 2.4G or 5G bands */
- if (band->bandtype == BRCM_BAND_2G)
- maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)];
- else
- maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)];
-
- maxpwr = maxpwr - delta;
- maxpwr = max(maxpwr, 0);
- maxpwr = min(maxpwr, conducted_ofdm_max);
-
- /* Keep OFDM lmit below CCK limit */
- if (band->bandtype == BRCM_BAND_2G)
- maxpwr = min_t(int, maxpwr, txpwr->cck[0]);
-
- for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
txpwr->ofdm[i] = (u8) maxpwr;
- for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
/*
* OFDM 40 MHz SISO has the same power as the corresponding
* MCS0-7 rate unless overriden by the locale specific code.
@@ -1282,14 +467,9 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
txpwr->ofdm_40_cdd[i] = 0;
}
- /* MIMO/HT specific limits */
- if (li_mimo->flags & BRCMS_EIRP) {
- delta = band->antgain;
- } else {
- delta = 0;
- if (band->antgain > QDB(6))
- delta = band->antgain - QDB(6); /* Excess over 6 dB */
- }
+ delta = 0;
+ if (band->antgain > QDB(6))
+ delta = band->antgain - QDB(6); /* Excess over 6 dB */
if (band->bandtype == BRCM_BAND_2G)
maxpwr_idx = (chan - 1);
@@ -1431,8 +611,7 @@ static bool brcms_c_chspec_malformed(u16 chanspec)
* and they are also a legal HT combination
*/
static bool
-brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec,
- bool dualband)
+brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
u8 channel = CHSPEC_CHANNEL(chspec);
@@ -1448,59 +627,163 @@ brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec,
chspec_bandunit(chspec))
return false;
- /* Check a 20Mhz channel */
- if (CHSPEC_IS20(chspec)) {
- if (dualband)
- return brcms_c_valid_channel20_db(wlc_cm->wlc->cmi,
- channel);
- else
- return brcms_c_valid_channel20(wlc_cm->wlc->cmi,
- channel);
+ return true;
+}
+
+bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec)
+{
+ return brcms_c_valid_chanspec_ext(wlc_cm, chspec);
+}
+
+static bool brcms_is_radar_freq(u16 center_freq)
+{
+ return center_freq >= 5260 && center_freq <= 5700;
+}
+
+static void brcms_reg_apply_radar_flags(struct wiphy *wiphy)
+{
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *ch;
+ int i;
+
+ sband = wiphy->bands[IEEE80211_BAND_5GHZ];
+ if (!sband)
+ return;
+
+ for (i = 0; i < sband->n_channels; i++) {
+ ch = &sband->channels[i];
+
+ if (!brcms_is_radar_freq(ch->center_freq))
+ continue;
+
+ /*
+ * All channels in this range should be passive and have
+ * DFS enabled.
+ */
+ if (!(ch->flags & IEEE80211_CHAN_DISABLED))
+ ch->flags |= IEEE80211_CHAN_RADAR |
+ IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN;
}
-#ifdef SUPPORT_40MHZ
- /*
- * We know we are now checking a 40MHZ channel, so we should
- * only be here for NPHYS
- */
- if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) {
- u8 upper_sideband = 0, idx;
- u8 num_ch20_entries =
- sizeof(chan20_info) / sizeof(struct chan20_info);
-
- if (!VALID_40CHANSPEC_IN_BAND(wlc, chspec_bandunit(chspec)))
- return false;
-
- if (dualband) {
- if (!brcms_c_valid_channel20_db(wlc->cmi,
- lower_20_sb(channel)) ||
- !brcms_c_valid_channel20_db(wlc->cmi,
- upper_20_sb(channel)))
- return false;
- } else {
- if (!brcms_c_valid_channel20(wlc->cmi,
- lower_20_sb(channel)) ||
- !brcms_c_valid_channel20(wlc->cmi,
- upper_20_sb(channel)))
- return false;
+}
+
+static void
+brcms_reg_apply_beaconing_flags(struct wiphy *wiphy,
+ enum nl80211_reg_initiator initiator)
+{
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *ch;
+ const struct ieee80211_reg_rule *rule;
+ int band, i, ret;
+
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ sband = wiphy->bands[band];
+ if (!sband)
+ continue;
+
+ for (i = 0; i < sband->n_channels; i++) {
+ ch = &sband->channels[i];
+
+ if (ch->flags &
+ (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_RADAR))
+ continue;
+
+ if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
+ ret = freq_reg_info(wiphy, ch->center_freq,
+ 0, &rule);
+ if (ret)
+ continue;
+
+ if (!(rule->flags & NL80211_RRF_NO_IBSS))
+ ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
+ if (!(rule->flags & NL80211_RRF_PASSIVE_SCAN))
+ ch->flags &=
+ ~IEEE80211_CHAN_PASSIVE_SCAN;
+ } else if (ch->beacon_found) {
+ ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN);
+ }
}
+ }
+}
- /* find the lower sideband info in the sideband array */
- for (idx = 0; idx < num_ch20_entries; idx++) {
- if (chan20_info[idx].sb == lower_20_sb(channel))
- upper_sideband = chan20_info[idx].adj_sbs;
+static int brcms_reg_notifier(struct wiphy *wiphy,
+ struct regulatory_request *request)
+{
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct brcms_info *wl = hw->priv;
+ struct brcms_c_info *wlc = wl->wlc;
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *ch;
+ int band, i;
+ bool ch_found = false;
+
+ brcms_reg_apply_radar_flags(wiphy);
+
+ if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
+ brcms_reg_apply_beaconing_flags(wiphy, request->initiator);
+
+ /* Disable radio if all channels disallowed by regulatory */
+ for (band = 0; !ch_found && band < IEEE80211_NUM_BANDS; band++) {
+ sband = wiphy->bands[band];
+ if (!sband)
+ continue;
+
+ for (i = 0; !ch_found && i < sband->n_channels; i++) {
+ ch = &sband->channels[i];
+
+ if (!(ch->flags & IEEE80211_CHAN_DISABLED))
+ ch_found = true;
}
- /* check that the lower sideband allows an upper sideband */
- if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) ==
- (CH_UPPER_SB | CH_EWA_VALID))
- return true;
- return false;
}
-#endif /* 40 MHZ */
- return false;
+ if (ch_found) {
+ mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
+ } else {
+ mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
+ wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\"\n",
+ wlc->pub->unit, __func__, request->alpha2);
+ }
+
+ if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
+ wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
+ brcms_c_japan_ccode(request->alpha2));
+
+ return 0;
}
-bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec)
+void brcms_c_regd_init(struct brcms_c_info *wlc)
{
- return brcms_c_valid_chanspec_ext(wlc_cm, chspec, true);
+ struct wiphy *wiphy = wlc->wiphy;
+ const struct brcms_regd *regd = wlc->cmi->world_regd;
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *ch;
+ struct brcms_chanvec sup_chan;
+ struct brcms_band *band;
+ int band_idx, i;
+
+ /* Disable any channels not supported by the phy */
+ for (band_idx = 0; band_idx < wlc->pub->_nbands; band_idx++) {
+ band = wlc->bandstate[band_idx];
+
+ wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
+ &sup_chan);
+
+ if (band_idx == BAND_2G_INDEX)
+ sband = wiphy->bands[IEEE80211_BAND_2GHZ];
+ else
+ sband = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+ for (i = 0; i < sband->n_channels; i++) {
+ ch = &sband->channels[i];
+ if (!isset(sup_chan.vec, ch->hw_value))
+ ch->flags |= IEEE80211_CHAN_DISABLED;
+ }
+ }
+
+ wlc->wiphy->reg_notifier = brcms_reg_notifier;
+ wlc->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
+ WIPHY_FLAG_STRICT_REGULATORY;
+ wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain);
+ brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER);
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.h b/drivers/net/wireless/brcm80211/brcmsmac/channel.h
index 808cb4fbfbe7..006483a0abe6 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.h
@@ -37,9 +37,6 @@ brcms_c_channel_mgr_attach(struct brcms_c_info *wlc);
extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm);
-extern u8 brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
- uint bandunit);
-
extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm,
u16 chspec);
@@ -49,5 +46,6 @@ extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm,
extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm,
u16 chanspec,
u8 local_constraint_qdbm);
+extern void brcms_c_regd_init(struct brcms_c_info *wlc);
#endif /* _WLC_CHANNEL_H */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c
index 11054ae9d4f6..f64c5cf3fccc 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c
@@ -573,6 +573,7 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
struct dma_info *di;
u8 rev = core->id.rev;
uint size;
+ struct si_info *sii = container_of(sih, struct si_info, pub);
/* allocate private info structure */
di = kzalloc(sizeof(struct dma_info), GFP_ATOMIC);
@@ -633,16 +634,20 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
*/
di->ddoffsetlow = 0;
di->dataoffsetlow = 0;
- /* add offset for pcie with DMA64 bus */
- di->ddoffsetlow = 0;
- di->ddoffsethigh = SI_PCIE_DMA_H32;
+ /* for pci bus, add offset */
+ if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) {
+ /* add offset for pcie with DMA64 bus */
+ di->ddoffsetlow = 0;
+ di->ddoffsethigh = SI_PCIE_DMA_H32;
+ }
di->dataoffsetlow = di->ddoffsetlow;
di->dataoffsethigh = di->ddoffsethigh;
+
/* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */
- if ((core->id.id == SDIOD_CORE_ID)
+ if ((core->id.id == BCMA_CORE_SDIO_DEV)
&& ((rev > 0) && (rev <= 2)))
di->addrext = false;
- else if ((core->id.id == I2S_CORE_ID) &&
+ else if ((core->id.id == BCMA_CORE_I2S) &&
((rev == 0) || (rev == 1)))
di->addrext = false;
else
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 50f92a0b7c41..2b57f57a7927 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -319,8 +319,7 @@ static void brcms_ops_stop(struct ieee80211_hw *hw)
return;
spin_lock_bh(&wl->lock);
- status = brcms_c_chipmatch(wl->wlc->hw->vendorid,
- wl->wlc->hw->deviceid);
+ status = brcms_c_chipmatch(wl->wlc->hw->d11core);
spin_unlock_bh(&wl->lock);
if (!status) {
wiphy_err(wl->wiphy,
@@ -721,14 +720,6 @@ static const struct ieee80211_ops brcms_ops = {
.flush = brcms_ops_flush,
};
-/*
- * is called in brcms_bcma_probe() context, therefore no locking required.
- */
-static int brcms_set_hint(struct brcms_info *wl, char *abbrev)
-{
- return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev);
-}
-
void brcms_dpc(unsigned long data)
{
struct brcms_info *wl;
@@ -1058,6 +1049,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
goto fail;
}
+ brcms_c_regd_init(wl->wlc);
+
memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN);
if (WARN_ON(!is_valid_ether_addr(perm)))
goto fail;
@@ -1068,9 +1061,9 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status"
"%d\n", __func__, err);
- if (wl->pub->srom_ccode[0] && brcms_set_hint(wl, wl->pub->srom_ccode))
- wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n",
- __func__, err);
+ if (wl->pub->srom_ccode[0] &&
+ regulatory_hint(wl->wiphy, wl->pub->srom_ccode))
+ wiphy_err(wl->wiphy, "%s: regulatory hint failed\n", __func__);
n_adapters_found++;
return wl;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 19db4052c44c..d39f7d041e0b 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -18,6 +18,7 @@
#include <linux/pci_ids.h>
#include <linux/if_ether.h>
+#include <net/cfg80211.h>
#include <net/mac80211.h>
#include <brcm_hw_ids.h>
#include <aiutils.h>
@@ -268,7 +269,7 @@ struct brcms_c_bit_desc {
*/
/* Starting corerev for the fifo size table */
-#define XMTFIFOTBL_STARTREV 20
+#define XMTFIFOTBL_STARTREV 17
struct d11init {
__le16 addr;
@@ -332,6 +333,12 @@ const u8 wlc_prio2prec_map[] = {
};
static const u16 xmtfifo_sz[][NFIFO] = {
+ /* corerev 17: 5120, 49152, 49152, 5376, 4352, 1280 */
+ {20, 192, 192, 21, 17, 5},
+ /* corerev 18: */
+ {0, 0, 0, 0, 0, 0},
+ /* corerev 19: */
+ {0, 0, 0, 0, 0, 0},
/* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */
{20, 192, 192, 21, 17, 5},
/* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */
@@ -342,6 +349,14 @@ static const u16 xmtfifo_sz[][NFIFO] = {
{20, 192, 192, 21, 17, 5},
/* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */
{9, 58, 22, 14, 14, 5},
+ /* corerev 25: */
+ {0, 0, 0, 0, 0, 0},
+ /* corerev 26: */
+ {0, 0, 0, 0, 0, 0},
+ /* corerev 27: */
+ {0, 0, 0, 0, 0, 0},
+ /* corerev 28: 2304, 14848, 5632, 3584, 3584, 1280 */
+ {9, 58, 22, 14, 14, 5},
};
#ifdef DEBUG
@@ -1941,7 +1956,8 @@ static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw)
* accesses phyreg throughput mac. This can be skipped since
* only mac reg is accessed below
*/
- flags |= SICF_PCLKE;
+ if (D11REV_GE(wlc_hw->corerev, 18))
+ flags |= SICF_PCLKE;
/*
* TODO: test suspend/resume
@@ -2022,7 +2038,8 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
* phyreg throughput mac, AND phy_reset is skipped at early stage when
* band->pi is invalid. need to enable PHY CLK
*/
- flags |= SICF_PCLKE;
+ if (D11REV_GE(wlc_hw->corerev, 18))
+ flags |= SICF_PCLKE;
/*
* reset the core
@@ -2125,8 +2142,8 @@ void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode)
{
struct bcma_device *core = wlc_hw->d11core;
- if ((ai_get_chip_id(wlc_hw->sih) == BCM43224_CHIP_ID) ||
- (ai_get_chip_id(wlc_hw->sih) == BCM43225_CHIP_ID)) {
+ if ((ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM43224) ||
+ (ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM43225)) {
if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */
bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x2082);
bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0x8);
@@ -2790,7 +2807,7 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
tmp = 0;
if (on) {
- if ((ai_get_chip_id(wlc_hw->sih) == BCM4313_CHIP_ID)) {
+ if ((ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM4313)) {
bcma_set32(core, D11REGOFFS(clk_ctl_st),
CCS_ERSRC_REQ_HT |
CCS_ERSRC_REQ_D11PLL |
@@ -3139,20 +3156,6 @@ void brcms_c_reset(struct brcms_c_info *wlc)
brcms_b_reset(wlc->hw);
}
-/* Return the channel the driver should initialize during brcms_c_init.
- * the channel may have to be changed from the currently configured channel
- * if other configurations are in conflict (bandlocked, 11n mode disabled,
- * invalid channel for current country, etc.)
- */
-static u16 brcms_c_init_chanspec(struct brcms_c_info *wlc)
-{
- u16 chanspec =
- 1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE |
- WL_CHANSPEC_BAND_2G;
-
- return chanspec;
-}
-
void brcms_c_init_scb(struct scb *scb)
{
int i;
@@ -4231,9 +4234,8 @@ static void brcms_c_radio_timer(void *arg)
}
/* common low-level watchdog code */
-static void brcms_b_watchdog(void *arg)
+static void brcms_b_watchdog(struct brcms_c_info *wlc)
{
- struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
struct brcms_hardware *wlc_hw = wlc->hw;
BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
@@ -4254,10 +4256,8 @@ static void brcms_b_watchdog(void *arg)
}
/* common watchdog code */
-static void brcms_c_watchdog(void *arg)
+static void brcms_c_watchdog(struct brcms_c_info *wlc)
{
- struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
-
BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
if (!wlc->pub->up)
@@ -4297,7 +4297,9 @@ static void brcms_c_watchdog(void *arg)
static void brcms_c_watchdog_by_timer(void *arg)
{
- brcms_c_watchdog(arg);
+ struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
+
+ brcms_c_watchdog(wlc);
}
static bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit)
@@ -4467,11 +4469,9 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
}
/* verify again the device is supported */
- if (core->bus->hosttype == BCMA_HOSTTYPE_PCI &&
- !brcms_c_chipmatch(pcidev->vendor, pcidev->device)) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported "
- "vendor/device (0x%x/0x%x)\n",
- unit, pcidev->vendor, pcidev->device);
+ if (!brcms_c_chipmatch(core)) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported device\n",
+ unit);
err = 12;
goto fail;
}
@@ -4541,7 +4541,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
else
wlc_hw->_nbands = 1;
- if ((ai_get_chip_id(wlc_hw->sih) == BCM43225_CHIP_ID))
+ if ((ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM43225))
wlc_hw->_nbands = 1;
/* BMAC_NOTE: remove init of pub values when brcms_c_attach()
@@ -4608,8 +4608,12 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
wlc_hw->machwcap_backup = wlc_hw->machwcap;
/* init tx fifo size */
+ WARN_ON((wlc_hw->corerev - XMTFIFOTBL_STARTREV) < 0 ||
+ (wlc_hw->corerev - XMTFIFOTBL_STARTREV) >
+ ARRAY_SIZE(xmtfifo_sz));
wlc_hw->xmtfifo_sz =
xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)];
+ WARN_ON(!wlc_hw->xmtfifo_sz[0]);
/* Get a phy for this band */
wlc_hw->band->pi =
@@ -5049,7 +5053,7 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
wlc_hw->wlc->pub->hw_up = true;
if ((wlc_hw->boardflags & BFL_FEM)
- && (ai_get_chip_id(wlc_hw->sih) == BCM4313_CHIP_ID)) {
+ && (ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM4313)) {
if (!
(wlc_hw->boardrev >= 0x1250
&& (wlc_hw->boardflags & BFL_FEM_BT)))
@@ -5129,6 +5133,8 @@ static void brcms_c_wme_retries_write(struct brcms_c_info *wlc)
/* make interface operational */
int brcms_c_up(struct brcms_c_info *wlc)
{
+ struct ieee80211_channel *ch;
+
BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
/* HW is turned off so don't try to access it */
@@ -5141,7 +5147,7 @@ int brcms_c_up(struct brcms_c_info *wlc)
}
if ((wlc->pub->boardflags & BFL_FEM)
- && (ai_get_chip_id(wlc->hw->sih) == BCM4313_CHIP_ID)) {
+ && (ai_get_chip_id(wlc->hw->sih) == BCMA_CHIP_ID_BCM4313)) {
if (wlc->pub->boardrev >= 0x1250
&& (wlc->pub->boardflags & BFL_FEM_BT))
brcms_b_mhf(wlc->hw, MHF5, MHF5_4313_GPIOCTRL,
@@ -5195,8 +5201,9 @@ int brcms_c_up(struct brcms_c_info *wlc)
wlc->pub->up = true;
if (wlc->bandinit_pending) {
+ ch = wlc->pub->ieee_hw->conf.channel;
brcms_c_suspend_mac_and_wait(wlc);
- brcms_c_set_chanspec(wlc, wlc->default_bss->chanspec);
+ brcms_c_set_chanspec(wlc, ch20mhz_chspec(ch->hw_value));
wlc->bandinit_pending = false;
brcms_c_enable_mac(wlc);
}
@@ -5397,11 +5404,6 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
else
return -EINVAL;
- /* Legacy or bust when no OFDM is supported by regulatory */
- if ((brcms_c_channel_locale_flags_in_band(wlc->cmi, band->bandunit) &
- BRCMS_NO_OFDM) && (gmode != GMODE_LEGACY_B))
- return -EINVAL;
-
/* update configuration value */
if (config)
brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode);
@@ -5782,8 +5784,12 @@ void brcms_c_print_txstatus(struct tx_status *txs)
(txs->ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT);
}
-bool brcms_c_chipmatch(u16 vendor, u16 device)
+static bool brcms_c_chipmatch_pci(struct bcma_device *core)
{
+ struct pci_dev *pcidev = core->bus->host_pci;
+ u16 vendor = pcidev->vendor;
+ u16 device = pcidev->device;
+
if (vendor != PCI_VENDOR_ID_BROADCOM) {
pr_err("unknown vendor id %04x\n", vendor);
return false;
@@ -5802,6 +5808,30 @@ bool brcms_c_chipmatch(u16 vendor, u16 device)
return false;
}
+static bool brcms_c_chipmatch_soc(struct bcma_device *core)
+{
+ struct bcma_chipinfo *chipinfo = &core->bus->chipinfo;
+
+ if (chipinfo->id == BCMA_CHIP_ID_BCM4716)
+ return true;
+
+ pr_err("unknown chip id %04x\n", chipinfo->id);
+ return false;
+}
+
+bool brcms_c_chipmatch(struct bcma_device *core)
+{
+ switch (core->bus->hosttype) {
+ case BCMA_HOSTTYPE_PCI:
+ return brcms_c_chipmatch_pci(core);
+ case BCMA_HOSTTYPE_SOC:
+ return brcms_c_chipmatch_soc(core);
+ default:
+ pr_err("unknown host type: %i\n", core->bus->hosttype);
+ return false;
+ }
+}
+
#if defined(DEBUG)
void brcms_c_print_txdesc(struct d11txh *txh)
{
@@ -8201,19 +8231,12 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
{
struct bcma_device *core = wlc->hw->d11core;
+ struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
u16 chanspec;
BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
- /*
- * This will happen if a big-hammer was executed. In
- * that case, we want to go back to the channel that
- * we were on and not new channel
- */
- if (wlc->pub->associated)
- chanspec = wlc->home_chanspec;
- else
- chanspec = brcms_c_init_chanspec(wlc);
+ chanspec = ch20mhz_chspec(ch->hw_value);
brcms_b_init(wlc->hw, chanspec);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
index 264f8c4c703d..91937c5025ce 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
@@ -198,6 +198,8 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
+ struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub);
+
if ((D11REV_GE(pi->sh->corerev, 24)) ||
(D11REV_IS(pi->sh->corerev, 22)
&& (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
@@ -209,7 +211,8 @@ void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val);
}
- if (++pi->phy_wreg >= pi->phy_wreg_limit) {
+ if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) &&
+ (++pi->phy_wreg >= pi->phy_wreg_limit)) {
(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
pi->phy_wreg = 0;
}
@@ -292,10 +295,13 @@ void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
bcma_write16(pi->d11core, D11REGOFFS(phyregdata), val);
if (addr == 0x72)
- (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion));
+ (void)bcma_read16(pi->d11core, D11REGOFFS(phyregdata));
#else
+ struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub);
+
bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16));
- if (++pi->phy_wreg >= pi->phy_wreg_limit) {
+ if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) &&
+ (++pi->phy_wreg >= pi->phy_wreg_limit)) {
pi->phy_wreg = 0;
(void)bcma_read16(pi->d11core, D11REGOFFS(phyversion));
}
@@ -837,7 +843,7 @@ wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset,
pi->tbl_data_hi = tblDataHi;
pi->tbl_data_lo = tblDataLo;
- if (pi->sh->chip == BCM43224_CHIP_ID &&
+ if (pi->sh->chip == BCMA_CHIP_ID_BCM43224 &&
pi->sh->chiprev == 1) {
pi->tbl_addr = tblAddr;
pi->tbl_save_id = tbl_id;
@@ -847,7 +853,7 @@ wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset,
void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val)
{
- if ((pi->sh->chip == BCM43224_CHIP_ID) &&
+ if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) &&
(pi->sh->chiprev == 1) &&
(pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
read_phy_reg(pi, pi->tbl_data_lo);
@@ -881,7 +887,7 @@ wlc_phy_write_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
- if ((pi->sh->chip == BCM43224_CHIP_ID) &&
+ if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) &&
(pi->sh->chiprev == 1) &&
(tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
read_phy_reg(pi, tblDataLo);
@@ -918,7 +924,7 @@ wlc_phy_read_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
- if ((pi->sh->chip == BCM43224_CHIP_ID) &&
+ if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) &&
(pi->sh->chiprev == 1)) {
(void)read_phy_reg(pi, tblDataLo);
@@ -2894,7 +2900,7 @@ const u8 *wlc_phy_get_ofdm_rate_lookup(void)
void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode)
{
- if ((pi->sh->chip == BCM4313_CHIP_ID) &&
+ if ((pi->sh->chip == BCMA_CHIP_ID_BCM4313) &&
(pi->sh->boardflags & BFL_FEM)) {
if (mode) {
u16 txant = 0;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
index 366718146418..65db9b7458dc 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
@@ -17893,6 +17893,8 @@ static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi)
nphy_tpc_txgain_ipa_2g_2057rev7;
} else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6;
+ if (pi->sh->chip == BCMA_CHIP_ID_BCM47162)
+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
} else {
@@ -19254,8 +19256,14 @@ static void wlc_phy_spurwar_nphy(struct brcms_phy *pi)
case 38:
case 102:
case 118:
- nphy_adj_tone_id_buf[0] = 0;
- nphy_adj_noise_var_buf[0] = 0x0;
+ if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) &&
+ (pi->sh->chippkg == BCMA_PKG_ID_BCM4717)) {
+ nphy_adj_tone_id_buf[0] = 32;
+ nphy_adj_noise_var_buf[0] = 0x21f;
+ } else {
+ nphy_adj_tone_id_buf[0] = 0;
+ nphy_adj_noise_var_buf[0] = 0x0;
+ }
break;
case 134:
nphy_adj_tone_id_buf[0] = 32;
@@ -19309,8 +19317,8 @@ void wlc_phy_init_nphy(struct brcms_phy *pi)
pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) &&
- ((pi->sh->chippkg == BCM4717_PKG_ID) ||
- (pi->sh->chippkg == BCM4718_PKG_ID))) {
+ ((pi->sh->chippkg == BCMA_PKG_ID_BCM4717) ||
+ (pi->sh->chippkg == BCMA_PKG_ID_BCM4718))) {
if ((pi->sh->boardflags & BFL_EXTLNA) &&
(CHSPEC_IS2G(pi->radio_chanspec)))
ai_cc_reg(pi->sh->sih,
@@ -19318,6 +19326,10 @@ void wlc_phy_init_nphy(struct brcms_phy *pi)
0x40, 0x40);
}
+ if ((!PHY_IPA(pi)) && (pi->sh->chip == BCMA_CHIP_ID_BCM5357))
+ si_pmu_chipcontrol(pi->sh->sih, 1, CCTRL5357_EXTPA,
+ CCTRL5357_EXTPA);
+
if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
CHSPEC_IS40(pi->radio_chanspec)) {
@@ -20695,12 +20707,22 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 |
RADIO_2056_SYN, 0x1f);
- write_radio_reg(pi,
- RADIO_2056_SYN_PLL_LOOPFILTER4 |
- RADIO_2056_SYN, 0xb);
- write_radio_reg(pi,
- RADIO_2056_SYN_PLL_CP2 |
- RADIO_2056_SYN, 0x14);
+ if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) ||
+ (pi->sh->chip == BCMA_CHIP_ID_BCM47162)) {
+ write_radio_reg(pi,
+ RADIO_2056_SYN_PLL_LOOPFILTER4 |
+ RADIO_2056_SYN, 0x14);
+ write_radio_reg(pi,
+ RADIO_2056_SYN_PLL_CP2 |
+ RADIO_2056_SYN, 0x00);
+ } else {
+ write_radio_reg(pi,
+ RADIO_2056_SYN_PLL_LOOPFILTER4 |
+ RADIO_2056_SYN, 0xb);
+ write_radio_reg(pi,
+ RADIO_2056_SYN_PLL_CP2 |
+ RADIO_2056_SYN, 0x14);
+ }
}
}
@@ -20747,24 +20769,30 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
PADG_IDAC, 0xcc);
- bias = 0x25;
- cascbias = 0x20;
+ if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) ||
+ (pi->sh->chip == BCMA_CHIP_ID_BCM47162)) {
+ bias = 0x40;
+ cascbias = 0x45;
+ pag_boost_tune = 0x5;
+ pgag_boost_tune = 0x33;
+ padg_boost_tune = 0x77;
+ mixg_boost_tune = 0x55;
+ } else {
+ bias = 0x25;
+ cascbias = 0x20;
- if ((pi->sh->chip ==
- BCM43224_CHIP_ID)
- || (pi->sh->chip ==
- BCM43225_CHIP_ID)) {
- if (pi->sh->chippkg ==
- BCM43224_FAB_SMIC) {
+ if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224 ||
+ pi->sh->chip == BCMA_CHIP_ID_BCM43225) &&
+ pi->sh->chippkg == BCMA_PKG_ID_BCM43224_FAB_SMIC) {
bias = 0x2a;
cascbias = 0x38;
}
- }
- pag_boost_tune = 0x4;
- pgag_boost_tune = 0x03;
- padg_boost_tune = 0x77;
- mixg_boost_tune = 0x65;
+ pag_boost_tune = 0x4;
+ pgag_boost_tune = 0x03;
+ padg_boost_tune = 0x77;
+ mixg_boost_tune = 0x65;
+ }
WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
INTPAG_IMAIN_STAT, bias);
@@ -20863,11 +20891,10 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
cascbias = 0x30;
- if ((pi->sh->chip == BCM43224_CHIP_ID) ||
- (pi->sh->chip == BCM43225_CHIP_ID)) {
- if (pi->sh->chippkg == BCM43224_FAB_SMIC)
- cascbias = 0x35;
- }
+ if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224 ||
+ pi->sh->chip == BCMA_CHIP_ID_BCM43225) &&
+ pi->sh->chippkg == BCMA_PKG_ID_BCM43224_FAB_SMIC)
+ cascbias = 0x35;
pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias;
@@ -21106,6 +21133,7 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
const struct nphy_sfo_cfg *ci)
{
u16 val;
+ struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub);
val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
if (CHSPEC_IS5G(chanspec) && !val) {
@@ -21178,22 +21206,32 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
} else if (NREV_GE(pi->pubpi.phy_rev, 7)) {
if (val == 54)
spuravoid = 1;
- } else {
- if (pi->nphy_aband_spurwar_en &&
- ((val == 38) || (val == 102)
- || (val == 118)))
+ } else if (pi->nphy_aband_spurwar_en &&
+ ((val == 38) || (val == 102) || (val == 118))) {
+ if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716)
+ && (pi->sh->chippkg == BCMA_PKG_ID_BCM4717)) {
+ spuravoid = 0;
+ } else {
spuravoid = 1;
+ }
}
if (pi->phy_spuravoid == SPURAVOID_FORCEON)
spuravoid = 1;
- wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false);
- si_pmu_spuravoid_pllupdate(pi->sh->sih, spuravoid);
- wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true);
+ if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) ||
+ (pi->sh->chip == BCMA_CHIP_ID_BCM43225)) {
+ bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc,
+ spuravoid);
+ } else {
+ wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false);
+ bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc,
+ spuravoid);
+ wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true);
+ }
- if ((pi->sh->chip == BCM43224_CHIP_ID) ||
- (pi->sh->chip == BCM43225_CHIP_ID)) {
+ if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) ||
+ (pi->sh->chip == BCMA_CHIP_ID_BCM43225)) {
if (spuravoid == 1) {
bcma_write16(pi->d11core,
D11REGOFFS(tsf_clk_frac_l),
@@ -21209,7 +21247,9 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
}
}
- wlapi_bmac_core_phypll_reset(pi->sh->physhim);
+ if (!((pi->sh->chip == BCMA_CHIP_ID_BCM4716) ||
+ (pi->sh->chip == BCMA_CHIP_ID_BCM47162)))
+ wlapi_bmac_core_phypll_reset(pi->sh->physhim);
mod_phy_reg(pi, 0x01, (0x1 << 15),
((spuravoid > 0) ? (0x1 << 15) : 0));
@@ -22171,9 +22211,15 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi)
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
&auxADC_rssi_ctrlH_save);
- radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1])
- + 82 * (auxADC_Vl) - 28861 +
- 128) / 256;
+ if (pi->sh->chip == BCMA_CHIP_ID_BCM5357) {
+ radio_temp[0] = (193 * (radio_temp[1] + radio_temp2[1])
+ + 88 * (auxADC_Vl) - 27111 +
+ 128) / 256;
+ } else {
+ radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1])
+ + 82 * (auxADC_Vl) - 28861 +
+ 128) / 256;
+ }
offset = (s16) pi->phy_tempsense_offset;
@@ -24923,14 +24969,16 @@ wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains,
if (txgains->useindex) {
phy_a4 = 15 - ((txgains->index) >> 3);
if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if (NREV_GE(pi->pubpi.phy_rev, 6))
+ if (NREV_GE(pi->pubpi.phy_rev, 6) &&
+ pi->sh->chip == BCMA_CHIP_ID_BCM47162) {
+ phy_a5 = 0x10f7 | (phy_a4 << 8);
+ } else if (NREV_GE(pi->pubpi.phy_rev, 6)) {
phy_a5 = 0x00f7 | (phy_a4 << 8);
-
- else
- if (NREV_IS(pi->pubpi.phy_rev, 5))
+ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
phy_a5 = 0x10f7 | (phy_a4 << 8);
- else
+ } else {
phy_a5 = 0x50f7 | (phy_a4 << 8);
+ }
} else {
phy_a5 = 0x70f7 | (phy_a4 << 8);
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.c b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c
index 4931d29d077b..7e9df566c733 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c
@@ -74,16 +74,6 @@
* PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary
* number to differentiate different PLLs controlled by the same PMU rev.
*/
-/* pllcontrol registers:
- * ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>,
- * p1div, p2div, _bypass_sdmod
- */
-#define PMU1_PLL0_PLLCTL0 0
-#define PMU1_PLL0_PLLCTL1 1
-#define PMU1_PLL0_PLLCTL2 2
-#define PMU1_PLL0_PLLCTL3 3
-#define PMU1_PLL0_PLLCTL4 4
-#define PMU1_PLL0_PLLCTL5 5
/* pmu XtalFreqRatio */
#define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF
@@ -108,118 +98,14 @@
#define RES4313_HT_AVAIL_RSRC 14
#define RES4313_MACPHY_CLK_AVAIL_RSRC 15
-/* Determine min/max rsrc masks. Value 0 leaves hardware at default. */
-static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax)
-{
- u32 min_mask = 0, max_mask = 0;
- uint rsrcs;
-
- /* # resources */
- rsrcs = (ai_get_pmucaps(sih) & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
-
- /* determine min/max rsrc masks */
- switch (ai_get_chip_id(sih)) {
- case BCM43224_CHIP_ID:
- case BCM43225_CHIP_ID:
- /* ??? */
- break;
-
- case BCM4313_CHIP_ID:
- min_mask = PMURES_BIT(RES4313_BB_PU_RSRC) |
- PMURES_BIT(RES4313_XTAL_PU_RSRC) |
- PMURES_BIT(RES4313_ALP_AVAIL_RSRC) |
- PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC);
- max_mask = 0xffff;
- break;
- default:
- break;
- }
-
- *pmin = min_mask;
- *pmax = max_mask;
-}
-
-void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid)
-{
- u32 tmp = 0;
- struct bcma_device *core;
-
- /* switch to chipc */
- core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
-
- switch (ai_get_chip_id(sih)) {
- case BCM43224_CHIP_ID:
- case BCM43225_CHIP_ID:
- if (spuravoid == 1) {
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
- PMU1_PLL0_PLLCTL0);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
- 0x11500010);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
- PMU1_PLL0_PLLCTL1);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
- 0x000C0C06);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
- PMU1_PLL0_PLLCTL2);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
- 0x0F600a08);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
- PMU1_PLL0_PLLCTL3);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
- 0x00000000);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
- PMU1_PLL0_PLLCTL4);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
- 0x2001E920);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
- PMU1_PLL0_PLLCTL5);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
- 0x88888815);
- } else {
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
- PMU1_PLL0_PLLCTL0);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
- 0x11100010);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
- PMU1_PLL0_PLLCTL1);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
- 0x000c0c06);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
- PMU1_PLL0_PLLCTL2);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
- 0x03000a08);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
- PMU1_PLL0_PLLCTL3);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
- 0x00000000);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
- PMU1_PLL0_PLLCTL4);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
- 0x200005c0);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
- PMU1_PLL0_PLLCTL5);
- bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
- 0x88888815);
- }
- tmp = 1 << 10;
- break;
-
- default:
- /* bail out */
- return;
- }
-
- bcma_set32(core, CHIPCREGOFFS(pmucontrol), tmp);
-}
-
u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
{
uint delay = PMU_MAX_TRANSITION_DLY;
switch (ai_get_chip_id(sih)) {
- case BCM43224_CHIP_ID:
- case BCM43225_CHIP_ID:
- case BCM4313_CHIP_ID:
+ case BCMA_CHIP_ID_BCM43224:
+ case BCMA_CHIP_ID_BCM43225:
+ case BCMA_CHIP_ID_BCM4313:
delay = 3700;
break;
default:
@@ -270,9 +156,9 @@ u32 si_pmu_alp_clock(struct si_pub *sih)
return clock;
switch (ai_get_chip_id(sih)) {
- case BCM43224_CHIP_ID:
- case BCM43225_CHIP_ID:
- case BCM4313_CHIP_ID:
+ case BCMA_CHIP_ID_BCM43224:
+ case BCMA_CHIP_ID_BCM43225:
+ case BCMA_CHIP_ID_BCM4313:
/* always 20Mhz */
clock = 20000 * 1000;
break;
@@ -283,51 +169,9 @@ u32 si_pmu_alp_clock(struct si_pub *sih)
return clock;
}
-/* initialize PMU */
-void si_pmu_init(struct si_pub *sih)
-{
- struct bcma_device *core;
-
- /* select chipc */
- core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
-
- if (ai_get_pmurev(sih) == 1)
- bcma_mask32(core, CHIPCREGOFFS(pmucontrol),
- ~PCTL_NOILP_ON_WAIT);
- else if (ai_get_pmurev(sih) >= 2)
- bcma_set32(core, CHIPCREGOFFS(pmucontrol), PCTL_NOILP_ON_WAIT);
-}
-
-/* initialize PMU resources */
-void si_pmu_res_init(struct si_pub *sih)
-{
- struct bcma_device *core;
- u32 min_mask = 0, max_mask = 0;
-
- /* select to chipc */
- core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
-
- /* Determine min/max rsrc masks */
- si_pmu_res_masks(sih, &min_mask, &max_mask);
-
- /* It is required to program max_mask first and then min_mask */
-
- /* Program max resource mask */
-
- if (max_mask)
- bcma_write32(core, CHIPCREGOFFS(max_res_mask), max_mask);
-
- /* Program min resource mask */
-
- if (min_mask)
- bcma_write32(core, CHIPCREGOFFS(min_res_mask), min_mask);
-
- /* Add some delay; allow resources to come up and settle. */
- mdelay(2);
-}
-
u32 si_pmu_measure_alpclk(struct si_pub *sih)
{
+ struct si_info *sii = container_of(sih, struct si_info, pub);
struct bcma_device *core;
u32 alp_khz;
@@ -335,7 +179,7 @@ u32 si_pmu_measure_alpclk(struct si_pub *sih)
return 0;
/* Remember original core before switch to chipc */
- core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
+ core = sii->icbus->drv_cc.core;
if (bcma_read32(core, CHIPCREGOFFS(pmustatus)) & PST_EXTLPOAVAIL) {
u32 ilp_ctr, alp_hz;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h
index 3e39c5e0f9ff..f7cff873578b 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h
@@ -26,10 +26,7 @@ extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
extern u32 si_pmu_alp_clock(struct si_pub *sih);
extern void si_pmu_pllupd(struct si_pub *sih);
-extern void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid);
extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
-extern void si_pmu_init(struct si_pub *sih);
-extern void si_pmu_res_init(struct si_pub *sih);
extern u32 si_pmu_measure_alpclk(struct si_pub *sih);
#endif /* _BRCM_PMU_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index aa5d67f8d874..5855f4fd16dc 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
@@ -311,7 +311,7 @@ extern uint brcms_c_detach(struct brcms_c_info *wlc);
extern int brcms_c_up(struct brcms_c_info *wlc);
extern uint brcms_c_down(struct brcms_c_info *wlc);
-extern bool brcms_c_chipmatch(u16 vendor, u16 device);
+extern bool brcms_c_chipmatch(struct bcma_device *core);
extern void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx);
extern void brcms_c_reset(struct brcms_c_info *wlc);
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
index 333193f20e1c..bcc79b4e3267 100644
--- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
@@ -37,5 +37,6 @@
#define BCM4329_CHIP_ID 0x4329
#define BCM4330_CHIP_ID 0x4330
#define BCM4331_CHIP_ID 0x4331
+#define BCM4334_CHIP_ID 0x4334
#endif /* _BRCM_HW_IDS_H_ */
diff --git a/drivers/net/wireless/brcm80211/include/soc.h b/drivers/net/wireless/brcm80211/include/soc.h
index 4e9b7e4827ea..123cfa854a0d 100644
--- a/drivers/net/wireless/brcm80211/include/soc.h
+++ b/drivers/net/wireless/brcm80211/include/soc.h
@@ -19,68 +19,6 @@
#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */
-/* core codes */
-#define NODEV_CORE_ID 0x700 /* Invalid coreid */
-#define CC_CORE_ID 0x800 /* chipcommon core */
-#define ILINE20_CORE_ID 0x801 /* iline20 core */
-#define SRAM_CORE_ID 0x802 /* sram core */
-#define SDRAM_CORE_ID 0x803 /* sdram core */
-#define PCI_CORE_ID 0x804 /* pci core */
-#define MIPS_CORE_ID 0x805 /* mips core */
-#define ENET_CORE_ID 0x806 /* enet mac core */
-#define CODEC_CORE_ID 0x807 /* v90 codec core */
-#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */
-#define ADSL_CORE_ID 0x809 /* ADSL core */
-#define ILINE100_CORE_ID 0x80a /* iline100 core */
-#define IPSEC_CORE_ID 0x80b /* ipsec core */
-#define UTOPIA_CORE_ID 0x80c /* utopia core */
-#define PCMCIA_CORE_ID 0x80d /* pcmcia core */
-#define SOCRAM_CORE_ID 0x80e /* internal memory core */
-#define MEMC_CORE_ID 0x80f /* memc sdram core */
-#define OFDM_CORE_ID 0x810 /* OFDM phy core */
-#define EXTIF_CORE_ID 0x811 /* external interface core */
-#define D11_CORE_ID 0x812 /* 802.11 MAC core */
-#define APHY_CORE_ID 0x813 /* 802.11a phy core */
-#define BPHY_CORE_ID 0x814 /* 802.11b phy core */
-#define GPHY_CORE_ID 0x815 /* 802.11g phy core */
-#define MIPS33_CORE_ID 0x816 /* mips3302 core */
-#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */
-#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */
-#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */
-#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */
-#define SDIOH_CORE_ID 0x81b /* sdio host core */
-#define ROBO_CORE_ID 0x81c /* roboswitch core */
-#define ATA100_CORE_ID 0x81d /* parallel ATA core */
-#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */
-#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */
-#define PCIE_CORE_ID 0x820 /* pci express core */
-#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */
-#define SRAMC_CORE_ID 0x822 /* SRAM controller core */
-#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */
-#define ARM11_CORE_ID 0x824 /* ARM 1176 core */
-#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */
-#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */
-#define PMU_CORE_ID 0x827 /* PMU core */
-#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */
-#define SDIOD_CORE_ID 0x829 /* SDIO device core */
-#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */
-#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */
-#define MIPS74K_CORE_ID 0x82c /* mips 74k core */
-#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */
-#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */
-#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */
-#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */
-#define SC_CORE_ID 0x831 /* shared common core */
-#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */
-#define SPIH_CORE_ID 0x833 /* SPI host core */
-#define I2S_CORE_ID 0x834 /* I2S core */
-#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */
-#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */
-#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */
-#define DEF_AI_COMP 0xfff /* Default component, in ai chips it
- * maps all unused address ranges
- */
-
/* Common core control flags */
#define SICF_BIST_EN 0x8000
#define SICF_PME_EN 0x4000
diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c
index 4b10157d8686..d4fd29ad90dc 100644
--- a/drivers/net/wireless/iwlegacy/3945-rs.c
+++ b/drivers/net/wireless/iwlegacy/3945-rs.c
@@ -946,7 +946,7 @@ il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
case IEEE80211_BAND_5GHZ:
rs_sta->expected_tpt = il3945_expected_tpt_a;
break;
- case IEEE80211_NUM_BANDS:
+ default:
BUG();
break;
}
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index d24eaf89ffb5..34f61a0581a2 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -3405,7 +3405,7 @@ il4965_remove_dynamic_key(struct il_priv *il,
return 0;
}
- if (il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
+ if (il->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_INVALID) {
IL_WARN("Removing wrong key %d 0x%x\n", keyconf->keyidx,
key_flags);
spin_unlock_irqrestore(&il->sta_lock, flags);
@@ -3420,7 +3420,7 @@ il4965_remove_dynamic_key(struct il_priv *il,
memset(&il->stations[sta_id].sta.key, 0, sizeof(struct il4965_keyinfo));
il->stations[sta_id].sta.key.key_flags =
STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
- il->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
+ il->stations[sta_id].sta.key.key_offset = keyconf->hw_key_idx;
il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index cbf2dc18341f..0370403fd0bd 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -4717,10 +4717,11 @@ il_check_stuck_queue(struct il_priv *il, int cnt)
struct il_tx_queue *txq = &il->txq[cnt];
struct il_queue *q = &txq->q;
unsigned long timeout;
+ unsigned long now = jiffies;
int ret;
if (q->read_ptr == q->write_ptr) {
- txq->time_stamp = jiffies;
+ txq->time_stamp = now;
return 0;
}
@@ -4728,9 +4729,9 @@ il_check_stuck_queue(struct il_priv *il, int cnt)
txq->time_stamp +
msecs_to_jiffies(il->cfg->wd_timeout);
- if (time_after(jiffies, timeout)) {
+ if (time_after(now, timeout)) {
IL_ERR("Queue %d stuck for %u ms.\n", q->id,
- il->cfg->wd_timeout);
+ jiffies_to_msecs(now - txq->time_stamp));
ret = il_force_reset(il, false);
return (ret == -EAGAIN) ? 0 : 1;
}
@@ -4767,14 +4768,12 @@ il_bg_watchdog(unsigned long data)
return;
/* monitor and check for other stuck queues */
- if (il_is_any_associated(il)) {
- for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
- /* skip as we already checked the command queue */
- if (cnt == il->cmd_queue)
- continue;
- if (il_check_stuck_queue(il, cnt))
- return;
- }
+ for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
+ /* skip as we already checked the command queue */
+ if (cnt == il->cmd_queue)
+ continue;
+ if (il_check_stuck_queue(il, cnt))
+ return;
}
mod_timer(&il->watchdog,
@@ -5360,7 +5359,7 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (changes & BSS_CHANGED_ASSOC) {
D_MAC80211("ASSOC %d\n", bss_conf->assoc);
if (bss_conf->assoc) {
- il->timestamp = bss_conf->last_tsf;
+ il->timestamp = bss_conf->sync_tsf;
if (!il_is_rfkill(il))
il->ops->post_associate(il);
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
index b0f125c985cd..46782f1102ac 100644
--- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
@@ -2228,6 +2228,7 @@ static ssize_t iwl_dbgfs_echo_test_write(struct file *file,
return count;
}
+#ifdef CONFIG_IWLWIFI_DEBUG
static ssize_t iwl_dbgfs_log_event_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
@@ -2269,6 +2270,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file,
return count;
}
+#endif
static ssize_t iwl_dbgfs_calib_disabled_read(struct file *file,
char __user *user_buf,
@@ -2338,7 +2340,9 @@ DEBUGFS_READ_FILE_OPS(bt_traffic);
DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
DEBUGFS_READ_FILE_OPS(reply_tx_error);
DEBUGFS_WRITE_FILE_OPS(echo_test);
+#ifdef CONFIG_IWLWIFI_DEBUG
DEBUGFS_READ_WRITE_FILE_OPS(log_event);
+#endif
DEBUGFS_READ_WRITE_FILE_OPS(calib_disabled);
/*
@@ -2398,7 +2402,9 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR);
+#ifdef CONFIG_IWLWIFI_DEBUG
DEBUGFS_ADD_FILE(log_event, dir_debug, S_IWUSR | S_IRUSR);
+#endif
if (iwl_advanced_bt_coexist(priv))
DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR);
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index b83ca358eb18..a5f7bce96325 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -801,6 +801,18 @@ static int iwlagn_mac_sta_state(struct ieee80211_hw *hw,
switch (op) {
case ADD:
ret = iwlagn_mac_sta_add(hw, vif, sta);
+ if (ret)
+ break;
+ /*
+ * Clear the in-progress flag, the AP station entry was added
+ * but we'll initialize LQ only when we've associated (which
+ * would also clear the in-progress flag). This is necessary
+ * in case we never initialize LQ because association fails.
+ */
+ spin_lock_bh(&priv->sta_lock);
+ priv->stations[iwl_sta_id(sta)].used &=
+ ~IWL_STA_UCODE_INPROGRESS;
+ spin_unlock_bh(&priv->sta_lock);
break;
case REMOVE:
ret = iwlagn_mac_sta_remove(hw, vif, sta);
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c
index 6ee940f497f9..10896393e5a0 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rxon.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c
@@ -1447,7 +1447,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
if (changes & BSS_CHANGED_ASSOC) {
if (bss_conf->assoc) {
- priv->timestamp = bss_conf->last_tsf;
+ priv->timestamp = bss_conf->sync_tsf;
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
} else {
/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 6322e2a692cc..cc41cfaedfbd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -911,8 +911,10 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
const struct iwl_op_mode_ops *ops = op->ops;
drv->op_mode = ops->start(drv->trans, drv->cfg, &drv->fw);
- if (!drv->op_mode)
+ if (!drv->op_mode) {
+ mutex_unlock(&iwlwifi_opmode_table_mtx);
goto out_unbind;
+ }
} else {
load_module = true;
}
diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig
deleted file mode 100644
index 7107ce53d4d4..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/Kconfig
+++ /dev/null
@@ -1,39 +0,0 @@
-config IWM
- tristate "Intel Wireless Multicomm 3200 WiFi driver (EXPERIMENTAL)"
- depends on MMC && EXPERIMENTAL
- depends on CFG80211
- select FW_LOADER
- select IWMC3200TOP
- help
- The Intel Wireless Multicomm 3200 hardware is a combo
- card with GPS, Bluetooth, WiMax and 802.11 radios. It
- runs over SDIO and is typically found on Moorestown
- based platform. This driver takes care of the 802.11
- part, which is a fullmac one.
-
- If you choose to build it as a module, it'll be called
- iwmc3200wifi.ko.
-
-config IWM_DEBUG
- bool "Enable full debugging output in iwmc3200wifi"
- depends on IWM && DEBUG_FS
- help
- This option will enable debug tracing and setting for iwm
-
- You can set the debug level and module through debugfs. By
- default all modules are set to the IWL_DL_ERR level.
- To see the list of debug modules and levels, see iwm/debug.h
-
- For example, if you want the full MLME debug output:
- echo 0xff > /sys/kernel/debug/iwm/phyN/debug/mlme
-
- Or, if you want the full debug, for all modules:
- echo 0xff > /sys/kernel/debug/iwm/phyN/debug/level
- echo 0xff > /sys/kernel/debug/iwm/phyN/debug/modules
-
-config IWM_TRACING
- bool "Enable event tracing for iwmc3200wifi"
- depends on IWM && EVENT_TRACING
- help
- Say Y here to trace all the commands and responses between
- the driver and firmware (including TX/RX frames) with ftrace.
diff --git a/drivers/net/wireless/iwmc3200wifi/Makefile b/drivers/net/wireless/iwmc3200wifi/Makefile
deleted file mode 100644
index cdc7e07ba113..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-obj-$(CONFIG_IWM) := iwmc3200wifi.o
-iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o
-iwmc3200wifi-objs += commands.o cfg80211.o eeprom.o
-
-iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o
-iwmc3200wifi-$(CONFIG_IWM_TRACING) += trace.o
-
-CFLAGS_trace.o := -I$(src)
-
-ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/iwmc3200wifi/bus.h b/drivers/net/wireless/iwmc3200wifi/bus.h
deleted file mode 100644
index 62edd5888a7b..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/bus.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-
-#ifndef __IWM_BUS_H__
-#define __IWM_BUS_H__
-
-#include "iwm.h"
-
-struct iwm_if_ops {
- int (*enable)(struct iwm_priv *iwm);
- int (*disable)(struct iwm_priv *iwm);
- int (*send_chunk)(struct iwm_priv *iwm, u8* buf, int count);
-
- void (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir);
- void (*debugfs_exit)(struct iwm_priv *iwm);
-
- const char *umac_name;
- const char *calib_lmac_name;
- const char *lmac_name;
-};
-
-static inline int iwm_bus_send_chunk(struct iwm_priv *iwm, u8 *buf, int count)
-{
- return iwm->bus_ops->send_chunk(iwm, buf, count);
-}
-
-static inline int iwm_bus_enable(struct iwm_priv *iwm)
-{
- return iwm->bus_ops->enable(iwm);
-}
-
-static inline int iwm_bus_disable(struct iwm_priv *iwm)
-{
- return iwm->bus_ops->disable(iwm);
-}
-
-#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
deleted file mode 100644
index 48e8218fd23b..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c
+++ /dev/null
@@ -1,882 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/sched.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-#include <linux/ieee80211.h>
-#include <linux/slab.h>
-#include <net/cfg80211.h>
-
-#include "iwm.h"
-#include "commands.h"
-#include "cfg80211.h"
-#include "debug.h"
-
-#define RATETAB_ENT(_rate, _rateid, _flags) \
- { \
- .bitrate = (_rate), \
- .hw_value = (_rateid), \
- .flags = (_flags), \
- }
-
-#define CHAN2G(_channel, _freq, _flags) { \
- .band = IEEE80211_BAND_2GHZ, \
- .center_freq = (_freq), \
- .hw_value = (_channel), \
- .flags = (_flags), \
- .max_antenna_gain = 0, \
- .max_power = 30, \
-}
-
-#define CHAN5G(_channel, _flags) { \
- .band = IEEE80211_BAND_5GHZ, \
- .center_freq = 5000 + (5 * (_channel)), \
- .hw_value = (_channel), \
- .flags = (_flags), \
- .max_antenna_gain = 0, \
- .max_power = 30, \
-}
-
-static struct ieee80211_rate iwm_rates[] = {
- RATETAB_ENT(10, 0x1, 0),
- RATETAB_ENT(20, 0x2, 0),
- RATETAB_ENT(55, 0x4, 0),
- RATETAB_ENT(110, 0x8, 0),
- RATETAB_ENT(60, 0x10, 0),
- RATETAB_ENT(90, 0x20, 0),
- RATETAB_ENT(120, 0x40, 0),
- RATETAB_ENT(180, 0x80, 0),
- RATETAB_ENT(240, 0x100, 0),
- RATETAB_ENT(360, 0x200, 0),
- RATETAB_ENT(480, 0x400, 0),
- RATETAB_ENT(540, 0x800, 0),
-};
-
-#define iwm_a_rates (iwm_rates + 4)
-#define iwm_a_rates_size 8
-#define iwm_g_rates (iwm_rates + 0)
-#define iwm_g_rates_size 12
-
-static struct ieee80211_channel iwm_2ghz_channels[] = {
- CHAN2G(1, 2412, 0),
- CHAN2G(2, 2417, 0),
- CHAN2G(3, 2422, 0),
- CHAN2G(4, 2427, 0),
- CHAN2G(5, 2432, 0),
- CHAN2G(6, 2437, 0),
- CHAN2G(7, 2442, 0),
- CHAN2G(8, 2447, 0),
- CHAN2G(9, 2452, 0),
- CHAN2G(10, 2457, 0),
- CHAN2G(11, 2462, 0),
- CHAN2G(12, 2467, 0),
- CHAN2G(13, 2472, 0),
- CHAN2G(14, 2484, 0),
-};
-
-static struct ieee80211_channel iwm_5ghz_a_channels[] = {
- CHAN5G(34, 0), CHAN5G(36, 0),
- CHAN5G(38, 0), CHAN5G(40, 0),
- CHAN5G(42, 0), CHAN5G(44, 0),
- CHAN5G(46, 0), CHAN5G(48, 0),
- CHAN5G(52, 0), CHAN5G(56, 0),
- CHAN5G(60, 0), CHAN5G(64, 0),
- CHAN5G(100, 0), CHAN5G(104, 0),
- CHAN5G(108, 0), CHAN5G(112, 0),
- CHAN5G(116, 0), CHAN5G(120, 0),
- CHAN5G(124, 0), CHAN5G(128, 0),
- CHAN5G(132, 0), CHAN5G(136, 0),
- CHAN5G(140, 0), CHAN5G(149, 0),
- CHAN5G(153, 0), CHAN5G(157, 0),
- CHAN5G(161, 0), CHAN5G(165, 0),
- CHAN5G(184, 0), CHAN5G(188, 0),
- CHAN5G(192, 0), CHAN5G(196, 0),
- CHAN5G(200, 0), CHAN5G(204, 0),
- CHAN5G(208, 0), CHAN5G(212, 0),
- CHAN5G(216, 0),
-};
-
-static struct ieee80211_supported_band iwm_band_2ghz = {
- .channels = iwm_2ghz_channels,
- .n_channels = ARRAY_SIZE(iwm_2ghz_channels),
- .bitrates = iwm_g_rates,
- .n_bitrates = iwm_g_rates_size,
-};
-
-static struct ieee80211_supported_band iwm_band_5ghz = {
- .channels = iwm_5ghz_a_channels,
- .n_channels = ARRAY_SIZE(iwm_5ghz_a_channels),
- .bitrates = iwm_a_rates,
- .n_bitrates = iwm_a_rates_size,
-};
-
-static int iwm_key_init(struct iwm_key *key, u8 key_index,
- const u8 *mac_addr, struct key_params *params)
-{
- key->hdr.key_idx = key_index;
- if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
- key->hdr.multicast = 1;
- memset(key->hdr.mac, 0xff, ETH_ALEN);
- } else {
- key->hdr.multicast = 0;
- memcpy(key->hdr.mac, mac_addr, ETH_ALEN);
- }
-
- if (params) {
- if (params->key_len > WLAN_MAX_KEY_LEN ||
- params->seq_len > IW_ENCODE_SEQ_MAX_SIZE)
- return -EINVAL;
-
- key->cipher = params->cipher;
- key->key_len = params->key_len;
- key->seq_len = params->seq_len;
- memcpy(key->key, params->key, key->key_len);
- memcpy(key->seq, params->seq, key->seq_len);
- }
-
- return 0;
-}
-
-static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
- u8 key_index, bool pairwise, const u8 *mac_addr,
- struct key_params *params)
-{
- struct iwm_priv *iwm = ndev_to_iwm(ndev);
- struct iwm_key *key;
- int ret;
-
- IWM_DBG_WEXT(iwm, DBG, "Adding key for %pM\n", mac_addr);
-
- if (key_index >= IWM_NUM_KEYS)
- return -ENOENT;
-
- key = &iwm->keys[key_index];
- memset(key, 0, sizeof(struct iwm_key));
- ret = iwm_key_init(key, key_index, mac_addr, params);
- if (ret < 0) {
- IWM_ERR(iwm, "Invalid key_params\n");
- return ret;
- }
-
- return iwm_set_key(iwm, 0, key);
-}
-
-static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
- u8 key_index, bool pairwise, const u8 *mac_addr,
- void *cookie,
- void (*callback)(void *cookie,
- struct key_params*))
-{
- struct iwm_priv *iwm = ndev_to_iwm(ndev);
- struct iwm_key *key;
- struct key_params params;
-
- IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index);
-
- if (key_index >= IWM_NUM_KEYS)
- return -ENOENT;
-
- memset(&params, 0, sizeof(params));
-
- key = &iwm->keys[key_index];
- params.cipher = key->cipher;
- params.key_len = key->key_len;
- params.seq_len = key->seq_len;
- params.seq = key->seq;
- params.key = key->key;
-
- callback(cookie, &params);
-
- return key->key_len ? 0 : -ENOENT;
-}
-
-
-static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
- u8 key_index, bool pairwise, const u8 *mac_addr)
-{
- struct iwm_priv *iwm = ndev_to_iwm(ndev);
- struct iwm_key *key;
-
- if (key_index >= IWM_NUM_KEYS)
- return -ENOENT;
-
- key = &iwm->keys[key_index];
- if (!iwm->keys[key_index].key_len) {
- IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index);
- return 0;
- }
-
- if (key_index == iwm->default_key)
- iwm->default_key = -1;
-
- return iwm_set_key(iwm, 1, key);
-}
-
-static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
- struct net_device *ndev,
- u8 key_index, bool unicast,
- bool multicast)
-{
- struct iwm_priv *iwm = ndev_to_iwm(ndev);
-
- IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index);
-
- if (key_index >= IWM_NUM_KEYS)
- return -ENOENT;
-
- if (!iwm->keys[key_index].key_len) {
- IWM_ERR(iwm, "Key %d not used\n", key_index);
- return -EINVAL;
- }
-
- iwm->default_key = key_index;
-
- return iwm_set_tx_key(iwm, key_index);
-}
-
-static int iwm_cfg80211_get_station(struct wiphy *wiphy,
- struct net_device *ndev,
- u8 *mac, struct station_info *sinfo)
-{
- struct iwm_priv *iwm = ndev_to_iwm(ndev);
-
- if (memcmp(mac, iwm->bssid, ETH_ALEN))
- return -ENOENT;
-
- sinfo->filled |= STATION_INFO_TX_BITRATE;
- sinfo->txrate.legacy = iwm->rate * 10;
-
- if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
- sinfo->filled |= STATION_INFO_SIGNAL;
- sinfo->signal = iwm->wstats.qual.level;
- }
-
- return 0;
-}
-
-
-int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
-{
- struct wiphy *wiphy = iwm_to_wiphy(iwm);
- struct iwm_bss_info *bss;
- struct iwm_umac_notif_bss_info *umac_bss;
- struct ieee80211_mgmt *mgmt;
- struct ieee80211_channel *channel;
- struct ieee80211_supported_band *band;
- s32 signal;
- int freq;
-
- list_for_each_entry(bss, &iwm->bss_list, node) {
- umac_bss = bss->bss;
- mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
-
- if (umac_bss->band == UMAC_BAND_2GHZ)
- band = wiphy->bands[IEEE80211_BAND_2GHZ];
- else if (umac_bss->band == UMAC_BAND_5GHZ)
- band = wiphy->bands[IEEE80211_BAND_5GHZ];
- else {
- IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
- return -EINVAL;
- }
-
- freq = ieee80211_channel_to_frequency(umac_bss->channel,
- band->band);
- channel = ieee80211_get_channel(wiphy, freq);
- signal = umac_bss->rssi * 100;
-
- if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
- le16_to_cpu(umac_bss->frame_len),
- signal, GFP_KERNEL))
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int iwm_cfg80211_change_iface(struct wiphy *wiphy,
- struct net_device *ndev,
- enum nl80211_iftype type, u32 *flags,
- struct vif_params *params)
-{
- struct wireless_dev *wdev;
- struct iwm_priv *iwm;
- u32 old_mode;
-
- wdev = ndev->ieee80211_ptr;
- iwm = ndev_to_iwm(ndev);
- old_mode = iwm->conf.mode;
-
- switch (type) {
- case NL80211_IFTYPE_STATION:
- iwm->conf.mode = UMAC_MODE_BSS;
- break;
- case NL80211_IFTYPE_ADHOC:
- iwm->conf.mode = UMAC_MODE_IBSS;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- wdev->iftype = type;
-
- if ((old_mode == iwm->conf.mode) || !iwm->umac_profile)
- return 0;
-
- iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
-
- if (iwm->umac_profile_active)
- iwm_invalidate_mlme_profile(iwm);
-
- return 0;
-}
-
-static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
- struct cfg80211_scan_request *request)
-{
- struct iwm_priv *iwm = ndev_to_iwm(ndev);
- int ret;
-
- if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
- IWM_ERR(iwm, "Scan while device is not ready\n");
- return -EIO;
- }
-
- if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) {
- IWM_ERR(iwm, "Scanning already\n");
- return -EAGAIN;
- }
-
- if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) {
- IWM_ERR(iwm, "Scanning being aborted\n");
- return -EAGAIN;
- }
-
- set_bit(IWM_STATUS_SCANNING, &iwm->status);
-
- ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids);
- if (ret) {
- clear_bit(IWM_STATUS_SCANNING, &iwm->status);
- return ret;
- }
-
- iwm->scan_request = request;
- return 0;
-}
-
-static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
-{
- struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
-
- if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
- (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
- int ret;
-
- iwm->conf.rts_threshold = wiphy->rts_threshold;
-
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_RTS_THRESHOLD,
- iwm->conf.rts_threshold);
- if (ret < 0)
- return ret;
- }
-
- if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
- (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
- int ret;
-
- iwm->conf.frag_threshold = wiphy->frag_threshold;
-
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
- CFG_FRAG_THRESHOLD,
- iwm->conf.frag_threshold);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
-static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_ibss_params *params)
-{
- struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
- struct ieee80211_channel *chan = params->channel;
-
- if (!test_bit(IWM_STATUS_READY, &iwm->status))
- return -EIO;
-
- /* UMAC doesn't support creating or joining an IBSS network
- * with specified bssid. */
- if (params->bssid)
- return -EOPNOTSUPP;
-
- iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
- iwm->umac_profile->ibss.band = chan->band;
- iwm->umac_profile->ibss.channel = iwm->channel;
- iwm->umac_profile->ssid.ssid_len = params->ssid_len;
- memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
-
- return iwm_send_mlme_profile(iwm);
-}
-
-static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
-{
- struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
-
- if (iwm->umac_profile_active)
- return iwm_invalidate_mlme_profile(iwm);
-
- return 0;
-}
-
-static int iwm_set_auth_type(struct iwm_priv *iwm,
- enum nl80211_auth_type sme_auth_type)
-{
- u8 *auth_type = &iwm->umac_profile->sec.auth_type;
-
- switch (sme_auth_type) {
- case NL80211_AUTHTYPE_AUTOMATIC:
- case NL80211_AUTHTYPE_OPEN_SYSTEM:
- IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n");
- *auth_type = UMAC_AUTH_TYPE_OPEN;
- break;
- case NL80211_AUTHTYPE_SHARED_KEY:
- if (iwm->umac_profile->sec.flags &
- (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
- IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n");
- *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
- } else {
- IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n");
- *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
- }
-
- break;
- default:
- IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type);
- return -ENOTSUPP;
- }
-
- return 0;
-}
-
-static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
-{
- IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version);
-
- if (!wpa_version) {
- iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
- return 0;
- }
-
- if (wpa_version & NL80211_WPA_VERSION_1)
- iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK;
-
- if (wpa_version & NL80211_WPA_VERSION_2)
- iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
-
- return 0;
-}
-
-static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
-{
- u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
- &iwm->umac_profile->sec.mcast_cipher;
-
- if (!cipher) {
- *profile_cipher = UMAC_CIPHER_TYPE_NONE;
- return 0;
- }
-
- IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm',
- cipher);
-
- switch (cipher) {
- case IW_AUTH_CIPHER_NONE:
- *profile_cipher = UMAC_CIPHER_TYPE_NONE;
- break;
- case WLAN_CIPHER_SUITE_WEP40:
- *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
- break;
- case WLAN_CIPHER_SUITE_WEP104:
- *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
- break;
- case WLAN_CIPHER_SUITE_TKIP:
- *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
- break;
- case WLAN_CIPHER_SUITE_CCMP:
- *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
- break;
- default:
- IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
- return -ENOTSUPP;
- }
-
- return 0;
-}
-
-static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt)
-{
- u8 *auth_type = &iwm->umac_profile->sec.auth_type;
-
- IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
-
- if (key_mgt == WLAN_AKM_SUITE_8021X)
- *auth_type = UMAC_AUTH_TYPE_8021X;
- else if (key_mgt == WLAN_AKM_SUITE_PSK) {
- if (iwm->umac_profile->sec.flags &
- (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
- *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
- else
- *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
- } else {
- IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
- return -EINVAL;
- }
-
- return 0;
-}
-
-
-static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_connect_params *sme)
-{
- struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
- struct ieee80211_channel *chan = sme->channel;
- struct key_params key_param;
- int ret;
-
- if (!test_bit(IWM_STATUS_READY, &iwm->status))
- return -EIO;
-
- if (!sme->ssid)
- return -EINVAL;
-
- if (iwm->umac_profile_active) {
- ret = iwm_invalidate_mlme_profile(iwm);
- if (ret) {
- IWM_ERR(iwm, "Couldn't invalidate profile\n");
- return ret;
- }
- }
-
- if (chan)
- iwm->channel =
- ieee80211_frequency_to_channel(chan->center_freq);
-
- iwm->umac_profile->ssid.ssid_len = sme->ssid_len;
- memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len);
-
- if (sme->bssid) {
- IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid);
- memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN);
- iwm->umac_profile->bss_num = 1;
- } else {
- memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
- iwm->umac_profile->bss_num = 0;
- }
-
- ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
- if (ret < 0)
- return ret;
-
- ret = iwm_set_auth_type(iwm, sme->auth_type);
- if (ret < 0)
- return ret;
-
- if (sme->crypto.n_ciphers_pairwise) {
- ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0],
- true);
- if (ret < 0)
- return ret;
- }
-
- ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false);
- if (ret < 0)
- return ret;
-
- if (sme->crypto.n_akm_suites) {
- ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]);
- if (ret < 0)
- return ret;
- }
-
- /*
- * We save the WEP key in case we want to do shared authentication.
- * We have to do it so because UMAC will assert whenever it gets a
- * key before a profile.
- */
- if (sme->key) {
- key_param.key = kmemdup(sme->key, sme->key_len, GFP_KERNEL);
- if (key_param.key == NULL)
- return -ENOMEM;
- key_param.key_len = sme->key_len;
- key_param.seq_len = 0;
- key_param.cipher = sme->crypto.ciphers_pairwise[0];
-
- ret = iwm_key_init(&iwm->keys[sme->key_idx], sme->key_idx,
- NULL, &key_param);
- kfree(key_param.key);
- if (ret < 0) {
- IWM_ERR(iwm, "Invalid key_params\n");
- return ret;
- }
-
- iwm->default_key = sme->key_idx;
- }
-
- /* WPA and open AUTH type from wpa_s means WPS (a.k.a. WSC) */
- if ((iwm->umac_profile->sec.flags &
- (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) &&
- iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN) {
- iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WSC_ON_MSK;
- }
-
- ret = iwm_send_mlme_profile(iwm);
-
- if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK ||
- sme->key == NULL)
- return ret;
-
- /*
- * We want to do shared auth.
- * We need to actually set the key we previously cached,
- * and then tell the UMAC it's the default one.
- * That will trigger the auth+assoc UMAC machinery, and again,
- * this must be done after setting the profile.
- */
- ret = iwm_set_key(iwm, 0, &iwm->keys[sme->key_idx]);
- if (ret < 0)
- return ret;
-
- return iwm_set_tx_key(iwm, iwm->default_key);
-}
-
-static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
- u16 reason_code)
-{
- struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
-
- IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
-
- if (iwm->umac_profile_active)
- iwm_invalidate_mlme_profile(iwm);
-
- return 0;
-}
-
-static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
- enum nl80211_tx_power_setting type, int mbm)
-{
- struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
- int ret;
-
- switch (type) {
- case NL80211_TX_POWER_AUTOMATIC:
- return 0;
- case NL80211_TX_POWER_FIXED:
- if (mbm < 0 || (mbm % 100))
- return -EOPNOTSUPP;
-
- if (!test_bit(IWM_STATUS_READY, &iwm->status))
- return 0;
-
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_TX_PWR_LIMIT_USR,
- MBM_TO_DBM(mbm) * 2);
- if (ret < 0)
- return ret;
-
- return iwm_tx_power_trigger(iwm);
- default:
- IWM_ERR(iwm, "Unsupported power type: %d\n", type);
- return -EOPNOTSUPP;
- }
-
- return 0;
-}
-
-static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
-{
- struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
-
- *dbm = iwm->txpower >> 1;
-
- return 0;
-}
-
-static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
- struct net_device *dev,
- bool enabled, int timeout)
-{
- struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
- u32 power_index;
-
- if (enabled)
- power_index = IWM_POWER_INDEX_DEFAULT;
- else
- power_index = IWM_POWER_INDEX_MIN;
-
- if (power_index == iwm->conf.power_index)
- return 0;
-
- iwm->conf.power_index = power_index;
-
- return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_POWER_INDEX, iwm->conf.power_index);
-}
-
-static int iwm_cfg80211_set_pmksa(struct wiphy *wiphy,
- struct net_device *netdev,
- struct cfg80211_pmksa *pmksa)
-{
- struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
-
- return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD);
-}
-
-static int iwm_cfg80211_del_pmksa(struct wiphy *wiphy,
- struct net_device *netdev,
- struct cfg80211_pmksa *pmksa)
-{
- struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
-
- return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL);
-}
-
-static int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy,
- struct net_device *netdev)
-{
- struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
- struct cfg80211_pmksa pmksa;
-
- memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
-
- return iwm_send_pmkid_update(iwm, &pmksa, IWM_CMD_PMKID_FLUSH);
-}
-
-
-static struct cfg80211_ops iwm_cfg80211_ops = {
- .change_virtual_intf = iwm_cfg80211_change_iface,
- .add_key = iwm_cfg80211_add_key,
- .get_key = iwm_cfg80211_get_key,
- .del_key = iwm_cfg80211_del_key,
- .set_default_key = iwm_cfg80211_set_default_key,
- .get_station = iwm_cfg80211_get_station,
- .scan = iwm_cfg80211_scan,
- .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
- .connect = iwm_cfg80211_connect,
- .disconnect = iwm_cfg80211_disconnect,
- .join_ibss = iwm_cfg80211_join_ibss,
- .leave_ibss = iwm_cfg80211_leave_ibss,
- .set_tx_power = iwm_cfg80211_set_txpower,
- .get_tx_power = iwm_cfg80211_get_txpower,
- .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
- .set_pmksa = iwm_cfg80211_set_pmksa,
- .del_pmksa = iwm_cfg80211_del_pmksa,
- .flush_pmksa = iwm_cfg80211_flush_pmksa,
-};
-
-static const u32 cipher_suites[] = {
- WLAN_CIPHER_SUITE_WEP40,
- WLAN_CIPHER_SUITE_WEP104,
- WLAN_CIPHER_SUITE_TKIP,
- WLAN_CIPHER_SUITE_CCMP,
-};
-
-struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
-{
- int ret = 0;
- struct wireless_dev *wdev;
-
- /*
- * We're trying to have the following memory
- * layout:
- *
- * +-------------------------+
- * | struct wiphy |
- * +-------------------------+
- * | struct iwm_priv |
- * +-------------------------+
- * | bus private data |
- * | (e.g. iwm_priv_sdio) |
- * +-------------------------+
- *
- */
-
- wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
- if (!wdev) {
- dev_err(dev, "Couldn't allocate wireless device\n");
- return ERR_PTR(-ENOMEM);
- }
-
- wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
- sizeof(struct iwm_priv) + sizeof_bus);
- if (!wdev->wiphy) {
- dev_err(dev, "Couldn't allocate wiphy device\n");
- ret = -ENOMEM;
- goto out_err_new;
- }
-
- set_wiphy_dev(wdev->wiphy, dev);
- wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
- wdev->wiphy->max_num_pmkids = UMAC_MAX_NUM_PMKIDS;
- wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC);
- wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
- wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
- wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
-
- wdev->wiphy->cipher_suites = cipher_suites;
- wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
-
- ret = wiphy_register(wdev->wiphy);
- if (ret < 0) {
- dev_err(dev, "Couldn't register wiphy device\n");
- goto out_err_register;
- }
-
- return wdev;
-
- out_err_register:
- wiphy_free(wdev->wiphy);
-
- out_err_new:
- kfree(wdev);
-
- return ERR_PTR(ret);
-}
-
-void iwm_wdev_free(struct iwm_priv *iwm)
-{
- struct wireless_dev *wdev = iwm_to_wdev(iwm);
-
- if (!wdev)
- return;
-
- wiphy_unregister(wdev->wiphy);
- wiphy_free(wdev->wiphy);
- kfree(wdev);
-}
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.h b/drivers/net/wireless/iwmc3200wifi/cfg80211.h
deleted file mode 100644
index 56a34145acbf..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/cfg80211.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-
-#ifndef __IWM_CFG80211_H__
-#define __IWM_CFG80211_H__
-
-int iwm_cfg80211_inform_bss(struct iwm_priv *iwm);
-struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev);
-void iwm_wdev_free(struct iwm_priv *iwm);
-
-#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c
deleted file mode 100644
index bd75078c454b..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/commands.c
+++ /dev/null
@@ -1,1002 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/wireless.h>
-#include <linux/etherdevice.h>
-#include <linux/ieee80211.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/moduleparam.h>
-
-#include "iwm.h"
-#include "bus.h"
-#include "hal.h"
-#include "umac.h"
-#include "commands.h"
-#include "debug.h"
-
-static int iwm_send_lmac_ptrough_cmd(struct iwm_priv *iwm,
- u8 lmac_cmd_id,
- const void *lmac_payload,
- u16 lmac_payload_size,
- u8 resp)
-{
- struct iwm_udma_wifi_cmd udma_cmd = UDMA_LMAC_INIT;
- struct iwm_umac_cmd umac_cmd;
- struct iwm_lmac_cmd lmac_cmd;
-
- lmac_cmd.id = lmac_cmd_id;
-
- umac_cmd.id = UMAC_CMD_OPCODE_WIFI_PASS_THROUGH;
- umac_cmd.resp = resp;
-
- return iwm_hal_send_host_cmd(iwm, &udma_cmd, &umac_cmd, &lmac_cmd,
- lmac_payload, lmac_payload_size);
-}
-
-int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
- bool resp)
-{
- struct iwm_umac_wifi_if *hdr = (struct iwm_umac_wifi_if *)payload;
- struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
- struct iwm_umac_cmd umac_cmd;
- int ret;
- u8 oid = hdr->oid;
-
- if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
- IWM_ERR(iwm, "Interface is not ready yet");
- return -EAGAIN;
- }
-
- umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER;
- umac_cmd.resp = resp;
-
- ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd,
- payload, payload_size);
-
- if (resp) {
- ret = wait_event_interruptible_timeout(iwm->wifi_ntfy_queue,
- test_and_clear_bit(oid, &iwm->wifi_ntfy[0]),
- 3 * HZ);
-
- return ret ? 0 : -EBUSY;
- }
-
- return ret;
-}
-
-static int modparam_wiwi = COEX_MODE_CM;
-module_param_named(wiwi, modparam_wiwi, int, 0644);
-MODULE_PARM_DESC(wiwi, "Wifi-WiMAX coexistence: 1=SA, 2=XOR, 3=CM (default)");
-
-static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] =
-{
- {4, 3, 0, COEX_UNASSOC_IDLE_FLAGS},
- {4, 3, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
- {4, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
- {4, 3, 0, COEX_CALIBRATION_FLAGS},
- {4, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS},
- {4, 3, 0, COEX_CONNECTION_ESTAB_FLAGS},
- {4, 3, 0, COEX_ASSOCIATED_IDLE_FLAGS},
- {4, 3, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
- {4, 3, 0, COEX_ASSOC_AUTO_SCAN_FLAGS},
- {4, 3, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS},
- {6, 3, 0, COEX_XOR_RF_ON_FLAGS},
- {4, 3, 0, COEX_RF_OFF_FLAGS},
- {6, 6, 0, COEX_STAND_ALONE_DEBUG_FLAGS},
- {4, 3, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS},
- {4, 3, 0, COEX_RSRVD1_FLAGS},
- {4, 3, 0, COEX_RSRVD2_FLAGS}
-};
-
-static struct coex_event iwm_sta_cm_prio_tbl[COEX_EVENTS_NUM] =
-{
- {1, 1, 0, COEX_UNASSOC_IDLE_FLAGS},
- {4, 4, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
- {3, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
- {6, 6, 0, COEX_CALIBRATION_FLAGS},
- {3, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS},
- {6, 5, 0, COEX_CONNECTION_ESTAB_FLAGS},
- {4, 4, 0, COEX_ASSOCIATED_IDLE_FLAGS},
- {4, 4, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
- {4, 4, 0, COEX_ASSOC_AUTO_SCAN_FLAGS},
- {4, 4, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS},
- {1, 1, 0, COEX_RF_ON_FLAGS},
- {1, 1, 0, COEX_RF_OFF_FLAGS},
- {7, 7, 0, COEX_STAND_ALONE_DEBUG_FLAGS},
- {5, 4, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS},
- {1, 1, 0, COEX_RSRVD1_FLAGS},
- {1, 1, 0, COEX_RSRVD2_FLAGS}
-};
-
-int iwm_send_prio_table(struct iwm_priv *iwm)
-{
- struct iwm_coex_prio_table_cmd coex_table_cmd;
- u32 coex_enabled, mode_enabled;
-
- memset(&coex_table_cmd, 0, sizeof(struct iwm_coex_prio_table_cmd));
-
- coex_table_cmd.flags = COEX_FLAGS_STA_TABLE_VALID_MSK;
-
- switch (modparam_wiwi) {
- case COEX_MODE_XOR:
- case COEX_MODE_CM:
- coex_enabled = 1;
- break;
- default:
- coex_enabled = 0;
- break;
- }
-
- switch (iwm->conf.mode) {
- case UMAC_MODE_BSS:
- case UMAC_MODE_IBSS:
- mode_enabled = 1;
- break;
- default:
- mode_enabled = 0;
- break;
- }
-
- if (coex_enabled && mode_enabled) {
- coex_table_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK |
- COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK |
- COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK;
-
- switch (modparam_wiwi) {
- case COEX_MODE_XOR:
- memcpy(coex_table_cmd.sta_prio, iwm_sta_xor_prio_tbl,
- sizeof(iwm_sta_xor_prio_tbl));
- break;
- case COEX_MODE_CM:
- memcpy(coex_table_cmd.sta_prio, iwm_sta_cm_prio_tbl,
- sizeof(iwm_sta_cm_prio_tbl));
- break;
- default:
- IWM_ERR(iwm, "Invalid coex_mode 0x%x\n",
- modparam_wiwi);
- break;
- }
- } else
- IWM_WARN(iwm, "coexistense disabled\n");
-
- return iwm_send_lmac_ptrough_cmd(iwm, COEX_PRIORITY_TABLE_CMD,
- &coex_table_cmd,
- sizeof(struct iwm_coex_prio_table_cmd), 0);
-}
-
-int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested)
-{
- struct iwm_lmac_cal_cfg_cmd cal_cfg_cmd;
-
- memset(&cal_cfg_cmd, 0, sizeof(struct iwm_lmac_cal_cfg_cmd));
-
- cal_cfg_cmd.ucode_cfg.init.enable = cpu_to_le32(calib_requested);
- cal_cfg_cmd.ucode_cfg.init.start = cpu_to_le32(calib_requested);
- cal_cfg_cmd.ucode_cfg.init.send_res = cpu_to_le32(calib_requested);
- cal_cfg_cmd.ucode_cfg.flags =
- cpu_to_le32(CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK);
-
- return iwm_send_lmac_ptrough_cmd(iwm, CALIBRATION_CFG_CMD, &cal_cfg_cmd,
- sizeof(struct iwm_lmac_cal_cfg_cmd), 1);
-}
-
-int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested)
-{
- struct iwm_lmac_cal_cfg_cmd cal_cfg_cmd;
-
- memset(&cal_cfg_cmd, 0, sizeof(struct iwm_lmac_cal_cfg_cmd));
-
- cal_cfg_cmd.ucode_cfg.periodic.enable = cpu_to_le32(calib_requested);
- cal_cfg_cmd.ucode_cfg.periodic.start = cpu_to_le32(calib_requested);
-
- return iwm_send_lmac_ptrough_cmd(iwm, CALIBRATION_CFG_CMD, &cal_cfg_cmd,
- sizeof(struct iwm_lmac_cal_cfg_cmd), 0);
-}
-
-int iwm_store_rxiq_calib_result(struct iwm_priv *iwm)
-{
- struct iwm_calib_rxiq *rxiq;
- u8 *eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ);
- int grplen = sizeof(struct iwm_calib_rxiq_group);
-
- rxiq = kzalloc(sizeof(struct iwm_calib_rxiq), GFP_KERNEL);
- if (!rxiq) {
- IWM_ERR(iwm, "Couldn't alloc memory for RX IQ\n");
- return -ENOMEM;
- }
-
- eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ);
- if (IS_ERR(eeprom_rxiq)) {
- IWM_ERR(iwm, "Couldn't access EEPROM RX IQ entry\n");
- kfree(rxiq);
- return PTR_ERR(eeprom_rxiq);
- }
-
- iwm->calib_res[SHILOH_PHY_CALIBRATE_RX_IQ_CMD].buf = (u8 *)rxiq;
- iwm->calib_res[SHILOH_PHY_CALIBRATE_RX_IQ_CMD].size = sizeof(*rxiq);
-
- rxiq->hdr.opcode = SHILOH_PHY_CALIBRATE_RX_IQ_CMD;
- rxiq->hdr.first_grp = 0;
- rxiq->hdr.grp_num = 1;
- rxiq->hdr.all_data_valid = 1;
-
- memcpy(&rxiq->group[0], eeprom_rxiq, 4 * grplen);
- memcpy(&rxiq->group[4], eeprom_rxiq + 6 * grplen, grplen);
-
- return 0;
-}
-
-int iwm_send_calib_results(struct iwm_priv *iwm)
-{
- int i, ret = 0;
-
- for (i = PHY_CALIBRATE_OPCODES_NUM; i < CALIBRATION_CMD_NUM; i++) {
- if (test_bit(i - PHY_CALIBRATE_OPCODES_NUM,
- &iwm->calib_done_map)) {
- IWM_DBG_CMD(iwm, DBG,
- "Send calibration %d result\n", i);
- ret |= iwm_send_lmac_ptrough_cmd(iwm,
- REPLY_PHY_CALIBRATION_CMD,
- iwm->calib_res[i].buf,
- iwm->calib_res[i].size, 0);
-
- kfree(iwm->calib_res[i].buf);
- iwm->calib_res[i].buf = NULL;
- iwm->calib_res[i].size = 0;
- }
- }
-
- return ret;
-}
-
-int iwm_send_ct_kill_cfg(struct iwm_priv *iwm, u8 entry, u8 exit)
-{
- struct iwm_ct_kill_cfg_cmd cmd;
-
- cmd.entry_threshold = entry;
- cmd.exit_threshold = exit;
-
- return iwm_send_lmac_ptrough_cmd(iwm, REPLY_CT_KILL_CONFIG_CMD, &cmd,
- sizeof(struct iwm_ct_kill_cfg_cmd), 0);
-}
-
-int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp)
-{
- struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
- struct iwm_umac_cmd umac_cmd;
- struct iwm_umac_cmd_reset reset;
-
- reset.flags = reset_flags;
-
- umac_cmd.id = UMAC_CMD_OPCODE_RESET;
- umac_cmd.resp = resp;
-
- return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &reset,
- sizeof(struct iwm_umac_cmd_reset));
-}
-
-int iwm_umac_set_config_fix(struct iwm_priv *iwm, u16 tbl, u16 key, u32 value)
-{
- struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
- struct iwm_umac_cmd umac_cmd;
- struct iwm_umac_cmd_set_param_fix param;
-
- if ((tbl != UMAC_PARAM_TBL_CFG_FIX) &&
- (tbl != UMAC_PARAM_TBL_FA_CFG_FIX))
- return -EINVAL;
-
- umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_FIX;
- umac_cmd.resp = 0;
-
- param.tbl = cpu_to_le16(tbl);
- param.key = cpu_to_le16(key);
- param.value = cpu_to_le32(value);
-
- return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &param,
- sizeof(struct iwm_umac_cmd_set_param_fix));
-}
-
-int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key,
- void *payload, u16 payload_size)
-{
- struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
- struct iwm_umac_cmd umac_cmd;
- struct iwm_umac_cmd_set_param_var *param_hdr;
- u8 *param;
- int ret;
-
- param = kzalloc(payload_size +
- sizeof(struct iwm_umac_cmd_set_param_var), GFP_KERNEL);
- if (!param) {
- IWM_ERR(iwm, "Couldn't allocate param\n");
- return -ENOMEM;
- }
-
- param_hdr = (struct iwm_umac_cmd_set_param_var *)param;
-
- umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_VAR;
- umac_cmd.resp = 0;
-
- param_hdr->tbl = cpu_to_le16(UMAC_PARAM_TBL_CFG_VAR);
- param_hdr->key = cpu_to_le16(key);
- param_hdr->len = cpu_to_le16(payload_size);
- memcpy(param + sizeof(struct iwm_umac_cmd_set_param_var),
- payload, payload_size);
-
- ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, param,
- sizeof(struct iwm_umac_cmd_set_param_var) +
- payload_size);
- kfree(param);
-
- return ret;
-}
-
-int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags)
-{
- int ret;
-
- /* Use UMAC default values */
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_POWER_INDEX, iwm->conf.power_index);
- if (ret < 0)
- return ret;
-
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
- CFG_FRAG_THRESHOLD,
- iwm->conf.frag_threshold);
- if (ret < 0)
- return ret;
-
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_RTS_THRESHOLD,
- iwm->conf.rts_threshold);
- if (ret < 0)
- return ret;
-
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_CTS_TO_SELF, iwm->conf.cts_to_self);
- if (ret < 0)
- return ret;
-
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_WIRELESS_MODE,
- iwm->conf.wireless_mode);
- if (ret < 0)
- return ret;
-
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_COEX_MODE, modparam_wiwi);
- if (ret < 0)
- return ret;
-
- /*
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_ASSOCIATION_TIMEOUT,
- iwm->conf.assoc_timeout);
- if (ret < 0)
- return ret;
-
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_ROAM_TIMEOUT,
- iwm->conf.roam_timeout);
- if (ret < 0)
- return ret;
-
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_WIRELESS_MODE,
- WIRELESS_MODE_11A | WIRELESS_MODE_11G);
- if (ret < 0)
- return ret;
- */
-
- ret = iwm_umac_set_config_var(iwm, CFG_NET_ADDR,
- iwm_to_ndev(iwm)->dev_addr, ETH_ALEN);
- if (ret < 0)
- return ret;
-
- /* UMAC PM static configurations */
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_PM_LEGACY_RX_TIMEOUT, 0x12C);
- if (ret < 0)
- return ret;
-
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_PM_LEGACY_TX_TIMEOUT, 0x15E);
- if (ret < 0)
- return ret;
-
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_PM_CTRL_FLAGS, 0x1);
- if (ret < 0)
- return ret;
-
- ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_PM_KEEP_ALIVE_IN_BEACONS, 0x80);
- if (ret < 0)
- return ret;
-
- /* reset UMAC */
- ret = iwm_send_umac_reset(iwm, reset_flags, 1);
- if (ret < 0)
- return ret;
-
- ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_RESET, IWM_SRC_UMAC,
- WAIT_NOTIF_TIMEOUT);
- if (ret) {
- IWM_ERR(iwm, "Wait for UMAC RESET timeout\n");
- return ret;
- }
-
- return ret;
-}
-
-int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id)
-{
- struct iwm_udma_wifi_cmd udma_cmd;
- struct iwm_umac_cmd umac_cmd;
- struct iwm_tx_info *tx_info = skb_to_tx_info(skb);
-
- udma_cmd.eop = 1; /* always set eop for non-concatenated Tx */
- udma_cmd.credit_group = pool_id;
- udma_cmd.ra_tid = tx_info->sta << 4 | tx_info->tid;
- udma_cmd.lmac_offset = 0;
-
- umac_cmd.id = REPLY_TX;
- umac_cmd.color = tx_info->color;
- umac_cmd.resp = 0;
-
- return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd,
- skb->data, skb->len);
-}
-
-static int iwm_target_read(struct iwm_priv *iwm, __le32 address,
- u8 *response, u32 resp_size)
-{
- struct iwm_udma_nonwifi_cmd target_cmd;
- struct iwm_nonwifi_cmd *cmd;
- u16 seq_num;
- int ret = 0;
-
- target_cmd.opcode = UMAC_HDI_OUT_OPCODE_READ;
- target_cmd.addr = address;
- target_cmd.op1_sz = cpu_to_le32(resp_size);
- target_cmd.op2 = 0;
- target_cmd.handle_by_hw = 0;
- target_cmd.resp = 1;
- target_cmd.eop = 1;
-
- ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't send READ command\n");
- return ret;
- }
-
- /* When succeeding, the send_target routine returns the seq number */
- seq_num = ret;
-
- ret = wait_event_interruptible_timeout(iwm->nonwifi_queue,
- (cmd = iwm_get_pending_nonwifi_cmd(iwm, seq_num,
- UMAC_HDI_OUT_OPCODE_READ)) != NULL,
- 2 * HZ);
-
- if (!ret) {
- IWM_ERR(iwm, "Didn't receive a target READ answer\n");
- return ret;
- }
-
- memcpy(response, cmd->buf.hdr + sizeof(struct iwm_udma_in_hdr),
- resp_size);
-
- kfree(cmd);
-
- return 0;
-}
-
-int iwm_read_mac(struct iwm_priv *iwm, u8 *mac)
-{
- int ret;
- u8 mac_align[ALIGN(ETH_ALEN, 8)];
-
- ret = iwm_target_read(iwm, cpu_to_le32(WICO_MAC_ADDRESS_ADDR),
- mac_align, sizeof(mac_align));
- if (ret)
- return ret;
-
- if (is_valid_ether_addr(mac_align))
- memcpy(mac, mac_align, ETH_ALEN);
- else {
- IWM_ERR(iwm, "Invalid EEPROM MAC\n");
- memcpy(mac, iwm->conf.mac_addr, ETH_ALEN);
- get_random_bytes(&mac[3], 3);
- }
-
- return 0;
-}
-
-static int iwm_check_profile(struct iwm_priv *iwm)
-{
- if (!iwm->umac_profile_active)
- return -EAGAIN;
-
- if (iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_40 &&
- iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_104 &&
- iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_TKIP &&
- iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_CCMP) {
- IWM_ERR(iwm, "Wrong unicast cipher: 0x%x\n",
- iwm->umac_profile->sec.ucast_cipher);
- return -EAGAIN;
- }
-
- if (iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_WEP_40 &&
- iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_WEP_104 &&
- iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_TKIP &&
- iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_CCMP) {
- IWM_ERR(iwm, "Wrong multicast cipher: 0x%x\n",
- iwm->umac_profile->sec.mcast_cipher);
- return -EAGAIN;
- }
-
- if ((iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_40 ||
- iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_104) &&
- (iwm->umac_profile->sec.ucast_cipher !=
- iwm->umac_profile->sec.mcast_cipher)) {
- IWM_ERR(iwm, "Unicast and multicast ciphers differ for WEP\n");
- }
-
- return 0;
-}
-
-int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx)
-{
- struct iwm_umac_tx_key_id tx_key_id;
- int ret;
-
- ret = iwm_check_profile(iwm);
- if (ret < 0)
- return ret;
-
- /* UMAC only allows to set default key for WEP and auth type is
- * NOT 802.1X or RSNA. */
- if ((iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_40 &&
- iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_104) ||
- iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_8021X ||
- iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_RSNA_PSK)
- return 0;
-
- tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID;
- tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) -
- sizeof(struct iwm_umac_wifi_if));
-
- tx_key_id.key_idx = key_idx;
-
- return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1);
-}
-
-int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key)
-{
- int ret = 0;
- u8 cmd[64], *sta_addr, *key_data, key_len;
- s8 key_idx;
- u16 cmd_size = 0;
- struct iwm_umac_key_hdr *key_hdr = &key->hdr;
- struct iwm_umac_key_wep40 *wep40 = (struct iwm_umac_key_wep40 *)cmd;
- struct iwm_umac_key_wep104 *wep104 = (struct iwm_umac_key_wep104 *)cmd;
- struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd;
- struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd;
-
- if (!remove) {
- ret = iwm_check_profile(iwm);
- if (ret < 0)
- return ret;
- }
-
- sta_addr = key->hdr.mac;
- key_data = key->key;
- key_len = key->key_len;
- key_idx = key->hdr.key_idx;
-
- if (!remove) {
- u8 auth_type = iwm->umac_profile->sec.auth_type;
-
- IWM_DBG_WEXT(iwm, DBG, "key_idx:%d\n", key_idx);
- IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len);
- IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n",
- key_hdr->mac, key_hdr->key_idx, key_hdr->multicast);
-
- IWM_DBG_WEXT(iwm, DBG, "profile: mcast:0x%x, ucast:0x%x\n",
- iwm->umac_profile->sec.mcast_cipher,
- iwm->umac_profile->sec.ucast_cipher);
- IWM_DBG_WEXT(iwm, DBG, "profile: auth_type:0x%x, flags:0x%x\n",
- iwm->umac_profile->sec.auth_type,
- iwm->umac_profile->sec.flags);
-
- switch (key->cipher) {
- case WLAN_CIPHER_SUITE_WEP40:
- wep40->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP40_KEY;
- wep40->hdr.buf_size =
- cpu_to_le16(sizeof(struct iwm_umac_key_wep40) -
- sizeof(struct iwm_umac_wifi_if));
-
- memcpy(&wep40->key_hdr, key_hdr,
- sizeof(struct iwm_umac_key_hdr));
- memcpy(wep40->key, key_data, key_len);
- wep40->static_key =
- !!((auth_type != UMAC_AUTH_TYPE_8021X) &&
- (auth_type != UMAC_AUTH_TYPE_RSNA_PSK));
-
- cmd_size = sizeof(struct iwm_umac_key_wep40);
- break;
-
- case WLAN_CIPHER_SUITE_WEP104:
- wep104->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP104_KEY;
- wep104->hdr.buf_size =
- cpu_to_le16(sizeof(struct iwm_umac_key_wep104) -
- sizeof(struct iwm_umac_wifi_if));
-
- memcpy(&wep104->key_hdr, key_hdr,
- sizeof(struct iwm_umac_key_hdr));
- memcpy(wep104->key, key_data, key_len);
- wep104->static_key =
- !!((auth_type != UMAC_AUTH_TYPE_8021X) &&
- (auth_type != UMAC_AUTH_TYPE_RSNA_PSK));
-
- cmd_size = sizeof(struct iwm_umac_key_wep104);
- break;
-
- case WLAN_CIPHER_SUITE_CCMP:
- key_hdr->key_idx++;
- ccmp->hdr.oid = UMAC_WIFI_IF_CMD_ADD_CCMP_KEY;
- ccmp->hdr.buf_size =
- cpu_to_le16(sizeof(struct iwm_umac_key_ccmp) -
- sizeof(struct iwm_umac_wifi_if));
-
- memcpy(&ccmp->key_hdr, key_hdr,
- sizeof(struct iwm_umac_key_hdr));
-
- memcpy(ccmp->key, key_data, key_len);
-
- if (key->seq_len)
- memcpy(ccmp->iv_count, key->seq, key->seq_len);
-
- cmd_size = sizeof(struct iwm_umac_key_ccmp);
- break;
-
- case WLAN_CIPHER_SUITE_TKIP:
- key_hdr->key_idx++;
- tkip->hdr.oid = UMAC_WIFI_IF_CMD_ADD_TKIP_KEY;
- tkip->hdr.buf_size =
- cpu_to_le16(sizeof(struct iwm_umac_key_tkip) -
- sizeof(struct iwm_umac_wifi_if));
-
- memcpy(&tkip->key_hdr, key_hdr,
- sizeof(struct iwm_umac_key_hdr));
-
- memcpy(tkip->tkip_key, key_data, IWM_TKIP_KEY_SIZE);
- memcpy(tkip->mic_tx_key, key_data + IWM_TKIP_KEY_SIZE,
- IWM_TKIP_MIC_SIZE);
- memcpy(tkip->mic_rx_key,
- key_data + IWM_TKIP_KEY_SIZE + IWM_TKIP_MIC_SIZE,
- IWM_TKIP_MIC_SIZE);
-
- if (key->seq_len)
- memcpy(ccmp->iv_count, key->seq, key->seq_len);
-
- cmd_size = sizeof(struct iwm_umac_key_tkip);
- break;
-
- default:
- return -ENOTSUPP;
- }
-
- if ((key->cipher == WLAN_CIPHER_SUITE_TKIP) ||
- (key->cipher == WLAN_CIPHER_SUITE_CCMP))
- /*
- * UGLY_UGLY_UGLY
- * Copied HACK from the MWG driver.
- * Without it, the key is set before the second
- * EAPOL frame is sent, and the latter is thus
- * encrypted.
- */
- schedule_timeout_interruptible(usecs_to_jiffies(300));
-
- ret = iwm_send_wifi_if_cmd(iwm, cmd, cmd_size, 1);
- } else {
- struct iwm_umac_key_remove key_remove;
-
- IWM_DBG_WEXT(iwm, ERR, "Removing key_idx:%d\n", key_idx);
-
- key_remove.hdr.oid = UMAC_WIFI_IF_CMD_REMOVE_KEY;
- key_remove.hdr.buf_size =
- cpu_to_le16(sizeof(struct iwm_umac_key_remove) -
- sizeof(struct iwm_umac_wifi_if));
- memcpy(&key_remove.key_hdr, key_hdr,
- sizeof(struct iwm_umac_key_hdr));
-
- ret = iwm_send_wifi_if_cmd(iwm, &key_remove,
- sizeof(struct iwm_umac_key_remove),
- 1);
- if (ret)
- return ret;
-
- iwm->keys[key_idx].key_len = 0;
- }
-
- return ret;
-}
-
-
-int iwm_send_mlme_profile(struct iwm_priv *iwm)
-{
- int ret;
- struct iwm_umac_profile profile;
-
- memcpy(&profile, iwm->umac_profile, sizeof(profile));
-
- profile.hdr.oid = UMAC_WIFI_IF_CMD_SET_PROFILE;
- profile.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_profile) -
- sizeof(struct iwm_umac_wifi_if));
-
- ret = iwm_send_wifi_if_cmd(iwm, &profile, sizeof(profile), 1);
- if (ret) {
- IWM_ERR(iwm, "Send profile command failed\n");
- return ret;
- }
-
- set_bit(IWM_STATUS_SME_CONNECTING, &iwm->status);
- return 0;
-}
-
-int __iwm_invalidate_mlme_profile(struct iwm_priv *iwm)
-{
- struct iwm_umac_invalidate_profile invalid;
-
- invalid.hdr.oid = UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE;
- invalid.hdr.buf_size =
- cpu_to_le16(sizeof(struct iwm_umac_invalidate_profile) -
- sizeof(struct iwm_umac_wifi_if));
-
- invalid.reason = WLAN_REASON_UNSPECIFIED;
-
- return iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1);
-}
-
-int iwm_invalidate_mlme_profile(struct iwm_priv *iwm)
-{
- int ret;
-
- ret = __iwm_invalidate_mlme_profile(iwm);
- if (ret)
- return ret;
-
- ret = wait_event_interruptible_timeout(iwm->mlme_queue,
- (iwm->umac_profile_active == 0), 5 * HZ);
-
- return ret ? 0 : -EBUSY;
-}
-
-int iwm_tx_power_trigger(struct iwm_priv *iwm)
-{
- struct iwm_umac_pwr_trigger pwr_trigger;
-
- pwr_trigger.hdr.oid = UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER;
- pwr_trigger.hdr.buf_size =
- cpu_to_le16(sizeof(struct iwm_umac_pwr_trigger) -
- sizeof(struct iwm_umac_wifi_if));
-
-
- return iwm_send_wifi_if_cmd(iwm, &pwr_trigger, sizeof(pwr_trigger), 1);
-}
-
-int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags)
-{
- struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
- struct iwm_umac_cmd umac_cmd;
- struct iwm_umac_cmd_stats_req stats_req;
-
- stats_req.flags = cpu_to_le32(flags);
-
- umac_cmd.id = UMAC_CMD_OPCODE_STATISTIC_REQUEST;
- umac_cmd.resp = 0;
-
- return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &stats_req,
- sizeof(struct iwm_umac_cmd_stats_req));
-}
-
-int iwm_send_umac_channel_list(struct iwm_priv *iwm)
-{
- struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
- struct iwm_umac_cmd umac_cmd;
- struct iwm_umac_cmd_get_channel_list *ch_list;
- int size = sizeof(struct iwm_umac_cmd_get_channel_list) +
- sizeof(struct iwm_umac_channel_info) * 4;
- int ret;
-
- ch_list = kzalloc(size, GFP_KERNEL);
- if (!ch_list) {
- IWM_ERR(iwm, "Couldn't allocate channel list cmd\n");
- return -ENOMEM;
- }
-
- ch_list->ch[0].band = UMAC_BAND_2GHZ;
- ch_list->ch[0].type = UMAC_CHANNEL_WIDTH_20MHZ;
- ch_list->ch[0].flags = UMAC_CHANNEL_FLAG_VALID;
-
- ch_list->ch[1].band = UMAC_BAND_5GHZ;
- ch_list->ch[1].type = UMAC_CHANNEL_WIDTH_20MHZ;
- ch_list->ch[1].flags = UMAC_CHANNEL_FLAG_VALID;
-
- ch_list->ch[2].band = UMAC_BAND_2GHZ;
- ch_list->ch[2].type = UMAC_CHANNEL_WIDTH_20MHZ;
- ch_list->ch[2].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS;
-
- ch_list->ch[3].band = UMAC_BAND_5GHZ;
- ch_list->ch[3].type = UMAC_CHANNEL_WIDTH_20MHZ;
- ch_list->ch[3].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS;
-
- ch_list->count = cpu_to_le16(4);
-
- umac_cmd.id = UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST;
- umac_cmd.resp = 1;
-
- ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, ch_list, size);
-
- kfree(ch_list);
-
- return ret;
-}
-
-int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
- int ssid_num)
-{
- struct iwm_umac_cmd_scan_request req;
- int i, ret;
-
- memset(&req, 0, sizeof(struct iwm_umac_cmd_scan_request));
-
- req.hdr.oid = UMAC_WIFI_IF_CMD_SCAN_REQUEST;
- req.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_cmd_scan_request)
- - sizeof(struct iwm_umac_wifi_if));
- req.type = UMAC_WIFI_IF_SCAN_TYPE_USER;
- req.timeout = 2;
- req.seq_num = iwm->scan_id;
- req.ssid_num = min(ssid_num, UMAC_WIFI_IF_PROBE_OPTION_MAX);
-
- for (i = 0; i < req.ssid_num; i++) {
- memcpy(req.ssids[i].ssid, ssids[i].ssid, ssids[i].ssid_len);
- req.ssids[i].ssid_len = ssids[i].ssid_len;
- }
-
- ret = iwm_send_wifi_if_cmd(iwm, &req, sizeof(req), 0);
- if (ret) {
- IWM_ERR(iwm, "Couldn't send scan request\n");
- return ret;
- }
-
- iwm->scan_id = (iwm->scan_id + 1) % IWM_SCAN_ID_MAX;
-
- return 0;
-}
-
-int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len)
-{
- struct cfg80211_ssid one_ssid;
-
- if (test_and_set_bit(IWM_STATUS_SCANNING, &iwm->status))
- return 0;
-
- one_ssid.ssid_len = min(ssid_len, IEEE80211_MAX_SSID_LEN);
- memcpy(&one_ssid.ssid, ssid, one_ssid.ssid_len);
-
- return iwm_scan_ssids(iwm, &one_ssid, 1);
-}
-
-int iwm_target_reset(struct iwm_priv *iwm)
-{
- struct iwm_udma_nonwifi_cmd target_cmd;
-
- target_cmd.opcode = UMAC_HDI_OUT_OPCODE_REBOOT;
- target_cmd.addr = 0;
- target_cmd.op1_sz = 0;
- target_cmd.op2 = 0;
- target_cmd.handle_by_hw = 0;
- target_cmd.resp = 0;
- target_cmd.eop = 1;
-
- return iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
-}
-
-int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm,
- struct iwm_umac_notif_stop_resume_tx *ntf)
-{
- struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
- struct iwm_umac_cmd umac_cmd;
- struct iwm_umac_cmd_stop_resume_tx stp_res_cmd;
- struct iwm_sta_info *sta_info;
- u8 sta_id = STA_ID_N_COLOR_ID(ntf->sta_id);
- int i;
-
- sta_info = &iwm->sta_table[sta_id];
- if (!sta_info->valid) {
- IWM_ERR(iwm, "Invalid STA: %d\n", sta_id);
- return -EINVAL;
- }
-
- umac_cmd.id = UMAC_CMD_OPCODE_STOP_RESUME_STA_TX;
- umac_cmd.resp = 0;
-
- stp_res_cmd.flags = ntf->flags;
- stp_res_cmd.sta_id = ntf->sta_id;
- stp_res_cmd.stop_resume_tid_msk = ntf->stop_resume_tid_msk;
- for (i = 0; i < IWM_UMAC_TID_NR; i++)
- stp_res_cmd.last_seq_num[i] =
- sta_info->tid_info[i].last_seq_num;
-
- return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &stp_res_cmd,
- sizeof(struct iwm_umac_cmd_stop_resume_tx));
-
-}
-
-int iwm_send_pmkid_update(struct iwm_priv *iwm,
- struct cfg80211_pmksa *pmksa, u32 command)
-{
- struct iwm_umac_pmkid_update update;
- int ret;
-
- memset(&update, 0, sizeof(struct iwm_umac_pmkid_update));
-
- update.hdr.oid = UMAC_WIFI_IF_CMD_PMKID_UPDATE;
- update.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_pmkid_update) -
- sizeof(struct iwm_umac_wifi_if));
-
- update.command = cpu_to_le32(command);
- if (pmksa->bssid)
- memcpy(&update.bssid, pmksa->bssid, ETH_ALEN);
- if (pmksa->pmkid)
- memcpy(&update.pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
-
- ret = iwm_send_wifi_if_cmd(iwm, &update,
- sizeof(struct iwm_umac_pmkid_update), 0);
- if (ret) {
- IWM_ERR(iwm, "PMKID update command failed\n");
- return ret;
- }
-
- return 0;
-}
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h
deleted file mode 100644
index 6421689f5e8e..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/commands.h
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-#ifndef __IWM_COMMANDS_H__
-#define __IWM_COMMANDS_H__
-
-#include <linux/ieee80211.h>
-
-#define IWM_BARKER_REBOOT_NOTIFICATION 0xF
-#define IWM_ACK_BARKER_NOTIFICATION 0x10
-
-/* UMAC commands */
-#define UMAC_RST_CTRL_FLG_LARC_CLK_EN 0x0001
-#define UMAC_RST_CTRL_FLG_LARC_RESET 0x0002
-#define UMAC_RST_CTRL_FLG_FUNC_RESET 0x0004
-#define UMAC_RST_CTRL_FLG_DEV_RESET 0x0008
-#define UMAC_RST_CTRL_FLG_WIFI_CORE_EN 0x0010
-#define UMAC_RST_CTRL_FLG_WIFI_LINK_EN 0x0040
-#define UMAC_RST_CTRL_FLG_WIFI_MLME_EN 0x0080
-#define UMAC_RST_CTRL_FLG_NVM_RELOAD 0x0100
-
-struct iwm_umac_cmd_reset {
- __le32 flags;
-} __packed;
-
-#define UMAC_PARAM_TBL_ORD_FIX 0x0
-#define UMAC_PARAM_TBL_ORD_VAR 0x1
-#define UMAC_PARAM_TBL_CFG_FIX 0x2
-#define UMAC_PARAM_TBL_CFG_VAR 0x3
-#define UMAC_PARAM_TBL_BSS_TRK 0x4
-#define UMAC_PARAM_TBL_FA_CFG_FIX 0x5
-#define UMAC_PARAM_TBL_STA 0x6
-#define UMAC_PARAM_TBL_CHN 0x7
-#define UMAC_PARAM_TBL_STATISTICS 0x8
-
-/* fast access table */
-enum {
- CFG_FRAG_THRESHOLD = 0,
- CFG_FRAME_RETRY_LIMIT,
- CFG_OS_QUEUE_UTIL_TH,
- CFG_RX_FILTER,
- /* <-- LAST --> */
- FAST_ACCESS_CFG_TBL_FIX_LAST
-};
-
-/* fixed size table */
-enum {
- CFG_POWER_INDEX = 0,
- CFG_PM_LEGACY_RX_TIMEOUT,
- CFG_PM_LEGACY_TX_TIMEOUT,
- CFG_PM_CTRL_FLAGS,
- CFG_PM_KEEP_ALIVE_IN_BEACONS,
- CFG_BT_ON_THRESHOLD,
- CFG_RTS_THRESHOLD,
- CFG_CTS_TO_SELF,
- CFG_COEX_MODE,
- CFG_WIRELESS_MODE,
- CFG_ASSOCIATION_TIMEOUT,
- CFG_ROAM_TIMEOUT,
- CFG_CAPABILITY_SUPPORTED_RATES,
- CFG_SCAN_ALLOWED_UNASSOC_FLAGS,
- CFG_SCAN_ALLOWED_MAIN_ASSOC_FLAGS,
- CFG_SCAN_ALLOWED_PAN_ASSOC_FLAGS,
- CFG_SCAN_INTERNAL_PERIODIC_ENABLED,
- CFG_SCAN_IMM_INTERNAL_PERIODIC_SCAN_ON_INIT,
- CFG_SCAN_DEFAULT_PERIODIC_FREQ_SEC,
- CFG_SCAN_NUM_PASSIVE_CHAN_PER_PARTIAL_SCAN,
- CFG_TLC_SUPPORTED_TX_HT_RATES,
- CFG_TLC_SUPPORTED_TX_RATES,
- CFG_TLC_SPATIAL_STREAM_SUPPORTED,
- CFG_TLC_RETRY_PER_RATE,
- CFG_TLC_RETRY_PER_HT_RATE,
- CFG_TLC_FIXED_MCS,
- CFG_TLC_CONTROL_FLAGS,
- CFG_TLC_SR_MIN_FAIL,
- CFG_TLC_SR_MIN_PASS,
- CFG_TLC_HT_STAY_IN_COL_PASS_THRESH,
- CFG_TLC_HT_STAY_IN_COL_FAIL_THRESH,
- CFG_TLC_LEGACY_STAY_IN_COL_PASS_THRESH,
- CFG_TLC_LEGACY_STAY_IN_COL_FAIL_THRESH,
- CFG_TLC_HT_FLUSH_STATS_PACKETS,
- CFG_TLC_LEGACY_FLUSH_STATS_PACKETS,
- CFG_TLC_LEGACY_FLUSH_STATS_MS,
- CFG_TLC_HT_FLUSH_STATS_MS,
- CFG_TLC_STAY_IN_COL_TIME_OUT,
- CFG_TLC_AGG_SHORT_LIM,
- CFG_TLC_AGG_LONG_LIM,
- CFG_TLC_HT_SR_NO_DECREASE,
- CFG_TLC_LEGACY_SR_NO_DECREASE,
- CFG_TLC_SR_FORCE_DECREASE,
- CFG_TLC_SR_ALLOW_INCREASE,
- CFG_TLC_AGG_SET_LONG,
- CFG_TLC_AUTO_AGGREGATION,
- CFG_TLC_AGG_THRESHOLD,
- CFG_TLC_TID_LOAD_THRESHOLD,
- CFG_TLC_BLOCK_ACK_TIMEOUT,
- CFG_TLC_NO_BA_COUNTED_AS_ONE,
- CFG_TLC_NUM_BA_STREAMS_ALLOWED,
- CFG_TLC_NUM_BA_STREAMS_PRESENT,
- CFG_TLC_RENEW_ADDBA_DELAY,
- CFG_TLC_NUM_OF_MULTISEC_TO_COUN_LOAD,
- CFG_TLC_IS_STABLE_IN_HT,
- CFG_TLC_SR_SIC_1ST_FAIL,
- CFG_TLC_SR_SIC_1ST_PASS,
- CFG_TLC_SR_SIC_TOTAL_FAIL,
- CFG_TLC_SR_SIC_TOTAL_PASS,
- CFG_RLC_CHAIN_CTRL,
- CFG_TRK_TABLE_OP_MODE,
- CFG_TRK_TABLE_RSSI_THRESHOLD,
- CFG_TX_PWR_TARGET, /* Used By xVT */
- CFG_TX_PWR_LIMIT_USR,
- CFG_TX_PWR_LIMIT_BSS, /* 11d limit */
- CFG_TX_PWR_LIMIT_BSS_CONSTRAINT, /* 11h constraint */
- CFG_TX_PWR_MODE,
- CFG_MLME_DBG_NOTIF_BLOCK,
- CFG_BT_OFF_BECONS_INTERVALS,
- CFG_BT_FRAG_DURATION,
- CFG_ACTIVE_CHAINS,
- CFG_CALIB_CTRL,
- CFG_CAPABILITY_SUPPORTED_HT_RATES,
- CFG_HT_MAC_PARAM_INFO,
- CFG_MIMO_PS_MODE,
- CFG_HT_DEFAULT_CAPABILIES_INFO,
- CFG_LED_SC_RESOLUTION_FACTOR,
- CFG_PTAM_ENERGY_CCK_DET_DEFAULT,
- CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_DEFAULT,
- CFG_PTAM_CORR40_4_TH_ADD_MIN_DEFAULT,
- CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_DEFAULT,
- CFG_PTAM_CORR32_4_TH_ADD_MIN_DEFAULT,
- CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_DEFAULT,
- CFG_PTAM_CORR32_1_TH_ADD_MIN_DEFAULT,
- CFG_PTAM_ENERGY_CCK_DET_MIN_VAL,
- CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_MIN_VAL,
- CFG_PTAM_CORR40_4_TH_ADD_MIN_MIN_VAL,
- CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_MIN_VAL,
- CFG_PTAM_CORR32_4_TH_ADD_MIN_MIN_VAL,
- CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_MIN_VAL,
- CFG_PTAM_CORR32_1_TH_ADD_MIN_MIN_VAL,
- CFG_PTAM_ENERGY_CCK_DET_MAX_VAL,
- CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_MAX_VAL,
- CFG_PTAM_CORR40_4_TH_ADD_MIN_MAX_VAL,
- CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_MAX_VAL,
- CFG_PTAM_CORR32_4_TH_ADD_MIN_MAX_VAL,
- CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_MAX_VAL,
- CFG_PTAM_CORR32_1_TH_ADD_MIN_MAX_VAL,
- CFG_PTAM_ENERGY_CCK_DET_STEP_VAL,
- CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_STEP_VAL,
- CFG_PTAM_CORR40_4_TH_ADD_MIN_STEP_VAL,
- CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_STEP_VAL,
- CFG_PTAM_CORR32_4_TH_ADD_MIN_STEP_VAL,
- CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_STEP_VAL,
- CFG_PTAM_CORR32_1_TH_ADD_MIN_STEP_VAL,
- CFG_PTAM_LINK_SENS_FA_OFDM_MAX,
- CFG_PTAM_LINK_SENS_FA_OFDM_MIN,
- CFG_PTAM_LINK_SENS_FA_CCK_MAX,
- CFG_PTAM_LINK_SENS_FA_CCK_MIN,
- CFG_PTAM_LINK_SENS_NRG_DIFF,
- CFG_PTAM_LINK_SENS_NRG_MARGIN,
- CFG_PTAM_LINK_SENS_MAX_NUMBER_OF_TIMES_IN_CCK_NO_FA,
- CFG_PTAM_LINK_SENS_AUTO_CORR_MAX_TH_CCK,
- CFG_AGG_MGG_TID_LOAD_ADDBA_THRESHOLD,
- CFG_AGG_MGG_TID_LOAD_DELBA_THRESHOLD,
- CFG_AGG_MGG_ADDBA_BUF_SIZE,
- CFG_AGG_MGG_ADDBA_INACTIVE_TIMEOUT,
- CFG_AGG_MGG_ADDBA_DEBUG_FLAGS,
- CFG_SCAN_PERIODIC_RSSI_HIGH_THRESHOLD,
- CFG_SCAN_PERIODIC_COEF_RSSI_HIGH,
- CFG_11D_ENABLED,
- CFG_11H_FEATURE_FLAGS,
-
- /* <-- LAST --> */
- CFG_TBL_FIX_LAST
-};
-
-/* variable size table */
-enum {
- CFG_NET_ADDR = 0,
- CFG_LED_PATTERN_TABLE,
-
- /* <-- LAST --> */
- CFG_TBL_VAR_LAST
-};
-
-struct iwm_umac_cmd_set_param_fix {
- __le16 tbl;
- __le16 key;
- __le32 value;
-} __packed;
-
-struct iwm_umac_cmd_set_param_var {
- __le16 tbl;
- __le16 key;
- __le16 len;
- __le16 reserved;
-} __packed;
-
-struct iwm_umac_cmd_get_param {
- __le16 tbl;
- __le16 key;
-} __packed;
-
-struct iwm_umac_cmd_get_param_resp {
- __le16 tbl;
- __le16 key;
- __le16 len;
- __le16 reserved;
-} __packed;
-
-struct iwm_umac_cmd_eeprom_proxy_hdr {
- __le32 type;
- __le32 offset;
- __le32 len;
-} __packed;
-
-struct iwm_umac_cmd_eeprom_proxy {
- struct iwm_umac_cmd_eeprom_proxy_hdr hdr;
- u8 buf[0];
-} __packed;
-
-#define IWM_UMAC_CMD_EEPROM_TYPE_READ 0x1
-#define IWM_UMAC_CMD_EEPROM_TYPE_WRITE 0x2
-
-#define UMAC_CHANNEL_FLAG_VALID BIT(0)
-#define UMAC_CHANNEL_FLAG_IBSS BIT(1)
-#define UMAC_CHANNEL_FLAG_ACTIVE BIT(3)
-#define UMAC_CHANNEL_FLAG_RADAR BIT(4)
-#define UMAC_CHANNEL_FLAG_DFS BIT(7)
-
-struct iwm_umac_channel_info {
- u8 band;
- u8 type;
- u8 reserved;
- u8 flags;
- __le32 channels_mask;
-} __packed;
-
-struct iwm_umac_cmd_get_channel_list {
- __le16 count;
- __le16 reserved;
- struct iwm_umac_channel_info ch[0];
-} __packed;
-
-
-/* UMAC WiFi interface commands */
-
-/* Coexistence mode */
-#define COEX_MODE_SA 0x1
-#define COEX_MODE_XOR 0x2
-#define COEX_MODE_CM 0x3
-#define COEX_MODE_MAX 0x4
-
-/* Wireless mode */
-#define WIRELESS_MODE_11A 0x1
-#define WIRELESS_MODE_11G 0x2
-#define WIRELESS_MODE_11N 0x4
-
-#define UMAC_PROFILE_EX_IE_REQUIRED 0x1
-#define UMAC_PROFILE_QOS_ALLOWED 0x2
-
-/* Scanning */
-#define UMAC_WIFI_IF_PROBE_OPTION_MAX 10
-
-#define UMAC_WIFI_IF_SCAN_TYPE_USER 0x0
-#define UMAC_WIFI_IF_SCAN_TYPE_UMAC_RESERVED 0x1
-#define UMAC_WIFI_IF_SCAN_TYPE_HOST_PERIODIC 0x2
-#define UMAC_WIFI_IF_SCAN_TYPE_MAX 0x3
-
-struct iwm_umac_ssid {
- u8 ssid_len;
- u8 ssid[IEEE80211_MAX_SSID_LEN];
- u8 reserved[3];
-} __packed;
-
-struct iwm_umac_cmd_scan_request {
- struct iwm_umac_wifi_if hdr;
- __le32 type; /* UMAC_WIFI_IF_SCAN_TYPE_* */
- u8 ssid_num;
- u8 seq_num;
- u8 timeout; /* In seconds */
- u8 reserved;
- struct iwm_umac_ssid ssids[UMAC_WIFI_IF_PROBE_OPTION_MAX];
-} __packed;
-
-#define UMAC_CIPHER_TYPE_NONE 0xFF
-#define UMAC_CIPHER_TYPE_USE_GROUPCAST 0x00
-#define UMAC_CIPHER_TYPE_WEP_40 0x01
-#define UMAC_CIPHER_TYPE_WEP_104 0x02
-#define UMAC_CIPHER_TYPE_TKIP 0x04
-#define UMAC_CIPHER_TYPE_CCMP 0x08
-
-/* Supported authentication types - bitmap */
-#define UMAC_AUTH_TYPE_OPEN 0x00
-#define UMAC_AUTH_TYPE_LEGACY_PSK 0x01
-#define UMAC_AUTH_TYPE_8021X 0x02
-#define UMAC_AUTH_TYPE_RSNA_PSK 0x04
-
-/* iwm_umac_security.flag is WPA supported -- bits[0:0] */
-#define UMAC_SEC_FLG_WPA_ON_POS 0
-#define UMAC_SEC_FLG_WPA_ON_SEED 1
-#define UMAC_SEC_FLG_WPA_ON_MSK (UMAC_SEC_FLG_WPA_ON_SEED << \
- UMAC_SEC_FLG_WPA_ON_POS)
-
-/* iwm_umac_security.flag is WPA2 supported -- bits [1:1] */
-#define UMAC_SEC_FLG_RSNA_ON_POS 1
-#define UMAC_SEC_FLG_RSNA_ON_SEED 1
-#define UMAC_SEC_FLG_RSNA_ON_MSK (UMAC_SEC_FLG_RSNA_ON_SEED << \
- UMAC_SEC_FLG_RSNA_ON_POS)
-
-/* iwm_umac_security.flag is WSC mode on -- bits [2:2] */
-#define UMAC_SEC_FLG_WSC_ON_POS 2
-#define UMAC_SEC_FLG_WSC_ON_SEED 1
-#define UMAC_SEC_FLG_WSC_ON_MSK (UMAC_SEC_FLG_WSC_ON_SEED << \
- UMAC_SEC_FLG_WSC_ON_POS)
-
-
-/* Legacy profile can use only WEP40 and WEP104 for encryption and
- * OPEN or PSK for authentication */
-#define UMAC_SEC_FLG_LEGACY_PROFILE 0
-
-struct iwm_umac_security {
- u8 auth_type;
- u8 ucast_cipher;
- u8 mcast_cipher;
- u8 flags;
-} __packed;
-
-struct iwm_umac_ibss {
- u8 beacon_interval; /* in millisecond */
- u8 atim; /* in millisecond */
- s8 join_only;
- u8 band;
- u8 channel;
- u8 reserved[3];
-} __packed;
-
-#define UMAC_MODE_BSS 0
-#define UMAC_MODE_IBSS 1
-
-#define UMAC_BSSID_MAX 4
-
-struct iwm_umac_profile {
- struct iwm_umac_wifi_if hdr;
- __le32 mode;
- struct iwm_umac_ssid ssid;
- u8 bssid[UMAC_BSSID_MAX][ETH_ALEN];
- struct iwm_umac_security sec;
- struct iwm_umac_ibss ibss;
- __le32 channel_2ghz;
- __le32 channel_5ghz;
- __le16 flags;
- u8 wireless_mode;
- u8 bss_num;
-} __packed;
-
-struct iwm_umac_invalidate_profile {
- struct iwm_umac_wifi_if hdr;
- u8 reason;
- u8 reserved[3];
-} __packed;
-
-/* Encryption key commands */
-struct iwm_umac_key_wep40 {
- struct iwm_umac_wifi_if hdr;
- struct iwm_umac_key_hdr key_hdr;
- u8 key[WLAN_KEY_LEN_WEP40];
- u8 static_key;
- u8 reserved[2];
-} __packed;
-
-struct iwm_umac_key_wep104 {
- struct iwm_umac_wifi_if hdr;
- struct iwm_umac_key_hdr key_hdr;
- u8 key[WLAN_KEY_LEN_WEP104];
- u8 static_key;
- u8 reserved[2];
-} __packed;
-
-#define IWM_TKIP_KEY_SIZE 16
-#define IWM_TKIP_MIC_SIZE 8
-struct iwm_umac_key_tkip {
- struct iwm_umac_wifi_if hdr;
- struct iwm_umac_key_hdr key_hdr;
- u8 iv_count[6];
- u8 reserved[2];
- u8 tkip_key[IWM_TKIP_KEY_SIZE];
- u8 mic_rx_key[IWM_TKIP_MIC_SIZE];
- u8 mic_tx_key[IWM_TKIP_MIC_SIZE];
-} __packed;
-
-struct iwm_umac_key_ccmp {
- struct iwm_umac_wifi_if hdr;
- struct iwm_umac_key_hdr key_hdr;
- u8 iv_count[6];
- u8 reserved[2];
- u8 key[WLAN_KEY_LEN_CCMP];
-} __packed;
-
-struct iwm_umac_key_remove {
- struct iwm_umac_wifi_if hdr;
- struct iwm_umac_key_hdr key_hdr;
-} __packed;
-
-struct iwm_umac_tx_key_id {
- struct iwm_umac_wifi_if hdr;
- u8 key_idx;
- u8 reserved[3];
-} __packed;
-
-struct iwm_umac_pwr_trigger {
- struct iwm_umac_wifi_if hdr;
- __le32 reseved;
-} __packed;
-
-struct iwm_umac_cmd_stats_req {
- __le32 flags;
-} __packed;
-
-struct iwm_umac_cmd_stop_resume_tx {
- u8 flags;
- u8 sta_id;
- __le16 stop_resume_tid_msk;
- __le16 last_seq_num[IWM_UMAC_TID_NR];
- u16 reserved;
-} __packed;
-
-#define IWM_CMD_PMKID_ADD 1
-#define IWM_CMD_PMKID_DEL 2
-#define IWM_CMD_PMKID_FLUSH 3
-
-struct iwm_umac_pmkid_update {
- struct iwm_umac_wifi_if hdr;
- __le32 command;
- u8 bssid[ETH_ALEN];
- __le16 reserved;
- u8 pmkid[WLAN_PMKID_LEN];
-} __packed;
-
-/* LMAC commands */
-int iwm_read_mac(struct iwm_priv *iwm, u8 *mac);
-int iwm_send_prio_table(struct iwm_priv *iwm);
-int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested);
-int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested);
-int iwm_send_calib_results(struct iwm_priv *iwm);
-int iwm_store_rxiq_calib_result(struct iwm_priv *iwm);
-int iwm_send_ct_kill_cfg(struct iwm_priv *iwm, u8 entry, u8 exit);
-
-/* UMAC commands */
-int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
- bool resp);
-int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp);
-int iwm_umac_set_config_fix(struct iwm_priv *iwm, u16 tbl, u16 key, u32 value);
-int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key,
- void *payload, u16 payload_size);
-int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags);
-int iwm_send_mlme_profile(struct iwm_priv *iwm);
-int __iwm_invalidate_mlme_profile(struct iwm_priv *iwm);
-int iwm_invalidate_mlme_profile(struct iwm_priv *iwm);
-int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id);
-int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx);
-int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key);
-int iwm_tx_power_trigger(struct iwm_priv *iwm);
-int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags);
-int iwm_send_umac_channel_list(struct iwm_priv *iwm);
-int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
- int ssid_num);
-int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len);
-int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm,
- struct iwm_umac_notif_stop_resume_tx *ntf);
-int iwm_send_pmkid_update(struct iwm_priv *iwm,
- struct cfg80211_pmksa *pmksa, u32 command);
-
-/* UDMA commands */
-int iwm_target_reset(struct iwm_priv *iwm);
-#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/debug.h b/drivers/net/wireless/iwmc3200wifi/debug.h
deleted file mode 100644
index a0c13a49ab3c..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/debug.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-
-#ifndef __IWM_DEBUG_H__
-#define __IWM_DEBUG_H__
-
-#define IWM_ERR(p, f, a...) dev_err(iwm_to_dev(p), f, ## a)
-#define IWM_WARN(p, f, a...) dev_warn(iwm_to_dev(p), f, ## a)
-#define IWM_INFO(p, f, a...) dev_info(iwm_to_dev(p), f, ## a)
-#define IWM_CRIT(p, f, a...) dev_crit(iwm_to_dev(p), f, ## a)
-
-#ifdef CONFIG_IWM_DEBUG
-
-#define IWM_DEBUG_MODULE(i, level, module, f, a...) \
-do { \
- if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\
- dev_printk(KERN_INFO, (iwm_to_dev(i)), \
- "%s " f, __func__ , ## a); \
-} while (0)
-
-#define IWM_HEXDUMP(i, level, module, pref, buf, len) \
-do { \
- if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\
- print_hex_dump(KERN_INFO, pref, DUMP_PREFIX_OFFSET, \
- 16, 1, buf, len, 1); \
-} while (0)
-
-#else
-
-#define IWM_DEBUG_MODULE(i, level, module, f, a...)
-#define IWM_HEXDUMP(i, level, module, pref, buf, len)
-
-#endif /* CONFIG_IWM_DEBUG */
-
-/* Debug modules */
-enum iwm_debug_module_id {
- IWM_DM_BOOT = 0,
- IWM_DM_FW,
- IWM_DM_SDIO,
- IWM_DM_NTF,
- IWM_DM_RX,
- IWM_DM_TX,
- IWM_DM_MLME,
- IWM_DM_CMD,
- IWM_DM_WEXT,
- __IWM_DM_NR,
-};
-#define IWM_DM_DEFAULT 0
-
-#define IWM_DBG_BOOT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, BOOT, f, ## a)
-#define IWM_DBG_FW(i, l, f, a...) IWM_DEBUG_MODULE(i, l, FW, f, ## a)
-#define IWM_DBG_SDIO(i, l, f, a...) IWM_DEBUG_MODULE(i, l, SDIO, f, ## a)
-#define IWM_DBG_NTF(i, l, f, a...) IWM_DEBUG_MODULE(i, l, NTF, f, ## a)
-#define IWM_DBG_RX(i, l, f, a...) IWM_DEBUG_MODULE(i, l, RX, f, ## a)
-#define IWM_DBG_TX(i, l, f, a...) IWM_DEBUG_MODULE(i, l, TX, f, ## a)
-#define IWM_DBG_MLME(i, l, f, a...) IWM_DEBUG_MODULE(i, l, MLME, f, ## a)
-#define IWM_DBG_CMD(i, l, f, a...) IWM_DEBUG_MODULE(i, l, CMD, f, ## a)
-#define IWM_DBG_WEXT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, WEXT, f, ## a)
-
-/* Debug levels */
-enum iwm_debug_level {
- IWM_DL_NONE = 0,
- IWM_DL_ERR,
- IWM_DL_WARN,
- IWM_DL_INFO,
- IWM_DL_DBG,
-};
-#define IWM_DL_DEFAULT IWM_DL_ERR
-
-struct iwm_debugfs {
- struct iwm_priv *iwm;
- struct dentry *rootdir;
- struct dentry *devdir;
- struct dentry *dbgdir;
- struct dentry *txdir;
- struct dentry *rxdir;
- struct dentry *busdir;
-
- u32 dbg_level;
- struct dentry *dbg_level_dentry;
-
- unsigned long dbg_modules;
- struct dentry *dbg_modules_dentry;
-
- u8 dbg_module[__IWM_DM_NR];
- struct dentry *dbg_module_dentries[__IWM_DM_NR];
-
- struct dentry *txq_dentry;
- struct dentry *tx_credit_dentry;
- struct dentry *rx_ticket_dentry;
-
- struct dentry *fw_err_dentry;
-};
-
-#ifdef CONFIG_IWM_DEBUG
-void iwm_debugfs_init(struct iwm_priv *iwm);
-void iwm_debugfs_exit(struct iwm_priv *iwm);
-#else
-static inline void iwm_debugfs_init(struct iwm_priv *iwm) {}
-static inline void iwm_debugfs_exit(struct iwm_priv *iwm) {}
-#endif
-
-#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c
deleted file mode 100644
index b6199d124bb9..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/debugfs.c
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/bitops.h>
-#include <linux/debugfs.h>
-#include <linux/export.h>
-
-#include "iwm.h"
-#include "bus.h"
-#include "rx.h"
-#include "debug.h"
-
-static struct {
- u8 id;
- char *name;
-} iwm_debug_module[__IWM_DM_NR] = {
- {IWM_DM_BOOT, "boot"},
- {IWM_DM_FW, "fw"},
- {IWM_DM_SDIO, "sdio"},
- {IWM_DM_NTF, "ntf"},
- {IWM_DM_RX, "rx"},
- {IWM_DM_TX, "tx"},
- {IWM_DM_MLME, "mlme"},
- {IWM_DM_CMD, "cmd"},
- {IWM_DM_WEXT, "wext"},
-};
-
-#define add_dbg_module(dbg, name, id, initlevel) \
-do { \
- dbg.dbg_module[id] = (initlevel); \
- dbg.dbg_module_dentries[id] = \
- debugfs_create_x8(name, 0600, \
- dbg.dbgdir, \
- &(dbg.dbg_module[id])); \
-} while (0)
-
-static int iwm_debugfs_u32_read(void *data, u64 *val)
-{
- struct iwm_priv *iwm = data;
-
- *val = iwm->dbg.dbg_level;
- return 0;
-}
-
-static int iwm_debugfs_dbg_level_write(void *data, u64 val)
-{
- struct iwm_priv *iwm = data;
- int i;
-
- iwm->dbg.dbg_level = val;
-
- for (i = 0; i < __IWM_DM_NR; i++)
- iwm->dbg.dbg_module[i] = val;
-
- return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_level,
- iwm_debugfs_u32_read, iwm_debugfs_dbg_level_write,
- "%llu\n");
-
-static int iwm_debugfs_dbg_modules_write(void *data, u64 val)
-{
- struct iwm_priv *iwm = data;
- int i, bit;
-
- iwm->dbg.dbg_modules = val;
-
- for (i = 0; i < __IWM_DM_NR; i++)
- iwm->dbg.dbg_module[i] = 0;
-
- for_each_set_bit(bit, &iwm->dbg.dbg_modules, __IWM_DM_NR)
- iwm->dbg.dbg_module[bit] = iwm->dbg.dbg_level;
-
- return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_modules,
- iwm_debugfs_u32_read, iwm_debugfs_dbg_modules_write,
- "%llu\n");
-
-
-static ssize_t iwm_debugfs_txq_read(struct file *filp, char __user *buffer,
- size_t count, loff_t *ppos)
-{
- struct iwm_priv *iwm = filp->private_data;
- char *buf;
- int i, buf_len = 4096;
- size_t len = 0;
- ssize_t ret;
-
- if (*ppos != 0)
- return 0;
- if (count < sizeof(buf))
- return -ENOSPC;
-
- buf = kzalloc(buf_len, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- for (i = 0; i < IWM_TX_QUEUES; i++) {
- struct iwm_tx_queue *txq = &iwm->txq[i];
- struct sk_buff *skb;
- int j;
- unsigned long flags;
-
- spin_lock_irqsave(&txq->queue.lock, flags);
-
- skb = (struct sk_buff *)&txq->queue;
-
- len += snprintf(buf + len, buf_len - len, "TXQ #%d\n", i);
- len += snprintf(buf + len, buf_len - len, "\tStopped: %d\n",
- __netif_subqueue_stopped(iwm_to_ndev(iwm),
- txq->id));
- len += snprintf(buf + len, buf_len - len, "\tConcat count:%d\n",
- txq->concat_count);
- len += snprintf(buf + len, buf_len - len, "\tQueue len: %d\n",
- skb_queue_len(&txq->queue));
- for (j = 0; j < skb_queue_len(&txq->queue); j++) {
- struct iwm_tx_info *tx_info;
-
- skb = skb->next;
- tx_info = skb_to_tx_info(skb);
-
- len += snprintf(buf + len, buf_len - len,
- "\tSKB #%d\n", j);
- len += snprintf(buf + len, buf_len - len,
- "\t\tsta: %d\n", tx_info->sta);
- len += snprintf(buf + len, buf_len - len,
- "\t\tcolor: %d\n", tx_info->color);
- len += snprintf(buf + len, buf_len - len,
- "\t\ttid: %d\n", tx_info->tid);
- }
-
- spin_unlock_irqrestore(&txq->queue.lock, flags);
-
- spin_lock_irqsave(&txq->stopped_queue.lock, flags);
-
- len += snprintf(buf + len, buf_len - len,
- "\tStopped Queue len: %d\n",
- skb_queue_len(&txq->stopped_queue));
- for (j = 0; j < skb_queue_len(&txq->stopped_queue); j++) {
- struct iwm_tx_info *tx_info;
-
- skb = skb->next;
- tx_info = skb_to_tx_info(skb);
-
- len += snprintf(buf + len, buf_len - len,
- "\tSKB #%d\n", j);
- len += snprintf(buf + len, buf_len - len,
- "\t\tsta: %d\n", tx_info->sta);
- len += snprintf(buf + len, buf_len - len,
- "\t\tcolor: %d\n", tx_info->color);
- len += snprintf(buf + len, buf_len - len,
- "\t\ttid: %d\n", tx_info->tid);
- }
-
- spin_unlock_irqrestore(&txq->stopped_queue.lock, flags);
- }
-
- ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
- kfree(buf);
-
- return ret;
-}
-
-static ssize_t iwm_debugfs_tx_credit_read(struct file *filp,
- char __user *buffer,
- size_t count, loff_t *ppos)
-{
- struct iwm_priv *iwm = filp->private_data;
- struct iwm_tx_credit *credit = &iwm->tx_credit;
- char *buf;
- int i, buf_len = 4096;
- size_t len = 0;
- ssize_t ret;
-
- if (*ppos != 0)
- return 0;
- if (count < sizeof(buf))
- return -ENOSPC;
-
- buf = kzalloc(buf_len, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- len += snprintf(buf + len, buf_len - len,
- "NR pools: %d\n", credit->pool_nr);
- len += snprintf(buf + len, buf_len - len,
- "pools map: 0x%lx\n", credit->full_pools_map);
-
- len += snprintf(buf + len, buf_len - len, "\n### POOLS ###\n");
- for (i = 0; i < IWM_MACS_OUT_GROUPS; i++) {
- len += snprintf(buf + len, buf_len - len,
- "pools entry #%d\n", i);
- len += snprintf(buf + len, buf_len - len,
- "\tid: %d\n",
- credit->pools[i].id);
- len += snprintf(buf + len, buf_len - len,
- "\tsid: %d\n",
- credit->pools[i].sid);
- len += snprintf(buf + len, buf_len - len,
- "\tmin_pages: %d\n",
- credit->pools[i].min_pages);
- len += snprintf(buf + len, buf_len - len,
- "\tmax_pages: %d\n",
- credit->pools[i].max_pages);
- len += snprintf(buf + len, buf_len - len,
- "\talloc_pages: %d\n",
- credit->pools[i].alloc_pages);
- len += snprintf(buf + len, buf_len - len,
- "\tfreed_pages: %d\n",
- credit->pools[i].total_freed_pages);
- }
-
- len += snprintf(buf + len, buf_len - len, "\n### SPOOLS ###\n");
- for (i = 0; i < IWM_MACS_OUT_SGROUPS; i++) {
- len += snprintf(buf + len, buf_len - len,
- "spools entry #%d\n", i);
- len += snprintf(buf + len, buf_len - len,
- "\tid: %d\n",
- credit->spools[i].id);
- len += snprintf(buf + len, buf_len - len,
- "\tmax_pages: %d\n",
- credit->spools[i].max_pages);
- len += snprintf(buf + len, buf_len - len,
- "\talloc_pages: %d\n",
- credit->spools[i].alloc_pages);
-
- }
-
- ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
- kfree(buf);
-
- return ret;
-}
-
-static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp,
- char __user *buffer,
- size_t count, loff_t *ppos)
-{
- struct iwm_priv *iwm = filp->private_data;
- struct iwm_rx_ticket_node *ticket;
- char *buf;
- int buf_len = 4096, i;
- size_t len = 0;
- ssize_t ret;
-
- if (*ppos != 0)
- return 0;
- if (count < sizeof(buf))
- return -ENOSPC;
-
- buf = kzalloc(buf_len, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- spin_lock(&iwm->ticket_lock);
- list_for_each_entry(ticket, &iwm->rx_tickets, node) {
- len += snprintf(buf + len, buf_len - len, "Ticket #%d\n",
- ticket->ticket->id);
- len += snprintf(buf + len, buf_len - len, "\taction: 0x%x\n",
- ticket->ticket->action);
- len += snprintf(buf + len, buf_len - len, "\tflags: 0x%x\n",
- ticket->ticket->flags);
- }
- spin_unlock(&iwm->ticket_lock);
-
- for (i = 0; i < IWM_RX_ID_HASH; i++) {
- struct iwm_rx_packet *packet;
- struct list_head *pkt_list = &iwm->rx_packets[i];
-
- if (!list_empty(pkt_list)) {
- len += snprintf(buf + len, buf_len - len,
- "Packet hash #%d\n", i);
- spin_lock(&iwm->packet_lock[i]);
- list_for_each_entry(packet, pkt_list, node) {
- len += snprintf(buf + len, buf_len - len,
- "\tPacket id: %d\n",
- packet->id);
- len += snprintf(buf + len, buf_len - len,
- "\tPacket length: %lu\n",
- packet->pkt_size);
- }
- spin_unlock(&iwm->packet_lock[i]);
- }
- }
-
- ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
- kfree(buf);
-
- return ret;
-}
-
-static ssize_t iwm_debugfs_fw_err_read(struct file *filp,
- char __user *buffer,
- size_t count, loff_t *ppos)
-{
-
- struct iwm_priv *iwm = filp->private_data;
- char buf[512];
- int buf_len = 512;
- size_t len = 0;
-
- if (*ppos != 0)
- return 0;
- if (count < sizeof(buf))
- return -ENOSPC;
-
- if (!iwm->last_fw_err)
- return -ENOMEM;
-
- if (iwm->last_fw_err->line_num == 0)
- goto out;
-
- len += snprintf(buf + len, buf_len - len, "%cMAC FW ERROR:\n",
- (le32_to_cpu(iwm->last_fw_err->category) == UMAC_SYS_ERR_CAT_LMAC)
- ? 'L' : 'U');
- len += snprintf(buf + len, buf_len - len,
- "\tCategory: %d\n",
- le32_to_cpu(iwm->last_fw_err->category));
-
- len += snprintf(buf + len, buf_len - len,
- "\tStatus: 0x%x\n",
- le32_to_cpu(iwm->last_fw_err->status));
-
- len += snprintf(buf + len, buf_len - len,
- "\tPC: 0x%x\n",
- le32_to_cpu(iwm->last_fw_err->pc));
-
- len += snprintf(buf + len, buf_len - len,
- "\tblink1: %d\n",
- le32_to_cpu(iwm->last_fw_err->blink1));
-
- len += snprintf(buf + len, buf_len - len,
- "\tblink2: %d\n",
- le32_to_cpu(iwm->last_fw_err->blink2));
-
- len += snprintf(buf + len, buf_len - len,
- "\tilink1: %d\n",
- le32_to_cpu(iwm->last_fw_err->ilink1));
-
- len += snprintf(buf + len, buf_len - len,
- "\tilink2: %d\n",
- le32_to_cpu(iwm->last_fw_err->ilink2));
-
- len += snprintf(buf + len, buf_len - len,
- "\tData1: 0x%x\n",
- le32_to_cpu(iwm->last_fw_err->data1));
-
- len += snprintf(buf + len, buf_len - len,
- "\tData2: 0x%x\n",
- le32_to_cpu(iwm->last_fw_err->data2));
-
- len += snprintf(buf + len, buf_len - len,
- "\tLine number: %d\n",
- le32_to_cpu(iwm->last_fw_err->line_num));
-
- len += snprintf(buf + len, buf_len - len,
- "\tUMAC status: 0x%x\n",
- le32_to_cpu(iwm->last_fw_err->umac_status));
-
- len += snprintf(buf + len, buf_len - len,
- "\tLMAC status: 0x%x\n",
- le32_to_cpu(iwm->last_fw_err->lmac_status));
-
- len += snprintf(buf + len, buf_len - len,
- "\tSDIO status: 0x%x\n",
- le32_to_cpu(iwm->last_fw_err->sdio_status));
-
-out:
-
- return simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
-}
-
-static const struct file_operations iwm_debugfs_txq_fops = {
- .owner = THIS_MODULE,
- .open = simple_open,
- .read = iwm_debugfs_txq_read,
- .llseek = default_llseek,
-};
-
-static const struct file_operations iwm_debugfs_tx_credit_fops = {
- .owner = THIS_MODULE,
- .open = simple_open,
- .read = iwm_debugfs_tx_credit_read,
- .llseek = default_llseek,
-};
-
-static const struct file_operations iwm_debugfs_rx_ticket_fops = {
- .owner = THIS_MODULE,
- .open = simple_open,
- .read = iwm_debugfs_rx_ticket_read,
- .llseek = default_llseek,
-};
-
-static const struct file_operations iwm_debugfs_fw_err_fops = {
- .owner = THIS_MODULE,
- .open = simple_open,
- .read = iwm_debugfs_fw_err_read,
- .llseek = default_llseek,
-};
-
-void iwm_debugfs_init(struct iwm_priv *iwm)
-{
- int i;
-
- iwm->dbg.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
- iwm->dbg.devdir = debugfs_create_dir(wiphy_name(iwm_to_wiphy(iwm)),
- iwm->dbg.rootdir);
- iwm->dbg.dbgdir = debugfs_create_dir("debug", iwm->dbg.devdir);
- iwm->dbg.rxdir = debugfs_create_dir("rx", iwm->dbg.devdir);
- iwm->dbg.txdir = debugfs_create_dir("tx", iwm->dbg.devdir);
- iwm->dbg.busdir = debugfs_create_dir("bus", iwm->dbg.devdir);
- if (iwm->bus_ops->debugfs_init)
- iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir);
-
- iwm->dbg.dbg_level = IWM_DL_NONE;
- iwm->dbg.dbg_level_dentry =
- debugfs_create_file("level", 0200, iwm->dbg.dbgdir, iwm,
- &fops_iwm_dbg_level);
-
- iwm->dbg.dbg_modules = IWM_DM_DEFAULT;
- iwm->dbg.dbg_modules_dentry =
- debugfs_create_file("modules", 0200, iwm->dbg.dbgdir, iwm,
- &fops_iwm_dbg_modules);
-
- for (i = 0; i < __IWM_DM_NR; i++)
- add_dbg_module(iwm->dbg, iwm_debug_module[i].name,
- iwm_debug_module[i].id, IWM_DL_DEFAULT);
-
- iwm->dbg.txq_dentry = debugfs_create_file("queues", 0200,
- iwm->dbg.txdir, iwm,
- &iwm_debugfs_txq_fops);
- iwm->dbg.tx_credit_dentry = debugfs_create_file("credits", 0200,
- iwm->dbg.txdir, iwm,
- &iwm_debugfs_tx_credit_fops);
- iwm->dbg.rx_ticket_dentry = debugfs_create_file("tickets", 0200,
- iwm->dbg.rxdir, iwm,
- &iwm_debugfs_rx_ticket_fops);
- iwm->dbg.fw_err_dentry = debugfs_create_file("last_fw_err", 0200,
- iwm->dbg.dbgdir, iwm,
- &iwm_debugfs_fw_err_fops);
-}
-
-void iwm_debugfs_exit(struct iwm_priv *iwm)
-{
- int i;
-
- for (i = 0; i < __IWM_DM_NR; i++)
- debugfs_remove(iwm->dbg.dbg_module_dentries[i]);
-
- debugfs_remove(iwm->dbg.dbg_modules_dentry);
- debugfs_remove(iwm->dbg.dbg_level_dentry);
- debugfs_remove(iwm->dbg.txq_dentry);
- debugfs_remove(iwm->dbg.tx_credit_dentry);
- debugfs_remove(iwm->dbg.rx_ticket_dentry);
- debugfs_remove(iwm->dbg.fw_err_dentry);
- if (iwm->bus_ops->debugfs_exit)
- iwm->bus_ops->debugfs_exit(iwm);
-
- debugfs_remove(iwm->dbg.busdir);
- debugfs_remove(iwm->dbg.dbgdir);
- debugfs_remove(iwm->dbg.txdir);
- debugfs_remove(iwm->dbg.rxdir);
- debugfs_remove(iwm->dbg.devdir);
- debugfs_remove(iwm->dbg.rootdir);
-}
diff --git a/drivers/net/wireless/iwmc3200wifi/eeprom.c b/drivers/net/wireless/iwmc3200wifi/eeprom.c
deleted file mode 100644
index e80e776b74f7..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/eeprom.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-
-#include "iwm.h"
-#include "umac.h"
-#include "commands.h"
-#include "eeprom.h"
-
-static struct iwm_eeprom_entry eeprom_map[] = {
- [IWM_EEPROM_SIG] =
- {"Signature", IWM_EEPROM_SIG_OFF, IWM_EEPROM_SIG_LEN},
-
- [IWM_EEPROM_VERSION] =
- {"Version", IWM_EEPROM_VERSION_OFF, IWM_EEPROM_VERSION_LEN},
-
- [IWM_EEPROM_OEM_HW_VERSION] =
- {"OEM HW version", IWM_EEPROM_OEM_HW_VERSION_OFF,
- IWM_EEPROM_OEM_HW_VERSION_LEN},
-
- [IWM_EEPROM_MAC_VERSION] =
- {"MAC version", IWM_EEPROM_MAC_VERSION_OFF, IWM_EEPROM_MAC_VERSION_LEN},
-
- [IWM_EEPROM_CARD_ID] =
- {"Card ID", IWM_EEPROM_CARD_ID_OFF, IWM_EEPROM_CARD_ID_LEN},
-
- [IWM_EEPROM_RADIO_CONF] =
- {"Radio config", IWM_EEPROM_RADIO_CONF_OFF, IWM_EEPROM_RADIO_CONF_LEN},
-
- [IWM_EEPROM_SKU_CAP] =
- {"SKU capabilities", IWM_EEPROM_SKU_CAP_OFF, IWM_EEPROM_SKU_CAP_LEN},
-
- [IWM_EEPROM_FAT_CHANNELS_CAP] =
- {"HT channels capabilities", IWM_EEPROM_FAT_CHANNELS_CAP_OFF,
- IWM_EEPROM_FAT_CHANNELS_CAP_LEN},
-
- [IWM_EEPROM_CALIB_RXIQ_OFFSET] =
- {"RX IQ offset", IWM_EEPROM_CALIB_RXIQ_OFF, IWM_EEPROM_INDIRECT_LEN},
-
- [IWM_EEPROM_CALIB_RXIQ] =
- {"Calib RX IQ", 0, IWM_EEPROM_CALIB_RXIQ_LEN},
-};
-
-
-static int iwm_eeprom_read(struct iwm_priv *iwm, u8 eeprom_id)
-{
- int ret;
- u32 entry_size, chunk_size, data_offset = 0, addr_offset = 0;
- u32 addr;
- struct iwm_udma_wifi_cmd udma_cmd;
- struct iwm_umac_cmd umac_cmd;
- struct iwm_umac_cmd_eeprom_proxy eeprom_cmd;
-
- if (eeprom_id > (IWM_EEPROM_LAST - 1))
- return -EINVAL;
-
- entry_size = eeprom_map[eeprom_id].length;
-
- if (eeprom_id >= IWM_EEPROM_INDIRECT_DATA) {
- /* indirect data */
- u32 off_id = eeprom_id - IWM_EEPROM_INDIRECT_DATA +
- IWM_EEPROM_INDIRECT_OFFSET;
-
- eeprom_map[eeprom_id].offset =
- *(u16 *)(iwm->eeprom + eeprom_map[off_id].offset) << 1;
- }
-
- addr = eeprom_map[eeprom_id].offset;
-
- udma_cmd.eop = 1;
- udma_cmd.credit_group = 0x4;
- udma_cmd.ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD;
- udma_cmd.lmac_offset = 0;
-
- umac_cmd.id = UMAC_CMD_OPCODE_EEPROM_PROXY;
- umac_cmd.resp = 1;
-
- while (entry_size > 0) {
- chunk_size = min_t(u32, entry_size, IWM_MAX_EEPROM_DATA_LEN);
-
- eeprom_cmd.hdr.type =
- cpu_to_le32(IWM_UMAC_CMD_EEPROM_TYPE_READ);
- eeprom_cmd.hdr.offset = cpu_to_le32(addr + addr_offset);
- eeprom_cmd.hdr.len = cpu_to_le32(chunk_size);
-
- ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd,
- &umac_cmd, &eeprom_cmd,
- sizeof(struct iwm_umac_cmd_eeprom_proxy));
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't read eeprom\n");
- return ret;
- }
-
- ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_EEPROM_PROXY,
- IWM_SRC_UMAC, 2*HZ);
- if (ret < 0) {
- IWM_ERR(iwm, "Did not get any eeprom answer\n");
- return ret;
- }
-
- data_offset += chunk_size;
- addr_offset += chunk_size;
- entry_size -= chunk_size;
- }
-
- return 0;
-}
-
-u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id)
-{
- if (!iwm->eeprom)
- return ERR_PTR(-ENODEV);
-
- return iwm->eeprom + eeprom_map[eeprom_id].offset;
-}
-
-int iwm_eeprom_fat_channels(struct iwm_priv *iwm)
-{
- struct wiphy *wiphy = iwm_to_wiphy(iwm);
- struct ieee80211_supported_band *band;
- u16 *channels, i;
-
- channels = (u16 *)iwm_eeprom_access(iwm, IWM_EEPROM_FAT_CHANNELS_CAP);
- if (IS_ERR(channels))
- return PTR_ERR(channels);
-
- band = wiphy->bands[IEEE80211_BAND_2GHZ];
- band->ht_cap.ht_supported = true;
-
- for (i = 0; i < IWM_EEPROM_FAT_CHANNELS_24; i++)
- if (!(channels[i] & IWM_EEPROM_FAT_CHANNEL_ENABLED))
- band->ht_cap.ht_supported = false;
-
- band = wiphy->bands[IEEE80211_BAND_5GHZ];
- band->ht_cap.ht_supported = true;
- for (i = IWM_EEPROM_FAT_CHANNELS_24; i < IWM_EEPROM_FAT_CHANNELS; i++)
- if (!(channels[i] & IWM_EEPROM_FAT_CHANNEL_ENABLED))
- band->ht_cap.ht_supported = false;
-
- return 0;
-}
-
-u32 iwm_eeprom_wireless_mode(struct iwm_priv *iwm)
-{
- u16 sku_cap;
- u32 wireless_mode = 0;
-
- sku_cap = *((u16 *)iwm_eeprom_access(iwm, IWM_EEPROM_SKU_CAP));
-
- if (sku_cap & IWM_EEPROM_SKU_CAP_BAND_24GHZ)
- wireless_mode |= WIRELESS_MODE_11G;
-
- if (sku_cap & IWM_EEPROM_SKU_CAP_BAND_52GHZ)
- wireless_mode |= WIRELESS_MODE_11A;
-
- if (sku_cap & IWM_EEPROM_SKU_CAP_11N_ENABLE)
- wireless_mode |= WIRELESS_MODE_11N;
-
- return wireless_mode;
-}
-
-
-int iwm_eeprom_init(struct iwm_priv *iwm)
-{
- int i, ret = 0;
- char name[32];
-
- iwm->eeprom = kzalloc(IWM_EEPROM_LEN, GFP_KERNEL);
- if (!iwm->eeprom)
- return -ENOMEM;
-
- for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) {
- ret = iwm_eeprom_read(iwm, i);
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't read eeprom entry #%d: %s\n",
- i, eeprom_map[i].name);
- break;
- }
- }
-
- IWM_DBG_BOOT(iwm, DBG, "EEPROM dump:\n");
- for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) {
- memset(name, 0, 32);
- sprintf(name, "%s: ", eeprom_map[i].name);
-
- IWM_HEXDUMP(iwm, DBG, BOOT, name,
- iwm->eeprom + eeprom_map[i].offset,
- eeprom_map[i].length);
- }
-
- return ret;
-}
-
-void iwm_eeprom_exit(struct iwm_priv *iwm)
-{
- kfree(iwm->eeprom);
-}
diff --git a/drivers/net/wireless/iwmc3200wifi/eeprom.h b/drivers/net/wireless/iwmc3200wifi/eeprom.h
deleted file mode 100644
index 4e3a3fdab0d3..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/eeprom.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-#ifndef __IWM_EEPROM_H__
-#define __IWM_EEPROM_H__
-
-enum {
- IWM_EEPROM_SIG = 0,
- IWM_EEPROM_FIRST = IWM_EEPROM_SIG,
- IWM_EEPROM_VERSION,
- IWM_EEPROM_OEM_HW_VERSION,
- IWM_EEPROM_MAC_VERSION,
- IWM_EEPROM_CARD_ID,
- IWM_EEPROM_RADIO_CONF,
- IWM_EEPROM_SKU_CAP,
- IWM_EEPROM_FAT_CHANNELS_CAP,
-
- IWM_EEPROM_INDIRECT_OFFSET,
- IWM_EEPROM_CALIB_RXIQ_OFFSET = IWM_EEPROM_INDIRECT_OFFSET,
-
- IWM_EEPROM_INDIRECT_DATA,
- IWM_EEPROM_CALIB_RXIQ = IWM_EEPROM_INDIRECT_DATA,
-
- IWM_EEPROM_LAST,
-};
-
-#define IWM_EEPROM_SIG_OFF 0x00
-#define IWM_EEPROM_VERSION_OFF (0x54 << 1)
-#define IWM_EEPROM_OEM_HW_VERSION_OFF (0x56 << 1)
-#define IWM_EEPROM_MAC_VERSION_OFF (0x30 << 1)
-#define IWM_EEPROM_CARD_ID_OFF (0x5d << 1)
-#define IWM_EEPROM_RADIO_CONF_OFF (0x58 << 1)
-#define IWM_EEPROM_SKU_CAP_OFF (0x55 << 1)
-#define IWM_EEPROM_CALIB_CONFIG_OFF (0x7c << 1)
-#define IWM_EEPROM_FAT_CHANNELS_CAP_OFF (0xde << 1)
-
-#define IWM_EEPROM_SIG_LEN 4
-#define IWM_EEPROM_VERSION_LEN 2
-#define IWM_EEPROM_OEM_HW_VERSION_LEN 2
-#define IWM_EEPROM_MAC_VERSION_LEN 1
-#define IWM_EEPROM_CARD_ID_LEN 2
-#define IWM_EEPROM_RADIO_CONF_LEN 2
-#define IWM_EEPROM_SKU_CAP_LEN 2
-#define IWM_EEPROM_FAT_CHANNELS_CAP_LEN 40
-#define IWM_EEPROM_INDIRECT_LEN 2
-
-#define IWM_MAX_EEPROM_DATA_LEN 240
-#define IWM_EEPROM_LEN 0x800
-
-#define IWM_EEPROM_MIN_ALLOWED_VERSION 0x0610
-#define IWM_EEPROM_MAX_ALLOWED_VERSION 0x0700
-#define IWM_EEPROM_CURRENT_VERSION 0x0612
-
-#define IWM_EEPROM_SKU_CAP_BAND_24GHZ (1 << 4)
-#define IWM_EEPROM_SKU_CAP_BAND_52GHZ (1 << 5)
-#define IWM_EEPROM_SKU_CAP_11N_ENABLE (1 << 6)
-
-#define IWM_EEPROM_FAT_CHANNELS 20
-/* 2.4 gHz FAT primary channels: 1, 2, 3, 4, 5, 6, 7, 8, 9 */
-#define IWM_EEPROM_FAT_CHANNELS_24 9
-/* 5.2 gHz FAT primary channels: 36,44,52,60,100,108,116,124,132,149,157 */
-#define IWM_EEPROM_FAT_CHANNELS_52 11
-
-#define IWM_EEPROM_FAT_CHANNEL_ENABLED (1 << 0)
-
-enum {
- IWM_EEPROM_CALIB_CAL_HDR,
- IWM_EEPROM_CALIB_TX_POWER,
- IWM_EEPROM_CALIB_XTAL,
- IWM_EEPROM_CALIB_TEMPERATURE,
- IWM_EEPROM_CALIB_RX_BB_FILTER,
- IWM_EEPROM_CALIB_RX_IQ,
- IWM_EEPROM_CALIB_MAX,
-};
-
-#define IWM_EEPROM_CALIB_RXIQ_OFF (IWM_EEPROM_CALIB_CONFIG_OFF + \
- (IWM_EEPROM_CALIB_RX_IQ << 1))
-#define IWM_EEPROM_CALIB_RXIQ_LEN sizeof(struct iwm_lmac_calib_rxiq)
-
-struct iwm_eeprom_entry {
- char *name;
- u32 offset;
- u32 length;
-};
-
-int iwm_eeprom_init(struct iwm_priv *iwm);
-void iwm_eeprom_exit(struct iwm_priv *iwm);
-u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id);
-int iwm_eeprom_fat_channels(struct iwm_priv *iwm);
-u32 iwm_eeprom_wireless_mode(struct iwm_priv *iwm);
-
-#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c
deleted file mode 100644
index 6f1afe6bbc8c..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/fw.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/firmware.h>
-
-#include "iwm.h"
-#include "bus.h"
-#include "hal.h"
-#include "umac.h"
-#include "debug.h"
-#include "fw.h"
-#include "commands.h"
-
-static const char fw_barker[] = "*WESTOPFORNOONE*";
-
-/*
- * @op_code: Op code we're looking for.
- * @index: There can be several instances of the same opcode within
- * the firmware. Index specifies which one we're looking for.
- */
-static int iwm_fw_op_offset(struct iwm_priv *iwm, const struct firmware *fw,
- u16 op_code, u32 index)
-{
- int offset = -EINVAL, fw_offset;
- u32 op_index = 0;
- const u8 *fw_ptr;
- struct iwm_fw_hdr_rec *rec;
-
- fw_offset = 0;
- fw_ptr = fw->data;
-
- /* We first need to look for the firmware barker */
- if (memcmp(fw_ptr, fw_barker, IWM_HDR_BARKER_LEN)) {
- IWM_ERR(iwm, "No barker string in this FW\n");
- return -EINVAL;
- }
-
- if (fw->size < IWM_HDR_LEN) {
- IWM_ERR(iwm, "FW is too small (%zu)\n", fw->size);
- return -EINVAL;
- }
-
- fw_offset += IWM_HDR_BARKER_LEN;
-
- while (fw_offset < fw->size) {
- rec = (struct iwm_fw_hdr_rec *)(fw_ptr + fw_offset);
-
- IWM_DBG_FW(iwm, DBG, "FW: op_code: 0x%x, len: %d @ 0x%x\n",
- rec->op_code, rec->len, fw_offset);
-
- if (rec->op_code == IWM_HDR_REC_OP_INVALID) {
- IWM_DBG_FW(iwm, DBG, "Reached INVALID op code\n");
- break;
- }
-
- if (rec->op_code == op_code) {
- if (op_index == index) {
- fw_offset += sizeof(struct iwm_fw_hdr_rec);
- offset = fw_offset;
- goto out;
- }
- op_index++;
- }
-
- fw_offset += sizeof(struct iwm_fw_hdr_rec) + rec->len;
- }
-
- out:
- return offset;
-}
-
-static int iwm_load_firmware_chunk(struct iwm_priv *iwm,
- const struct firmware *fw,
- struct iwm_fw_img_desc *img_desc)
-{
- struct iwm_udma_nonwifi_cmd target_cmd;
- u32 chunk_size;
- const u8 *chunk_ptr;
- int ret = 0;
-
- IWM_DBG_FW(iwm, INFO, "Loading FW chunk: %d bytes @ 0x%x\n",
- img_desc->length, img_desc->address);
-
- target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE;
- target_cmd.handle_by_hw = 1;
- target_cmd.op2 = 0;
- target_cmd.resp = 0;
- target_cmd.eop = 1;
-
- chunk_size = img_desc->length;
- chunk_ptr = fw->data + img_desc->offset;
-
- while (chunk_size > 0) {
- u32 tmp_chunk_size;
-
- tmp_chunk_size = min_t(u32, chunk_size,
- IWM_MAX_NONWIFI_CMD_BUFF_SIZE);
-
- target_cmd.addr = cpu_to_le32(img_desc->address +
- (chunk_ptr - fw->data - img_desc->offset));
- target_cmd.op1_sz = cpu_to_le32(tmp_chunk_size);
-
- IWM_DBG_FW(iwm, DBG, "\t%d bytes @ 0x%x\n",
- tmp_chunk_size, target_cmd.addr);
-
- ret = iwm_hal_send_target_cmd(iwm, &target_cmd, chunk_ptr);
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't load FW chunk\n");
- break;
- }
-
- chunk_size -= tmp_chunk_size;
- chunk_ptr += tmp_chunk_size;
- }
-
- return ret;
-}
-/*
- * To load a fw image to the target, we basically go through the
- * fw, looking for OP_MEM_DESC records. Once we found one, we
- * pass it to iwm_load_firmware_chunk().
- * The OP_MEM_DESC records contain the actuall memory chunk to be
- * sent, but also the destination address.
- */
-static int iwm_load_img(struct iwm_priv *iwm, const char *img_name)
-{
- const struct firmware *fw;
- struct iwm_fw_img_desc *img_desc;
- struct iwm_fw_img_ver *ver;
- int ret = 0, fw_offset;
- u32 opcode_idx = 0, build_date;
- char *build_tag;
-
- ret = request_firmware(&fw, img_name, iwm_to_dev(iwm));
- if (ret) {
- IWM_ERR(iwm, "Request firmware failed");
- return ret;
- }
-
- IWM_DBG_FW(iwm, INFO, "Start to load FW %s\n", img_name);
-
- while (1) {
- fw_offset = iwm_fw_op_offset(iwm, fw,
- IWM_HDR_REC_OP_MEM_DESC,
- opcode_idx);
- if (fw_offset < 0)
- break;
-
- img_desc = (struct iwm_fw_img_desc *)(fw->data + fw_offset);
- ret = iwm_load_firmware_chunk(iwm, fw, img_desc);
- if (ret < 0)
- goto err_release_fw;
- opcode_idx++;
- }
-
- /* Read firmware version */
- fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_SW_VER, 0);
- if (fw_offset < 0)
- goto err_release_fw;
-
- ver = (struct iwm_fw_img_ver *)(fw->data + fw_offset);
-
- /* Read build tag */
- fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_BUILD_TAG, 0);
- if (fw_offset < 0)
- goto err_release_fw;
-
- build_tag = (char *)(fw->data + fw_offset);
-
- /* Read build date */
- fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_BUILD_DATE, 0);
- if (fw_offset < 0)
- goto err_release_fw;
-
- build_date = *(u32 *)(fw->data + fw_offset);
-
- IWM_INFO(iwm, "%s:\n", img_name);
- IWM_INFO(iwm, "\tVersion: %02X.%02X\n", ver->major, ver->minor);
- IWM_INFO(iwm, "\tBuild tag: %s\n", build_tag);
- IWM_INFO(iwm, "\tBuild date: %x-%x-%x\n",
- IWM_BUILD_YEAR(build_date), IWM_BUILD_MONTH(build_date),
- IWM_BUILD_DAY(build_date));
-
- if (!strcmp(img_name, iwm->bus_ops->umac_name))
- sprintf(iwm->umac_version, "%02X.%02X",
- ver->major, ver->minor);
-
- if (!strcmp(img_name, iwm->bus_ops->lmac_name))
- sprintf(iwm->lmac_version, "%02X.%02X",
- ver->major, ver->minor);
-
- err_release_fw:
- release_firmware(fw);
-
- return ret;
-}
-
-static int iwm_load_umac(struct iwm_priv *iwm)
-{
- struct iwm_udma_nonwifi_cmd target_cmd;
- int ret;
-
- ret = iwm_load_img(iwm, iwm->bus_ops->umac_name);
- if (ret < 0)
- return ret;
-
- /* We've loaded the UMAC, we can tell the target to jump there */
- target_cmd.opcode = UMAC_HDI_OUT_OPCODE_JUMP;
- target_cmd.addr = cpu_to_le32(UMAC_MU_FW_INST_DATA_12_ADDR);
- target_cmd.op1_sz = 0;
- target_cmd.op2 = 0;
- target_cmd.handle_by_hw = 0;
- target_cmd.resp = 1 ;
- target_cmd.eop = 1;
-
- ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
- if (ret < 0)
- IWM_ERR(iwm, "Couldn't send JMP command\n");
-
- return ret;
-}
-
-static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name)
-{
- int ret;
-
- ret = iwm_load_img(iwm, img_name);
- if (ret < 0)
- return ret;
-
- return iwm_send_umac_reset(iwm,
- cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_CLK_EN), 0);
-}
-
-static int iwm_init_calib(struct iwm_priv *iwm, unsigned long cfg_bitmap,
- unsigned long expected_bitmap, u8 rx_iq_cmd)
-{
- /* Read RX IQ calibration result from EEPROM */
- if (test_bit(rx_iq_cmd, &cfg_bitmap)) {
- iwm_store_rxiq_calib_result(iwm);
- set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map);
- }
-
- iwm_send_prio_table(iwm);
- iwm_send_init_calib_cfg(iwm, cfg_bitmap);
-
- while (iwm->calib_done_map != expected_bitmap) {
- if (iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION,
- IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT)) {
- IWM_DBG_FW(iwm, DBG, "Initial calibration timeout\n");
- return -ETIMEDOUT;
- }
-
- IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: "
- "0x%lx, expected calibrations: 0x%lx\n",
- iwm->calib_done_map, expected_bitmap);
- }
-
- return 0;
-}
-
-/*
- * We currently have to load 3 FWs:
- * 1) The UMAC (Upper MAC).
- * 2) The calibration LMAC (Lower MAC).
- * We then send the calibration init command, so that the device can
- * run a first calibration round.
- * 3) The operational LMAC, which replaces the calibration one when it's
- * done with the first calibration round.
- *
- * Once those 3 FWs have been loaded, we send the periodic calibration
- * command, and then the device is available for regular 802.11 operations.
- */
-int iwm_load_fw(struct iwm_priv *iwm)
-{
- unsigned long init_calib_map, periodic_calib_map;
- unsigned long expected_calib_map;
- int ret;
-
- /* We first start downloading the UMAC */
- ret = iwm_load_umac(iwm);
- if (ret < 0) {
- IWM_ERR(iwm, "UMAC loading failed\n");
- return ret;
- }
-
- /* Handle UMAC_ALIVE notification */
- ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_ALIVE, IWM_SRC_UMAC,
- WAIT_NOTIF_TIMEOUT);
- if (ret) {
- IWM_ERR(iwm, "Handle UMAC_ALIVE failed: %d\n", ret);
- return ret;
- }
-
- /* UMAC is alive, we can download the calibration LMAC */
- ret = iwm_load_lmac(iwm, iwm->bus_ops->calib_lmac_name);
- if (ret) {
- IWM_ERR(iwm, "Calibration LMAC loading failed\n");
- return ret;
- }
-
- /* Handle UMAC_INIT_COMPLETE notification */
- ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_INIT_COMPLETE,
- IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
- if (ret) {
- IWM_ERR(iwm, "Handle INIT_COMPLETE failed for calibration "
- "LMAC: %d\n", ret);
- return ret;
- }
-
- /* Read EEPROM data */
- ret = iwm_eeprom_init(iwm);
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't init eeprom array\n");
- return ret;
- }
-
- init_calib_map = iwm->conf.calib_map & IWM_CALIB_MAP_INIT_MSK;
- expected_calib_map = iwm->conf.expected_calib_map &
- IWM_CALIB_MAP_INIT_MSK;
- periodic_calib_map = IWM_CALIB_MAP_PER_LMAC(iwm->conf.calib_map);
-
- ret = iwm_init_calib(iwm, init_calib_map, expected_calib_map,
- CALIB_CFG_RX_IQ_IDX);
- if (ret < 0) {
- /* Let's try the old way */
- ret = iwm_init_calib(iwm, expected_calib_map,
- expected_calib_map,
- PHY_CALIBRATE_RX_IQ_CMD);
- if (ret < 0) {
- IWM_ERR(iwm, "Calibration result timeout\n");
- goto out;
- }
- }
-
- /* Handle LMAC CALIBRATION_COMPLETE notification */
- ret = iwm_notif_handle(iwm, CALIBRATION_COMPLETE_NOTIFICATION,
- IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT);
- if (ret) {
- IWM_ERR(iwm, "Wait for CALIBRATION_COMPLETE timeout\n");
- goto out;
- }
-
- IWM_INFO(iwm, "LMAC calibration done: 0x%lx\n", iwm->calib_done_map);
-
- iwm_send_umac_reset(iwm, cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_RESET), 1);
-
- ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_RESET, IWM_SRC_UMAC,
- WAIT_NOTIF_TIMEOUT);
- if (ret) {
- IWM_ERR(iwm, "Wait for UMAC RESET timeout\n");
- goto out;
- }
-
- /* Download the operational LMAC */
- ret = iwm_load_lmac(iwm, iwm->bus_ops->lmac_name);
- if (ret) {
- IWM_ERR(iwm, "LMAC loading failed\n");
- goto out;
- }
-
- ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_INIT_COMPLETE,
- IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
- if (ret) {
- IWM_ERR(iwm, "Handle INIT_COMPLETE failed for LMAC: %d\n", ret);
- goto out;
- }
-
- iwm_send_prio_table(iwm);
- iwm_send_calib_results(iwm);
- iwm_send_periodic_calib_cfg(iwm, periodic_calib_map);
- iwm_send_ct_kill_cfg(iwm, iwm->conf.ct_kill_entry,
- iwm->conf.ct_kill_exit);
-
- return 0;
-
- out:
- iwm_eeprom_exit(iwm);
- return ret;
-}
diff --git a/drivers/net/wireless/iwmc3200wifi/fw.h b/drivers/net/wireless/iwmc3200wifi/fw.h
deleted file mode 100644
index c70a3b40dad3..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/fw.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-#ifndef __IWM_FW_H__
-#define __IWM_FW_H__
-
-/**
- * struct iwm_fw_hdr_rec - An iwm firmware image is a
- * concatenation of various records. Each of them is
- * defined by an ID (aka op code), a length, and the
- * actual data.
- * @op_code: The record ID, see IWM_HDR_REC_OP_*
- *
- * @len: The record payload length
- *
- * @buf: The record payload
- */
-struct iwm_fw_hdr_rec {
- u16 op_code;
- u16 len;
- u8 buf[0];
-};
-
-/* Header's definitions */
-#define IWM_HDR_LEN (512)
-#define IWM_HDR_BARKER_LEN (16)
-
-/* Header's opcodes */
-#define IWM_HDR_REC_OP_INVALID (0x00)
-#define IWM_HDR_REC_OP_BUILD_DATE (0x01)
-#define IWM_HDR_REC_OP_BUILD_TAG (0x02)
-#define IWM_HDR_REC_OP_SW_VER (0x03)
-#define IWM_HDR_REC_OP_HW_SKU (0x04)
-#define IWM_HDR_REC_OP_BUILD_OPT (0x05)
-#define IWM_HDR_REC_OP_MEM_DESC (0x06)
-#define IWM_HDR_REC_USERDEFS (0x07)
-
-/* Header's records length (in bytes) */
-#define IWM_HDR_REC_LEN_BUILD_DATE (4)
-#define IWM_HDR_REC_LEN_BUILD_TAG (64)
-#define IWM_HDR_REC_LEN_SW_VER (4)
-#define IWM_HDR_REC_LEN_HW_SKU (4)
-#define IWM_HDR_REC_LEN_BUILD_OPT (4)
-#define IWM_HDR_REC_LEN_MEM_DESC (12)
-#define IWM_HDR_REC_LEN_USERDEF (64)
-
-#define IWM_BUILD_YEAR(date) ((date >> 16) & 0xffff)
-#define IWM_BUILD_MONTH(date) ((date >> 8) & 0xff)
-#define IWM_BUILD_DAY(date) (date & 0xff)
-
-struct iwm_fw_img_desc {
- u32 offset;
- u32 address;
- u32 length;
-};
-
-struct iwm_fw_img_ver {
- u8 minor;
- u8 major;
- u16 reserved;
-};
-
-int iwm_load_fw(struct iwm_priv *iwm);
-
-#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/hal.c b/drivers/net/wireless/iwmc3200wifi/hal.c
deleted file mode 100644
index 1cabcb39643f..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/hal.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-/*
- * Hardware Abstraction Layer for iwm.
- *
- * This file mostly defines an abstraction API for
- * sending various commands to the target.
- *
- * We have 2 types of commands: wifi and non-wifi ones.
- *
- * - wifi commands:
- * They are used for sending LMAC and UMAC commands,
- * and thus are the most commonly used ones.
- * There are 2 different wifi command types, the regular
- * one and the LMAC one. The former is used to send
- * UMAC commands (see UMAC_CMD_OPCODE_* from umac.h)
- * while the latter is used for sending commands to the
- * LMAC. If you look at LMAC commands you'll se that they
- * are actually regular iwlwifi target commands encapsulated
- * into a special UMAC command called UMAC passthrough.
- * This is due to the fact the host talks exclusively
- * to the UMAC and so there needs to be a special UMAC
- * command for talking to the LMAC.
- * This is how a wifi command is laid out:
- * ------------------------
- * | iwm_udma_out_wifi_hdr |
- * ------------------------
- * | SW meta_data (32 bits) |
- * ------------------------
- * | iwm_dev_cmd_hdr |
- * ------------------------
- * | payload |
- * | .... |
- *
- * - non-wifi, or general commands:
- * Those commands are handled by the device's bootrom,
- * and are typically sent when the UMAC and the LMAC
- * are not yet available.
- * * This is how a non-wifi command is laid out:
- * ---------------------------
- * | iwm_udma_out_nonwifi_hdr |
- * ---------------------------
- * | payload |
- * | .... |
-
- *
- * All the commands start with a UDMA header, which is
- * basically a 32 bits field. The 4 LSB there define
- * an opcode that allows the target to differentiate
- * between wifi (opcode is 0xf) and non-wifi commands
- * (opcode is [0..0xe]).
- *
- * When a command (wifi or non-wifi) is supposed to receive
- * an answer, we queue the command buffer. When we do receive
- * a command response from the UMAC, we go through the list
- * of pending command, and pass both the command and the answer
- * to the rx handler. Each command is sent with a unique
- * sequence id, and the answer is sent with the same one. This
- * is how we're supposed to match an answer with its command.
- * See rx.c:iwm_rx_handle_[non]wifi() and iwm_get_pending_[non]wifi()
- * for the implementation details.
- */
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/slab.h>
-
-#include "iwm.h"
-#include "bus.h"
-#include "hal.h"
-#include "umac.h"
-#include "debug.h"
-#include "trace.h"
-
-static int iwm_nonwifi_cmd_init(struct iwm_priv *iwm,
- struct iwm_nonwifi_cmd *cmd,
- struct iwm_udma_nonwifi_cmd *udma_cmd)
-{
- INIT_LIST_HEAD(&cmd->pending);
-
- spin_lock(&iwm->cmd_lock);
-
- cmd->resp_received = 0;
-
- cmd->seq_num = iwm->nonwifi_seq_num;
- udma_cmd->seq_num = cpu_to_le16(cmd->seq_num);
-
- iwm->nonwifi_seq_num++;
- iwm->nonwifi_seq_num %= UMAC_NONWIFI_SEQ_NUM_MAX;
-
- if (udma_cmd->resp)
- list_add_tail(&cmd->pending, &iwm->nonwifi_pending_cmd);
-
- spin_unlock(&iwm->cmd_lock);
-
- cmd->buf.start = cmd->buf.payload;
- cmd->buf.len = 0;
-
- memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd));
-
- return cmd->seq_num;
-}
-
-u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm)
-{
- u16 seq_num = iwm->wifi_seq_num;
-
- iwm->wifi_seq_num++;
- iwm->wifi_seq_num %= UMAC_WIFI_SEQ_NUM_MAX;
-
- return seq_num;
-}
-
-static void iwm_wifi_cmd_init(struct iwm_priv *iwm,
- struct iwm_wifi_cmd *cmd,
- struct iwm_udma_wifi_cmd *udma_cmd,
- struct iwm_umac_cmd *umac_cmd,
- struct iwm_lmac_cmd *lmac_cmd,
- u16 payload_size)
-{
- INIT_LIST_HEAD(&cmd->pending);
-
- spin_lock(&iwm->cmd_lock);
-
- cmd->seq_num = iwm_alloc_wifi_cmd_seq(iwm);
- umac_cmd->seq_num = cpu_to_le16(cmd->seq_num);
-
- if (umac_cmd->resp)
- list_add_tail(&cmd->pending, &iwm->wifi_pending_cmd);
-
- spin_unlock(&iwm->cmd_lock);
-
- cmd->buf.start = cmd->buf.payload;
- cmd->buf.len = 0;
-
- if (lmac_cmd) {
- cmd->buf.start -= sizeof(struct iwm_lmac_hdr);
-
- lmac_cmd->seq_num = cpu_to_le16(cmd->seq_num);
- lmac_cmd->count = cpu_to_le16(payload_size);
-
- memcpy(&cmd->lmac_cmd, lmac_cmd, sizeof(*lmac_cmd));
-
- umac_cmd->count = cpu_to_le16(sizeof(struct iwm_lmac_hdr));
- } else
- umac_cmd->count = 0;
-
- umac_cmd->count = cpu_to_le16(payload_size +
- le16_to_cpu(umac_cmd->count));
- udma_cmd->count = cpu_to_le16(sizeof(struct iwm_umac_fw_cmd_hdr) +
- le16_to_cpu(umac_cmd->count));
-
- memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd));
- memcpy(&cmd->umac_cmd, umac_cmd, sizeof(*umac_cmd));
-}
-
-void iwm_cmd_flush(struct iwm_priv *iwm)
-{
- struct iwm_wifi_cmd *wcmd, *wnext;
- struct iwm_nonwifi_cmd *nwcmd, *nwnext;
-
- list_for_each_entry_safe(wcmd, wnext, &iwm->wifi_pending_cmd, pending) {
- list_del(&wcmd->pending);
- kfree(wcmd);
- }
-
- list_for_each_entry_safe(nwcmd, nwnext, &iwm->nonwifi_pending_cmd,
- pending) {
- list_del(&nwcmd->pending);
- kfree(nwcmd);
- }
-}
-
-struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, u16 seq_num)
-{
- struct iwm_wifi_cmd *cmd;
-
- list_for_each_entry(cmd, &iwm->wifi_pending_cmd, pending)
- if (cmd->seq_num == seq_num) {
- list_del(&cmd->pending);
- return cmd;
- }
-
- return NULL;
-}
-
-struct iwm_nonwifi_cmd *iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm,
- u8 seq_num, u8 cmd_opcode)
-{
- struct iwm_nonwifi_cmd *cmd;
-
- list_for_each_entry(cmd, &iwm->nonwifi_pending_cmd, pending)
- if ((cmd->seq_num == seq_num) &&
- (cmd->udma_cmd.opcode == cmd_opcode) &&
- (cmd->resp_received)) {
- list_del(&cmd->pending);
- return cmd;
- }
-
- return NULL;
-}
-
-static void iwm_build_udma_nonwifi_hdr(struct iwm_priv *iwm,
- struct iwm_udma_out_nonwifi_hdr *hdr,
- struct iwm_udma_nonwifi_cmd *cmd)
-{
- memset(hdr, 0, sizeof(*hdr));
-
- SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE, cmd->opcode);
- SET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_RESP, cmd->resp);
- SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, 1);
- SET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW,
- cmd->handle_by_hw);
- SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_SIGNATURE, UMAC_HDI_OUT_SIGNATURE);
- SET_VAL32(hdr->cmd, UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM,
- le16_to_cpu(cmd->seq_num));
-
- hdr->addr = cmd->addr;
- hdr->op1_sz = cmd->op1_sz;
- hdr->op2 = cmd->op2;
-}
-
-static int iwm_send_udma_nonwifi_cmd(struct iwm_priv *iwm,
- struct iwm_nonwifi_cmd *cmd)
-{
- struct iwm_udma_out_nonwifi_hdr *udma_hdr;
- struct iwm_nonwifi_cmd_buff *buf;
- struct iwm_udma_nonwifi_cmd *udma_cmd = &cmd->udma_cmd;
-
- buf = &cmd->buf;
-
- buf->start -= sizeof(struct iwm_umac_nonwifi_out_hdr);
- buf->len += sizeof(struct iwm_umac_nonwifi_out_hdr);
-
- udma_hdr = (struct iwm_udma_out_nonwifi_hdr *)(buf->start);
-
- iwm_build_udma_nonwifi_hdr(iwm, udma_hdr, udma_cmd);
-
- IWM_DBG_CMD(iwm, DBG,
- "Send UDMA nonwifi cmd: opcode = 0x%x, resp = 0x%x, "
- "hw = 0x%x, seqnum = %d, addr = 0x%x, op1_sz = 0x%x, "
- "op2 = 0x%x\n", udma_cmd->opcode, udma_cmd->resp,
- udma_cmd->handle_by_hw, cmd->seq_num, udma_cmd->addr,
- udma_cmd->op1_sz, udma_cmd->op2);
-
- trace_iwm_tx_nonwifi_cmd(iwm, udma_hdr);
- return iwm_bus_send_chunk(iwm, buf->start, buf->len);
-}
-
-void iwm_udma_wifi_hdr_set_eop(struct iwm_priv *iwm, u8 *buf, u8 eop)
-{
- struct iwm_udma_out_wifi_hdr *hdr = (struct iwm_udma_out_wifi_hdr *)buf;
-
- SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, eop);
-}
-
-void iwm_build_udma_wifi_hdr(struct iwm_priv *iwm,
- struct iwm_udma_out_wifi_hdr *hdr,
- struct iwm_udma_wifi_cmd *cmd)
-{
- memset(hdr, 0, sizeof(*hdr));
-
- SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE, UMAC_HDI_OUT_OPCODE_WIFI);
- SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, cmd->eop);
- SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_SIGNATURE, UMAC_HDI_OUT_SIGNATURE);
-
- SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_BYTE_COUNT,
- le16_to_cpu(cmd->count));
- SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_CREDIT_GRP, cmd->credit_group);
- SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_RATID, cmd->ra_tid);
- SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_LMAC_OFFSET, cmd->lmac_offset);
-}
-
-void iwm_build_umac_hdr(struct iwm_priv *iwm,
- struct iwm_umac_fw_cmd_hdr *hdr,
- struct iwm_umac_cmd *cmd)
-{
- memset(hdr, 0, sizeof(*hdr));
-
- SET_VAL32(hdr->meta_data, UMAC_FW_CMD_BYTE_COUNT,
- le16_to_cpu(cmd->count));
- SET_VAL32(hdr->meta_data, UMAC_FW_CMD_TX_STA_COLOR, cmd->color);
- SET_VAL8(hdr->cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ, cmd->resp);
-
- hdr->cmd.cmd = cmd->id;
- hdr->cmd.seq_num = cmd->seq_num;
-}
-
-static int iwm_send_udma_wifi_cmd(struct iwm_priv *iwm,
- struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_wifi_out_hdr *umac_hdr;
- struct iwm_wifi_cmd_buff *buf;
- struct iwm_udma_wifi_cmd *udma_cmd = &cmd->udma_cmd;
- struct iwm_umac_cmd *umac_cmd = &cmd->umac_cmd;
- int ret;
-
- buf = &cmd->buf;
-
- buf->start -= sizeof(struct iwm_umac_wifi_out_hdr);
- buf->len += sizeof(struct iwm_umac_wifi_out_hdr);
-
- umac_hdr = (struct iwm_umac_wifi_out_hdr *)(buf->start);
-
- iwm_build_udma_wifi_hdr(iwm, &umac_hdr->hw_hdr, udma_cmd);
- iwm_build_umac_hdr(iwm, &umac_hdr->sw_hdr, umac_cmd);
-
- IWM_DBG_CMD(iwm, DBG,
- "Send UDMA wifi cmd: opcode = 0x%x, UMAC opcode = 0x%x, "
- "eop = 0x%x, count = 0x%x, credit_group = 0x%x, "
- "ra_tid = 0x%x, lmac_offset = 0x%x, seqnum = %d\n",
- UMAC_HDI_OUT_OPCODE_WIFI, umac_cmd->id,
- udma_cmd->eop, udma_cmd->count, udma_cmd->credit_group,
- udma_cmd->ra_tid, udma_cmd->lmac_offset, cmd->seq_num);
-
- if (umac_cmd->id == UMAC_CMD_OPCODE_WIFI_PASS_THROUGH)
- IWM_DBG_CMD(iwm, DBG, "\tLMAC opcode: 0x%x\n",
- cmd->lmac_cmd.id);
-
- ret = iwm_tx_credit_alloc(iwm, udma_cmd->credit_group, buf->len);
-
- /* We keep sending UMAC reset regardless of the command credits.
- * The UMAC is supposed to be reset anyway and the Tx credits are
- * reinitialized afterwards. If we are lucky, the reset could
- * still be done even though we have run out of credits for the
- * command pool at this moment.*/
- if (ret && (umac_cmd->id != UMAC_CMD_OPCODE_RESET)) {
- IWM_DBG_TX(iwm, DBG, "Failed to alloc tx credit for cmd %d\n",
- umac_cmd->id);
- return ret;
- }
-
- trace_iwm_tx_wifi_cmd(iwm, umac_hdr);
- return iwm_bus_send_chunk(iwm, buf->start, buf->len);
-}
-
-/* target_cmd a.k.a udma_nonwifi_cmd can be sent when UMAC is not available */
-int iwm_hal_send_target_cmd(struct iwm_priv *iwm,
- struct iwm_udma_nonwifi_cmd *udma_cmd,
- const void *payload)
-{
- struct iwm_nonwifi_cmd *cmd;
- int ret, seq_num;
-
- cmd = kzalloc(sizeof(struct iwm_nonwifi_cmd), GFP_KERNEL);
- if (!cmd) {
- IWM_ERR(iwm, "Couldn't alloc memory for hal cmd\n");
- return -ENOMEM;
- }
-
- seq_num = iwm_nonwifi_cmd_init(iwm, cmd, udma_cmd);
-
- if (cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE ||
- cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT) {
- cmd->buf.len = le32_to_cpu(cmd->udma_cmd.op1_sz);
- memcpy(&cmd->buf.payload, payload, cmd->buf.len);
- }
-
- ret = iwm_send_udma_nonwifi_cmd(iwm, cmd);
-
- if (!udma_cmd->resp)
- kfree(cmd);
-
- if (ret < 0)
- return ret;
-
- return seq_num;
-}
-
-static void iwm_build_lmac_hdr(struct iwm_priv *iwm, struct iwm_lmac_hdr *hdr,
- struct iwm_lmac_cmd *cmd)
-{
- memset(hdr, 0, sizeof(*hdr));
-
- hdr->id = cmd->id;
- hdr->flags = 0; /* Is this ever used? */
- hdr->seq_num = cmd->seq_num;
-}
-
-/*
- * iwm_hal_send_host_cmd(): sends commands to the UMAC or the LMAC.
- * Sending command to the LMAC is equivalent to sending a
- * regular UMAC command with the LMAC passthrough or the LMAC
- * wrapper UMAC command IDs.
- */
-int iwm_hal_send_host_cmd(struct iwm_priv *iwm,
- struct iwm_udma_wifi_cmd *udma_cmd,
- struct iwm_umac_cmd *umac_cmd,
- struct iwm_lmac_cmd *lmac_cmd,
- const void *payload, u16 payload_size)
-{
- struct iwm_wifi_cmd *cmd;
- struct iwm_lmac_hdr *hdr;
- int lmac_hdr_len = 0;
- int ret;
-
- cmd = kzalloc(sizeof(struct iwm_wifi_cmd), GFP_KERNEL);
- if (!cmd) {
- IWM_ERR(iwm, "Couldn't alloc memory for wifi hal cmd\n");
- return -ENOMEM;
- }
-
- iwm_wifi_cmd_init(iwm, cmd, udma_cmd, umac_cmd, lmac_cmd, payload_size);
-
- if (lmac_cmd) {
- hdr = (struct iwm_lmac_hdr *)(cmd->buf.start);
-
- iwm_build_lmac_hdr(iwm, hdr, &cmd->lmac_cmd);
- lmac_hdr_len = sizeof(struct iwm_lmac_hdr);
- }
-
- memcpy(cmd->buf.payload, payload, payload_size);
- cmd->buf.len = le16_to_cpu(umac_cmd->count);
-
- ret = iwm_send_udma_wifi_cmd(iwm, cmd);
-
- /* We free the cmd if we're not expecting any response */
- if (!umac_cmd->resp)
- kfree(cmd);
- return ret;
-}
-
-/*
- * iwm_hal_send_umac_cmd(): This is a special case for
- * iwm_hal_send_host_cmd() to send direct UMAC cmd (without
- * LMAC involved).
- */
-int iwm_hal_send_umac_cmd(struct iwm_priv *iwm,
- struct iwm_udma_wifi_cmd *udma_cmd,
- struct iwm_umac_cmd *umac_cmd,
- const void *payload, u16 payload_size)
-{
- return iwm_hal_send_host_cmd(iwm, udma_cmd, umac_cmd, NULL,
- payload, payload_size);
-}
diff --git a/drivers/net/wireless/iwmc3200wifi/hal.h b/drivers/net/wireless/iwmc3200wifi/hal.h
deleted file mode 100644
index c20936d9b6b7..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/hal.h
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-#ifndef _IWM_HAL_H_
-#define _IWM_HAL_H_
-
-#include "umac.h"
-
-#define GET_VAL8(s, name) ((s >> name##_POS) & name##_SEED)
-#define GET_VAL16(s, name) ((le16_to_cpu(s) >> name##_POS) & name##_SEED)
-#define GET_VAL32(s, name) ((le32_to_cpu(s) >> name##_POS) & name##_SEED)
-
-#define SET_VAL8(s, name, val) \
-do { \
- s = (s & ~(name##_SEED << name##_POS)) | \
- ((val & name##_SEED) << name##_POS); \
-} while (0)
-
-#define SET_VAL16(s, name, val) \
-do { \
- s = cpu_to_le16((le16_to_cpu(s) & ~(name##_SEED << name##_POS)) | \
- ((val & name##_SEED) << name##_POS)); \
-} while (0)
-
-#define SET_VAL32(s, name, val) \
-do { \
- s = cpu_to_le32((le32_to_cpu(s) & ~(name##_SEED << name##_POS)) | \
- ((val & name##_SEED) << name##_POS)); \
-} while (0)
-
-
-#define UDMA_UMAC_INIT { .eop = 1, \
- .credit_group = 0x4, \
- .ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD, \
- .lmac_offset = 0 }
-#define UDMA_LMAC_INIT { .eop = 1, \
- .credit_group = 0x4, \
- .ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD, \
- .lmac_offset = 4 }
-
-
-/* UDMA IN OP CODE -- cmd bits [3:0] */
-#define UDMA_HDI_IN_NW_CMD_OPCODE_POS 0
-#define UDMA_HDI_IN_NW_CMD_OPCODE_SEED 0xF
-
-#define UDMA_IN_OPCODE_GENERAL_RESP 0x0
-#define UDMA_IN_OPCODE_READ_RESP 0x1
-#define UDMA_IN_OPCODE_WRITE_RESP 0x2
-#define UDMA_IN_OPCODE_PERS_WRITE_RESP 0x5
-#define UDMA_IN_OPCODE_PERS_READ_RESP 0x6
-#define UDMA_IN_OPCODE_RD_MDFY_WR_RESP 0x7
-#define UDMA_IN_OPCODE_EP_MNGMT_MSG 0x8
-#define UDMA_IN_OPCODE_CRDT_CHNG_MSG 0x9
-#define UDMA_IN_OPCODE_CNTRL_DATABASE_MSG 0xA
-#define UDMA_IN_OPCODE_SW_MSG 0xB
-#define UDMA_IN_OPCODE_WIFI 0xF
-#define UDMA_IN_OPCODE_WIFI_LMAC 0x1F
-#define UDMA_IN_OPCODE_WIFI_UMAC 0x2F
-
-/* HW API: udma_hdi_nonwifi API (OUT and IN) */
-
-/* iwm_udma_nonwifi_cmd request response -- bits [9:9] */
-#define UDMA_HDI_OUT_NW_CMD_RESP_POS 9
-#define UDMA_HDI_OUT_NW_CMD_RESP_SEED 0x1
-
-/* iwm_udma_nonwifi_cmd handle by HW -- bits [11:11] */
-#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_POS 11
-#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_SEED 0x1
-
-/* iwm_udma_nonwifi_cmd sequence-number -- bits [12:15] */
-#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_POS 12
-#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_SEED 0xF
-
-/* UDMA IN Non-WIFI HW sequence number -- bits [12:15] */
-#define UDMA_IN_NW_HW_SEQ_NUM_POS 12
-#define UDMA_IN_NW_HW_SEQ_NUM_SEED 0xF
-
-/* UDMA IN Non-WIFI HW signature -- bits [16:31] */
-#define UDMA_IN_NW_HW_SIG_POS 16
-#define UDMA_IN_NW_HW_SIG_SEED 0xFFFF
-
-/* fixed signature */
-#define UDMA_IN_NW_HW_SIG 0xCBBC
-
-/* UDMA IN Non-WIFI HW block length -- bits [32:35] */
-#define UDMA_IN_NW_HW_LENGTH_SEED 0xF
-#define UDMA_IN_NW_HW_LENGTH_POS 32
-
-/* End of HW API: udma_hdi_nonwifi API (OUT and IN) */
-
-#define IWM_SDIO_FW_MAX_CHUNK_SIZE 2032
-#define IWM_MAX_WIFI_HEADERS_SIZE 32
-#define IWM_MAX_NONWIFI_HEADERS_SIZE 16
-#define IWM_MAX_NONWIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \
- IWM_MAX_NONWIFI_HEADERS_SIZE)
-#define IWM_MAX_WIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \
- IWM_MAX_WIFI_HEADERS_SIZE)
-
-#define IWM_HAL_CONCATENATE_BUF_SIZE (32 * 1024)
-
-struct iwm_wifi_cmd_buff {
- u16 len;
- u8 *start;
- u8 hdr[IWM_MAX_WIFI_HEADERS_SIZE];
- u8 payload[IWM_MAX_WIFI_CMD_BUFF_SIZE];
-};
-
-struct iwm_nonwifi_cmd_buff {
- u16 len;
- u8 *start;
- u8 hdr[IWM_MAX_NONWIFI_HEADERS_SIZE];
- u8 payload[IWM_MAX_NONWIFI_CMD_BUFF_SIZE];
-};
-
-struct iwm_udma_nonwifi_cmd {
- u8 opcode;
- u8 eop;
- u8 resp;
- u8 handle_by_hw;
- __le32 addr;
- __le32 op1_sz;
- __le32 op2;
- __le16 seq_num;
-};
-
-struct iwm_udma_wifi_cmd {
- __le16 count;
- u8 eop;
- u8 credit_group;
- u8 ra_tid;
- u8 lmac_offset;
-};
-
-struct iwm_umac_cmd {
- u8 id;
- __le16 count;
- u8 resp;
- __le16 seq_num;
- u8 color;
-};
-
-struct iwm_lmac_cmd {
- u8 id;
- __le16 count;
- u8 resp;
- __le16 seq_num;
-};
-
-struct iwm_nonwifi_cmd {
- u16 seq_num;
- bool resp_received;
- struct list_head pending;
- struct iwm_udma_nonwifi_cmd udma_cmd;
- struct iwm_umac_cmd umac_cmd;
- struct iwm_lmac_cmd lmac_cmd;
- struct iwm_nonwifi_cmd_buff buf;
- u32 flags;
-};
-
-struct iwm_wifi_cmd {
- u16 seq_num;
- struct list_head pending;
- struct iwm_udma_wifi_cmd udma_cmd;
- struct iwm_umac_cmd umac_cmd;
- struct iwm_lmac_cmd lmac_cmd;
- struct iwm_wifi_cmd_buff buf;
- u32 flags;
-};
-
-void iwm_cmd_flush(struct iwm_priv *iwm);
-
-struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm,
- u16 seq_num);
-struct iwm_nonwifi_cmd *iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm,
- u8 seq_num, u8 cmd_opcode);
-
-
-int iwm_hal_send_target_cmd(struct iwm_priv *iwm,
- struct iwm_udma_nonwifi_cmd *ucmd,
- const void *payload);
-
-int iwm_hal_send_host_cmd(struct iwm_priv *iwm,
- struct iwm_udma_wifi_cmd *udma_cmd,
- struct iwm_umac_cmd *umac_cmd,
- struct iwm_lmac_cmd *lmac_cmd,
- const void *payload, u16 payload_size);
-
-int iwm_hal_send_umac_cmd(struct iwm_priv *iwm,
- struct iwm_udma_wifi_cmd *udma_cmd,
- struct iwm_umac_cmd *umac_cmd,
- const void *payload, u16 payload_size);
-
-u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm);
-
-void iwm_udma_wifi_hdr_set_eop(struct iwm_priv *iwm, u8 *buf, u8 eop);
-void iwm_build_udma_wifi_hdr(struct iwm_priv *iwm,
- struct iwm_udma_out_wifi_hdr *hdr,
- struct iwm_udma_wifi_cmd *cmd);
-void iwm_build_umac_hdr(struct iwm_priv *iwm,
- struct iwm_umac_fw_cmd_hdr *hdr,
- struct iwm_umac_cmd *cmd);
-#endif /* _IWM_HAL_H_ */
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h
deleted file mode 100644
index 51d7efa15ae6..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/iwm.h
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-#ifndef __IWM_H__
-#define __IWM_H__
-
-#include <linux/netdevice.h>
-#include <linux/wireless.h>
-#include <net/cfg80211.h>
-
-#include "debug.h"
-#include "hal.h"
-#include "umac.h"
-#include "lmac.h"
-#include "eeprom.h"
-#include "trace.h"
-
-#define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation"
-#define IWM_AUTHOR "<ilw@linux.intel.com>"
-
-#define IWM_SRC_LMAC UMAC_HDI_IN_SOURCE_FHRX
-#define IWM_SRC_UDMA UMAC_HDI_IN_SOURCE_UDMA
-#define IWM_SRC_UMAC UMAC_HDI_IN_SOURCE_FW
-#define IWM_SRC_NUM 3
-
-#define IWM_POWER_INDEX_MIN 0
-#define IWM_POWER_INDEX_MAX 5
-#define IWM_POWER_INDEX_DEFAULT 3
-
-struct iwm_conf {
- u32 sdio_ior_timeout;
- unsigned long calib_map;
- unsigned long expected_calib_map;
- u8 ct_kill_entry;
- u8 ct_kill_exit;
- bool reset_on_fatal_err;
- bool auto_connect;
- bool wimax_not_present;
- bool enable_qos;
- u32 mode;
-
- u32 power_index;
- u32 frag_threshold;
- u32 rts_threshold;
- bool cts_to_self;
-
- u32 assoc_timeout;
- u32 roam_timeout;
- u32 wireless_mode;
-
- u8 ibss_band;
- u8 ibss_channel;
-
- u8 mac_addr[ETH_ALEN];
-};
-
-enum {
- COEX_MODE_SA = 1,
- COEX_MODE_XOR,
- COEX_MODE_CM,
- COEX_MODE_MAX,
-};
-
-struct iwm_if_ops;
-struct iwm_wifi_cmd;
-
-struct pool_entry {
- int id; /* group id */
- int sid; /* super group id */
- int min_pages; /* min capacity in pages */
- int max_pages; /* max capacity in pages */
- int alloc_pages; /* allocated # of pages. incresed by driver */
- int total_freed_pages; /* total freed # of pages. incresed by UMAC */
-};
-
-struct spool_entry {
- int id;
- int max_pages;
- int alloc_pages;
-};
-
-struct iwm_tx_credit {
- spinlock_t lock;
- int pool_nr;
- unsigned long full_pools_map; /* bitmap for # of filled tx pools */
- struct pool_entry pools[IWM_MACS_OUT_GROUPS];
- struct spool_entry spools[IWM_MACS_OUT_SGROUPS];
-};
-
-struct iwm_notif {
- struct list_head pending;
- u32 cmd_id;
- void *cmd;
- u8 src;
- void *buf;
- unsigned long buf_size;
-};
-
-struct iwm_tid_info {
- __le16 last_seq_num;
- bool stopped;
- struct mutex mutex;
-};
-
-struct iwm_sta_info {
- u8 addr[ETH_ALEN];
- bool valid;
- bool qos;
- u8 color;
- struct iwm_tid_info tid_info[IWM_UMAC_TID_NR];
-};
-
-struct iwm_tx_info {
- u8 sta;
- u8 color;
- u8 tid;
-};
-
-struct iwm_rx_info {
- unsigned long rx_size;
- unsigned long rx_buf_size;
-};
-
-#define IWM_NUM_KEYS 4
-
-struct iwm_umac_key_hdr {
- u8 mac[ETH_ALEN];
- u8 key_idx;
- u8 multicast; /* BCast encrypt & BCast decrypt of frames FROM mac */
-} __packed;
-
-struct iwm_key {
- struct iwm_umac_key_hdr hdr;
- u32 cipher;
- u8 key[WLAN_MAX_KEY_LEN];
- u8 seq[IW_ENCODE_SEQ_MAX_SIZE];
- int key_len;
- int seq_len;
-};
-
-#define IWM_RX_ID_HASH 0xff
-#define IWM_RX_ID_GET_HASH(id) ((id) % IWM_RX_ID_HASH)
-
-#define IWM_STA_TABLE_NUM 16
-#define IWM_TX_LIST_SIZE 64
-#define IWM_RX_LIST_SIZE 256
-
-#define IWM_SCAN_ID_MAX 0xff
-
-#define IWM_STATUS_READY 0
-#define IWM_STATUS_SCANNING 1
-#define IWM_STATUS_SCAN_ABORTING 2
-#define IWM_STATUS_SME_CONNECTING 3
-#define IWM_STATUS_ASSOCIATED 4
-#define IWM_STATUS_RESETTING 5
-
-struct iwm_tx_queue {
- int id;
- struct sk_buff_head queue;
- struct sk_buff_head stopped_queue;
- spinlock_t lock;
- struct workqueue_struct *wq;
- struct work_struct worker;
- u8 concat_buf[IWM_HAL_CONCATENATE_BUF_SIZE];
- int concat_count;
- u8 *concat_ptr;
-};
-
-/* Queues 0 ~ 3 for AC data, 5 for iPAN */
-#define IWM_TX_QUEUES 5
-#define IWM_TX_DATA_QUEUES 4
-#define IWM_TX_CMD_QUEUE 4
-
-struct iwm_bss_info {
- struct list_head node;
- struct cfg80211_bss *cfg_bss;
- struct iwm_umac_notif_bss_info *bss;
-};
-
-typedef int (*iwm_handler)(struct iwm_priv *priv, u8 *buf,
- unsigned long buf_size, struct iwm_wifi_cmd *cmd);
-
-#define IWM_WATCHDOG_PERIOD (6 * HZ)
-
-struct iwm_priv {
- struct wireless_dev *wdev;
- struct iwm_if_ops *bus_ops;
-
- struct iwm_conf conf;
-
- unsigned long status;
-
- struct list_head pending_notif;
- wait_queue_head_t notif_queue;
-
- wait_queue_head_t nonwifi_queue;
-
- unsigned long calib_done_map;
- struct {
- u8 *buf;
- u32 size;
- } calib_res[CALIBRATION_CMD_NUM];
-
- struct iwm_umac_profile *umac_profile;
- bool umac_profile_active;
-
- u8 bssid[ETH_ALEN];
- u8 channel;
- u16 rate;
- u32 txpower;
-
- struct iwm_sta_info sta_table[IWM_STA_TABLE_NUM];
- struct list_head bss_list;
-
- void (*nonwifi_rx_handlers[UMAC_HDI_IN_OPCODE_NONWIFI_MAX])
- (struct iwm_priv *priv, u8 *buf, unsigned long buf_size);
-
- const iwm_handler *umac_handlers;
- const iwm_handler *lmac_handlers;
- DECLARE_BITMAP(lmac_handler_map, LMAC_COMMAND_ID_NUM);
- DECLARE_BITMAP(umac_handler_map, LMAC_COMMAND_ID_NUM);
- DECLARE_BITMAP(udma_handler_map, LMAC_COMMAND_ID_NUM);
-
- struct list_head wifi_pending_cmd;
- struct list_head nonwifi_pending_cmd;
- u16 wifi_seq_num;
- u8 nonwifi_seq_num;
- spinlock_t cmd_lock;
-
- u32 core_enabled;
-
- u8 scan_id;
- struct cfg80211_scan_request *scan_request;
-
- struct sk_buff_head rx_list;
- struct list_head rx_tickets;
- spinlock_t ticket_lock;
- struct list_head rx_packets[IWM_RX_ID_HASH];
- spinlock_t packet_lock[IWM_RX_ID_HASH];
- struct workqueue_struct *rx_wq;
- struct work_struct rx_worker;
-
- struct iwm_tx_credit tx_credit;
- struct iwm_tx_queue txq[IWM_TX_QUEUES];
-
- struct iwm_key keys[IWM_NUM_KEYS];
- s8 default_key;
-
- DECLARE_BITMAP(wifi_ntfy, WIFI_IF_NTFY_MAX);
- wait_queue_head_t wifi_ntfy_queue;
-
- wait_queue_head_t mlme_queue;
-
- struct iw_statistics wstats;
- struct delayed_work stats_request;
- struct delayed_work disconnect;
- struct delayed_work ct_kill_delay;
-
- struct iwm_debugfs dbg;
-
- u8 *eeprom;
- struct timer_list watchdog;
- struct work_struct reset_worker;
- struct work_struct auth_retry_worker;
- struct mutex mutex;
-
- u8 *req_ie;
- int req_ie_len;
- u8 *resp_ie;
- int resp_ie_len;
-
- struct iwm_fw_error_hdr *last_fw_err;
- char umac_version[8];
- char lmac_version[8];
-
- char private[0] __attribute__((__aligned__(NETDEV_ALIGN)));
-};
-
-static inline void *iwm_private(struct iwm_priv *iwm)
-{
- BUG_ON(!iwm);
- return &iwm->private;
-}
-
-#define hw_to_iwm(h) (h->iwm)
-#define iwm_to_dev(i) (wiphy_dev(i->wdev->wiphy))
-#define iwm_to_wiphy(i) (i->wdev->wiphy)
-#define wiphy_to_iwm(w) (struct iwm_priv *)(wiphy_priv(w))
-#define iwm_to_wdev(i) (i->wdev)
-#define wdev_to_iwm(w) (struct iwm_priv *)(wdev_priv(w))
-#define iwm_to_ndev(i) (i->wdev->netdev)
-#define ndev_to_iwm(n) (wdev_to_iwm(n->ieee80211_ptr))
-#define skb_to_rx_info(s) ((struct iwm_rx_info *)(s->cb))
-#define skb_to_tx_info(s) ((struct iwm_tx_info *)s->cb)
-
-void *iwm_if_alloc(int sizeof_bus, struct device *dev,
- struct iwm_if_ops *if_ops);
-void iwm_if_free(struct iwm_priv *iwm);
-int iwm_if_add(struct iwm_priv *iwm);
-void iwm_if_remove(struct iwm_priv *iwm);
-int iwm_mode_to_nl80211_iftype(int mode);
-int iwm_priv_init(struct iwm_priv *iwm);
-void iwm_priv_deinit(struct iwm_priv *iwm);
-void iwm_reset(struct iwm_priv *iwm);
-void iwm_resetting(struct iwm_priv *iwm);
-void iwm_tx_credit_init_pools(struct iwm_priv *iwm,
- struct iwm_umac_notif_alive *alive);
-int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb);
-int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd,
- u8 cmd_id, u8 source, u8 *buf, unsigned long buf_size);
-int iwm_notif_handle(struct iwm_priv *iwm, u32 cmd, u8 source, long timeout);
-void iwm_init_default_profile(struct iwm_priv *iwm,
- struct iwm_umac_profile *profile);
-void iwm_link_on(struct iwm_priv *iwm);
-void iwm_link_off(struct iwm_priv *iwm);
-int iwm_up(struct iwm_priv *iwm);
-int iwm_down(struct iwm_priv *iwm);
-
-/* TX API */
-int iwm_tid_to_queue(u16 tid);
-void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages);
-void iwm_tx_worker(struct work_struct *work);
-int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
-
-/* RX API */
-void iwm_rx_setup_handlers(struct iwm_priv *iwm);
-int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size);
-int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size,
- struct iwm_wifi_cmd *cmd);
-void iwm_rx_free(struct iwm_priv *iwm);
-
-#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/lmac.h b/drivers/net/wireless/iwmc3200wifi/lmac.h
deleted file mode 100644
index 5ddcdf8c70c0..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/lmac.h
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-#ifndef __IWM_LMAC_H__
-#define __IWM_LMAC_H__
-
-struct iwm_lmac_hdr {
- u8 id;
- u8 flags;
- __le16 seq_num;
-} __packed;
-
-/* LMAC commands */
-#define CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK 0x1
-
-struct iwm_lmac_cal_cfg_elt {
- __le32 enable; /* 1 means LMAC needs to do something */
- __le32 start; /* 1 to start calibration, 0 to stop */
- __le32 send_res; /* 1 for sending back results */
- __le32 apply_res; /* 1 for applying calibration results to HW */
- __le32 reserved;
-} __packed;
-
-struct iwm_lmac_cal_cfg_status {
- struct iwm_lmac_cal_cfg_elt init;
- struct iwm_lmac_cal_cfg_elt periodic;
- __le32 flags; /* CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK */
-} __packed;
-
-struct iwm_lmac_cal_cfg_cmd {
- struct iwm_lmac_cal_cfg_status ucode_cfg;
- struct iwm_lmac_cal_cfg_status driver_cfg;
- __le32 reserved;
-} __packed;
-
-struct iwm_lmac_cal_cfg_resp {
- __le32 status;
-} __packed;
-
-#define IWM_CARD_STATE_SW_HW_ENABLED 0x00
-#define IWM_CARD_STATE_HW_DISABLED 0x01
-#define IWM_CARD_STATE_SW_DISABLED 0x02
-#define IWM_CARD_STATE_CTKILL_DISABLED 0x04
-#define IWM_CARD_STATE_IS_RXON 0x10
-
-struct iwm_lmac_card_state {
- __le32 flags;
-} __packed;
-
-/**
- * COEX_PRIORITY_TABLE_CMD
- *
- * Priority entry for each state
- * Will keep two tables, for STA and WIPAN
- */
-enum {
- /* UN-ASSOCIATION PART */
- COEX_UNASSOC_IDLE = 0,
- COEX_UNASSOC_MANUAL_SCAN,
- COEX_UNASSOC_AUTO_SCAN,
-
- /* CALIBRATION */
- COEX_CALIBRATION,
- COEX_PERIODIC_CALIBRATION,
-
- /* CONNECTION */
- COEX_CONNECTION_ESTAB,
-
- /* ASSOCIATION PART */
- COEX_ASSOCIATED_IDLE,
- COEX_ASSOC_MANUAL_SCAN,
- COEX_ASSOC_AUTO_SCAN,
- COEX_ASSOC_ACTIVE_LEVEL,
-
- /* RF ON/OFF */
- COEX_RF_ON,
- COEX_RF_OFF,
- COEX_STAND_ALONE_DEBUG,
-
- /* IPNN */
- COEX_IPAN_ASSOC_LEVEL,
-
- /* RESERVED */
- COEX_RSRVD1,
- COEX_RSRVD2,
-
- COEX_EVENTS_NUM
-};
-
-#define COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK 0x1
-#define COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK 0x2
-#define COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK 0x4
-
-struct coex_event {
- u8 req_prio;
- u8 win_med_prio;
- u8 reserved;
- u8 flags;
-} __packed;
-
-#define COEX_FLAGS_STA_TABLE_VALID_MSK 0x1
-#define COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK 0x4
-#define COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK 0x8
-#define COEX_FLAGS_COEX_ENABLE_MSK 0x80
-
-struct iwm_coex_prio_table_cmd {
- u8 flags;
- u8 reserved[3];
- struct coex_event sta_prio[COEX_EVENTS_NUM];
-} __packed;
-
-/* Coexistence definitions
- *
- * Constants to fill in the Priorities' Tables
- * RP - Requested Priority
- * WP - Win Medium Priority: priority assigned when the contention has been won
- * FLAGS - Combination of COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK and
- * COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK
- */
-
-#define COEX_UNASSOC_IDLE_FLAGS 0
-#define COEX_UNASSOC_MANUAL_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
- COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
-#define COEX_UNASSOC_AUTO_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
- COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
-#define COEX_CALIBRATION_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
- COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
-#define COEX_PERIODIC_CALIBRATION_FLAGS 0
-/* COEX_CONNECTION_ESTAB: we need DELAY_MEDIUM_FREE_NTFY to let WiMAX
- * disconnect from network. */
-#define COEX_CONNECTION_ESTAB_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
- COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \
- COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK)
-#define COEX_ASSOCIATED_IDLE_FLAGS 0
-#define COEX_ASSOC_MANUAL_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
- COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
-#define COEX_ASSOC_AUTO_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
- COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
-#define COEX_ASSOC_ACTIVE_LEVEL_FLAGS 0
-#define COEX_RF_ON_FLAGS 0
-#define COEX_RF_OFF_FLAGS 0
-#define COEX_STAND_ALONE_DEBUG_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
- COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
-#define COEX_IPAN_ASSOC_LEVEL_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
- COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \
- COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK)
-#define COEX_RSRVD1_FLAGS 0
-#define COEX_RSRVD2_FLAGS 0
-/* XOR_RF_ON is the event wrapping all radio ownership. We need
- * DELAY_MEDIUM_FREE_NTFY to let WiMAX disconnect from network. */
-#define COEX_XOR_RF_ON_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
- COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \
- COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK)
-
-/* CT kill config command */
-struct iwm_ct_kill_cfg_cmd {
- u32 exit_threshold;
- u32 reserved;
- u32 entry_threshold;
-} __packed;
-
-
-/* LMAC OP CODES */
-#define REPLY_PAD 0x0
-#define REPLY_ALIVE 0x1
-#define REPLY_ERROR 0x2
-#define REPLY_ECHO 0x3
-#define REPLY_HALT 0x6
-
-/* RXON state commands */
-#define REPLY_RX_ON 0x10
-#define REPLY_RX_ON_ASSOC 0x11
-#define REPLY_RX_OFF 0x12
-#define REPLY_QOS_PARAM 0x13
-#define REPLY_RX_ON_TIMING 0x14
-#define REPLY_INTERNAL_QOS_PARAM 0x15
-#define REPLY_RX_INT_TIMEOUT_CNFG 0x16
-#define REPLY_NULL 0x17
-
-/* Multi-Station support */
-#define REPLY_ADD_STA 0x18
-#define REPLY_REMOVE_STA 0x19
-#define REPLY_RESET_ALL_STA 0x1a
-
-/* RX, TX */
-#define REPLY_ALM_RX 0x1b
-#define REPLY_TX 0x1c
-#define REPLY_TXFIFO_FLUSH 0x1e
-
-/* MISC commands */
-#define REPLY_MGMT_MCAST_KEY 0x1f
-#define REPLY_WEPKEY 0x20
-#define REPLY_INIT_IV 0x21
-#define REPLY_WRITE_MIB 0x22
-#define REPLY_READ_MIB 0x23
-#define REPLY_RADIO_FE 0x24
-#define REPLY_TXFIFO_CFG 0x25
-#define REPLY_WRITE_READ 0x26
-#define REPLY_INSTALL_SEC_KEY 0x27
-
-
-#define REPLY_RATE_SCALE 0x47
-#define REPLY_LEDS_CMD 0x48
-#define REPLY_TX_LINK_QUALITY_CMD 0x4e
-#define REPLY_ANA_MIB_OVERRIDE_CMD 0x4f
-#define REPLY_WRITE2REG_CMD 0x50
-
-/* winfi-wifi coexistence */
-#define COEX_PRIORITY_TABLE_CMD 0x5a
-#define COEX_MEDIUM_NOTIFICATION 0x5b
-#define COEX_EVENT_CMD 0x5c
-
-/* more Protocol and Protocol-test commands */
-#define REPLY_MAX_SLEEP_TIME_CMD 0x61
-#define CALIBRATION_CFG_CMD 0x65
-#define CALIBRATION_RES_NOTIFICATION 0x66
-#define CALIBRATION_COMPLETE_NOTIFICATION 0x67
-
-/* Measurements */
-#define REPLY_QUIET_CMD 0x71
-#define REPLY_CHANNEL_SWITCH 0x72
-#define CHANNEL_SWITCH_NOTIFICATION 0x73
-
-#define REPLY_SPECTRUM_MEASUREMENT_CMD 0x74
-#define SPECTRUM_MEASURE_NOTIFICATION 0x75
-#define REPLY_MEASUREMENT_ABORT_CMD 0x76
-
-/* Power Management */
-#define POWER_TABLE_CMD 0x77
-#define SAVE_RESTORE_ADDRESS_CMD 0x78
-#define REPLY_WATERMARK_CMD 0x79
-#define PM_DEBUG_STATISTIC_NOTIFIC 0x7B
-#define PD_FLUSH_N_NOTIFICATION 0x7C
-
-/* Scan commands and notifications */
-#define REPLY_SCAN_REQUEST_CMD 0x80
-#define REPLY_SCAN_ABORT_CMD 0x81
-#define SCAN_START_NOTIFICATION 0x82
-#define SCAN_RESULTS_NOTIFICATION 0x83
-#define SCAN_COMPLETE_NOTIFICATION 0x84
-
-/* Continuous TX commands */
-#define REPLY_CONT_TX_CMD 0x85
-#define END_OF_CONT_TX_NOTIFICATION 0x86
-
-/* Timer/Eeprom commands */
-#define TIMER_CMD 0x87
-#define EEPROM_WRITE_CMD 0x88
-
-/* PAPD commands */
-#define FEEDBACK_REQUEST_NOTIFICATION 0x8b
-#define REPLY_CW_CMD 0x8c
-
-/* IBSS/AP commands Continue */
-#define BEACON_NOTIFICATION 0x90
-#define REPLY_TX_BEACON 0x91
-#define REPLY_REQUEST_ATIM 0x93
-#define WHO_IS_AWAKE_NOTIFICATION 0x94
-#define TX_PWR_DBM_LIMIT_CMD 0x95
-#define QUIET_NOTIFICATION 0x96
-#define TX_PWR_TABLE_CMD 0x97
-#define TX_ANT_CONFIGURATION_CMD 0x98
-#define MEASURE_ABORT_NOTIFICATION 0x99
-#define REPLY_CALIBRATION_TUNE 0x9a
-
-/* bt config command */
-#define REPLY_BT_CONFIG 0x9b
-#define REPLY_STATISTICS_CMD 0x9c
-#define STATISTICS_NOTIFICATION 0x9d
-
-/* RF-KILL commands and notifications */
-#define REPLY_CARD_STATE_CMD 0xa0
-#define CARD_STATE_NOTIFICATION 0xa1
-
-/* Missed beacons notification */
-#define MISSED_BEACONS_NOTIFICATION 0xa2
-#define MISSED_BEACONS_NOTIFICATION_TH_CMD 0xa3
-
-#define REPLY_CT_KILL_CONFIG_CMD 0xa4
-
-/* HD commands and notifications */
-#define REPLY_HD_PARAMS_CMD 0xa6
-#define HD_PARAMS_NOTIFICATION 0xa7
-#define SENSITIVITY_CMD 0xa8
-#define U_APSD_PARAMS_CMD 0xa9
-#define NOISY_PLATFORM_CMD 0xaa
-#define ILLEGAL_CMD 0xac
-#define REPLY_PHY_CALIBRATION_CMD 0xb0
-#define REPLAY_RX_GAIN_CALIB_CMD 0xb1
-
-/* WiPAN commands */
-#define REPLY_WIPAN_PARAMS_CMD 0xb2
-#define REPLY_WIPAN_RX_ON_CMD 0xb3
-#define REPLY_WIPAN_RX_ON_TIMING 0xb4
-#define REPLY_WIPAN_TX_PWR_TABLE_CMD 0xb5
-#define REPLY_WIPAN_RXON_ASSOC_CMD 0xb6
-#define REPLY_WIPAN_QOS_PARAM 0xb7
-#define WIPAN_REPLY_WEPKEY 0xb8
-
-/* BeamForming commands */
-#define BEAMFORMER_CFG_CMD 0xba
-#define BEAMFORMEE_NOTIFICATION 0xbb
-
-/* TGn new Commands */
-#define REPLY_RX_PHY_CMD 0xc0
-#define REPLY_RX_MPDU_CMD 0xc1
-#define REPLY_MULTICAST_HASH 0xc2
-#define REPLY_KDR_RX 0xc3
-#define REPLY_RX_DSP_EXT_INFO 0xc4
-#define REPLY_COMPRESSED_BA 0xc5
-
-/* PNC commands */
-#define PNC_CONFIG_CMD 0xc8
-#define PNC_UPDATE_TABLE_CMD 0xc9
-#define XVT_GENERAL_CTRL_CMD 0xca
-#define REPLY_LEGACY_RADIO_FE 0xdd
-
-/* WoWLAN commands */
-#define WOWLAN_PATTERNS 0xe0
-#define WOWLAN_WAKEUP_FILTER 0xe1
-#define WOWLAN_TSC_RSC_PARAM 0xe2
-#define WOWLAN_TKIP_PARAM 0xe3
-#define WOWLAN_KEK_KCK_MATERIAL 0xe4
-#define WOWLAN_GET_STATUSES 0xe5
-#define WOWLAN_TX_POWER_PER_DB 0xe6
-#define REPLY_WOWLAN_GET_STATUSES WOWLAN_GET_STATUSES
-
-#define REPLY_DEBUG_CMD 0xf0
-#define REPLY_DSP_DEBUG_CMD 0xf1
-#define REPLY_DEBUG_MONITOR_CMD 0xf2
-#define REPLY_DEBUG_XVT_CMD 0xf3
-#define REPLY_DEBUG_DC_CALIB 0xf4
-#define REPLY_DYNAMIC_BP 0xf5
-
-/* General purpose Commands */
-#define REPLY_GP1_CMD 0xfa
-#define REPLY_GP2_CMD 0xfb
-#define REPLY_GP3_CMD 0xfc
-#define REPLY_GP4_CMD 0xfd
-#define REPLY_REPLAY_WRAPPER 0xfe
-#define REPLY_FRAME_DURATION_CALC_CMD 0xff
-
-#define LMAC_COMMAND_ID_MAX 0xff
-#define LMAC_COMMAND_ID_NUM (LMAC_COMMAND_ID_MAX + 1)
-
-
-/* Calibration */
-
-enum {
- PHY_CALIBRATE_DC_CMD = 0,
- PHY_CALIBRATE_LO_CMD = 1,
- PHY_CALIBRATE_RX_BB_CMD = 2,
- PHY_CALIBRATE_TX_IQ_CMD = 3,
- PHY_CALIBRATE_RX_IQ_CMD = 4,
- PHY_CALIBRATION_NOISE_CMD = 5,
- PHY_CALIBRATE_AGC_TABLE_CMD = 6,
- PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 7,
- PHY_CALIBRATE_OPCODES_NUM,
- SHILOH_PHY_CALIBRATE_DC_CMD = 8,
- SHILOH_PHY_CALIBRATE_LO_CMD = 9,
- SHILOH_PHY_CALIBRATE_RX_BB_CMD = 10,
- SHILOH_PHY_CALIBRATE_TX_IQ_CMD = 11,
- SHILOH_PHY_CALIBRATE_RX_IQ_CMD = 12,
- SHILOH_PHY_CALIBRATION_NOISE_CMD = 13,
- SHILOH_PHY_CALIBRATE_AGC_TABLE_CMD = 14,
- SHILOH_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
- SHILOH_PHY_CALIBRATE_BASE_BAND_CMD = 16,
- SHILOH_PHY_CALIBRATE_TXIQ_PERIODIC_CMD = 17,
- CALIBRATION_CMD_NUM,
-};
-
-enum {
- CALIB_CFG_RX_BB_IDX = 0,
- CALIB_CFG_DC_IDX = 1,
- CALIB_CFG_LO_IDX = 2,
- CALIB_CFG_TX_IQ_IDX = 3,
- CALIB_CFG_RX_IQ_IDX = 4,
- CALIB_CFG_NOISE_IDX = 5,
- CALIB_CFG_CRYSTAL_IDX = 6,
- CALIB_CFG_TEMPERATURE_IDX = 7,
- CALIB_CFG_PAPD_IDX = 8,
- CALIB_CFG_LAST_IDX = CALIB_CFG_PAPD_IDX,
- CALIB_CFG_MODULE_NUM,
-};
-
-#define IWM_CALIB_MAP_INIT_MSK 0xFFFF
-#define IWM_CALIB_MAP_PER_LMAC(m) ((m & 0xFF0000) >> 16)
-#define IWM_CALIB_MAP_PER_UMAC(m) ((m & 0xFF000000) >> 24)
-#define IWM_CALIB_OPCODE_TO_INDEX(op) (op - PHY_CALIBRATE_OPCODES_NUM)
-
-struct iwm_lmac_calib_hdr {
- u8 opcode;
- u8 first_grp;
- u8 grp_num;
- u8 all_data_valid;
-} __packed;
-
-#define IWM_LMAC_CALIB_FREQ_GROUPS_NR 7
-#define IWM_CALIB_FREQ_GROUPS_NR 5
-#define IWM_CALIB_DC_MODES_NR 12
-
-struct iwm_calib_rxiq_entry {
- u16 ptam_postdist_ars;
- u16 ptam_postdist_arc;
-} __packed;
-
-struct iwm_calib_rxiq_group {
- struct iwm_calib_rxiq_entry mode[IWM_CALIB_DC_MODES_NR];
-} __packed;
-
-struct iwm_lmac_calib_rxiq {
- struct iwm_calib_rxiq_group group[IWM_LMAC_CALIB_FREQ_GROUPS_NR];
-} __packed;
-
-struct iwm_calib_rxiq {
- struct iwm_lmac_calib_hdr hdr;
- struct iwm_calib_rxiq_group group[IWM_CALIB_FREQ_GROUPS_NR];
-} __packed;
-
-#define LMAC_STA_ID_SEED 0x0f
-#define LMAC_STA_ID_POS 0
-
-#define LMAC_STA_COLOR_SEED 0x7
-#define LMAC_STA_COLOR_POS 4
-
-struct iwm_lmac_power_report {
- u8 pa_status;
- u8 pa_integ_res_A[3];
- u8 pa_integ_res_B[3];
- u8 pa_integ_res_C[3];
-} __packed;
-
-struct iwm_lmac_tx_resp {
- u8 frame_cnt; /* 1-no aggregation, greater then 1 - aggregation */
- u8 bt_kill_cnt;
- __le16 retry_cnt;
- __le32 initial_tx_rate;
- __le16 wireless_media_time;
- struct iwm_lmac_power_report power_report;
- __le32 tfd_info;
- __le16 seq_ctl;
- __le16 byte_cnt;
- u8 tlc_rate_info;
- u8 ra_tid;
- __le16 frame_ctl;
- __le32 status;
-} __packed;
-
-#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c
deleted file mode 100644
index 1f868b166d10..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/main.c
+++ /dev/null
@@ -1,847 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/sched.h>
-#include <linux/ieee80211.h>
-#include <linux/wireless.h>
-#include <linux/slab.h>
-#include <linux/moduleparam.h>
-
-#include "iwm.h"
-#include "debug.h"
-#include "bus.h"
-#include "umac.h"
-#include "commands.h"
-#include "hal.h"
-#include "fw.h"
-#include "rx.h"
-
-static struct iwm_conf def_iwm_conf = {
-
- .sdio_ior_timeout = 5000,
- .calib_map = BIT(CALIB_CFG_DC_IDX) |
- BIT(CALIB_CFG_LO_IDX) |
- BIT(CALIB_CFG_TX_IQ_IDX) |
- BIT(CALIB_CFG_RX_IQ_IDX) |
- BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD),
- .expected_calib_map = BIT(PHY_CALIBRATE_DC_CMD) |
- BIT(PHY_CALIBRATE_LO_CMD) |
- BIT(PHY_CALIBRATE_TX_IQ_CMD) |
- BIT(PHY_CALIBRATE_RX_IQ_CMD) |
- BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD),
- .ct_kill_entry = 110,
- .ct_kill_exit = 110,
- .reset_on_fatal_err = 1,
- .auto_connect = 1,
- .enable_qos = 1,
- .mode = UMAC_MODE_BSS,
-
- /* UMAC configuration */
- .power_index = 0,
- .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
- .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD,
- .cts_to_self = 0,
-
- .assoc_timeout = 2,
- .roam_timeout = 10,
- .wireless_mode = WIRELESS_MODE_11A | WIRELESS_MODE_11G |
- WIRELESS_MODE_11N,
-
- /* IBSS */
- .ibss_band = UMAC_BAND_2GHZ,
- .ibss_channel = 1,
-
- .mac_addr = {0x00, 0x02, 0xb3, 0x01, 0x02, 0x03},
-};
-
-static bool modparam_reset;
-module_param_named(reset, modparam_reset, bool, 0644);
-MODULE_PARM_DESC(reset, "reset on firmware errors (default 0 [not reset])");
-
-static bool modparam_wimax_enable = true;
-module_param_named(wimax_enable, modparam_wimax_enable, bool, 0644);
-MODULE_PARM_DESC(wimax_enable, "Enable wimax core (default 1 [wimax enabled])");
-
-int iwm_mode_to_nl80211_iftype(int mode)
-{
- switch (mode) {
- case UMAC_MODE_BSS:
- return NL80211_IFTYPE_STATION;
- case UMAC_MODE_IBSS:
- return NL80211_IFTYPE_ADHOC;
- default:
- return NL80211_IFTYPE_UNSPECIFIED;
- }
-
- return 0;
-}
-
-static void iwm_statistics_request(struct work_struct *work)
-{
- struct iwm_priv *iwm =
- container_of(work, struct iwm_priv, stats_request.work);
-
- iwm_send_umac_stats_req(iwm, 0);
-}
-
-static void iwm_disconnect_work(struct work_struct *work)
-{
- struct iwm_priv *iwm =
- container_of(work, struct iwm_priv, disconnect.work);
-
- if (iwm->umac_profile_active)
- iwm_invalidate_mlme_profile(iwm);
-
- clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
- iwm->umac_profile_active = false;
- memset(iwm->bssid, 0, ETH_ALEN);
- iwm->channel = 0;
-
- iwm_link_off(iwm);
-
- wake_up_interruptible(&iwm->mlme_queue);
-
- cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, GFP_KERNEL);
-}
-
-static void iwm_ct_kill_work(struct work_struct *work)
-{
- struct iwm_priv *iwm =
- container_of(work, struct iwm_priv, ct_kill_delay.work);
- struct wiphy *wiphy = iwm_to_wiphy(iwm);
-
- IWM_INFO(iwm, "CT kill delay timeout\n");
-
- wiphy_rfkill_set_hw_state(wiphy, false);
-}
-
-static int __iwm_up(struct iwm_priv *iwm);
-static int __iwm_down(struct iwm_priv *iwm);
-
-static void iwm_reset_worker(struct work_struct *work)
-{
- struct iwm_priv *iwm;
- struct iwm_umac_profile *profile = NULL;
- int uninitialized_var(ret), retry = 0;
-
- iwm = container_of(work, struct iwm_priv, reset_worker);
-
- /*
- * XXX: The iwm->mutex is introduced purely for this reset work,
- * because the other users for iwm_up and iwm_down are only netdev
- * ndo_open and ndo_stop which are already protected by rtnl.
- * Please remove iwm->mutex together if iwm_reset_worker() is not
- * required in the future.
- */
- if (!mutex_trylock(&iwm->mutex)) {
- IWM_WARN(iwm, "We are in the middle of interface bringing "
- "UP/DOWN. Skip driver resetting.\n");
- return;
- }
-
- if (iwm->umac_profile_active) {
- profile = kmalloc(sizeof(struct iwm_umac_profile), GFP_KERNEL);
- if (profile)
- memcpy(profile, iwm->umac_profile, sizeof(*profile));
- else
- IWM_ERR(iwm, "Couldn't alloc memory for profile\n");
- }
-
- __iwm_down(iwm);
-
- while (retry++ < 3) {
- ret = __iwm_up(iwm);
- if (!ret)
- break;
-
- schedule_timeout_uninterruptible(10 * HZ);
- }
-
- if (ret) {
- IWM_WARN(iwm, "iwm_up() failed: %d\n", ret);
-
- kfree(profile);
- goto out;
- }
-
- if (profile) {
- IWM_DBG_MLME(iwm, DBG, "Resend UMAC profile\n");
- memcpy(iwm->umac_profile, profile, sizeof(*profile));
- iwm_send_mlme_profile(iwm);
- kfree(profile);
- } else
- clear_bit(IWM_STATUS_RESETTING, &iwm->status);
-
- out:
- mutex_unlock(&iwm->mutex);
-}
-
-static void iwm_auth_retry_worker(struct work_struct *work)
-{
- struct iwm_priv *iwm;
- int i, ret;
-
- iwm = container_of(work, struct iwm_priv, auth_retry_worker);
- if (iwm->umac_profile_active) {
- ret = iwm_invalidate_mlme_profile(iwm);
- if (ret < 0)
- return;
- }
-
- iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
-
- ret = iwm_send_mlme_profile(iwm);
- if (ret < 0)
- return;
-
- for (i = 0; i < IWM_NUM_KEYS; i++)
- if (iwm->keys[i].key_len)
- iwm_set_key(iwm, 0, &iwm->keys[i]);
-
- iwm_set_tx_key(iwm, iwm->default_key);
-}
-
-
-
-static void iwm_watchdog(unsigned long data)
-{
- struct iwm_priv *iwm = (struct iwm_priv *)data;
-
- IWM_WARN(iwm, "Watchdog expired: UMAC stalls!\n");
-
- if (modparam_reset)
- iwm_resetting(iwm);
-}
-
-int iwm_priv_init(struct iwm_priv *iwm)
-{
- int i, j;
- char name[32];
-
- iwm->status = 0;
- INIT_LIST_HEAD(&iwm->pending_notif);
- init_waitqueue_head(&iwm->notif_queue);
- init_waitqueue_head(&iwm->nonwifi_queue);
- init_waitqueue_head(&iwm->wifi_ntfy_queue);
- init_waitqueue_head(&iwm->mlme_queue);
- memcpy(&iwm->conf, &def_iwm_conf, sizeof(struct iwm_conf));
- spin_lock_init(&iwm->tx_credit.lock);
- INIT_LIST_HEAD(&iwm->wifi_pending_cmd);
- INIT_LIST_HEAD(&iwm->nonwifi_pending_cmd);
- iwm->wifi_seq_num = UMAC_WIFI_SEQ_NUM_BASE;
- iwm->nonwifi_seq_num = UMAC_NONWIFI_SEQ_NUM_BASE;
- spin_lock_init(&iwm->cmd_lock);
- iwm->scan_id = 1;
- INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request);
- INIT_DELAYED_WORK(&iwm->disconnect, iwm_disconnect_work);
- INIT_DELAYED_WORK(&iwm->ct_kill_delay, iwm_ct_kill_work);
- INIT_WORK(&iwm->reset_worker, iwm_reset_worker);
- INIT_WORK(&iwm->auth_retry_worker, iwm_auth_retry_worker);
- INIT_LIST_HEAD(&iwm->bss_list);
-
- skb_queue_head_init(&iwm->rx_list);
- INIT_LIST_HEAD(&iwm->rx_tickets);
- spin_lock_init(&iwm->ticket_lock);
- for (i = 0; i < IWM_RX_ID_HASH; i++) {
- INIT_LIST_HEAD(&iwm->rx_packets[i]);
- spin_lock_init(&iwm->packet_lock[i]);
- }
-
- INIT_WORK(&iwm->rx_worker, iwm_rx_worker);
-
- iwm->rx_wq = create_singlethread_workqueue(KBUILD_MODNAME "_rx");
- if (!iwm->rx_wq)
- return -EAGAIN;
-
- for (i = 0; i < IWM_TX_QUEUES; i++) {
- INIT_WORK(&iwm->txq[i].worker, iwm_tx_worker);
- snprintf(name, 32, KBUILD_MODNAME "_tx_%d", i);
- iwm->txq[i].id = i;
- iwm->txq[i].wq = create_singlethread_workqueue(name);
- if (!iwm->txq[i].wq)
- return -EAGAIN;
-
- skb_queue_head_init(&iwm->txq[i].queue);
- skb_queue_head_init(&iwm->txq[i].stopped_queue);
- spin_lock_init(&iwm->txq[i].lock);
- }
-
- for (i = 0; i < IWM_NUM_KEYS; i++)
- memset(&iwm->keys[i], 0, sizeof(struct iwm_key));
-
- iwm->default_key = -1;
-
- for (i = 0; i < IWM_STA_TABLE_NUM; i++)
- for (j = 0; j < IWM_UMAC_TID_NR; j++) {
- mutex_init(&iwm->sta_table[i].tid_info[j].mutex);
- iwm->sta_table[i].tid_info[j].stopped = false;
- }
-
- init_timer(&iwm->watchdog);
- iwm->watchdog.function = iwm_watchdog;
- iwm->watchdog.data = (unsigned long)iwm;
- mutex_init(&iwm->mutex);
-
- iwm->last_fw_err = kzalloc(sizeof(struct iwm_fw_error_hdr),
- GFP_KERNEL);
- if (iwm->last_fw_err == NULL)
- return -ENOMEM;
-
- return 0;
-}
-
-void iwm_priv_deinit(struct iwm_priv *iwm)
-{
- int i;
-
- for (i = 0; i < IWM_TX_QUEUES; i++)
- destroy_workqueue(iwm->txq[i].wq);
-
- destroy_workqueue(iwm->rx_wq);
- kfree(iwm->last_fw_err);
-}
-
-/*
- * We reset all the structures, and we reset the UMAC.
- * After calling this routine, you're expected to reload
- * the firmware.
- */
-void iwm_reset(struct iwm_priv *iwm)
-{
- struct iwm_notif *notif, *next;
-
- if (test_bit(IWM_STATUS_READY, &iwm->status))
- iwm_target_reset(iwm);
-
- if (test_bit(IWM_STATUS_RESETTING, &iwm->status)) {
- iwm->status = 0;
- set_bit(IWM_STATUS_RESETTING, &iwm->status);
- } else
- iwm->status = 0;
- iwm->scan_id = 1;
-
- list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) {
- list_del(&notif->pending);
- kfree(notif->buf);
- kfree(notif);
- }
-
- iwm_cmd_flush(iwm);
-
- flush_workqueue(iwm->rx_wq);
-
- iwm_link_off(iwm);
-}
-
-void iwm_resetting(struct iwm_priv *iwm)
-{
- set_bit(IWM_STATUS_RESETTING, &iwm->status);
-
- schedule_work(&iwm->reset_worker);
-}
-
-/*
- * Notification code:
- *
- * We're faced with the following issue: Any host command can
- * have an answer or not, and if there's an answer to expect,
- * it can be treated synchronously or asynchronously.
- * To work around the synchronous answer case, we implemented
- * our notification mechanism.
- * When a code path needs to wait for a command response
- * synchronously, it calls notif_handle(), which waits for the
- * right notification to show up, and then process it. Before
- * starting to wait, it registered as a waiter for this specific
- * answer (by toggling a bit in on of the handler_map), so that
- * the rx code knows that it needs to send a notification to the
- * waiting processes. It does so by calling iwm_notif_send(),
- * which adds the notification to the pending notifications list,
- * and then wakes the waiting processes up.
- */
-int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd,
- u8 cmd_id, u8 source, u8 *buf, unsigned long buf_size)
-{
- struct iwm_notif *notif;
-
- notif = kzalloc(sizeof(struct iwm_notif), GFP_KERNEL);
- if (!notif) {
- IWM_ERR(iwm, "Couldn't alloc memory for notification\n");
- return -ENOMEM;
- }
-
- INIT_LIST_HEAD(&notif->pending);
- notif->cmd = cmd;
- notif->cmd_id = cmd_id;
- notif->src = source;
- notif->buf = kzalloc(buf_size, GFP_KERNEL);
- if (!notif->buf) {
- IWM_ERR(iwm, "Couldn't alloc notification buffer\n");
- kfree(notif);
- return -ENOMEM;
- }
- notif->buf_size = buf_size;
- memcpy(notif->buf, buf, buf_size);
- list_add_tail(&notif->pending, &iwm->pending_notif);
-
- wake_up_interruptible(&iwm->notif_queue);
-
- return 0;
-}
-
-static struct iwm_notif *iwm_notif_find(struct iwm_priv *iwm, u32 cmd,
- u8 source)
-{
- struct iwm_notif *notif;
-
- list_for_each_entry(notif, &iwm->pending_notif, pending) {
- if ((notif->cmd_id == cmd) && (notif->src == source)) {
- list_del(&notif->pending);
- return notif;
- }
- }
-
- return NULL;
-}
-
-static struct iwm_notif *iwm_notif_wait(struct iwm_priv *iwm, u32 cmd,
- u8 source, long timeout)
-{
- int ret;
- struct iwm_notif *notif;
- unsigned long *map = NULL;
-
- switch (source) {
- case IWM_SRC_LMAC:
- map = &iwm->lmac_handler_map[0];
- break;
- case IWM_SRC_UMAC:
- map = &iwm->umac_handler_map[0];
- break;
- case IWM_SRC_UDMA:
- map = &iwm->udma_handler_map[0];
- break;
- }
-
- set_bit(cmd, map);
-
- ret = wait_event_interruptible_timeout(iwm->notif_queue,
- ((notif = iwm_notif_find(iwm, cmd, source)) != NULL),
- timeout);
- clear_bit(cmd, map);
-
- if (!ret)
- return NULL;
-
- return notif;
-}
-
-int iwm_notif_handle(struct iwm_priv *iwm, u32 cmd, u8 source, long timeout)
-{
- int ret;
- struct iwm_notif *notif;
-
- notif = iwm_notif_wait(iwm, cmd, source, timeout);
- if (!notif)
- return -ETIME;
-
- ret = iwm_rx_handle_resp(iwm, notif->buf, notif->buf_size, notif->cmd);
- kfree(notif->buf);
- kfree(notif);
-
- return ret;
-}
-
-static int iwm_config_boot_params(struct iwm_priv *iwm)
-{
- struct iwm_udma_nonwifi_cmd target_cmd;
- int ret;
-
- /* check Wimax is off and config debug monitor */
- if (!modparam_wimax_enable) {
- u32 data1 = 0x1f;
- u32 addr1 = 0x606BE258;
-
- u32 data2_set = 0x0;
- u32 data2_clr = 0x1;
- u32 addr2 = 0x606BE100;
-
- u32 data3 = 0x1;
- u32 addr3 = 0x606BEC00;
-
- target_cmd.resp = 0;
- target_cmd.handle_by_hw = 0;
- target_cmd.eop = 1;
-
- target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE;
- target_cmd.addr = cpu_to_le32(addr1);
- target_cmd.op1_sz = cpu_to_le32(sizeof(u32));
- target_cmd.op2 = 0;
-
- ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data1);
- if (ret < 0) {
- IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n");
- return ret;
- }
-
- target_cmd.opcode = UMAC_HDI_OUT_OPCODE_READ_MODIFY_WRITE;
- target_cmd.addr = cpu_to_le32(addr2);
- target_cmd.op1_sz = cpu_to_le32(data2_set);
- target_cmd.op2 = cpu_to_le32(data2_clr);
-
- ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data1);
- if (ret < 0) {
- IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n");
- return ret;
- }
-
- target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE;
- target_cmd.addr = cpu_to_le32(addr3);
- target_cmd.op1_sz = cpu_to_le32(sizeof(u32));
- target_cmd.op2 = 0;
-
- ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data3);
- if (ret < 0) {
- IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n");
- return ret;
- }
- }
-
- return 0;
-}
-
-void iwm_init_default_profile(struct iwm_priv *iwm,
- struct iwm_umac_profile *profile)
-{
- memset(profile, 0, sizeof(struct iwm_umac_profile));
-
- profile->sec.auth_type = UMAC_AUTH_TYPE_OPEN;
- profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
- profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_NONE;
- profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_NONE;
-
- if (iwm->conf.enable_qos)
- profile->flags |= cpu_to_le16(UMAC_PROFILE_QOS_ALLOWED);
-
- profile->wireless_mode = iwm->conf.wireless_mode;
- profile->mode = cpu_to_le32(iwm->conf.mode);
-
- profile->ibss.atim = 0;
- profile->ibss.beacon_interval = 100;
- profile->ibss.join_only = 0;
- profile->ibss.band = iwm->conf.ibss_band;
- profile->ibss.channel = iwm->conf.ibss_channel;
-}
-
-void iwm_link_on(struct iwm_priv *iwm)
-{
- netif_carrier_on(iwm_to_ndev(iwm));
- netif_tx_wake_all_queues(iwm_to_ndev(iwm));
-
- iwm_send_umac_stats_req(iwm, 0);
-}
-
-void iwm_link_off(struct iwm_priv *iwm)
-{
- struct iw_statistics *wstats = &iwm->wstats;
- int i;
-
- netif_tx_stop_all_queues(iwm_to_ndev(iwm));
- netif_carrier_off(iwm_to_ndev(iwm));
-
- for (i = 0; i < IWM_TX_QUEUES; i++) {
- skb_queue_purge(&iwm->txq[i].queue);
- skb_queue_purge(&iwm->txq[i].stopped_queue);
-
- iwm->txq[i].concat_count = 0;
- iwm->txq[i].concat_ptr = iwm->txq[i].concat_buf;
-
- flush_workqueue(iwm->txq[i].wq);
- }
-
- iwm_rx_free(iwm);
-
- cancel_delayed_work_sync(&iwm->stats_request);
- memset(wstats, 0, sizeof(struct iw_statistics));
- wstats->qual.updated = IW_QUAL_ALL_INVALID;
-
- kfree(iwm->req_ie);
- iwm->req_ie = NULL;
- iwm->req_ie_len = 0;
- kfree(iwm->resp_ie);
- iwm->resp_ie = NULL;
- iwm->resp_ie_len = 0;
-
- del_timer_sync(&iwm->watchdog);
-}
-
-static void iwm_bss_list_clean(struct iwm_priv *iwm)
-{
- struct iwm_bss_info *bss, *next;
-
- list_for_each_entry_safe(bss, next, &iwm->bss_list, node) {
- list_del(&bss->node);
- kfree(bss->bss);
- kfree(bss);
- }
-}
-
-static int iwm_channels_init(struct iwm_priv *iwm)
-{
- int ret;
-
- ret = iwm_send_umac_channel_list(iwm);
- if (ret) {
- IWM_ERR(iwm, "Send channel list failed\n");
- return ret;
- }
-
- ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST,
- IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
- if (ret) {
- IWM_ERR(iwm, "Didn't get a channel list notification\n");
- return ret;
- }
-
- return 0;
-}
-
-static int __iwm_up(struct iwm_priv *iwm)
-{
- int ret;
- struct iwm_notif *notif_reboot, *notif_ack = NULL;
- struct wiphy *wiphy = iwm_to_wiphy(iwm);
- u32 wireless_mode;
-
- ret = iwm_bus_enable(iwm);
- if (ret) {
- IWM_ERR(iwm, "Couldn't enable function\n");
- return ret;
- }
-
- iwm_rx_setup_handlers(iwm);
-
- /* Wait for initial BARKER_REBOOT from hardware */
- notif_reboot = iwm_notif_wait(iwm, IWM_BARKER_REBOOT_NOTIFICATION,
- IWM_SRC_UDMA, 2 * HZ);
- if (!notif_reboot) {
- IWM_ERR(iwm, "Wait for REBOOT_BARKER timeout\n");
- goto err_disable;
- }
-
- /* We send the barker back */
- ret = iwm_bus_send_chunk(iwm, notif_reboot->buf, 16);
- if (ret) {
- IWM_ERR(iwm, "REBOOT barker response failed\n");
- kfree(notif_reboot);
- goto err_disable;
- }
-
- kfree(notif_reboot->buf);
- kfree(notif_reboot);
-
- /* Wait for ACK_BARKER from hardware */
- notif_ack = iwm_notif_wait(iwm, IWM_ACK_BARKER_NOTIFICATION,
- IWM_SRC_UDMA, 2 * HZ);
- if (!notif_ack) {
- IWM_ERR(iwm, "Wait for ACK_BARKER timeout\n");
- goto err_disable;
- }
-
- kfree(notif_ack->buf);
- kfree(notif_ack);
-
- /* We start to config static boot parameters */
- ret = iwm_config_boot_params(iwm);
- if (ret) {
- IWM_ERR(iwm, "Config boot parameters failed\n");
- goto err_disable;
- }
-
- ret = iwm_read_mac(iwm, iwm_to_ndev(iwm)->dev_addr);
- if (ret) {
- IWM_ERR(iwm, "MAC reading failed\n");
- goto err_disable;
- }
- memcpy(iwm_to_ndev(iwm)->perm_addr, iwm_to_ndev(iwm)->dev_addr,
- ETH_ALEN);
-
- /* We can load the FWs */
- ret = iwm_load_fw(iwm);
- if (ret) {
- IWM_ERR(iwm, "FW loading failed\n");
- goto err_disable;
- }
-
- ret = iwm_eeprom_fat_channels(iwm);
- if (ret) {
- IWM_ERR(iwm, "Couldnt read HT channels EEPROM entries\n");
- goto err_fw;
- }
-
- /*
- * Read our SKU capabilities.
- * If it's valid, we AND the configured wireless mode with the
- * device EEPROM value as the current profile wireless mode.
- */
- wireless_mode = iwm_eeprom_wireless_mode(iwm);
- if (wireless_mode) {
- iwm->conf.wireless_mode &= wireless_mode;
- if (iwm->umac_profile)
- iwm->umac_profile->wireless_mode =
- iwm->conf.wireless_mode;
- } else
- IWM_ERR(iwm, "Wrong SKU capabilities: 0x%x\n",
- *((u16 *)iwm_eeprom_access(iwm, IWM_EEPROM_SKU_CAP)));
-
- snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "L%s_U%s",
- iwm->lmac_version, iwm->umac_version);
-
- /* We configure the UMAC and enable the wifi module */
- ret = iwm_send_umac_config(iwm,
- cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_CORE_EN) |
- cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_LINK_EN) |
- cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_MLME_EN));
- if (ret) {
- IWM_ERR(iwm, "UMAC config failed\n");
- goto err_fw;
- }
-
- ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS,
- IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
- if (ret) {
- IWM_ERR(iwm, "Didn't get a wifi core status notification\n");
- goto err_fw;
- }
-
- if (iwm->core_enabled != (UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN |
- UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN)) {
- IWM_DBG_BOOT(iwm, DBG, "Not all cores enabled:0x%x\n",
- iwm->core_enabled);
- ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS,
- IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
- if (ret) {
- IWM_ERR(iwm, "Didn't get a core status notification\n");
- goto err_fw;
- }
-
- if (iwm->core_enabled != (UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN |
- UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN)) {
- IWM_ERR(iwm, "Not all cores enabled: 0x%x\n",
- iwm->core_enabled);
- goto err_fw;
- } else {
- IWM_INFO(iwm, "All cores enabled\n");
- }
- }
-
- ret = iwm_channels_init(iwm);
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't init channels\n");
- goto err_fw;
- }
-
- /* Set the READY bit to indicate interface is brought up successfully */
- set_bit(IWM_STATUS_READY, &iwm->status);
-
- return 0;
-
- err_fw:
- iwm_eeprom_exit(iwm);
-
- err_disable:
- ret = iwm_bus_disable(iwm);
- if (ret < 0)
- IWM_ERR(iwm, "Couldn't disable function\n");
-
- return -EIO;
-}
-
-int iwm_up(struct iwm_priv *iwm)
-{
- int ret;
-
- mutex_lock(&iwm->mutex);
- ret = __iwm_up(iwm);
- mutex_unlock(&iwm->mutex);
-
- return ret;
-}
-
-static int __iwm_down(struct iwm_priv *iwm)
-{
- int ret;
-
- /* The interface is already down */
- if (!test_bit(IWM_STATUS_READY, &iwm->status))
- return 0;
-
- if (iwm->scan_request) {
- cfg80211_scan_done(iwm->scan_request, true);
- iwm->scan_request = NULL;
- }
-
- clear_bit(IWM_STATUS_READY, &iwm->status);
-
- iwm_eeprom_exit(iwm);
- iwm_bss_list_clean(iwm);
- iwm_init_default_profile(iwm, iwm->umac_profile);
- iwm->umac_profile_active = false;
- iwm->default_key = -1;
- iwm->core_enabled = 0;
-
- ret = iwm_bus_disable(iwm);
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't disable function\n");
- return ret;
- }
-
- return 0;
-}
-
-int iwm_down(struct iwm_priv *iwm)
-{
- int ret;
-
- mutex_lock(&iwm->mutex);
- ret = __iwm_down(iwm);
- mutex_unlock(&iwm->mutex);
-
- return ret;
-}
diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c
deleted file mode 100644
index 5091d77e02ce..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/netdev.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-
-/*
- * This is the netdev related hooks for iwm.
- *
- * Some interesting code paths:
- *
- * iwm_open() (Called at netdev interface bringup time)
- * -> iwm_up() (main.c)
- * -> iwm_bus_enable()
- * -> if_sdio_enable() (In case of an SDIO bus)
- * -> sdio_enable_func()
- * -> iwm_notif_wait(BARKER_REBOOT) (wait for reboot barker)
- * -> iwm_notif_wait(ACK_BARKER) (wait for ACK barker)
- * -> iwm_load_fw() (fw.c)
- * -> iwm_load_umac()
- * -> iwm_load_lmac() (Calibration LMAC)
- * -> iwm_load_lmac() (Operational LMAC)
- * -> iwm_send_umac_config()
- *
- * iwm_stop() (Called at netdev interface bringdown time)
- * -> iwm_down()
- * -> iwm_bus_disable()
- * -> if_sdio_disable() (In case of an SDIO bus)
- * -> sdio_disable_func()
- */
-#include <linux/netdevice.h>
-#include <linux/slab.h>
-
-#include "iwm.h"
-#include "commands.h"
-#include "cfg80211.h"
-#include "debug.h"
-
-static int iwm_open(struct net_device *ndev)
-{
- struct iwm_priv *iwm = ndev_to_iwm(ndev);
-
- return iwm_up(iwm);
-}
-
-static int iwm_stop(struct net_device *ndev)
-{
- struct iwm_priv *iwm = ndev_to_iwm(ndev);
-
- return iwm_down(iwm);
-}
-
-/*
- * iwm AC to queue mapping
- *
- * AC_VO -> queue 3
- * AC_VI -> queue 2
- * AC_BE -> queue 1
- * AC_BK -> queue 0
- */
-static const u16 iwm_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
-
-int iwm_tid_to_queue(u16 tid)
-{
- if (tid > IWM_UMAC_TID_NR - 2)
- return -EINVAL;
-
- return iwm_1d_to_queue[tid];
-}
-
-static u16 iwm_select_queue(struct net_device *dev, struct sk_buff *skb)
-{
- skb->priority = cfg80211_classify8021d(skb);
-
- return iwm_1d_to_queue[skb->priority];
-}
-
-static const struct net_device_ops iwm_netdev_ops = {
- .ndo_open = iwm_open,
- .ndo_stop = iwm_stop,
- .ndo_start_xmit = iwm_xmit_frame,
- .ndo_select_queue = iwm_select_queue,
-};
-
-void *iwm_if_alloc(int sizeof_bus, struct device *dev,
- struct iwm_if_ops *if_ops)
-{
- struct net_device *ndev;
- struct wireless_dev *wdev;
- struct iwm_priv *iwm;
- int ret = 0;
-
- wdev = iwm_wdev_alloc(sizeof_bus, dev);
- if (IS_ERR(wdev))
- return wdev;
-
- iwm = wdev_to_iwm(wdev);
- iwm->bus_ops = if_ops;
- iwm->wdev = wdev;
-
- ret = iwm_priv_init(iwm);
- if (ret) {
- dev_err(dev, "failed to init iwm_priv\n");
- goto out_wdev;
- }
-
- wdev->iftype = iwm_mode_to_nl80211_iftype(iwm->conf.mode);
-
- ndev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES);
- if (!ndev) {
- dev_err(dev, "no memory for network device instance\n");
- ret = -ENOMEM;
- goto out_priv;
- }
-
- ndev->netdev_ops = &iwm_netdev_ops;
- ndev->ieee80211_ptr = wdev;
- SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
- wdev->netdev = ndev;
-
- iwm->umac_profile = kmalloc(sizeof(struct iwm_umac_profile),
- GFP_KERNEL);
- if (!iwm->umac_profile) {
- dev_err(dev, "Couldn't alloc memory for profile\n");
- ret = -ENOMEM;
- goto out_profile;
- }
-
- iwm_init_default_profile(iwm, iwm->umac_profile);
-
- return iwm;
-
- out_profile:
- free_netdev(ndev);
-
- out_priv:
- iwm_priv_deinit(iwm);
-
- out_wdev:
- iwm_wdev_free(iwm);
- return ERR_PTR(ret);
-}
-
-void iwm_if_free(struct iwm_priv *iwm)
-{
- if (!iwm_to_ndev(iwm))
- return;
-
- cancel_delayed_work_sync(&iwm->ct_kill_delay);
- free_netdev(iwm_to_ndev(iwm));
- iwm_priv_deinit(iwm);
- kfree(iwm->umac_profile);
- iwm->umac_profile = NULL;
- iwm_wdev_free(iwm);
-}
-
-int iwm_if_add(struct iwm_priv *iwm)
-{
- struct net_device *ndev = iwm_to_ndev(iwm);
- int ret;
-
- ret = register_netdev(ndev);
- if (ret < 0) {
- dev_err(&ndev->dev, "Failed to register netdev: %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-void iwm_if_remove(struct iwm_priv *iwm)
-{
- unregister_netdev(iwm_to_ndev(iwm));
-}
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
deleted file mode 100644
index 7d708f4395f3..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ /dev/null
@@ -1,1701 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/sched.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-#include <linux/ieee80211.h>
-#include <linux/if_arp.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <net/iw_handler.h>
-
-#include "iwm.h"
-#include "debug.h"
-#include "hal.h"
-#include "umac.h"
-#include "lmac.h"
-#include "commands.h"
-#include "rx.h"
-#include "cfg80211.h"
-#include "eeprom.h"
-
-static int iwm_rx_check_udma_hdr(struct iwm_udma_in_hdr *hdr)
-{
- if ((le32_to_cpu(hdr->cmd) == UMAC_PAD_TERMINAL) ||
- (le32_to_cpu(hdr->size) == UMAC_PAD_TERMINAL))
- return -EINVAL;
-
- return 0;
-}
-
-static inline int iwm_rx_resp_size(struct iwm_udma_in_hdr *hdr)
-{
- return ALIGN(le32_to_cpu(hdr->size) + sizeof(struct iwm_udma_in_hdr),
- 16);
-}
-
-/*
- * Notification handlers:
- *
- * For every possible notification we can receive from the
- * target, we have a handler.
- * When we get a target notification, and there is no one
- * waiting for it, it's just processed through the rx code
- * path:
- *
- * iwm_rx_handle()
- * -> iwm_rx_handle_umac()
- * -> iwm_rx_handle_wifi()
- * -> iwm_rx_handle_resp()
- * -> iwm_ntf_*()
- *
- * OR
- *
- * -> iwm_rx_handle_non_wifi()
- *
- * If there are processes waiting for this notification, then
- * iwm_rx_handle_wifi() just wakes those processes up and they
- * grab the pending notification.
- */
-static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size, struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_notif_error *error;
- struct iwm_fw_error_hdr *fw_err;
-
- error = (struct iwm_umac_notif_error *)buf;
- fw_err = &error->err;
-
- memcpy(iwm->last_fw_err, fw_err, sizeof(struct iwm_fw_error_hdr));
-
- IWM_ERR(iwm, "%cMAC FW ERROR:\n",
- (le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U');
- IWM_ERR(iwm, "\tCategory: %d\n", le32_to_cpu(fw_err->category));
- IWM_ERR(iwm, "\tStatus: 0x%x\n", le32_to_cpu(fw_err->status));
- IWM_ERR(iwm, "\tPC: 0x%x\n", le32_to_cpu(fw_err->pc));
- IWM_ERR(iwm, "\tblink1: %d\n", le32_to_cpu(fw_err->blink1));
- IWM_ERR(iwm, "\tblink2: %d\n", le32_to_cpu(fw_err->blink2));
- IWM_ERR(iwm, "\tilink1: %d\n", le32_to_cpu(fw_err->ilink1));
- IWM_ERR(iwm, "\tilink2: %d\n", le32_to_cpu(fw_err->ilink2));
- IWM_ERR(iwm, "\tData1: 0x%x\n", le32_to_cpu(fw_err->data1));
- IWM_ERR(iwm, "\tData2: 0x%x\n", le32_to_cpu(fw_err->data2));
- IWM_ERR(iwm, "\tLine number: %d\n", le32_to_cpu(fw_err->line_num));
- IWM_ERR(iwm, "\tUMAC status: 0x%x\n", le32_to_cpu(fw_err->umac_status));
- IWM_ERR(iwm, "\tLMAC status: 0x%x\n", le32_to_cpu(fw_err->lmac_status));
- IWM_ERR(iwm, "\tSDIO status: 0x%x\n", le32_to_cpu(fw_err->sdio_status));
-
- iwm_resetting(iwm);
-
- return 0;
-}
-
-static int iwm_ntf_umac_alive(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size, struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_notif_alive *alive_resp =
- (struct iwm_umac_notif_alive *)(buf);
- u16 status = le16_to_cpu(alive_resp->status);
-
- if (status == UMAC_NTFY_ALIVE_STATUS_ERR) {
- IWM_ERR(iwm, "Receive error UMAC_ALIVE\n");
- return -EIO;
- }
-
- iwm_tx_credit_init_pools(iwm, alive_resp);
-
- return 0;
-}
-
-static int iwm_ntf_init_complete(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- struct wiphy *wiphy = iwm_to_wiphy(iwm);
- struct iwm_umac_notif_init_complete *init_complete =
- (struct iwm_umac_notif_init_complete *)(buf);
- u16 status = le16_to_cpu(init_complete->status);
- bool blocked = (status == UMAC_NTFY_INIT_COMPLETE_STATUS_ERR);
-
- if (blocked)
- IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is on (radio off)\n");
- else
- IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is off (radio on)\n");
-
- wiphy_rfkill_set_hw_state(wiphy, blocked);
-
- return 0;
-}
-
-static int iwm_ntf_tx_credit_update(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- int pool_nr, total_freed_pages;
- unsigned long pool_map;
- int i, id;
- struct iwm_umac_notif_page_dealloc *dealloc =
- (struct iwm_umac_notif_page_dealloc *)buf;
-
- pool_nr = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_CNT);
- pool_map = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_MSK);
-
- IWM_DBG_TX(iwm, DBG, "UMAC dealloc notification: pool nr %d, "
- "update map 0x%lx\n", pool_nr, pool_map);
-
- spin_lock(&iwm->tx_credit.lock);
-
- for (i = 0; i < pool_nr; i++) {
- id = GET_VAL32(dealloc->grp_info[i],
- UMAC_DEALLOC_NTFY_GROUP_NUM);
- if (test_bit(id, &pool_map)) {
- total_freed_pages = GET_VAL32(dealloc->grp_info[i],
- UMAC_DEALLOC_NTFY_PAGE_CNT);
- iwm_tx_credit_inc(iwm, id, total_freed_pages);
- }
- }
-
- spin_unlock(&iwm->tx_credit.lock);
-
- return 0;
-}
-
-static int iwm_ntf_umac_reset(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size, struct iwm_wifi_cmd *cmd)
-{
- IWM_DBG_NTF(iwm, DBG, "UMAC RESET done\n");
-
- return 0;
-}
-
-static int iwm_ntf_lmac_version(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- IWM_DBG_NTF(iwm, INFO, "LMAC Version: %x.%x\n", buf[9], buf[8]);
-
- return 0;
-}
-
-static int iwm_ntf_tx(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size, struct iwm_wifi_cmd *cmd)
-{
- struct iwm_lmac_tx_resp *tx_resp;
- struct iwm_umac_wifi_in_hdr *hdr;
-
- tx_resp = (struct iwm_lmac_tx_resp *)
- (buf + sizeof(struct iwm_umac_wifi_in_hdr));
- hdr = (struct iwm_umac_wifi_in_hdr *)buf;
-
- IWM_DBG_TX(iwm, DBG, "REPLY_TX, buf size: %lu\n", buf_size);
-
- IWM_DBG_TX(iwm, DBG, "Seqnum: %d\n",
- le16_to_cpu(hdr->sw_hdr.cmd.seq_num));
- IWM_DBG_TX(iwm, DBG, "\tFrame cnt: %d\n", tx_resp->frame_cnt);
- IWM_DBG_TX(iwm, DBG, "\tRetry cnt: %d\n",
- le16_to_cpu(tx_resp->retry_cnt));
- IWM_DBG_TX(iwm, DBG, "\tSeq ctl: %d\n", le16_to_cpu(tx_resp->seq_ctl));
- IWM_DBG_TX(iwm, DBG, "\tByte cnt: %d\n",
- le16_to_cpu(tx_resp->byte_cnt));
- IWM_DBG_TX(iwm, DBG, "\tStatus: 0x%x\n", le32_to_cpu(tx_resp->status));
-
- return 0;
-}
-
-
-static int iwm_ntf_calib_res(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size, struct iwm_wifi_cmd *cmd)
-{
- u8 opcode;
- u8 *calib_buf;
- struct iwm_lmac_calib_hdr *hdr = (struct iwm_lmac_calib_hdr *)
- (buf + sizeof(struct iwm_umac_wifi_in_hdr));
-
- opcode = hdr->opcode;
-
- BUG_ON(opcode >= CALIBRATION_CMD_NUM ||
- opcode < PHY_CALIBRATE_OPCODES_NUM);
-
- IWM_DBG_NTF(iwm, DBG, "Store calibration result for opcode: %d\n",
- opcode);
-
- buf_size -= sizeof(struct iwm_umac_wifi_in_hdr);
- calib_buf = iwm->calib_res[opcode].buf;
-
- if (!calib_buf || (iwm->calib_res[opcode].size < buf_size)) {
- kfree(calib_buf);
- calib_buf = kzalloc(buf_size, GFP_KERNEL);
- if (!calib_buf) {
- IWM_ERR(iwm, "Memory allocation failed: calib_res\n");
- return -ENOMEM;
- }
- iwm->calib_res[opcode].buf = calib_buf;
- iwm->calib_res[opcode].size = buf_size;
- }
-
- memcpy(calib_buf, hdr, buf_size);
- set_bit(opcode - PHY_CALIBRATE_OPCODES_NUM, &iwm->calib_done_map);
-
- return 0;
-}
-
-static int iwm_ntf_calib_complete(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- IWM_DBG_NTF(iwm, DBG, "Calibration completed\n");
-
- return 0;
-}
-
-static int iwm_ntf_calib_cfg(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size, struct iwm_wifi_cmd *cmd)
-{
- struct iwm_lmac_cal_cfg_resp *cal_resp;
-
- cal_resp = (struct iwm_lmac_cal_cfg_resp *)
- (buf + sizeof(struct iwm_umac_wifi_in_hdr));
-
- IWM_DBG_NTF(iwm, DBG, "Calibration CFG command status: %d\n",
- le32_to_cpu(cal_resp->status));
-
- return 0;
-}
-
-static int iwm_ntf_wifi_status(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size, struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_notif_wifi_status *status =
- (struct iwm_umac_notif_wifi_status *)buf;
-
- iwm->core_enabled |= le16_to_cpu(status->status);
-
- return 0;
-}
-
-static struct iwm_rx_ticket_node *
-iwm_rx_ticket_node_alloc(struct iwm_priv *iwm, struct iwm_rx_ticket *ticket)
-{
- struct iwm_rx_ticket_node *ticket_node;
-
- ticket_node = kzalloc(sizeof(struct iwm_rx_ticket_node), GFP_KERNEL);
- if (!ticket_node) {
- IWM_ERR(iwm, "Couldn't allocate ticket node\n");
- return ERR_PTR(-ENOMEM);
- }
-
- ticket_node->ticket = kmemdup(ticket, sizeof(struct iwm_rx_ticket),
- GFP_KERNEL);
- if (!ticket_node->ticket) {
- IWM_ERR(iwm, "Couldn't allocate RX ticket\n");
- kfree(ticket_node);
- return ERR_PTR(-ENOMEM);
- }
-
- INIT_LIST_HEAD(&ticket_node->node);
-
- return ticket_node;
-}
-
-static void iwm_rx_ticket_node_free(struct iwm_rx_ticket_node *ticket_node)
-{
- kfree(ticket_node->ticket);
- kfree(ticket_node);
-}
-
-static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id)
-{
- u8 id_hash = IWM_RX_ID_GET_HASH(id);
- struct iwm_rx_packet *packet;
-
- spin_lock(&iwm->packet_lock[id_hash]);
- list_for_each_entry(packet, &iwm->rx_packets[id_hash], node)
- if (packet->id == id) {
- list_del(&packet->node);
- spin_unlock(&iwm->packet_lock[id_hash]);
- return packet;
- }
-
- spin_unlock(&iwm->packet_lock[id_hash]);
- return NULL;
-}
-
-static struct iwm_rx_packet *iwm_rx_packet_alloc(struct iwm_priv *iwm, u8 *buf,
- u32 size, u16 id)
-{
- struct iwm_rx_packet *packet;
-
- packet = kzalloc(sizeof(struct iwm_rx_packet), GFP_KERNEL);
- if (!packet) {
- IWM_ERR(iwm, "Couldn't allocate packet\n");
- return ERR_PTR(-ENOMEM);
- }
-
- packet->skb = dev_alloc_skb(size);
- if (!packet->skb) {
- IWM_ERR(iwm, "Couldn't allocate packet SKB\n");
- kfree(packet);
- return ERR_PTR(-ENOMEM);
- }
-
- packet->pkt_size = size;
-
- skb_put(packet->skb, size);
- memcpy(packet->skb->data, buf, size);
- INIT_LIST_HEAD(&packet->node);
- packet->id = id;
-
- return packet;
-}
-
-void iwm_rx_free(struct iwm_priv *iwm)
-{
- struct iwm_rx_ticket_node *ticket, *nt;
- struct iwm_rx_packet *packet, *np;
- int i;
-
- spin_lock(&iwm->ticket_lock);
- list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) {
- list_del(&ticket->node);
- iwm_rx_ticket_node_free(ticket);
- }
- spin_unlock(&iwm->ticket_lock);
-
- for (i = 0; i < IWM_RX_ID_HASH; i++) {
- spin_lock(&iwm->packet_lock[i]);
- list_for_each_entry_safe(packet, np, &iwm->rx_packets[i],
- node) {
- list_del(&packet->node);
- kfree_skb(packet->skb);
- kfree(packet);
- }
- spin_unlock(&iwm->packet_lock[i]);
- }
-}
-
-static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size, struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_notif_rx_ticket *ntf_rx_ticket =
- (struct iwm_umac_notif_rx_ticket *)buf;
- struct iwm_rx_ticket *ticket =
- (struct iwm_rx_ticket *)ntf_rx_ticket->tickets;
- int i, schedule_rx = 0;
-
- for (i = 0; i < ntf_rx_ticket->num_tickets; i++) {
- struct iwm_rx_ticket_node *ticket_node;
-
- switch (le16_to_cpu(ticket->action)) {
- case IWM_RX_TICKET_RELEASE:
- case IWM_RX_TICKET_DROP:
- /* We can push the packet to the stack */
- ticket_node = iwm_rx_ticket_node_alloc(iwm, ticket);
- if (IS_ERR(ticket_node))
- return PTR_ERR(ticket_node);
-
- IWM_DBG_RX(iwm, DBG, "TICKET %s(%d)\n",
- __le16_to_cpu(ticket->action) ==
- IWM_RX_TICKET_RELEASE ?
- "RELEASE" : "DROP",
- ticket->id);
- spin_lock(&iwm->ticket_lock);
- list_add_tail(&ticket_node->node, &iwm->rx_tickets);
- spin_unlock(&iwm->ticket_lock);
-
- /*
- * We received an Rx ticket, most likely there's
- * a packet pending for it, it's not worth going
- * through the packet hash list to double check.
- * Let's just fire the rx worker..
- */
- schedule_rx = 1;
-
- break;
-
- default:
- IWM_ERR(iwm, "Invalid RX ticket action: 0x%x\n",
- ticket->action);
- }
-
- ticket++;
- }
-
- if (schedule_rx)
- queue_work(iwm->rx_wq, &iwm->rx_worker);
-
- return 0;
-}
-
-static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size, struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_wifi_in_hdr *wifi_hdr;
- struct iwm_rx_packet *packet;
- u16 id, buf_offset;
- u32 packet_size;
- u8 id_hash;
-
- IWM_DBG_RX(iwm, DBG, "\n");
-
- wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
- id = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num);
- buf_offset = sizeof(struct iwm_umac_wifi_in_hdr);
- packet_size = buf_size - sizeof(struct iwm_umac_wifi_in_hdr);
-
- IWM_DBG_RX(iwm, DBG, "CMD:0x%x, seqnum: %d, packet size: %d\n",
- wifi_hdr->sw_hdr.cmd.cmd, id, packet_size);
- IWM_DBG_RX(iwm, DBG, "Packet id: %d\n", id);
- IWM_HEXDUMP(iwm, DBG, RX, "PACKET: ", buf + buf_offset, packet_size);
-
- packet = iwm_rx_packet_alloc(iwm, buf + buf_offset, packet_size, id);
- if (IS_ERR(packet))
- return PTR_ERR(packet);
-
- id_hash = IWM_RX_ID_GET_HASH(id);
- spin_lock(&iwm->packet_lock[id_hash]);
- list_add_tail(&packet->node, &iwm->rx_packets[id_hash]);
- spin_unlock(&iwm->packet_lock[id_hash]);
-
- /* We might (unlikely) have received the packet _after_ the ticket */
- queue_work(iwm->rx_wq, &iwm->rx_worker);
-
- return 0;
-}
-
-/* MLME handlers */
-static int iwm_mlme_assoc_start(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_notif_assoc_start *start;
-
- start = (struct iwm_umac_notif_assoc_start *)buf;
-
- IWM_DBG_MLME(iwm, INFO, "Association with %pM Started, reason: %d\n",
- start->bssid, le32_to_cpu(start->roam_reason));
-
- wake_up_interruptible(&iwm->mlme_queue);
-
- return 0;
-}
-
-static u8 iwm_is_open_wep_profile(struct iwm_priv *iwm)
-{
- if ((iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_40 ||
- iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_104) &&
- (iwm->umac_profile->sec.ucast_cipher ==
- iwm->umac_profile->sec.mcast_cipher) &&
- (iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN))
- return 1;
-
- return 0;
-}
-
-static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- struct wiphy *wiphy = iwm_to_wiphy(iwm);
- struct ieee80211_channel *chan;
- struct iwm_umac_notif_assoc_complete *complete =
- (struct iwm_umac_notif_assoc_complete *)buf;
-
- IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n",
- complete->bssid, complete->status);
-
- switch (le32_to_cpu(complete->status)) {
- case UMAC_ASSOC_COMPLETE_SUCCESS:
- chan = ieee80211_get_channel(wiphy,
- ieee80211_channel_to_frequency(complete->channel,
- complete->band == UMAC_BAND_2GHZ ?
- IEEE80211_BAND_2GHZ :
- IEEE80211_BAND_5GHZ));
- if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
- /* Associated to a unallowed channel, disassociate. */
- __iwm_invalidate_mlme_profile(iwm);
- IWM_WARN(iwm, "Couldn't associate with %pM due to "
- "channel %d is disabled. Check your local "
- "regulatory setting.\n",
- complete->bssid, complete->channel);
- goto failure;
- }
-
- set_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
- memcpy(iwm->bssid, complete->bssid, ETH_ALEN);
- iwm->channel = complete->channel;
-
- /* Internal roaming state, avoid notifying SME. */
- if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status)
- && iwm->conf.mode == UMAC_MODE_BSS) {
- cancel_delayed_work(&iwm->disconnect);
- cfg80211_roamed(iwm_to_ndev(iwm), NULL,
- complete->bssid,
- iwm->req_ie, iwm->req_ie_len,
- iwm->resp_ie, iwm->resp_ie_len,
- GFP_KERNEL);
- break;
- }
-
- iwm_link_on(iwm);
-
- if (iwm->conf.mode == UMAC_MODE_IBSS)
- goto ibss;
-
- if (!test_bit(IWM_STATUS_RESETTING, &iwm->status))
- cfg80211_connect_result(iwm_to_ndev(iwm),
- complete->bssid,
- iwm->req_ie, iwm->req_ie_len,
- iwm->resp_ie, iwm->resp_ie_len,
- WLAN_STATUS_SUCCESS,
- GFP_KERNEL);
- else
- cfg80211_roamed(iwm_to_ndev(iwm), NULL,
- complete->bssid,
- iwm->req_ie, iwm->req_ie_len,
- iwm->resp_ie, iwm->resp_ie_len,
- GFP_KERNEL);
- break;
- case UMAC_ASSOC_COMPLETE_FAILURE:
- failure:
- clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
- memset(iwm->bssid, 0, ETH_ALEN);
- iwm->channel = 0;
-
- /* Internal roaming state, avoid notifying SME. */
- if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status)
- && iwm->conf.mode == UMAC_MODE_BSS) {
- cancel_delayed_work(&iwm->disconnect);
- break;
- }
-
- iwm_link_off(iwm);
-
- if (iwm->conf.mode == UMAC_MODE_IBSS)
- goto ibss;
-
- if (!test_bit(IWM_STATUS_RESETTING, &iwm->status))
- if (!iwm_is_open_wep_profile(iwm)) {
- cfg80211_connect_result(iwm_to_ndev(iwm),
- complete->bssid,
- NULL, 0, NULL, 0,
- WLAN_STATUS_UNSPECIFIED_FAILURE,
- GFP_KERNEL);
- } else {
- /* Let's try shared WEP auth */
- IWM_ERR(iwm, "Trying WEP shared auth\n");
- schedule_work(&iwm->auth_retry_worker);
- }
- else
- cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0,
- GFP_KERNEL);
- break;
- default:
- break;
- }
-
- clear_bit(IWM_STATUS_RESETTING, &iwm->status);
- return 0;
-
- ibss:
- cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL);
- clear_bit(IWM_STATUS_RESETTING, &iwm->status);
- return 0;
-}
-
-static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_notif_profile_invalidate *invalid;
- u32 reason;
-
- invalid = (struct iwm_umac_notif_profile_invalidate *)buf;
- reason = le32_to_cpu(invalid->reason);
-
- IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n", reason);
-
- if (reason != UMAC_PROFILE_INVALID_REQUEST &&
- test_bit(IWM_STATUS_SME_CONNECTING, &iwm->status))
- cfg80211_connect_result(iwm_to_ndev(iwm), NULL, NULL, 0, NULL,
- 0, WLAN_STATUS_UNSPECIFIED_FAILURE,
- GFP_KERNEL);
-
- clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status);
- clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
-
- iwm->umac_profile_active = false;
- memset(iwm->bssid, 0, ETH_ALEN);
- iwm->channel = 0;
-
- iwm_link_off(iwm);
-
- wake_up_interruptible(&iwm->mlme_queue);
-
- return 0;
-}
-
-#define IWM_DISCONNECT_INTERVAL (5 * HZ)
-
-static int iwm_mlme_connection_terminated(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- IWM_DBG_MLME(iwm, DBG, "Connection terminated\n");
-
- schedule_delayed_work(&iwm->disconnect, IWM_DISCONNECT_INTERVAL);
-
- return 0;
-}
-
-static int iwm_mlme_scan_complete(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- int ret;
- struct iwm_umac_notif_scan_complete *scan_complete =
- (struct iwm_umac_notif_scan_complete *)buf;
- u32 result = le32_to_cpu(scan_complete->result);
-
- IWM_DBG_MLME(iwm, INFO, "type:0x%x result:0x%x seq:%d\n",
- le32_to_cpu(scan_complete->type),
- le32_to_cpu(scan_complete->result),
- scan_complete->seq_num);
-
- if (!test_and_clear_bit(IWM_STATUS_SCANNING, &iwm->status)) {
- IWM_ERR(iwm, "Scan complete while device not scanning\n");
- return -EIO;
- }
- if (!iwm->scan_request)
- return 0;
-
- ret = iwm_cfg80211_inform_bss(iwm);
-
- cfg80211_scan_done(iwm->scan_request,
- (result & UMAC_SCAN_RESULT_ABORTED) ? 1 : !!ret);
- iwm->scan_request = NULL;
-
- return ret;
-}
-
-static int iwm_mlme_update_sta_table(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_notif_sta_info *umac_sta =
- (struct iwm_umac_notif_sta_info *)buf;
- struct iwm_sta_info *sta;
- int i;
-
- switch (le32_to_cpu(umac_sta->opcode)) {
- case UMAC_OPCODE_ADD_MODIFY:
- sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)];
-
- IWM_DBG_MLME(iwm, INFO, "%s STA: ID = %d, Color = %d, "
- "addr = %pM, qos = %d\n",
- sta->valid ? "Modify" : "Add",
- GET_VAL8(umac_sta->sta_id, LMAC_STA_ID),
- GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR),
- umac_sta->mac_addr,
- umac_sta->flags & UMAC_STA_FLAG_QOS);
-
- sta->valid = true;
- sta->qos = umac_sta->flags & UMAC_STA_FLAG_QOS;
- sta->color = GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR);
- memcpy(sta->addr, umac_sta->mac_addr, ETH_ALEN);
- break;
- case UMAC_OPCODE_REMOVE:
- IWM_DBG_MLME(iwm, INFO, "Remove STA: ID = %d, Color = %d, "
- "addr = %pM\n",
- GET_VAL8(umac_sta->sta_id, LMAC_STA_ID),
- GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR),
- umac_sta->mac_addr);
-
- sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)];
-
- if (!memcmp(sta->addr, umac_sta->mac_addr, ETH_ALEN))
- sta->valid = false;
-
- break;
- case UMAC_OPCODE_CLEAR_ALL:
- for (i = 0; i < IWM_STA_TABLE_NUM; i++)
- iwm->sta_table[i].valid = false;
-
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static int iwm_mlme_medium_lost(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- struct wiphy *wiphy = iwm_to_wiphy(iwm);
-
- IWM_DBG_NTF(iwm, DBG, "WiFi/WiMax coexistence radio is OFF\n");
-
- wiphy_rfkill_set_hw_state(wiphy, true);
-
- return 0;
-}
-
-static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- struct wiphy *wiphy = iwm_to_wiphy(iwm);
- struct ieee80211_mgmt *mgmt;
- struct iwm_umac_notif_bss_info *umac_bss =
- (struct iwm_umac_notif_bss_info *)buf;
- struct ieee80211_channel *channel;
- struct ieee80211_supported_band *band;
- struct iwm_bss_info *bss;
- s32 signal;
- int freq;
- u16 frame_len = le16_to_cpu(umac_bss->frame_len);
- size_t bss_len = sizeof(struct iwm_umac_notif_bss_info) + frame_len;
-
- mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
-
- IWM_DBG_MLME(iwm, DBG, "New BSS info entry: %pM\n", mgmt->bssid);
- IWM_DBG_MLME(iwm, DBG, "\tType: 0x%x\n", le32_to_cpu(umac_bss->type));
- IWM_DBG_MLME(iwm, DBG, "\tTimestamp: %d\n",
- le32_to_cpu(umac_bss->timestamp));
- IWM_DBG_MLME(iwm, DBG, "\tTable Index: %d\n",
- le16_to_cpu(umac_bss->table_idx));
- IWM_DBG_MLME(iwm, DBG, "\tBand: %d\n", umac_bss->band);
- IWM_DBG_MLME(iwm, DBG, "\tChannel: %d\n", umac_bss->channel);
- IWM_DBG_MLME(iwm, DBG, "\tRSSI: %d\n", umac_bss->rssi);
- IWM_DBG_MLME(iwm, DBG, "\tFrame Length: %d\n", frame_len);
-
- list_for_each_entry(bss, &iwm->bss_list, node)
- if (bss->bss->table_idx == umac_bss->table_idx)
- break;
-
- if (&bss->node != &iwm->bss_list) {
- /* Remove the old BSS entry, we will add it back later. */
- list_del(&bss->node);
- kfree(bss->bss);
- } else {
- /* New BSS entry */
-
- bss = kzalloc(sizeof(struct iwm_bss_info), GFP_KERNEL);
- if (!bss) {
- IWM_ERR(iwm, "Couldn't allocate bss_info\n");
- return -ENOMEM;
- }
- }
-
- bss->bss = kzalloc(bss_len, GFP_KERNEL);
- if (!bss->bss) {
- kfree(bss);
- IWM_ERR(iwm, "Couldn't allocate bss\n");
- return -ENOMEM;
- }
-
- INIT_LIST_HEAD(&bss->node);
- memcpy(bss->bss, umac_bss, bss_len);
-
- if (umac_bss->band == UMAC_BAND_2GHZ)
- band = wiphy->bands[IEEE80211_BAND_2GHZ];
- else if (umac_bss->band == UMAC_BAND_5GHZ)
- band = wiphy->bands[IEEE80211_BAND_5GHZ];
- else {
- IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
- goto err;
- }
-
- freq = ieee80211_channel_to_frequency(umac_bss->channel, band->band);
- channel = ieee80211_get_channel(wiphy, freq);
- signal = umac_bss->rssi * 100;
-
- bss->cfg_bss = cfg80211_inform_bss_frame(wiphy, channel,
- mgmt, frame_len,
- signal, GFP_KERNEL);
- if (!bss->cfg_bss)
- goto err;
-
- list_add_tail(&bss->node, &iwm->bss_list);
-
- return 0;
- err:
- kfree(bss->bss);
- kfree(bss);
-
- return -EINVAL;
-}
-
-static int iwm_mlme_remove_bss(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size, struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_notif_bss_removed *bss_rm =
- (struct iwm_umac_notif_bss_removed *)buf;
- struct iwm_bss_info *bss, *next;
- u16 table_idx;
- int i;
-
- for (i = 0; i < le32_to_cpu(bss_rm->count); i++) {
- table_idx = le16_to_cpu(bss_rm->entries[i]) &
- IWM_BSS_REMOVE_INDEX_MSK;
- list_for_each_entry_safe(bss, next, &iwm->bss_list, node)
- if (bss->bss->table_idx == cpu_to_le16(table_idx)) {
- struct ieee80211_mgmt *mgmt;
-
- mgmt = (struct ieee80211_mgmt *)
- (bss->bss->frame_buf);
- IWM_DBG_MLME(iwm, ERR, "BSS removed: %pM\n",
- mgmt->bssid);
- list_del(&bss->node);
- kfree(bss->bss);
- kfree(bss);
- }
- }
-
- return 0;
-}
-
-static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size, struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_notif_mgt_frame *mgt_frame =
- (struct iwm_umac_notif_mgt_frame *)buf;
- struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame;
-
- IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame,
- le16_to_cpu(mgt_frame->len));
-
- if (ieee80211_is_assoc_req(mgt->frame_control)) {
- iwm->req_ie_len = le16_to_cpu(mgt_frame->len)
- - offsetof(struct ieee80211_mgmt,
- u.assoc_req.variable);
- kfree(iwm->req_ie);
- iwm->req_ie = kmemdup(mgt->u.assoc_req.variable,
- iwm->req_ie_len, GFP_KERNEL);
- } else if (ieee80211_is_reassoc_req(mgt->frame_control)) {
- iwm->req_ie_len = le16_to_cpu(mgt_frame->len)
- - offsetof(struct ieee80211_mgmt,
- u.reassoc_req.variable);
- kfree(iwm->req_ie);
- iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable,
- iwm->req_ie_len, GFP_KERNEL);
- } else if (ieee80211_is_assoc_resp(mgt->frame_control)) {
- iwm->resp_ie_len = le16_to_cpu(mgt_frame->len)
- - offsetof(struct ieee80211_mgmt,
- u.assoc_resp.variable);
- kfree(iwm->resp_ie);
- iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable,
- iwm->resp_ie_len, GFP_KERNEL);
- } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) {
- iwm->resp_ie_len = le16_to_cpu(mgt_frame->len)
- - offsetof(struct ieee80211_mgmt,
- u.reassoc_resp.variable);
- kfree(iwm->resp_ie);
- iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable,
- iwm->resp_ie_len, GFP_KERNEL);
- } else {
- IWM_ERR(iwm, "Unsupported management frame: 0x%x",
- le16_to_cpu(mgt->frame_control));
- return 0;
- }
-
- return 0;
-}
-
-static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size, struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_notif_wifi_if *notif =
- (struct iwm_umac_notif_wifi_if *)buf;
-
- switch (notif->status) {
- case WIFI_IF_NTFY_ASSOC_START:
- return iwm_mlme_assoc_start(iwm, buf, buf_size, cmd);
- case WIFI_IF_NTFY_ASSOC_COMPLETE:
- return iwm_mlme_assoc_complete(iwm, buf, buf_size, cmd);
- case WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE:
- return iwm_mlme_profile_invalidate(iwm, buf, buf_size, cmd);
- case WIFI_IF_NTFY_CONNECTION_TERMINATED:
- return iwm_mlme_connection_terminated(iwm, buf, buf_size, cmd);
- case WIFI_IF_NTFY_SCAN_COMPLETE:
- return iwm_mlme_scan_complete(iwm, buf, buf_size, cmd);
- case WIFI_IF_NTFY_STA_TABLE_CHANGE:
- return iwm_mlme_update_sta_table(iwm, buf, buf_size, cmd);
- case WIFI_IF_NTFY_EXTENDED_IE_REQUIRED:
- IWM_DBG_MLME(iwm, DBG, "Extended IE required\n");
- break;
- case WIFI_IF_NTFY_RADIO_PREEMPTION:
- return iwm_mlme_medium_lost(iwm, buf, buf_size, cmd);
- case WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED:
- return iwm_mlme_update_bss_table(iwm, buf, buf_size, cmd);
- case WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED:
- return iwm_mlme_remove_bss(iwm, buf, buf_size, cmd);
- break;
- case WIFI_IF_NTFY_MGMT_FRAME:
- return iwm_mlme_mgt_frame(iwm, buf, buf_size, cmd);
- case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_START:
- case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_COMPLETE:
- case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_START:
- case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_RESULT:
- case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_START:
- case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_COMPLETE:
- case WIFI_DBG_IF_NTFY_CNCT_ATC_START:
- case WIFI_DBG_IF_NTFY_COEX_NOTIFICATION:
- case WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP:
- case WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP:
- IWM_DBG_MLME(iwm, DBG, "MLME debug notification: 0x%x\n",
- notif->status);
- break;
- default:
- IWM_ERR(iwm, "Unhandled notification: 0x%x\n", notif->status);
- break;
- }
-
- return 0;
-}
-
-#define IWM_STATS_UPDATE_INTERVAL (2 * HZ)
-
-static int iwm_ntf_statistics(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size, struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_notif_stats *stats = (struct iwm_umac_notif_stats *)buf;
- struct iw_statistics *wstats = &iwm->wstats;
- u16 max_rate = 0;
- int i;
-
- IWM_DBG_MLME(iwm, DBG, "Statistics notification received\n");
-
- if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
- for (i = 0; i < UMAC_NTF_RATE_SAMPLE_NR; i++) {
- max_rate = max_t(u16, max_rate,
- max(le16_to_cpu(stats->tx_rate[i]),
- le16_to_cpu(stats->rx_rate[i])));
- }
- /* UMAC passes rate info multiplies by 2 */
- iwm->rate = max_rate >> 1;
- }
- iwm->txpower = le32_to_cpu(stats->tx_power);
-
- wstats->status = 0;
-
- wstats->discard.nwid = le32_to_cpu(stats->rx_drop_other_bssid);
- wstats->discard.code = le32_to_cpu(stats->rx_drop_decode);
- wstats->discard.fragment = le32_to_cpu(stats->rx_drop_reassembly);
- wstats->discard.retries = le32_to_cpu(stats->tx_drop_max_retry);
-
- wstats->miss.beacon = le32_to_cpu(stats->missed_beacons);
-
- /* according to cfg80211 */
- if (stats->rssi_dbm < -110)
- wstats->qual.qual = 0;
- else if (stats->rssi_dbm > -40)
- wstats->qual.qual = 70;
- else
- wstats->qual.qual = stats->rssi_dbm + 110;
-
- wstats->qual.level = stats->rssi_dbm;
- wstats->qual.noise = stats->noise_dbm;
- wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
-
- schedule_delayed_work(&iwm->stats_request, IWM_STATS_UPDATE_INTERVAL);
-
- mod_timer(&iwm->watchdog, round_jiffies(jiffies + IWM_WATCHDOG_PERIOD));
-
- return 0;
-}
-
-static int iwm_ntf_eeprom_proxy(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_cmd_eeprom_proxy *eeprom_proxy =
- (struct iwm_umac_cmd_eeprom_proxy *)
- (buf + sizeof(struct iwm_umac_wifi_in_hdr));
- struct iwm_umac_cmd_eeprom_proxy_hdr *hdr = &eeprom_proxy->hdr;
- u32 hdr_offset = le32_to_cpu(hdr->offset);
- u32 hdr_len = le32_to_cpu(hdr->len);
- u32 hdr_type = le32_to_cpu(hdr->type);
-
- IWM_DBG_NTF(iwm, DBG, "type: 0x%x, len: %d, offset: 0x%x\n",
- hdr_type, hdr_len, hdr_offset);
-
- if ((hdr_offset + hdr_len) > IWM_EEPROM_LEN)
- return -EINVAL;
-
- switch (hdr_type) {
- case IWM_UMAC_CMD_EEPROM_TYPE_READ:
- memcpy(iwm->eeprom + hdr_offset, eeprom_proxy->buf, hdr_len);
- break;
- case IWM_UMAC_CMD_EEPROM_TYPE_WRITE:
- default:
- return -ENOTSUPP;
- }
-
- return 0;
-}
-
-static int iwm_ntf_channel_info_list(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_cmd_get_channel_list *ch_list =
- (struct iwm_umac_cmd_get_channel_list *)
- (buf + sizeof(struct iwm_umac_wifi_in_hdr));
- struct wiphy *wiphy = iwm_to_wiphy(iwm);
- struct ieee80211_supported_band *band;
- int i;
-
- band = wiphy->bands[IEEE80211_BAND_2GHZ];
-
- for (i = 0; i < band->n_channels; i++) {
- unsigned long ch_mask_0 =
- le32_to_cpu(ch_list->ch[0].channels_mask);
- unsigned long ch_mask_2 =
- le32_to_cpu(ch_list->ch[2].channels_mask);
-
- if (!test_bit(i, &ch_mask_0))
- band->channels[i].flags |= IEEE80211_CHAN_DISABLED;
-
- if (!test_bit(i, &ch_mask_2))
- band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS;
- }
-
- band = wiphy->bands[IEEE80211_BAND_5GHZ];
-
- for (i = 0; i < min(band->n_channels, 32); i++) {
- unsigned long ch_mask_1 =
- le32_to_cpu(ch_list->ch[1].channels_mask);
- unsigned long ch_mask_3 =
- le32_to_cpu(ch_list->ch[3].channels_mask);
-
- if (!test_bit(i, &ch_mask_1))
- band->channels[i].flags |= IEEE80211_CHAN_DISABLED;
-
- if (!test_bit(i, &ch_mask_3))
- band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS;
- }
-
- return 0;
-}
-
-static int iwm_ntf_stop_resume_tx(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_notif_stop_resume_tx *stp_res_tx =
- (struct iwm_umac_notif_stop_resume_tx *)buf;
- struct iwm_sta_info *sta_info;
- struct iwm_tid_info *tid_info;
- u8 sta_id = STA_ID_N_COLOR_ID(stp_res_tx->sta_id);
- u16 tid_msk = le16_to_cpu(stp_res_tx->stop_resume_tid_msk);
- int bit, ret = 0;
- bool stop = false;
-
- IWM_DBG_NTF(iwm, DBG, "stop/resume notification:\n"
- "\tflags: 0x%x\n"
- "\tSTA id: %d\n"
- "\tTID bitmask: 0x%x\n",
- stp_res_tx->flags, stp_res_tx->sta_id,
- stp_res_tx->stop_resume_tid_msk);
-
- if (stp_res_tx->flags & UMAC_STOP_TX_FLAG)
- stop = true;
-
- sta_info = &iwm->sta_table[sta_id];
- if (!sta_info->valid) {
- IWM_ERR(iwm, "Stoping an invalid STA: %d %d\n",
- sta_id, stp_res_tx->sta_id);
- return -EINVAL;
- }
-
- for_each_set_bit(bit, (unsigned long *)&tid_msk, IWM_UMAC_TID_NR) {
- tid_info = &sta_info->tid_info[bit];
-
- mutex_lock(&tid_info->mutex);
- tid_info->stopped = stop;
- mutex_unlock(&tid_info->mutex);
-
- if (!stop) {
- struct iwm_tx_queue *txq;
- int queue = iwm_tid_to_queue(bit);
-
- if (queue < 0)
- continue;
-
- txq = &iwm->txq[queue];
- /*
- * If we resume, we have to move our SKBs
- * back to the tx queue and queue some work.
- */
- spin_lock_bh(&txq->lock);
- skb_queue_splice_init(&txq->queue, &txq->stopped_queue);
- spin_unlock_bh(&txq->lock);
-
- queue_work(txq->wq, &txq->worker);
- }
-
- }
-
- /* We send an ACK only for the stop case */
- if (stop)
- ret = iwm_send_umac_stop_resume_tx(iwm, stp_res_tx);
-
- return ret;
-}
-
-static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- struct iwm_umac_wifi_if *hdr;
-
- if (cmd == NULL) {
- IWM_ERR(iwm, "Couldn't find expected wifi command\n");
- return -EINVAL;
- }
-
- hdr = (struct iwm_umac_wifi_if *)cmd->buf.payload;
-
- IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: "
- "oid is 0x%x\n", hdr->oid);
-
- set_bit(hdr->oid, &iwm->wifi_ntfy[0]);
- wake_up_interruptible(&iwm->wifi_ntfy_queue);
-
- switch (hdr->oid) {
- case UMAC_WIFI_IF_CMD_SET_PROFILE:
- iwm->umac_profile_active = true;
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-#define CT_KILL_DELAY (30 * HZ)
-static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size, struct iwm_wifi_cmd *cmd)
-{
- struct wiphy *wiphy = iwm_to_wiphy(iwm);
- struct iwm_lmac_card_state *state = (struct iwm_lmac_card_state *)
- (buf + sizeof(struct iwm_umac_wifi_in_hdr));
- u32 flags = le32_to_cpu(state->flags);
-
- IWM_INFO(iwm, "HW RF Kill %s, CT Kill %s\n",
- flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF",
- flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF");
-
- if (flags & IWM_CARD_STATE_CTKILL_DISABLED) {
- /*
- * We got a CTKILL event: We bring the interface down in
- * oder to cool the device down, and try to bring it up
- * 30 seconds later. If it's still too hot, we'll go through
- * this code path again.
- */
- cancel_delayed_work_sync(&iwm->ct_kill_delay);
- schedule_delayed_work(&iwm->ct_kill_delay, CT_KILL_DELAY);
- }
-
- wiphy_rfkill_set_hw_state(wiphy, flags &
- (IWM_CARD_STATE_HW_DISABLED |
- IWM_CARD_STATE_CTKILL_DISABLED));
-
- return 0;
-}
-
-static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size)
-{
- struct iwm_umac_wifi_in_hdr *wifi_hdr;
- struct iwm_wifi_cmd *cmd;
- u8 source, cmd_id;
- u16 seq_num;
- u32 count;
-
- wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
- cmd_id = wifi_hdr->sw_hdr.cmd.cmd;
- source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
- if (source >= IWM_SRC_NUM) {
- IWM_CRIT(iwm, "invalid source %d\n", source);
- return -EINVAL;
- }
-
- if (cmd_id == REPLY_RX_MPDU_CMD)
- trace_iwm_rx_packet(iwm, buf, buf_size);
- else if ((cmd_id == UMAC_NOTIFY_OPCODE_RX_TICKET) &&
- (source == UMAC_HDI_IN_SOURCE_FW))
- trace_iwm_rx_ticket(iwm, buf, buf_size);
- else
- trace_iwm_rx_wifi_cmd(iwm, wifi_hdr);
-
- count = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT);
- count += sizeof(struct iwm_umac_wifi_in_hdr) -
- sizeof(struct iwm_dev_cmd_hdr);
- if (count > buf_size) {
- IWM_CRIT(iwm, "count %d, buf size:%ld\n", count, buf_size);
- return -EINVAL;
- }
-
- seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num);
-
- IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n",
- cmd_id, source, seq_num);
-
- /*
- * If this is a response to a previously sent command, there must
- * be a pending command for this sequence number.
- */
- cmd = iwm_get_pending_wifi_cmd(iwm, seq_num);
-
- /* Notify the caller only for sync commands. */
- switch (source) {
- case UMAC_HDI_IN_SOURCE_FHRX:
- if (iwm->lmac_handlers[cmd_id] &&
- test_bit(cmd_id, &iwm->lmac_handler_map[0]))
- return iwm_notif_send(iwm, cmd, cmd_id, source,
- buf, count);
- break;
- case UMAC_HDI_IN_SOURCE_FW:
- if (iwm->umac_handlers[cmd_id] &&
- test_bit(cmd_id, &iwm->umac_handler_map[0]))
- return iwm_notif_send(iwm, cmd, cmd_id, source,
- buf, count);
- break;
- case UMAC_HDI_IN_SOURCE_UDMA:
- break;
- }
-
- return iwm_rx_handle_resp(iwm, buf, count, cmd);
-}
-
-int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size,
- struct iwm_wifi_cmd *cmd)
-{
- u8 source, cmd_id;
- struct iwm_umac_wifi_in_hdr *wifi_hdr;
- int ret = 0;
-
- wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
- cmd_id = wifi_hdr->sw_hdr.cmd.cmd;
-
- source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
-
- IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x\n", cmd_id, source);
-
- switch (source) {
- case UMAC_HDI_IN_SOURCE_FHRX:
- if (iwm->lmac_handlers[cmd_id])
- ret = iwm->lmac_handlers[cmd_id]
- (iwm, buf, buf_size, cmd);
- break;
- case UMAC_HDI_IN_SOURCE_FW:
- if (iwm->umac_handlers[cmd_id])
- ret = iwm->umac_handlers[cmd_id]
- (iwm, buf, buf_size, cmd);
- break;
- case UMAC_HDI_IN_SOURCE_UDMA:
- ret = -EINVAL;
- break;
- }
-
- kfree(cmd);
-
- return ret;
-}
-
-static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size)
-{
- u8 seq_num;
- struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf;
- struct iwm_nonwifi_cmd *cmd;
-
- trace_iwm_rx_nonwifi_cmd(iwm, buf, buf_size);
- seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM);
-
- /*
- * We received a non wifi answer.
- * Let's check if there's a pending command for it, and if so
- * replace the command payload with the buffer, and then wake the
- * callers up.
- * That means we only support synchronised non wifi command response
- * schemes.
- */
- list_for_each_entry(cmd, &iwm->nonwifi_pending_cmd, pending)
- if (cmd->seq_num == seq_num) {
- cmd->resp_received = true;
- cmd->buf.len = buf_size;
- memcpy(cmd->buf.hdr, buf, buf_size);
- wake_up_interruptible(&iwm->nonwifi_queue);
- }
-
- return 0;
-}
-
-static int iwm_rx_handle_umac(struct iwm_priv *iwm, u8 *buf,
- unsigned long buf_size)
-{
- int ret = 0;
- u8 op_code;
- unsigned long buf_offset = 0;
- struct iwm_udma_in_hdr *hdr;
-
- /*
- * To allow for a more efficient bus usage, UMAC
- * messages are encapsulated into UDMA ones. This
- * way we can have several UMAC messages in one bus
- * transfer.
- * A UDMA frame size is always aligned on 16 bytes,
- * and a UDMA frame must not start with a UMAC_PAD_TERMINAL
- * word. This is how we parse a bus frame into several
- * UDMA ones.
- */
- while (buf_offset < buf_size) {
-
- hdr = (struct iwm_udma_in_hdr *)(buf + buf_offset);
-
- if (iwm_rx_check_udma_hdr(hdr) < 0) {
- IWM_DBG_RX(iwm, DBG, "End of frame\n");
- break;
- }
-
- op_code = GET_VAL32(hdr->cmd, UMAC_HDI_IN_CMD_OPCODE);
-
- IWM_DBG_RX(iwm, DBG, "Op code: 0x%x\n", op_code);
-
- if (op_code == UMAC_HDI_IN_OPCODE_WIFI) {
- ret |= iwm_rx_handle_wifi(iwm, buf + buf_offset,
- buf_size - buf_offset);
- } else if (op_code < UMAC_HDI_IN_OPCODE_NONWIFI_MAX) {
- if (GET_VAL32(hdr->cmd,
- UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) !=
- UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) {
- IWM_ERR(iwm, "Incorrect hw signature\n");
- return -EINVAL;
- }
- ret |= iwm_rx_handle_nonwifi(iwm, buf + buf_offset,
- buf_size - buf_offset);
- } else {
- IWM_ERR(iwm, "Invalid RX opcode: 0x%x\n", op_code);
- ret |= -EINVAL;
- }
-
- buf_offset += iwm_rx_resp_size(hdr);
- }
-
- return ret;
-}
-
-int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size)
-{
- struct iwm_udma_in_hdr *hdr;
-
- hdr = (struct iwm_udma_in_hdr *)buf;
-
- switch (le32_to_cpu(hdr->cmd)) {
- case UMAC_REBOOT_BARKER:
- if (test_bit(IWM_STATUS_READY, &iwm->status)) {
- IWM_ERR(iwm, "Unexpected BARKER\n");
-
- schedule_work(&iwm->reset_worker);
-
- return 0;
- }
-
- return iwm_notif_send(iwm, NULL, IWM_BARKER_REBOOT_NOTIFICATION,
- IWM_SRC_UDMA, buf, buf_size);
- case UMAC_ACK_BARKER:
- return iwm_notif_send(iwm, NULL, IWM_ACK_BARKER_NOTIFICATION,
- IWM_SRC_UDMA, NULL, 0);
- default:
- IWM_DBG_RX(iwm, DBG, "Received cmd: 0x%x\n", hdr->cmd);
- return iwm_rx_handle_umac(iwm, buf, buf_size);
- }
-
- return 0;
-}
-
-static const iwm_handler iwm_umac_handlers[] =
-{
- [UMAC_NOTIFY_OPCODE_ERROR] = iwm_ntf_error,
- [UMAC_NOTIFY_OPCODE_ALIVE] = iwm_ntf_umac_alive,
- [UMAC_NOTIFY_OPCODE_INIT_COMPLETE] = iwm_ntf_init_complete,
- [UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS] = iwm_ntf_wifi_status,
- [UMAC_NOTIFY_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_mlme,
- [UMAC_NOTIFY_OPCODE_PAGE_DEALLOC] = iwm_ntf_tx_credit_update,
- [UMAC_NOTIFY_OPCODE_RX_TICKET] = iwm_ntf_rx_ticket,
- [UMAC_CMD_OPCODE_RESET] = iwm_ntf_umac_reset,
- [UMAC_NOTIFY_OPCODE_STATS] = iwm_ntf_statistics,
- [UMAC_CMD_OPCODE_EEPROM_PROXY] = iwm_ntf_eeprom_proxy,
- [UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST] = iwm_ntf_channel_info_list,
- [UMAC_CMD_OPCODE_STOP_RESUME_STA_TX] = iwm_ntf_stop_resume_tx,
- [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet,
- [UMAC_CMD_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_wifi_if_wrapper,
-};
-
-static const iwm_handler iwm_lmac_handlers[] =
-{
- [REPLY_TX] = iwm_ntf_tx,
- [REPLY_ALIVE] = iwm_ntf_lmac_version,
- [CALIBRATION_RES_NOTIFICATION] = iwm_ntf_calib_res,
- [CALIBRATION_COMPLETE_NOTIFICATION] = iwm_ntf_calib_complete,
- [CALIBRATION_CFG_CMD] = iwm_ntf_calib_cfg,
- [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet,
- [CARD_STATE_NOTIFICATION] = iwm_ntf_card_state,
-};
-
-void iwm_rx_setup_handlers(struct iwm_priv *iwm)
-{
- iwm->umac_handlers = (iwm_handler *) iwm_umac_handlers;
- iwm->lmac_handlers = (iwm_handler *) iwm_lmac_handlers;
-}
-
-static void iwm_remove_iv(struct sk_buff *skb, u32 hdr_total_len)
-{
- struct ieee80211_hdr *hdr;
- unsigned int hdr_len;
-
- hdr = (struct ieee80211_hdr *)skb->data;
-
- if (!ieee80211_has_protected(hdr->frame_control))
- return;
-
- hdr_len = ieee80211_hdrlen(hdr->frame_control);
- if (hdr_total_len <= hdr_len)
- return;
-
- memmove(skb->data + (hdr_total_len - hdr_len), skb->data, hdr_len);
- skb_pull(skb, (hdr_total_len - hdr_len));
-}
-
-static void iwm_rx_adjust_packet(struct iwm_priv *iwm,
- struct iwm_rx_packet *packet,
- struct iwm_rx_ticket_node *ticket_node)
-{
- u32 payload_offset = 0, payload_len;
- struct iwm_rx_ticket *ticket = ticket_node->ticket;
- struct iwm_rx_mpdu_hdr *mpdu_hdr;
- struct ieee80211_hdr *hdr;
-
- mpdu_hdr = (struct iwm_rx_mpdu_hdr *)packet->skb->data;
- payload_offset += sizeof(struct iwm_rx_mpdu_hdr);
- /* Padding is 0 or 2 bytes */
- payload_len = le16_to_cpu(mpdu_hdr->len) +
- (le16_to_cpu(ticket->flags) & IWM_RX_TICKET_PAD_SIZE_MSK);
- payload_len -= ticket->tail_len;
-
- IWM_DBG_RX(iwm, DBG, "Packet adjusted, len:%d, offset:%d, "
- "ticket offset:%d ticket tail len:%d\n",
- payload_len, payload_offset, ticket->payload_offset,
- ticket->tail_len);
-
- IWM_HEXDUMP(iwm, DBG, RX, "RAW: ", packet->skb->data, packet->skb->len);
-
- skb_pull(packet->skb, payload_offset);
- skb_trim(packet->skb, payload_len);
-
- iwm_remove_iv(packet->skb, ticket->payload_offset);
-
- hdr = (struct ieee80211_hdr *) packet->skb->data;
- if (ieee80211_is_data_qos(hdr->frame_control)) {
- /* UMAC handed QOS_DATA frame with 2 padding bytes appended
- * to the qos_ctl field in IEEE 802.11 headers. */
- memmove(packet->skb->data + IEEE80211_QOS_CTL_LEN + 2,
- packet->skb->data,
- ieee80211_hdrlen(hdr->frame_control) -
- IEEE80211_QOS_CTL_LEN);
- hdr = (struct ieee80211_hdr *) skb_pull(packet->skb,
- IEEE80211_QOS_CTL_LEN + 2);
- hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
- }
-
- IWM_HEXDUMP(iwm, DBG, RX, "ADJUSTED: ",
- packet->skb->data, packet->skb->len);
-}
-
-static void classify8023(struct sk_buff *skb)
-{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-
- if (ieee80211_is_data_qos(hdr->frame_control)) {
- u8 *qc = ieee80211_get_qos_ctl(hdr);
- /* frame has qos control */
- skb->priority = *qc & IEEE80211_QOS_CTL_TID_MASK;
- } else {
- skb->priority = 0;
- }
-}
-
-static void iwm_rx_process_amsdu(struct iwm_priv *iwm, struct sk_buff *skb)
-{
- struct wireless_dev *wdev = iwm_to_wdev(iwm);
- struct net_device *ndev = iwm_to_ndev(iwm);
- struct sk_buff_head list;
- struct sk_buff *frame;
-
- IWM_HEXDUMP(iwm, DBG, RX, "A-MSDU: ", skb->data, skb->len);
-
- __skb_queue_head_init(&list);
- ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0,
- true);
-
- while ((frame = __skb_dequeue(&list))) {
- ndev->stats.rx_packets++;
- ndev->stats.rx_bytes += frame->len;
-
- frame->protocol = eth_type_trans(frame, ndev);
- frame->ip_summed = CHECKSUM_NONE;
- memset(frame->cb, 0, sizeof(frame->cb));
-
- if (netif_rx_ni(frame) == NET_RX_DROP) {
- IWM_ERR(iwm, "Packet dropped\n");
- ndev->stats.rx_dropped++;
- }
- }
-}
-
-static void iwm_rx_process_packet(struct iwm_priv *iwm,
- struct iwm_rx_packet *packet,
- struct iwm_rx_ticket_node *ticket_node)
-{
- int ret;
- struct sk_buff *skb = packet->skb;
- struct wireless_dev *wdev = iwm_to_wdev(iwm);
- struct net_device *ndev = iwm_to_ndev(iwm);
-
- IWM_DBG_RX(iwm, DBG, "Processing packet ID %d\n", packet->id);
-
- switch (le16_to_cpu(ticket_node->ticket->action)) {
- case IWM_RX_TICKET_RELEASE:
- IWM_DBG_RX(iwm, DBG, "RELEASE packet\n");
-
- iwm_rx_adjust_packet(iwm, packet, ticket_node);
- skb->dev = iwm_to_ndev(iwm);
- classify8023(skb);
-
- if (le16_to_cpu(ticket_node->ticket->flags) &
- IWM_RX_TICKET_AMSDU_MSK) {
- iwm_rx_process_amsdu(iwm, skb);
- break;
- }
-
- ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype);
- if (ret < 0) {
- IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - "
- "%d\n", ret);
- kfree_skb(packet->skb);
- break;
- }
-
- IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len);
-
- ndev->stats.rx_packets++;
- ndev->stats.rx_bytes += skb->len;
-
- skb->protocol = eth_type_trans(skb, ndev);
- skb->ip_summed = CHECKSUM_NONE;
- memset(skb->cb, 0, sizeof(skb->cb));
-
- if (netif_rx_ni(skb) == NET_RX_DROP) {
- IWM_ERR(iwm, "Packet dropped\n");
- ndev->stats.rx_dropped++;
- }
- break;
- case IWM_RX_TICKET_DROP:
- IWM_DBG_RX(iwm, DBG, "DROP packet: 0x%x\n",
- le16_to_cpu(ticket_node->ticket->flags));
- kfree_skb(packet->skb);
- break;
- default:
- IWM_ERR(iwm, "Unknown ticket action: %d\n",
- le16_to_cpu(ticket_node->ticket->action));
- kfree_skb(packet->skb);
- }
-
- kfree(packet);
- iwm_rx_ticket_node_free(ticket_node);
-}
-
-/*
- * Rx data processing:
- *
- * We're receiving Rx packet from the LMAC, and Rx ticket from
- * the UMAC.
- * To forward a target data packet upstream (i.e. to the
- * kernel network stack), we must have received an Rx ticket
- * that tells us we're allowed to release this packet (ticket
- * action is IWM_RX_TICKET_RELEASE). The Rx ticket also indicates,
- * among other things, where valid data actually starts in the Rx
- * packet.
- */
-void iwm_rx_worker(struct work_struct *work)
-{
- struct iwm_priv *iwm;
- struct iwm_rx_ticket_node *ticket, *next;
-
- iwm = container_of(work, struct iwm_priv, rx_worker);
-
- /*
- * We go through the tickets list and if there is a pending
- * packet for it, we push it upstream.
- * We stop whenever a ticket is missing its packet, as we're
- * supposed to send the packets in order.
- */
- spin_lock(&iwm->ticket_lock);
- list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) {
- struct iwm_rx_packet *packet =
- iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id));
-
- if (!packet) {
- IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d "
- "to be handled first\n",
- le16_to_cpu(ticket->ticket->id));
- break;
- }
-
- list_del(&ticket->node);
- iwm_rx_process_packet(iwm, packet, ticket);
- }
- spin_unlock(&iwm->ticket_lock);
-}
-
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.h b/drivers/net/wireless/iwmc3200wifi/rx.h
deleted file mode 100644
index da0db91cee59..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/rx.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-#ifndef __IWM_RX_H__
-#define __IWM_RX_H__
-
-#include <linux/skbuff.h>
-
-#include "umac.h"
-
-struct iwm_rx_ticket_node {
- struct list_head node;
- struct iwm_rx_ticket *ticket;
-};
-
-struct iwm_rx_packet {
- struct list_head node;
- u16 id;
- struct sk_buff *skb;
- unsigned long pkt_size;
-};
-
-void iwm_rx_worker(struct work_struct *work);
-
-#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c
deleted file mode 100644
index 0042f204b07f..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/sdio.c
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-/*
- * This is the SDIO bus specific hooks for iwm.
- * It also is the module's entry point.
- *
- * Interesting code paths:
- * iwm_sdio_probe() (Called by an SDIO bus scan)
- * -> iwm_if_alloc() (netdev.c)
- * -> iwm_wdev_alloc() (cfg80211.c, allocates and register our wiphy)
- * -> wiphy_new()
- * -> wiphy_register()
- * -> alloc_netdev_mq()
- * -> register_netdev()
- *
- * iwm_sdio_remove()
- * -> iwm_if_free() (netdev.c)
- * -> unregister_netdev()
- * -> iwm_wdev_free() (cfg80211.c)
- * -> wiphy_unregister()
- * -> wiphy_free()
- *
- * iwm_sdio_isr() (called in process context from the SDIO core code)
- * -> queue_work(.., isr_worker)
- * -- [async] --> iwm_sdio_isr_worker()
- * -> iwm_rx_handle()
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/netdevice.h>
-#include <linux/debugfs.h>
-#include <linux/mmc/sdio_ids.h>
-#include <linux/mmc/sdio.h>
-#include <linux/mmc/sdio_func.h>
-
-#include "iwm.h"
-#include "debug.h"
-#include "bus.h"
-#include "sdio.h"
-
-static void iwm_sdio_isr_worker(struct work_struct *work)
-{
- struct iwm_sdio_priv *hw;
- struct iwm_priv *iwm;
- struct iwm_rx_info *rx_info;
- struct sk_buff *skb;
- u8 *rx_buf;
- unsigned long rx_size;
-
- hw = container_of(work, struct iwm_sdio_priv, isr_worker);
- iwm = hw_to_iwm(hw);
-
- while (!skb_queue_empty(&iwm->rx_list)) {
- skb = skb_dequeue(&iwm->rx_list);
- rx_info = skb_to_rx_info(skb);
- rx_size = rx_info->rx_size;
- rx_buf = skb->data;
-
- IWM_HEXDUMP(iwm, DBG, SDIO, "RX: ", rx_buf, rx_size);
- if (iwm_rx_handle(iwm, rx_buf, rx_size) < 0)
- IWM_WARN(iwm, "RX error\n");
-
- kfree_skb(skb);
- }
-}
-
-static void iwm_sdio_isr(struct sdio_func *func)
-{
- struct iwm_priv *iwm;
- struct iwm_sdio_priv *hw;
- struct iwm_rx_info *rx_info;
- struct sk_buff *skb;
- unsigned long buf_size, read_size;
- int ret;
- u8 val;
-
- hw = sdio_get_drvdata(func);
- iwm = hw_to_iwm(hw);
-
- buf_size = hw->blk_size;
-
- /* We're checking the status */
- val = sdio_readb(func, IWM_SDIO_INTR_STATUS_ADDR, &ret);
- if (val == 0 || ret < 0) {
- IWM_ERR(iwm, "Wrong INTR_STATUS\n");
- return;
- }
-
- /* See if we have free buffers */
- if (skb_queue_len(&iwm->rx_list) > IWM_RX_LIST_SIZE) {
- IWM_ERR(iwm, "No buffer for more Rx frames\n");
- return;
- }
-
- /* We first read the transaction size */
- read_size = sdio_readb(func, IWM_SDIO_INTR_GET_SIZE_ADDR + 1, &ret);
- read_size = read_size << 8;
-
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't read the xfer size\n");
- return;
- }
-
- /* We need to clear the INT register */
- sdio_writeb(func, 1, IWM_SDIO_INTR_CLEAR_ADDR, &ret);
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't clear the INT register\n");
- return;
- }
-
- while (buf_size < read_size)
- buf_size <<= 1;
-
- skb = dev_alloc_skb(buf_size);
- if (!skb) {
- IWM_ERR(iwm, "Couldn't alloc RX skb\n");
- return;
- }
- rx_info = skb_to_rx_info(skb);
- rx_info->rx_size = read_size;
- rx_info->rx_buf_size = buf_size;
-
- /* Now we can read the actual buffer */
- ret = sdio_memcpy_fromio(func, skb_put(skb, read_size),
- IWM_SDIO_DATA_ADDR, read_size);
-
- /* The skb is put on a driver's specific Rx SKB list */
- skb_queue_tail(&iwm->rx_list, skb);
-
- /* We can now schedule the actual worker */
- queue_work(hw->isr_wq, &hw->isr_worker);
-}
-
-static void iwm_sdio_rx_free(struct iwm_sdio_priv *hw)
-{
- struct iwm_priv *iwm = hw_to_iwm(hw);
-
- flush_workqueue(hw->isr_wq);
-
- skb_queue_purge(&iwm->rx_list);
-}
-
-/* Bus ops */
-static int if_sdio_enable(struct iwm_priv *iwm)
-{
- struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
- int ret;
-
- sdio_claim_host(hw->func);
-
- ret = sdio_enable_func(hw->func);
- if (ret) {
- IWM_ERR(iwm, "Couldn't enable the device: is TOP driver "
- "loaded and functional?\n");
- goto release_host;
- }
-
- iwm_reset(iwm);
-
- ret = sdio_claim_irq(hw->func, iwm_sdio_isr);
- if (ret) {
- IWM_ERR(iwm, "Failed to claim irq: %d\n", ret);
- goto release_host;
- }
-
- sdio_writeb(hw->func, 1, IWM_SDIO_INTR_ENABLE_ADDR, &ret);
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't enable INTR: %d\n", ret);
- goto release_irq;
- }
-
- sdio_release_host(hw->func);
-
- IWM_DBG_SDIO(iwm, INFO, "IWM SDIO enable\n");
-
- return 0;
-
- release_irq:
- sdio_release_irq(hw->func);
- release_host:
- sdio_release_host(hw->func);
-
- return ret;
-}
-
-static int if_sdio_disable(struct iwm_priv *iwm)
-{
- struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
- int ret;
-
- sdio_claim_host(hw->func);
- sdio_writeb(hw->func, 0, IWM_SDIO_INTR_ENABLE_ADDR, &ret);
- if (ret < 0)
- IWM_WARN(iwm, "Couldn't disable INTR: %d\n", ret);
-
- sdio_release_irq(hw->func);
- sdio_disable_func(hw->func);
- sdio_release_host(hw->func);
-
- iwm_sdio_rx_free(hw);
-
- iwm_reset(iwm);
-
- IWM_DBG_SDIO(iwm, INFO, "IWM SDIO disable\n");
-
- return 0;
-}
-
-static int if_sdio_send_chunk(struct iwm_priv *iwm, u8 *buf, int count)
-{
- struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
- int aligned_count = ALIGN(count, hw->blk_size);
- int ret;
-
- if ((unsigned long)buf & 0x3) {
- IWM_ERR(iwm, "buf <%p> is not dword aligned\n", buf);
- /* TODO: Is this a hardware limitation? use get_unligned */
- return -EINVAL;
- }
-
- sdio_claim_host(hw->func);
- ret = sdio_memcpy_toio(hw->func, IWM_SDIO_DATA_ADDR, buf,
- aligned_count);
- sdio_release_host(hw->func);
-
- return ret;
-}
-
-static ssize_t iwm_debugfs_sdio_read(struct file *filp, char __user *buffer,
- size_t count, loff_t *ppos)
-{
- struct iwm_priv *iwm = filp->private_data;
- struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
- char *buf;
- u8 cccr;
- int buf_len = 4096, ret;
- size_t len = 0;
-
- if (*ppos != 0)
- return 0;
- if (count < sizeof(buf))
- return -ENOSPC;
-
- buf = kzalloc(buf_len, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- sdio_claim_host(hw->func);
-
- cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IOEx, &ret);
- if (ret) {
- IWM_ERR(iwm, "Could not read SDIO_CCCR_IOEx\n");
- goto err;
- }
- len += snprintf(buf + len, buf_len - len, "CCCR_IOEx: 0x%x\n", cccr);
-
- cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IORx, &ret);
- if (ret) {
- IWM_ERR(iwm, "Could not read SDIO_CCCR_IORx\n");
- goto err;
- }
- len += snprintf(buf + len, buf_len - len, "CCCR_IORx: 0x%x\n", cccr);
-
-
- cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IENx, &ret);
- if (ret) {
- IWM_ERR(iwm, "Could not read SDIO_CCCR_IENx\n");
- goto err;
- }
- len += snprintf(buf + len, buf_len - len, "CCCR_IENx: 0x%x\n", cccr);
-
-
- cccr = sdio_f0_readb(hw->func, SDIO_CCCR_INTx, &ret);
- if (ret) {
- IWM_ERR(iwm, "Could not read SDIO_CCCR_INTx\n");
- goto err;
- }
- len += snprintf(buf + len, buf_len - len, "CCCR_INTx: 0x%x\n", cccr);
-
-
- cccr = sdio_f0_readb(hw->func, SDIO_CCCR_ABORT, &ret);
- if (ret) {
- IWM_ERR(iwm, "Could not read SDIO_CCCR_ABORTx\n");
- goto err;
- }
- len += snprintf(buf + len, buf_len - len, "CCCR_ABORT: 0x%x\n", cccr);
-
- cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IF, &ret);
- if (ret) {
- IWM_ERR(iwm, "Could not read SDIO_CCCR_IF\n");
- goto err;
- }
- len += snprintf(buf + len, buf_len - len, "CCCR_IF: 0x%x\n", cccr);
-
-
- cccr = sdio_f0_readb(hw->func, SDIO_CCCR_CAPS, &ret);
- if (ret) {
- IWM_ERR(iwm, "Could not read SDIO_CCCR_CAPS\n");
- goto err;
- }
- len += snprintf(buf + len, buf_len - len, "CCCR_CAPS: 0x%x\n", cccr);
-
- cccr = sdio_f0_readb(hw->func, SDIO_CCCR_CIS, &ret);
- if (ret) {
- IWM_ERR(iwm, "Could not read SDIO_CCCR_CIS\n");
- goto err;
- }
- len += snprintf(buf + len, buf_len - len, "CCCR_CIS: 0x%x\n", cccr);
-
- ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
-err:
- sdio_release_host(hw->func);
-
- kfree(buf);
-
- return ret;
-}
-
-static const struct file_operations iwm_debugfs_sdio_fops = {
- .owner = THIS_MODULE,
- .open = simple_open,
- .read = iwm_debugfs_sdio_read,
- .llseek = default_llseek,
-};
-
-static void if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir)
-{
- struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
-
- hw->cccr_dentry = debugfs_create_file("cccr", 0200,
- parent_dir, iwm,
- &iwm_debugfs_sdio_fops);
-}
-
-static void if_sdio_debugfs_exit(struct iwm_priv *iwm)
-{
- struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
-
- debugfs_remove(hw->cccr_dentry);
-}
-
-static struct iwm_if_ops if_sdio_ops = {
- .enable = if_sdio_enable,
- .disable = if_sdio_disable,
- .send_chunk = if_sdio_send_chunk,
- .debugfs_init = if_sdio_debugfs_init,
- .debugfs_exit = if_sdio_debugfs_exit,
- .umac_name = "iwmc3200wifi-umac-sdio.bin",
- .calib_lmac_name = "iwmc3200wifi-calib-sdio.bin",
- .lmac_name = "iwmc3200wifi-lmac-sdio.bin",
-};
-MODULE_FIRMWARE("iwmc3200wifi-umac-sdio.bin");
-MODULE_FIRMWARE("iwmc3200wifi-calib-sdio.bin");
-MODULE_FIRMWARE("iwmc3200wifi-lmac-sdio.bin");
-
-static int iwm_sdio_probe(struct sdio_func *func,
- const struct sdio_device_id *id)
-{
- struct iwm_priv *iwm;
- struct iwm_sdio_priv *hw;
- struct device *dev = &func->dev;
- int ret;
-
- /* check if TOP has already initialized the card */
- sdio_claim_host(func);
- ret = sdio_enable_func(func);
- if (ret) {
- dev_err(dev, "wait for TOP to enable the device\n");
- sdio_release_host(func);
- return ret;
- }
-
- ret = sdio_set_block_size(func, IWM_SDIO_BLK_SIZE);
-
- sdio_disable_func(func);
- sdio_release_host(func);
-
- if (ret < 0) {
- dev_err(dev, "Failed to set block size: %d\n", ret);
- return ret;
- }
-
- iwm = iwm_if_alloc(sizeof(struct iwm_sdio_priv), dev, &if_sdio_ops);
- if (IS_ERR(iwm)) {
- dev_err(dev, "allocate SDIO interface failed\n");
- return PTR_ERR(iwm);
- }
-
- hw = iwm_private(iwm);
- hw->iwm = iwm;
-
- iwm_debugfs_init(iwm);
-
- sdio_set_drvdata(func, hw);
-
- hw->func = func;
- hw->blk_size = IWM_SDIO_BLK_SIZE;
-
- hw->isr_wq = create_singlethread_workqueue(KBUILD_MODNAME "_sdio");
- if (!hw->isr_wq) {
- ret = -ENOMEM;
- goto debugfs_exit;
- }
-
- INIT_WORK(&hw->isr_worker, iwm_sdio_isr_worker);
-
- ret = iwm_if_add(iwm);
- if (ret) {
- dev_err(dev, "add SDIO interface failed\n");
- goto destroy_wq;
- }
-
- dev_info(dev, "IWM SDIO probe\n");
-
- return 0;
-
- destroy_wq:
- destroy_workqueue(hw->isr_wq);
- debugfs_exit:
- iwm_debugfs_exit(iwm);
- iwm_if_free(iwm);
- return ret;
-}
-
-static void iwm_sdio_remove(struct sdio_func *func)
-{
- struct iwm_sdio_priv *hw = sdio_get_drvdata(func);
- struct iwm_priv *iwm = hw_to_iwm(hw);
- struct device *dev = &func->dev;
-
- iwm_if_remove(iwm);
- destroy_workqueue(hw->isr_wq);
- iwm_debugfs_exit(iwm);
- iwm_if_free(iwm);
-
- sdio_set_drvdata(func, NULL);
-
- dev_info(dev, "IWM SDIO remove\n");
-}
-
-static const struct sdio_device_id iwm_sdio_ids[] = {
- /* Global/AGN SKU */
- { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 0x1403) },
- /* BGN SKU */
- { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 0x1408) },
- { /* end: all zeroes */ },
-};
-MODULE_DEVICE_TABLE(sdio, iwm_sdio_ids);
-
-static struct sdio_driver iwm_sdio_driver = {
- .name = "iwm_sdio",
- .id_table = iwm_sdio_ids,
- .probe = iwm_sdio_probe,
- .remove = iwm_sdio_remove,
-};
-
-static int __init iwm_sdio_init_module(void)
-{
- return sdio_register_driver(&iwm_sdio_driver);
-}
-
-static void __exit iwm_sdio_exit_module(void)
-{
- sdio_unregister_driver(&iwm_sdio_driver);
-}
-
-module_init(iwm_sdio_init_module);
-module_exit(iwm_sdio_exit_module);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR(IWM_COPYRIGHT " " IWM_AUTHOR);
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.h b/drivers/net/wireless/iwmc3200wifi/sdio.h
deleted file mode 100644
index aab6b6892e45..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/sdio.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-#ifndef __IWM_SDIO_H__
-#define __IWM_SDIO_H__
-
-#define IWM_SDIO_DATA_ADDR 0x0
-#define IWM_SDIO_INTR_ENABLE_ADDR 0x14
-#define IWM_SDIO_INTR_STATUS_ADDR 0x13
-#define IWM_SDIO_INTR_CLEAR_ADDR 0x13
-#define IWM_SDIO_INTR_GET_SIZE_ADDR 0x2C
-
-#define IWM_SDIO_BLK_SIZE 256
-
-#define iwm_to_if_sdio(i) (struct iwm_sdio_priv *)(iwm->private)
-
-struct iwm_sdio_priv {
- struct sdio_func *func;
- struct iwm_priv *iwm;
-
- struct workqueue_struct *isr_wq;
- struct work_struct isr_worker;
-
- struct dentry *cccr_dentry;
-
- unsigned int blk_size;
-};
-
-#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/trace.c b/drivers/net/wireless/iwmc3200wifi/trace.c
deleted file mode 100644
index 904d36f22311..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/trace.c
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "iwm.h"
-#define CREATE_TRACE_POINTS
-#include "trace.h"
diff --git a/drivers/net/wireless/iwmc3200wifi/trace.h b/drivers/net/wireless/iwmc3200wifi/trace.h
deleted file mode 100644
index f5f7070b7e22..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/trace.h
+++ /dev/null
@@ -1,283 +0,0 @@
-#if !defined(__IWM_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
-#define __IWM_TRACE_H__
-
-#include <linux/tracepoint.h>
-
-#if !defined(CONFIG_IWM_TRACING)
-#undef TRACE_EVENT
-#define TRACE_EVENT(name, proto, ...) \
-static inline void trace_ ## name(proto) {}
-#endif
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM iwm
-
-#define IWM_ENTRY __array(char, ndev_name, 16)
-#define IWM_ASSIGN strlcpy(__entry->ndev_name, iwm_to_ndev(iwm)->name, 16)
-#define IWM_PR_FMT "%s"
-#define IWM_PR_ARG __entry->ndev_name
-
-TRACE_EVENT(iwm_tx_nonwifi_cmd,
- TP_PROTO(struct iwm_priv *iwm, struct iwm_udma_out_nonwifi_hdr *hdr),
-
- TP_ARGS(iwm, hdr),
-
- TP_STRUCT__entry(
- IWM_ENTRY
- __field(u8, opcode)
- __field(u8, resp)
- __field(u8, eot)
- __field(u8, hw)
- __field(u16, seq)
- __field(u32, addr)
- __field(u32, op1)
- __field(u32, op2)
- ),
-
- TP_fast_assign(
- IWM_ASSIGN;
- __entry->opcode = GET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE);
- __entry->resp = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_RESP);
- __entry->eot = GET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT);
- __entry->hw = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW);
- __entry->seq = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM);
- __entry->addr = le32_to_cpu(hdr->addr);
- __entry->op1 = le32_to_cpu(hdr->op1_sz);
- __entry->op2 = le32_to_cpu(hdr->op2);
- ),
-
- TP_printk(
- IWM_PR_FMT " Tx TARGET CMD: opcode 0x%x, resp %d, eot %d, "
- "hw %d, seq 0x%x, addr 0x%x, op1 0x%x, op2 0x%x",
- IWM_PR_ARG, __entry->opcode, __entry->resp, __entry->eot,
- __entry->hw, __entry->seq, __entry->addr, __entry->op1,
- __entry->op2
- )
-);
-
-TRACE_EVENT(iwm_tx_wifi_cmd,
- TP_PROTO(struct iwm_priv *iwm, struct iwm_umac_wifi_out_hdr *hdr),
-
- TP_ARGS(iwm, hdr),
-
- TP_STRUCT__entry(
- IWM_ENTRY
- __field(u8, opcode)
- __field(u8, lmac)
- __field(u8, resp)
- __field(u8, eot)
- __field(u8, ra_tid)
- __field(u8, credit_group)
- __field(u8, color)
- __field(u16, seq)
- ),
-
- TP_fast_assign(
- IWM_ASSIGN;
- __entry->opcode = hdr->sw_hdr.cmd.cmd;
- __entry->lmac = 0;
- __entry->seq = __le16_to_cpu(hdr->sw_hdr.cmd.seq_num);
- __entry->resp = GET_VAL8(hdr->sw_hdr.cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ);
- __entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR);
- __entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT);
- __entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID);
- __entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP);
- if (__entry->opcode == UMAC_CMD_OPCODE_WIFI_PASS_THROUGH ||
- __entry->opcode == UMAC_CMD_OPCODE_WIFI_IF_WRAPPER) {
- __entry->lmac = 1;
- __entry->opcode = ((struct iwm_lmac_hdr *)(hdr + 1))->id;
- }
- ),
-
- TP_printk(
- IWM_PR_FMT " Tx %cMAC CMD: opcode 0x%x, resp %d, eot %d, "
- "seq 0x%x, sta_color 0x%x, ra_tid 0x%x, credit_group 0x%x",
- IWM_PR_ARG, __entry->lmac ? 'L' : 'U', __entry->opcode,
- __entry->resp, __entry->eot, __entry->seq, __entry->color,
- __entry->ra_tid, __entry->credit_group
- )
-);
-
-TRACE_EVENT(iwm_tx_packets,
- TP_PROTO(struct iwm_priv *iwm, u8 *buf, int len),
-
- TP_ARGS(iwm, buf, len),
-
- TP_STRUCT__entry(
- IWM_ENTRY
- __field(u8, eot)
- __field(u8, ra_tid)
- __field(u8, credit_group)
- __field(u8, color)
- __field(u16, seq)
- __field(u8, npkt)
- __field(u32, bytes)
- ),
-
- TP_fast_assign(
- struct iwm_umac_wifi_out_hdr *hdr =
- (struct iwm_umac_wifi_out_hdr *)buf;
-
- IWM_ASSIGN;
- __entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT);
- __entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID);
- __entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP);
- __entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR);
- __entry->seq = __le16_to_cpu(hdr->sw_hdr.cmd.seq_num);
- __entry->npkt = 1;
- __entry->bytes = len;
-
- if (!__entry->eot) {
- int count;
- u8 *ptr = buf;
-
- __entry->npkt = 0;
- while (ptr < buf + len) {
- count = GET_VAL32(hdr->sw_hdr.meta_data,
- UMAC_FW_CMD_BYTE_COUNT);
- ptr += ALIGN(sizeof(*hdr) + count, 16);
- hdr = (struct iwm_umac_wifi_out_hdr *)ptr;
- __entry->npkt++;
- }
- }
- ),
-
- TP_printk(
- IWM_PR_FMT " Tx %spacket: eot %d, seq 0x%x, sta_color 0x%x, "
- "ra_tid 0x%x, credit_group 0x%x, embedded_packets %d, %d bytes",
- IWM_PR_ARG, !__entry->eot ? "concatenated " : "",
- __entry->eot, __entry->seq, __entry->color, __entry->ra_tid,
- __entry->credit_group, __entry->npkt, __entry->bytes
- )
-);
-
-TRACE_EVENT(iwm_rx_nonwifi_cmd,
- TP_PROTO(struct iwm_priv *iwm, void *buf, int len),
-
- TP_ARGS(iwm, buf, len),
-
- TP_STRUCT__entry(
- IWM_ENTRY
- __field(u8, opcode)
- __field(u16, seq)
- __field(u32, len)
- ),
-
- TP_fast_assign(
- struct iwm_udma_in_hdr *hdr = buf;
-
- IWM_ASSIGN;
- __entry->opcode = GET_VAL32(hdr->cmd, UDMA_HDI_IN_NW_CMD_OPCODE);
- __entry->seq = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM);
- __entry->len = len;
- ),
-
- TP_printk(
- IWM_PR_FMT " Rx TARGET RESP: opcode 0x%x, seq 0x%x, len 0x%x",
- IWM_PR_ARG, __entry->opcode, __entry->seq, __entry->len
- )
-);
-
-TRACE_EVENT(iwm_rx_wifi_cmd,
- TP_PROTO(struct iwm_priv *iwm, struct iwm_umac_wifi_in_hdr *hdr),
-
- TP_ARGS(iwm, hdr),
-
- TP_STRUCT__entry(
- IWM_ENTRY
- __field(u8, cmd)
- __field(u8, source)
- __field(u16, seq)
- __field(u32, count)
- ),
-
- TP_fast_assign(
- IWM_ASSIGN;
- __entry->cmd = hdr->sw_hdr.cmd.cmd;
- __entry->source = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
- __entry->count = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT);
- __entry->seq = le16_to_cpu(hdr->sw_hdr.cmd.seq_num);
- ),
-
- TP_printk(
- IWM_PR_FMT " Rx %s RESP: cmd 0x%x, seq 0x%x, count 0x%x",
- IWM_PR_ARG, __entry->source == UMAC_HDI_IN_SOURCE_FHRX ? "LMAC" :
- __entry->source == UMAC_HDI_IN_SOURCE_FW ? "UMAC" : "UDMA",
- __entry->cmd, __entry->seq, __entry->count
- )
-);
-
-#define iwm_ticket_action_symbol \
- { IWM_RX_TICKET_DROP, "DROP" }, \
- { IWM_RX_TICKET_RELEASE, "RELEASE" }, \
- { IWM_RX_TICKET_SNIFFER, "SNIFFER" }, \
- { IWM_RX_TICKET_ENQUEUE, "ENQUEUE" }
-
-TRACE_EVENT(iwm_rx_ticket,
- TP_PROTO(struct iwm_priv *iwm, void *buf, int len),
-
- TP_ARGS(iwm, buf, len),
-
- TP_STRUCT__entry(
- IWM_ENTRY
- __field(u8, action)
- __field(u8, reason)
- __field(u16, id)
- __field(u16, flags)
- ),
-
- TP_fast_assign(
- struct iwm_rx_ticket *ticket =
- ((struct iwm_umac_notif_rx_ticket *)buf)->tickets;
-
- IWM_ASSIGN;
- __entry->id = le16_to_cpu(ticket->id);
- __entry->action = le16_to_cpu(ticket->action);
- __entry->flags = le16_to_cpu(ticket->flags);
- __entry->reason = (__entry->flags & IWM_RX_TICKET_DROP_REASON_MSK) >> IWM_RX_TICKET_DROP_REASON_POS;
- ),
-
- TP_printk(
- IWM_PR_FMT " Rx ticket: id 0x%x, action %s, %s 0x%x%s",
- IWM_PR_ARG, __entry->id,
- __print_symbolic(__entry->action, iwm_ticket_action_symbol),
- __entry->reason ? "reason" : "flags",
- __entry->reason ? __entry->reason : __entry->flags,
- __entry->flags & IWM_RX_TICKET_AMSDU_MSK ? ", AMSDU frame" : ""
- )
-);
-
-TRACE_EVENT(iwm_rx_packet,
- TP_PROTO(struct iwm_priv *iwm, void *buf, int len),
-
- TP_ARGS(iwm, buf, len),
-
- TP_STRUCT__entry(
- IWM_ENTRY
- __field(u8, source)
- __field(u16, id)
- __field(u32, len)
- ),
-
- TP_fast_assign(
- struct iwm_umac_wifi_in_hdr *hdr = buf;
-
- IWM_ASSIGN;
- __entry->source = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
- __entry->id = le16_to_cpu(hdr->sw_hdr.cmd.seq_num);
- __entry->len = len - sizeof(*hdr);
- ),
-
- TP_printk(
- IWM_PR_FMT " Rx %s packet: id 0x%x, %d bytes",
- IWM_PR_ARG, __entry->source == UMAC_HDI_IN_SOURCE_FHRX ?
- "LMAC" : "UMAC", __entry->id, __entry->len
- )
-);
-#endif
-
-#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
-#undef TRACE_INCLUDE_FILE
-#define TRACE_INCLUDE_FILE trace
-#include <trace/define_trace.h>
diff --git a/drivers/net/wireless/iwmc3200wifi/tx.c b/drivers/net/wireless/iwmc3200wifi/tx.c
deleted file mode 100644
index be98074c0608..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/tx.c
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-/*
- * iwm Tx theory of operation:
- *
- * 1) We receive a 802.3 frame from the stack
- * 2) We convert it to a 802.11 frame [iwm_xmit_frame]
- * 3) We queue it to its corresponding tx queue [iwm_xmit_frame]
- * 4) We schedule the tx worker. There is one worker per tx
- * queue. [iwm_xmit_frame]
- * 5) The tx worker is scheduled
- * 6) We go through every queued skb on the tx queue, and for each
- * and every one of them: [iwm_tx_worker]
- * a) We check if we have enough Tx credits (see below for a Tx
- * credits description) for the frame length. [iwm_tx_worker]
- * b) If we do, we aggregate the Tx frame into a UDMA one, by
- * concatenating one REPLY_TX command per Tx frame. [iwm_tx_worker]
- * c) When we run out of credits, or when we reach the maximum
- * concatenation size, we actually send the concatenated UDMA
- * frame. [iwm_tx_worker]
- *
- * When we run out of Tx credits, the skbs are filling the tx queue,
- * and eventually we will stop the netdev queue. [iwm_tx_worker]
- * The tx queue is emptied as we're getting new tx credits, by
- * scheduling the tx_worker. [iwm_tx_credit_inc]
- * The netdev queue is started again when we have enough tx credits,
- * and when our tx queue has some reasonable amout of space available
- * (i.e. half of the max size). [iwm_tx_worker]
- */
-
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/ieee80211.h>
-
-#include "iwm.h"
-#include "debug.h"
-#include "commands.h"
-#include "hal.h"
-#include "umac.h"
-#include "bus.h"
-
-#define IWM_UMAC_PAGE_ALLOC_WRAP 0xffff
-
-#define BYTES_TO_PAGES(n) (1 + ((n) >> ilog2(IWM_UMAC_PAGE_SIZE)) - \
- (((n) & (IWM_UMAC_PAGE_SIZE - 1)) == 0))
-
-#define pool_id_to_queue(id) ((id < IWM_TX_CMD_QUEUE) ? id : id - 1)
-#define queue_to_pool_id(q) ((q < IWM_TX_CMD_QUEUE) ? q : q + 1)
-
-/* require to hold tx_credit lock */
-static int iwm_tx_credit_get(struct iwm_tx_credit *tx_credit, int id)
-{
- struct pool_entry *pool = &tx_credit->pools[id];
- struct spool_entry *spool = &tx_credit->spools[pool->sid];
- int spool_pages;
-
- /* number of pages can be taken from spool by this pool */
- spool_pages = spool->max_pages - spool->alloc_pages +
- max(pool->min_pages - pool->alloc_pages, 0);
-
- return min(pool->max_pages - pool->alloc_pages, spool_pages);
-}
-
-static bool iwm_tx_credit_ok(struct iwm_priv *iwm, int id, int nb)
-{
- u32 npages = BYTES_TO_PAGES(nb);
-
- if (npages <= iwm_tx_credit_get(&iwm->tx_credit, id))
- return 1;
-
- set_bit(id, &iwm->tx_credit.full_pools_map);
-
- IWM_DBG_TX(iwm, DBG, "LINK: stop txq[%d], available credit: %d\n",
- pool_id_to_queue(id),
- iwm_tx_credit_get(&iwm->tx_credit, id));
-
- return 0;
-}
-
-void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages)
-{
- struct pool_entry *pool;
- struct spool_entry *spool;
- int freed_pages;
- int queue;
-
- BUG_ON(id >= IWM_MACS_OUT_GROUPS);
-
- pool = &iwm->tx_credit.pools[id];
- spool = &iwm->tx_credit.spools[pool->sid];
-
- freed_pages = total_freed_pages - pool->total_freed_pages;
- IWM_DBG_TX(iwm, DBG, "Free %d pages for pool[%d]\n", freed_pages, id);
-
- if (!freed_pages) {
- IWM_DBG_TX(iwm, DBG, "No pages are freed by UMAC\n");
- return;
- } else if (freed_pages < 0)
- freed_pages += IWM_UMAC_PAGE_ALLOC_WRAP + 1;
-
- if (pool->alloc_pages > pool->min_pages) {
- int spool_pages = pool->alloc_pages - pool->min_pages;
- spool_pages = min(spool_pages, freed_pages);
- spool->alloc_pages -= spool_pages;
- }
-
- pool->alloc_pages -= freed_pages;
- pool->total_freed_pages = total_freed_pages;
-
- IWM_DBG_TX(iwm, DBG, "Pool[%d] pages alloc: %d, total_freed: %d, "
- "Spool[%d] pages alloc: %d\n", id, pool->alloc_pages,
- pool->total_freed_pages, pool->sid, spool->alloc_pages);
-
- if (test_bit(id, &iwm->tx_credit.full_pools_map) &&
- (pool->alloc_pages < pool->max_pages / 2)) {
- clear_bit(id, &iwm->tx_credit.full_pools_map);
-
- queue = pool_id_to_queue(id);
-
- IWM_DBG_TX(iwm, DBG, "LINK: start txq[%d], available "
- "credit: %d\n", queue,
- iwm_tx_credit_get(&iwm->tx_credit, id));
- queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker);
- }
-}
-
-static void iwm_tx_credit_dec(struct iwm_priv *iwm, int id, int alloc_pages)
-{
- struct pool_entry *pool;
- struct spool_entry *spool;
- int spool_pages;
-
- IWM_DBG_TX(iwm, DBG, "Allocate %d pages for pool[%d]\n",
- alloc_pages, id);
-
- BUG_ON(id >= IWM_MACS_OUT_GROUPS);
-
- pool = &iwm->tx_credit.pools[id];
- spool = &iwm->tx_credit.spools[pool->sid];
-
- spool_pages = pool->alloc_pages + alloc_pages - pool->min_pages;
-
- if (pool->alloc_pages >= pool->min_pages)
- spool->alloc_pages += alloc_pages;
- else if (spool_pages > 0)
- spool->alloc_pages += spool_pages;
-
- pool->alloc_pages += alloc_pages;
-
- IWM_DBG_TX(iwm, DBG, "Pool[%d] pages alloc: %d, total_freed: %d, "
- "Spool[%d] pages alloc: %d\n", id, pool->alloc_pages,
- pool->total_freed_pages, pool->sid, spool->alloc_pages);
-}
-
-int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb)
-{
- u32 npages = BYTES_TO_PAGES(nb);
- int ret = 0;
-
- spin_lock(&iwm->tx_credit.lock);
-
- if (!iwm_tx_credit_ok(iwm, id, nb)) {
- IWM_DBG_TX(iwm, DBG, "No credit available for pool[%d]\n", id);
- ret = -ENOSPC;
- goto out;
- }
-
- iwm_tx_credit_dec(iwm, id, npages);
-
- out:
- spin_unlock(&iwm->tx_credit.lock);
- return ret;
-}
-
-/*
- * Since we're on an SDIO or USB bus, we are not sharing memory
- * for storing to be transmitted frames. The host needs to push
- * them upstream. As a consequence there needs to be a way for
- * the target to let us know if it can actually take more TX frames
- * or not. This is what Tx credits are for.
- *
- * For each Tx HW queue, we have a Tx pool, and then we have one
- * unique super pool (spool), which is actually a global pool of
- * all the UMAC pages.
- * For each Tx pool we have a min_pages, a max_pages fields, and a
- * alloc_pages fields. The alloc_pages tracks the number of pages
- * currently allocated from the tx pool.
- * Here are the rules to check if given a tx frame we have enough
- * tx credits for it:
- * 1) We translate the frame length into a number of UMAC pages.
- * Let's call them n_pages.
- * 2) For the corresponding tx pool, we check if n_pages +
- * pool->alloc_pages is higher than pool->min_pages. min_pages
- * represent a set of pre-allocated pages on the tx pool. If
- * that's the case, then we need to allocate those pages from
- * the spool. We can do so until we reach spool->max_pages.
- * 3) Each tx pool is not allowed to allocate more than pool->max_pages
- * from the spool, so once we're over min_pages, we can allocate
- * pages from the spool, but not more than max_pages.
- *
- * When the tx code path needs to send a tx frame, it checks first
- * if it has enough tx credits, following those rules. [iwm_tx_credit_get]
- * If it does, it then updates the pool and spool counters and
- * then send the frame. [iwm_tx_credit_alloc and iwm_tx_credit_dec]
- * On the other side, when the UMAC is done transmitting frames, it
- * will send a credit update notification to the host. This is when
- * the pool and spool counters gets to be decreased. [iwm_tx_credit_inc,
- * called from rx.c:iwm_ntf_tx_credit_update]
- *
- */
-void iwm_tx_credit_init_pools(struct iwm_priv *iwm,
- struct iwm_umac_notif_alive *alive)
-{
- int i, sid, pool_pages;
-
- spin_lock(&iwm->tx_credit.lock);
-
- iwm->tx_credit.pool_nr = le16_to_cpu(alive->page_grp_count);
- iwm->tx_credit.full_pools_map = 0;
- memset(&iwm->tx_credit.spools[0], 0, sizeof(struct spool_entry));
-
- IWM_DBG_TX(iwm, DBG, "Pools number is %d\n", iwm->tx_credit.pool_nr);
-
- for (i = 0; i < iwm->tx_credit.pool_nr; i++) {
- __le32 page_grp_state = alive->page_grp_state[i];
-
- iwm->tx_credit.pools[i].id = GET_VAL32(page_grp_state,
- UMAC_ALIVE_PAGE_STS_GRP_NUM);
- iwm->tx_credit.pools[i].sid = GET_VAL32(page_grp_state,
- UMAC_ALIVE_PAGE_STS_SGRP_NUM);
- iwm->tx_credit.pools[i].min_pages = GET_VAL32(page_grp_state,
- UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE);
- iwm->tx_credit.pools[i].max_pages = GET_VAL32(page_grp_state,
- UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE);
- iwm->tx_credit.pools[i].alloc_pages = 0;
- iwm->tx_credit.pools[i].total_freed_pages = 0;
-
- sid = iwm->tx_credit.pools[i].sid;
- pool_pages = iwm->tx_credit.pools[i].min_pages;
-
- if (iwm->tx_credit.spools[sid].max_pages == 0) {
- iwm->tx_credit.spools[sid].id = sid;
- iwm->tx_credit.spools[sid].max_pages =
- GET_VAL32(page_grp_state,
- UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE);
- iwm->tx_credit.spools[sid].alloc_pages = 0;
- }
-
- iwm->tx_credit.spools[sid].alloc_pages += pool_pages;
-
- IWM_DBG_TX(iwm, DBG, "Pool idx: %d, id: %d, sid: %d, capacity "
- "min: %d, max: %d, pool alloc: %d, total_free: %d, "
- "super poll alloc: %d\n",
- i, iwm->tx_credit.pools[i].id,
- iwm->tx_credit.pools[i].sid,
- iwm->tx_credit.pools[i].min_pages,
- iwm->tx_credit.pools[i].max_pages,
- iwm->tx_credit.pools[i].alloc_pages,
- iwm->tx_credit.pools[i].total_freed_pages,
- iwm->tx_credit.spools[sid].alloc_pages);
- }
-
- spin_unlock(&iwm->tx_credit.lock);
-}
-
-#define IWM_UDMA_HDR_LEN sizeof(struct iwm_umac_wifi_out_hdr)
-
-static __le16 iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb,
- int pool_id, u8 *buf)
-{
- struct iwm_umac_wifi_out_hdr *hdr = (struct iwm_umac_wifi_out_hdr *)buf;
- struct iwm_udma_wifi_cmd udma_cmd;
- struct iwm_umac_cmd umac_cmd;
- struct iwm_tx_info *tx_info = skb_to_tx_info(skb);
-
- udma_cmd.count = cpu_to_le16(skb->len +
- sizeof(struct iwm_umac_fw_cmd_hdr));
- /* set EOP to 0 here. iwm_udma_wifi_hdr_set_eop() will be
- * called later to set EOP for the last packet. */
- udma_cmd.eop = 0;
- udma_cmd.credit_group = pool_id;
- udma_cmd.ra_tid = tx_info->sta << 4 | tx_info->tid;
- udma_cmd.lmac_offset = 0;
-
- umac_cmd.id = REPLY_TX;
- umac_cmd.count = cpu_to_le16(skb->len);
- umac_cmd.color = tx_info->color;
- umac_cmd.resp = 0;
- umac_cmd.seq_num = cpu_to_le16(iwm_alloc_wifi_cmd_seq(iwm));
-
- iwm_build_udma_wifi_hdr(iwm, &hdr->hw_hdr, &udma_cmd);
- iwm_build_umac_hdr(iwm, &hdr->sw_hdr, &umac_cmd);
-
- memcpy(buf + sizeof(*hdr), skb->data, skb->len);
-
- return umac_cmd.seq_num;
-}
-
-static int iwm_tx_send_concat_packets(struct iwm_priv *iwm,
- struct iwm_tx_queue *txq)
-{
- int ret;
-
- if (!txq->concat_count)
- return 0;
-
- IWM_DBG_TX(iwm, DBG, "Send concatenated Tx: queue %d, %d bytes\n",
- txq->id, txq->concat_count);
-
- /* mark EOP for the last packet */
- iwm_udma_wifi_hdr_set_eop(iwm, txq->concat_ptr, 1);
-
- trace_iwm_tx_packets(iwm, txq->concat_buf, txq->concat_count);
- ret = iwm_bus_send_chunk(iwm, txq->concat_buf, txq->concat_count);
-
- txq->concat_count = 0;
- txq->concat_ptr = txq->concat_buf;
-
- return ret;
-}
-
-void iwm_tx_worker(struct work_struct *work)
-{
- struct iwm_priv *iwm;
- struct iwm_tx_info *tx_info = NULL;
- struct sk_buff *skb;
- struct iwm_tx_queue *txq;
- struct iwm_sta_info *sta_info;
- struct iwm_tid_info *tid_info;
- int cmdlen, ret, pool_id;
-
- txq = container_of(work, struct iwm_tx_queue, worker);
- iwm = container_of(txq, struct iwm_priv, txq[txq->id]);
-
- pool_id = queue_to_pool_id(txq->id);
-
- while (!test_bit(pool_id, &iwm->tx_credit.full_pools_map) &&
- !skb_queue_empty(&txq->queue)) {
-
- spin_lock_bh(&txq->lock);
- skb = skb_dequeue(&txq->queue);
- spin_unlock_bh(&txq->lock);
-
- tx_info = skb_to_tx_info(skb);
- sta_info = &iwm->sta_table[tx_info->sta];
- if (!sta_info->valid) {
- IWM_ERR(iwm, "Trying to send a frame to unknown STA\n");
- kfree_skb(skb);
- continue;
- }
-
- tid_info = &sta_info->tid_info[tx_info->tid];
-
- mutex_lock(&tid_info->mutex);
-
- /*
- * If the RAxTID is stopped, we queue the skb to the stopped
- * queue.
- * Whenever we'll get a UMAC notification to resume the tx flow
- * for this RAxTID, we'll merge back the stopped queue into the
- * regular queue. See iwm_ntf_stop_resume_tx() from rx.c.
- */
- if (tid_info->stopped) {
- IWM_DBG_TX(iwm, DBG, "%dx%d stopped\n",
- tx_info->sta, tx_info->tid);
- spin_lock_bh(&txq->lock);
- skb_queue_tail(&txq->stopped_queue, skb);
- spin_unlock_bh(&txq->lock);
-
- mutex_unlock(&tid_info->mutex);
- continue;
- }
-
- cmdlen = IWM_UDMA_HDR_LEN + skb->len;
-
- IWM_DBG_TX(iwm, DBG, "Tx frame on queue %d: skb: 0x%p, sta: "
- "%d, color: %d\n", txq->id, skb, tx_info->sta,
- tx_info->color);
-
- if (txq->concat_count + cmdlen > IWM_HAL_CONCATENATE_BUF_SIZE)
- iwm_tx_send_concat_packets(iwm, txq);
-
- ret = iwm_tx_credit_alloc(iwm, pool_id, cmdlen);
- if (ret) {
- IWM_DBG_TX(iwm, DBG, "not enough tx_credit for queue "
- "%d, Tx worker stopped\n", txq->id);
- spin_lock_bh(&txq->lock);
- skb_queue_head(&txq->queue, skb);
- spin_unlock_bh(&txq->lock);
-
- mutex_unlock(&tid_info->mutex);
- break;
- }
-
- txq->concat_ptr = txq->concat_buf + txq->concat_count;
- tid_info->last_seq_num =
- iwm_tx_build_packet(iwm, skb, pool_id, txq->concat_ptr);
- txq->concat_count += ALIGN(cmdlen, 16);
-
- mutex_unlock(&tid_info->mutex);
-
- kfree_skb(skb);
- }
-
- iwm_tx_send_concat_packets(iwm, txq);
-
- if (__netif_subqueue_stopped(iwm_to_ndev(iwm), txq->id) &&
- !test_bit(pool_id, &iwm->tx_credit.full_pools_map) &&
- (skb_queue_len(&txq->queue) < IWM_TX_LIST_SIZE / 2)) {
- IWM_DBG_TX(iwm, DBG, "LINK: start netif_subqueue[%d]", txq->id);
- netif_wake_subqueue(iwm_to_ndev(iwm), txq->id);
- }
-}
-
-int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
-{
- struct iwm_priv *iwm = ndev_to_iwm(netdev);
- struct wireless_dev *wdev = iwm_to_wdev(iwm);
- struct iwm_tx_info *tx_info;
- struct iwm_tx_queue *txq;
- struct iwm_sta_info *sta_info;
- u8 *dst_addr, sta_id;
- u16 queue;
- int ret;
-
-
- if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
- IWM_DBG_TX(iwm, DBG, "LINK: stop netif_all_queues: "
- "not associated\n");
- netif_tx_stop_all_queues(netdev);
- goto drop;
- }
-
- queue = skb_get_queue_mapping(skb);
- BUG_ON(queue >= IWM_TX_DATA_QUEUES); /* no iPAN yet */
-
- txq = &iwm->txq[queue];
-
- /* No free space for Tx, tx_worker is too slow */
- if ((skb_queue_len(&txq->queue) > IWM_TX_LIST_SIZE) ||
- (skb_queue_len(&txq->stopped_queue) > IWM_TX_LIST_SIZE)) {
- IWM_DBG_TX(iwm, DBG, "LINK: stop netif_subqueue[%d]\n", queue);
- netif_stop_subqueue(netdev, queue);
- return NETDEV_TX_BUSY;
- }
-
- ret = ieee80211_data_from_8023(skb, netdev->dev_addr, wdev->iftype,
- iwm->bssid, 0);
- if (ret) {
- IWM_ERR(iwm, "build wifi header failed\n");
- goto drop;
- }
-
- dst_addr = ((struct ieee80211_hdr *)(skb->data))->addr1;
-
- for (sta_id = 0; sta_id < IWM_STA_TABLE_NUM; sta_id++) {
- sta_info = &iwm->sta_table[sta_id];
- if (sta_info->valid &&
- !memcmp(dst_addr, sta_info->addr, ETH_ALEN))
- break;
- }
-
- if (sta_id == IWM_STA_TABLE_NUM) {
- IWM_ERR(iwm, "STA %pM not found in sta_table, Tx ignored\n",
- dst_addr);
- goto drop;
- }
-
- tx_info = skb_to_tx_info(skb);
- tx_info->sta = sta_id;
- tx_info->color = sta_info->color;
- /* UMAC uses TID 8 (vs. 0) for non QoS packets */
- if (sta_info->qos)
- tx_info->tid = skb->priority;
- else
- tx_info->tid = IWM_UMAC_MGMT_TID;
-
- spin_lock_bh(&iwm->txq[queue].lock);
- skb_queue_tail(&iwm->txq[queue].queue, skb);
- spin_unlock_bh(&iwm->txq[queue].lock);
-
- queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker);
-
- netdev->stats.tx_packets++;
- netdev->stats.tx_bytes += skb->len;
- return NETDEV_TX_OK;
-
- drop:
- netdev->stats.tx_dropped++;
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
-}
diff --git a/drivers/net/wireless/iwmc3200wifi/umac.h b/drivers/net/wireless/iwmc3200wifi/umac.h
deleted file mode 100644
index 4a137d334a42..000000000000
--- a/drivers/net/wireless/iwmc3200wifi/umac.h
+++ /dev/null
@@ -1,789 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- */
-
-#ifndef __IWM_UMAC_H__
-#define __IWM_UMAC_H__
-
-struct iwm_udma_in_hdr {
- __le32 cmd;
- __le32 size;
-} __packed;
-
-struct iwm_udma_out_nonwifi_hdr {
- __le32 cmd;
- __le32 addr;
- __le32 op1_sz;
- __le32 op2;
-} __packed;
-
-struct iwm_udma_out_wifi_hdr {
- __le32 cmd;
- __le32 meta_data;
-} __packed;
-
-/* Sequence numbering */
-#define UMAC_WIFI_SEQ_NUM_BASE 1
-#define UMAC_WIFI_SEQ_NUM_MAX 0x4000
-#define UMAC_NONWIFI_SEQ_NUM_BASE 1
-#define UMAC_NONWIFI_SEQ_NUM_MAX 0x10
-
-/* MAC address address */
-#define WICO_MAC_ADDRESS_ADDR 0x604008F8
-
-/* RA / TID */
-#define UMAC_HDI_ACT_TBL_IDX_TID_POS 0
-#define UMAC_HDI_ACT_TBL_IDX_TID_SEED 0xF
-
-#define UMAC_HDI_ACT_TBL_IDX_RA_POS 4
-#define UMAC_HDI_ACT_TBL_IDX_RA_SEED 0xF
-
-#define UMAC_HDI_ACT_TBL_IDX_RA_UMAC 0xF
-#define UMAC_HDI_ACT_TBL_IDX_TID_UMAC 0x9
-#define UMAC_HDI_ACT_TBL_IDX_TID_LMAC 0xA
-
-#define UMAC_HDI_ACT_TBL_IDX_HOST_CMD \
- ((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\
- (UMAC_HDI_ACT_TBL_IDX_TID_UMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS))
-#define UMAC_HDI_ACT_TBL_IDX_UMAC_CMD \
- ((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\
- (UMAC_HDI_ACT_TBL_IDX_TID_LMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS))
-
-/* STA ID and color */
-#define STA_ID_SEED (0x0f)
-#define STA_ID_POS (0)
-#define STA_ID_MSK (STA_ID_SEED << STA_ID_POS)
-
-#define STA_COLOR_SEED (0x7)
-#define STA_COLOR_POS (4)
-#define STA_COLOR_MSK (STA_COLOR_SEED << STA_COLOR_POS)
-
-#define STA_ID_N_COLOR_COLOR(id_n_color) \
- (((id_n_color) & STA_COLOR_MSK) >> STA_COLOR_POS)
-#define STA_ID_N_COLOR_ID(id_n_color) \
- (((id_n_color) & STA_ID_MSK) >> STA_ID_POS)
-
-/* iwm_umac_notif_alive.page_grp_state Group number -- bits [3:0] */
-#define UMAC_ALIVE_PAGE_STS_GRP_NUM_POS 0
-#define UMAC_ALIVE_PAGE_STS_GRP_NUM_SEED 0xF
-
-/* iwm_umac_notif_alive.page_grp_state Super group number -- bits [7:4] */
-#define UMAC_ALIVE_PAGE_STS_SGRP_NUM_POS 4
-#define UMAC_ALIVE_PAGE_STS_SGRP_NUM_SEED 0xF
-
-/* iwm_umac_notif_alive.page_grp_state Group min size -- bits [15:8] */
-#define UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE_POS 8
-#define UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE_SEED 0xFF
-
-/* iwm_umac_notif_alive.page_grp_state Group max size -- bits [23:16] */
-#define UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE_POS 16
-#define UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE_SEED 0xFF
-
-/* iwm_umac_notif_alive.page_grp_state Super group max size -- bits [31:24] */
-#define UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE_POS 24
-#define UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE_SEED 0xFF
-
-/* Barkers */
-#define UMAC_REBOOT_BARKER 0xdeadbeef
-#define UMAC_ACK_BARKER 0xfeedbabe
-#define UMAC_PAD_TERMINAL 0xadadadad
-
-/* UMAC JMP address */
-#define UMAC_MU_FW_INST_DATA_12_ADDR 0xBF0000
-
-/* iwm_umac_hdi_out_hdr.cmd OP code -- bits [3:0] */
-#define UMAC_HDI_OUT_CMD_OPCODE_POS 0
-#define UMAC_HDI_OUT_CMD_OPCODE_SEED 0xF
-
-/* iwm_umac_hdi_out_hdr.cmd End-Of-Transfer -- bits [10:10] */
-#define UMAC_HDI_OUT_CMD_EOT_POS 10
-#define UMAC_HDI_OUT_CMD_EOT_SEED 0x1
-
-/* iwm_umac_hdi_out_hdr.cmd UTFD only usage -- bits [11:11] */
-#define UMAC_HDI_OUT_CMD_UTFD_ONLY_POS 11
-#define UMAC_HDI_OUT_CMD_UTFD_ONLY_SEED 0x1
-
-/* iwm_umac_hdi_out_hdr.cmd Non-WiFi HW sequence number -- bits [12:15] */
-#define UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM_POS 12
-#define UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM_SEED 0xF
-
-/* iwm_umac_hdi_out_hdr.cmd Signature -- bits [31:16] */
-#define UMAC_HDI_OUT_CMD_SIGNATURE_POS 16
-#define UMAC_HDI_OUT_CMD_SIGNATURE_SEED 0xFFFF
-
-/* iwm_umac_hdi_out_hdr.meta_data Byte count -- bits [11:0] */
-#define UMAC_HDI_OUT_BYTE_COUNT_POS 0
-#define UMAC_HDI_OUT_BYTE_COUNT_SEED 0xFFF
-
-/* iwm_umac_hdi_out_hdr.meta_data Credit group -- bits [15:12] */
-#define UMAC_HDI_OUT_CREDIT_GRP_POS 12
-#define UMAC_HDI_OUT_CREDIT_GRP_SEED 0xF
-
-/* iwm_umac_hdi_out_hdr.meta_data RA/TID -- bits [23:16] */
-#define UMAC_HDI_OUT_RATID_POS 16
-#define UMAC_HDI_OUT_RATID_SEED 0xFF
-
-/* iwm_umac_hdi_out_hdr.meta_data LMAC offset -- bits [31:24] */
-#define UMAC_HDI_OUT_LMAC_OFFSET_POS 24
-#define UMAC_HDI_OUT_LMAC_OFFSET_SEED 0xFF
-
-/* Signature */
-#define UMAC_HDI_OUT_SIGNATURE 0xCBBC
-
-/* buffer alignment */
-#define UMAC_HDI_BUF_ALIGN_MSK 0xF
-
-/* iwm_umac_hdi_in_hdr.cmd OP code -- bits [3:0] */
-#define UMAC_HDI_IN_CMD_OPCODE_POS 0
-#define UMAC_HDI_IN_CMD_OPCODE_SEED 0xF
-
-/* iwm_umac_hdi_in_hdr.cmd Non-WiFi API response -- bits [6:4] */
-#define UMAC_HDI_IN_CMD_NON_WIFI_RESP_POS 4
-#define UMAC_HDI_IN_CMD_NON_WIFI_RESP_SEED 0x7
-
-/* iwm_umac_hdi_in_hdr.cmd WiFi API source -- bits [5:4] */
-#define UMAC_HDI_IN_CMD_SOURCE_POS 4
-#define UMAC_HDI_IN_CMD_SOURCE_SEED 0x3
-
-/* iwm_umac_hdi_in_hdr.cmd WiFi API EOT -- bits [6:6] */
-#define UMAC_HDI_IN_CMD_EOT_POS 6
-#define UMAC_HDI_IN_CMD_EOT_SEED 0x1
-
-/* iwm_umac_hdi_in_hdr.cmd timestamp present -- bits [7:7] */
-#define UMAC_HDI_IN_CMD_TIME_STAMP_PRESENT_POS 7
-#define UMAC_HDI_IN_CMD_TIME_STAMP_PRESENT_SEED 0x1
-
-/* iwm_umac_hdi_in_hdr.cmd WiFi Non-last AMSDU -- bits [8:8] */
-#define UMAC_HDI_IN_CMD_NON_LAST_AMSDU_POS 8
-#define UMAC_HDI_IN_CMD_NON_LAST_AMSDU_SEED 0x1
-
-/* iwm_umac_hdi_in_hdr.cmd WiFi HW sequence number -- bits [31:9] */
-#define UMAC_HDI_IN_CMD_HW_SEQ_NUM_POS 9
-#define UMAC_HDI_IN_CMD_HW_SEQ_NUM_SEED 0x7FFFFF
-
-/* iwm_umac_hdi_in_hdr.cmd Non-WiFi HW sequence number -- bits [12:15] */
-#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM_POS 12
-#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM_SEED 0xF
-
-/* iwm_umac_hdi_in_hdr.cmd Non-WiFi HW signature -- bits [16:31] */
-#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG_POS 16
-#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG_SEED 0xFFFF
-
-/* Fixed Non-WiFi signature */
-#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG 0xCBBC
-
-/* IN NTFY op-codes */
-#define UMAC_NOTIFY_OPCODE_ALIVE 0xA1
-#define UMAC_NOTIFY_OPCODE_INIT_COMPLETE 0xA2
-#define UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS 0xA3
-#define UMAC_NOTIFY_OPCODE_ERROR 0xA4
-#define UMAC_NOTIFY_OPCODE_DEBUG 0xA5
-#define UMAC_NOTIFY_OPCODE_WIFI_IF_WRAPPER 0xB0
-#define UMAC_NOTIFY_OPCODE_STATS 0xB1
-#define UMAC_NOTIFY_OPCODE_PAGE_DEALLOC 0xB3
-#define UMAC_NOTIFY_OPCODE_RX_TICKET 0xB4
-#define UMAC_NOTIFY_OPCODE_MAX (UMAC_NOTIFY_OPCODE_RX_TICKET -\
- UMAC_NOTIFY_OPCODE_ALIVE + 1)
-#define UMAC_NOTIFY_OPCODE_FIRST (UMAC_NOTIFY_OPCODE_ALIVE)
-
-/* HDI OUT OP CODE */
-#define UMAC_HDI_OUT_OPCODE_PING 0x0
-#define UMAC_HDI_OUT_OPCODE_READ 0x1
-#define UMAC_HDI_OUT_OPCODE_WRITE 0x2
-#define UMAC_HDI_OUT_OPCODE_JUMP 0x3
-#define UMAC_HDI_OUT_OPCODE_REBOOT 0x4
-#define UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT 0x5
-#define UMAC_HDI_OUT_OPCODE_READ_PERSISTENT 0x6
-#define UMAC_HDI_OUT_OPCODE_READ_MODIFY_WRITE 0x7
-/* #define UMAC_HDI_OUT_OPCODE_RESERVED 0x8..0xA */
-#define UMAC_HDI_OUT_OPCODE_WRITE_AUX_REG 0xB
-#define UMAC_HDI_OUT_OPCODE_WIFI 0xF
-
-/* HDI IN OP CODE -- Non WiFi*/
-#define UMAC_HDI_IN_OPCODE_PING 0x0
-#define UMAC_HDI_IN_OPCODE_READ 0x1
-#define UMAC_HDI_IN_OPCODE_WRITE 0x2
-#define UMAC_HDI_IN_OPCODE_WRITE_PERSISTENT 0x5
-#define UMAC_HDI_IN_OPCODE_READ_PERSISTENT 0x6
-#define UMAC_HDI_IN_OPCODE_READ_MODIFY_WRITE 0x7
-#define UMAC_HDI_IN_OPCODE_EP_MGMT 0x8
-#define UMAC_HDI_IN_OPCODE_CREDIT_CHANGE 0x9
-#define UMAC_HDI_IN_OPCODE_CTRL_DATABASE 0xA
-#define UMAC_HDI_IN_OPCODE_WRITE_AUX_REG 0xB
-#define UMAC_HDI_IN_OPCODE_NONWIFI_MAX \
- (UMAC_HDI_IN_OPCODE_WRITE_AUX_REG + 1)
-#define UMAC_HDI_IN_OPCODE_WIFI 0xF
-
-/* HDI IN SOURCE */
-#define UMAC_HDI_IN_SOURCE_FHRX 0x0
-#define UMAC_HDI_IN_SOURCE_UDMA 0x1
-#define UMAC_HDI_IN_SOURCE_FW 0x2
-#define UMAC_HDI_IN_SOURCE_RESERVED 0x3
-
-/* OUT CMD op-codes */
-#define UMAC_CMD_OPCODE_ECHO 0x01
-#define UMAC_CMD_OPCODE_HALT 0x02
-#define UMAC_CMD_OPCODE_RESET 0x03
-#define UMAC_CMD_OPCODE_BULK_EP_INACT_TIMEOUT 0x09
-#define UMAC_CMD_OPCODE_URB_CANCEL_ACK 0x0A
-#define UMAC_CMD_OPCODE_DCACHE_FLUSH 0x0B
-#define UMAC_CMD_OPCODE_EEPROM_PROXY 0x0C
-#define UMAC_CMD_OPCODE_TX_ECHO 0x0D
-#define UMAC_CMD_OPCODE_DBG_MON 0x0E
-#define UMAC_CMD_OPCODE_INTERNAL_TX 0x0F
-#define UMAC_CMD_OPCODE_SET_PARAM_FIX 0x10
-#define UMAC_CMD_OPCODE_SET_PARAM_VAR 0x11
-#define UMAC_CMD_OPCODE_GET_PARAM 0x12
-#define UMAC_CMD_OPCODE_DBG_EVENT_WRAPPER 0x13
-#define UMAC_CMD_OPCODE_TARGET 0x14
-#define UMAC_CMD_OPCODE_STATISTIC_REQUEST 0x15
-#define UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST 0x16
-#define UMAC_CMD_OPCODE_SET_PARAM_LIST 0x17
-#define UMAC_CMD_OPCODE_GET_PARAM_LIST 0x18
-#define UMAC_CMD_OPCODE_STOP_RESUME_STA_TX 0x19
-#define UMAC_CMD_OPCODE_TEST_BLOCK_ACK 0x1A
-
-#define UMAC_CMD_OPCODE_BASE_WRAPPER 0xFA
-#define UMAC_CMD_OPCODE_LMAC_WRAPPER 0xFB
-#define UMAC_CMD_OPCODE_HW_TEST_WRAPPER 0xFC
-#define UMAC_CMD_OPCODE_WIFI_IF_WRAPPER 0xFD
-#define UMAC_CMD_OPCODE_WIFI_WRAPPER 0xFE
-#define UMAC_CMD_OPCODE_WIFI_PASS_THROUGH 0xFF
-
-/* UMAC WiFi interface op-codes */
-#define UMAC_WIFI_IF_CMD_SET_PROFILE 0x11
-#define UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE 0x12
-#define UMAC_WIFI_IF_CMD_SET_EXCLUDE_LIST 0x13
-#define UMAC_WIFI_IF_CMD_SCAN_REQUEST 0x14
-#define UMAC_WIFI_IF_CMD_SCAN_CONFIG 0x15
-#define UMAC_WIFI_IF_CMD_ADD_WEP40_KEY 0x16
-#define UMAC_WIFI_IF_CMD_ADD_WEP104_KEY 0x17
-#define UMAC_WIFI_IF_CMD_ADD_TKIP_KEY 0x18
-#define UMAC_WIFI_IF_CMD_ADD_CCMP_KEY 0x19
-#define UMAC_WIFI_IF_CMD_REMOVE_KEY 0x1A
-#define UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID 0x1B
-#define UMAC_WIFI_IF_CMD_SET_HOST_EXTENDED_IE 0x1C
-#define UMAC_WIFI_IF_CMD_GET_SUPPORTED_CHANNELS 0x1E
-#define UMAC_WIFI_IF_CMD_PMKID_UPDATE 0x1F
-#define UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER 0x20
-
-/* UMAC WiFi interface ports */
-#define UMAC_WIFI_IF_FLG_PORT_DEF 0x00
-#define UMAC_WIFI_IF_FLG_PORT_PAN 0x01
-#define UMAC_WIFI_IF_FLG_PORT_PAN_INVALID WIFI_IF_FLG_PORT_DEF
-
-/* UMAC WiFi interface actions */
-#define UMAC_WIFI_IF_FLG_ACT_GET 0x10
-#define UMAC_WIFI_IF_FLG_ACT_SET 0x20
-
-/* iwm_umac_fw_cmd_hdr.meta_data byte count -- bits [11:0] */
-#define UMAC_FW_CMD_BYTE_COUNT_POS 0
-#define UMAC_FW_CMD_BYTE_COUNT_SEED 0xFFF
-
-/* iwm_umac_fw_cmd_hdr.meta_data status -- bits [15:12] */
-#define UMAC_FW_CMD_STATUS_POS 12
-#define UMAC_FW_CMD_STATUS_SEED 0xF
-
-/* iwm_umac_fw_cmd_hdr.meta_data full TX command by Driver -- bits [16:16] */
-#define UMAC_FW_CMD_TX_DRV_FULL_CMD_POS 16
-#define UMAC_FW_CMD_TX_DRV_FULL_CMD_SEED 0x1
-
-/* iwm_umac_fw_cmd_hdr.meta_data TX command by FW -- bits [17:17] */
-#define UMAC_FW_CMD_TX_FW_CMD_POS 17
-#define UMAC_FW_CMD_TX_FW_CMD_SEED 0x1
-
-/* iwm_umac_fw_cmd_hdr.meta_data TX plaintext mode -- bits [18:18] */
-#define UMAC_FW_CMD_TX_PLAINTEXT_POS 18
-#define UMAC_FW_CMD_TX_PLAINTEXT_SEED 0x1
-
-/* iwm_umac_fw_cmd_hdr.meta_data STA color -- bits [22:20] */
-#define UMAC_FW_CMD_TX_STA_COLOR_POS 20
-#define UMAC_FW_CMD_TX_STA_COLOR_SEED 0x7
-
-/* iwm_umac_fw_cmd_hdr.meta_data TX life time (TU) -- bits [31:24] */
-#define UMAC_FW_CMD_TX_LIFETIME_TU_POS 24
-#define UMAC_FW_CMD_TX_LIFETIME_TU_SEED 0xFF
-
-/* iwm_dev_cmd_hdr.flags Response required -- bits [5:5] */
-#define UMAC_DEV_CMD_FLAGS_RESP_REQ_POS 5
-#define UMAC_DEV_CMD_FLAGS_RESP_REQ_SEED 0x1
-
-/* iwm_dev_cmd_hdr.flags Aborted command -- bits [6:6] */
-#define UMAC_DEV_CMD_FLAGS_ABORT_POS 6
-#define UMAC_DEV_CMD_FLAGS_ABORT_SEED 0x1
-
-/* iwm_dev_cmd_hdr.flags Internal command -- bits [7:7] */
-#define DEV_CMD_FLAGS_FLD_INTERNAL_POS 7
-#define DEV_CMD_FLAGS_FLD_INTERNAL_SEED 0x1
-
-/* Rx */
-/* Rx actions */
-#define IWM_RX_TICKET_DROP 0x0
-#define IWM_RX_TICKET_RELEASE 0x1
-#define IWM_RX_TICKET_SNIFFER 0x2
-#define IWM_RX_TICKET_ENQUEUE 0x3
-
-/* Rx flags */
-#define IWM_RX_TICKET_PAD_SIZE_MSK 0x2
-#define IWM_RX_TICKET_SPECIAL_SNAP_MSK 0x4
-#define IWM_RX_TICKET_AMSDU_MSK 0x8
-#define IWM_RX_TICKET_DROP_REASON_POS 4
-#define IWM_RX_TICKET_DROP_REASON_MSK (0x1F << IWM_RX_TICKET_DROP_REASON_POS)
-
-#define IWM_RX_DROP_NO_DROP 0x0
-#define IWM_RX_DROP_BAD_CRC 0x1
-/* L2P no address match */
-#define IWM_RX_DROP_LMAC_ADDR_FILTER 0x2
-/* Multicast address not in list */
-#define IWM_RX_DROP_MCAST_ADDR_FILTER 0x3
-/* Control frames are not sent to the driver */
-#define IWM_RX_DROP_CTL_FRAME 0x4
-/* Our frame is back */
-#define IWM_RX_DROP_OUR_TX 0x5
-/* Association class filtering */
-#define IWM_RX_DROP_CLASS_FILTER 0x6
-/* Duplicated frame */
-#define IWM_RX_DROP_DUPLICATE_FILTER 0x7
-/* Decryption error */
-#define IWM_RX_DROP_SEC_ERR 0x8
-/* Unencrypted frame while encryption is on */
-#define IWM_RX_DROP_SEC_NO_ENCRYPTION 0x9
-/* Replay check failure */
-#define IWM_RX_DROP_SEC_REPLAY_ERR 0xa
-/* uCode and FW key color mismatch, check before replay */
-#define IWM_RX_DROP_SEC_KEY_COLOR_MISMATCH 0xb
-#define IWM_RX_DROP_SEC_TKIP_COUNTER_MEASURE 0xc
-/* No fragmentations Db is found */
-#define IWM_RX_DROP_FRAG_NO_RESOURCE 0xd
-/* Fragmention Db has seqCtl mismatch Vs. non-1st frag */
-#define IWM_RX_DROP_FRAG_ERR 0xe
-#define IWM_RX_DROP_FRAG_LOST 0xf
-#define IWM_RX_DROP_FRAG_COMPLETE 0x10
-/* Should be handled by UMAC */
-#define IWM_RX_DROP_MANAGEMENT 0x11
-/* STA not found by UMAC */
-#define IWM_RX_DROP_NO_STATION 0x12
-/* NULL or QoS NULL */
-#define IWM_RX_DROP_NULL_DATA 0x13
-#define IWM_RX_DROP_BA_REORDER_OLD_SEQCTL 0x14
-#define IWM_RX_DROP_BA_REORDER_DUPLICATE 0x15
-
-struct iwm_rx_ticket {
- __le16 action;
- __le16 id;
- __le16 flags;
- u8 payload_offset; /* includes: MAC header, pad, IV */
- u8 tail_len; /* includes: MIC, ICV, CRC (w/o STATUS) */
-} __packed;
-
-struct iwm_rx_mpdu_hdr {
- __le16 len;
- __le16 reserved;
-} __packed;
-
-/* UMAC SW WIFI API */
-
-struct iwm_dev_cmd_hdr {
- u8 cmd;
- u8 flags;
- __le16 seq_num;
-} __packed;
-
-struct iwm_umac_fw_cmd_hdr {
- __le32 meta_data;
- struct iwm_dev_cmd_hdr cmd;
-} __packed;
-
-struct iwm_umac_wifi_out_hdr {
- struct iwm_udma_out_wifi_hdr hw_hdr;
- struct iwm_umac_fw_cmd_hdr sw_hdr;
-} __packed;
-
-struct iwm_umac_nonwifi_out_hdr {
- struct iwm_udma_out_nonwifi_hdr hw_hdr;
-} __packed;
-
-struct iwm_umac_wifi_in_hdr {
- struct iwm_udma_in_hdr hw_hdr;
- struct iwm_umac_fw_cmd_hdr sw_hdr;
-} __packed;
-
-struct iwm_umac_nonwifi_in_hdr {
- struct iwm_udma_in_hdr hw_hdr;
- __le32 time_stamp;
-} __packed;
-
-#define IWM_UMAC_PAGE_SIZE 0x200
-
-/* Notify structures */
-struct iwm_fw_version {
- u8 minor;
- u8 major;
- __le16 id;
-};
-
-struct iwm_fw_build {
- u8 type;
- u8 subtype;
- u8 platform;
- u8 opt;
-};
-
-struct iwm_fw_alive_hdr {
- struct iwm_fw_version ver;
- struct iwm_fw_build build;
- __le32 os_build;
- __le32 log_hdr_addr;
- __le32 log_buf_addr;
- __le32 sys_timer_addr;
-};
-
-#define WAIT_NOTIF_TIMEOUT (2 * HZ)
-#define SCAN_COMPLETE_TIMEOUT (3 * HZ)
-
-#define UMAC_NTFY_ALIVE_STATUS_ERR 0xDEAD
-#define UMAC_NTFY_ALIVE_STATUS_OK 0xCAFE
-
-#define UMAC_NTFY_INIT_COMPLETE_STATUS_ERR 0xDEAD
-#define UMAC_NTFY_INIT_COMPLETE_STATUS_OK 0xCAFE
-
-#define UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN 0x40
-#define UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN 0x80
-
-#define IWM_MACS_OUT_GROUPS 6
-#define IWM_MACS_OUT_SGROUPS 1
-
-
-#define WIFI_IF_NTFY_ASSOC_START 0x80
-#define WIFI_IF_NTFY_ASSOC_COMPLETE 0x81
-#define WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE 0x82
-#define WIFI_IF_NTFY_CONNECTION_TERMINATED 0x83
-#define WIFI_IF_NTFY_SCAN_COMPLETE 0x84
-#define WIFI_IF_NTFY_STA_TABLE_CHANGE 0x85
-#define WIFI_IF_NTFY_EXTENDED_IE_REQUIRED 0x86
-#define WIFI_IF_NTFY_RADIO_PREEMPTION 0x87
-#define WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED 0x88
-#define WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED 0x89
-#define WIFI_IF_NTFY_LINK_QUALITY_STATISTICS 0x8A
-#define WIFI_IF_NTFY_MGMT_FRAME 0x8B
-
-/* DEBUG INDICATIONS */
-#define WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_START 0xE0
-#define WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_COMPLETE 0xE1
-#define WIFI_DBG_IF_NTFY_SCAN_CHANNEL_START 0xE2
-#define WIFI_DBG_IF_NTFY_SCAN_CHANNEL_RESULT 0xE3
-#define WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_START 0xE4
-#define WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_COMPLETE 0xE5
-#define WIFI_DBG_IF_NTFY_CNCT_ATC_START 0xE6
-#define WIFI_DBG_IF_NTFY_COEX_NOTIFICATION 0xE7
-#define WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP 0xE8
-#define WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP 0xE9
-
-#define WIFI_IF_NTFY_MAX 0xff
-
-/* Notification structures */
-struct iwm_umac_notif_wifi_if {
- struct iwm_umac_wifi_in_hdr hdr;
- u8 status;
- u8 flags;
- __le16 buf_size;
-} __packed;
-
-#define UMAC_ROAM_REASON_FIRST_SELECTION 0x1
-#define UMAC_ROAM_REASON_AP_DEAUTH 0x2
-#define UMAC_ROAM_REASON_AP_CONNECT_LOST 0x3
-#define UMAC_ROAM_REASON_RSSI 0x4
-#define UMAC_ROAM_REASON_AP_ASSISTED_ROAM 0x5
-#define UMAC_ROAM_REASON_IBSS_COALESCING 0x6
-
-struct iwm_umac_notif_assoc_start {
- struct iwm_umac_notif_wifi_if mlme_hdr;
- __le32 roam_reason;
- u8 bssid[ETH_ALEN];
- u8 reserved[2];
-} __packed;
-
-#define UMAC_ASSOC_COMPLETE_SUCCESS 0x0
-#define UMAC_ASSOC_COMPLETE_FAILURE 0x1
-
-struct iwm_umac_notif_assoc_complete {
- struct iwm_umac_notif_wifi_if mlme_hdr;
- __le32 status;
- u8 bssid[ETH_ALEN];
- u8 band;
- u8 channel;
-} __packed;
-
-#define UMAC_PROFILE_INVALID_ASSOC_TIMEOUT 0x0
-#define UMAC_PROFILE_INVALID_ROAM_TIMEOUT 0x1
-#define UMAC_PROFILE_INVALID_REQUEST 0x2
-#define UMAC_PROFILE_INVALID_RF_PREEMPTED 0x3
-
-struct iwm_umac_notif_profile_invalidate {
- struct iwm_umac_notif_wifi_if mlme_hdr;
- __le32 reason;
-} __packed;
-
-#define UMAC_SCAN_RESULT_SUCCESS 0x0
-#define UMAC_SCAN_RESULT_ABORTED 0x1
-#define UMAC_SCAN_RESULT_REJECTED 0x2
-#define UMAC_SCAN_RESULT_FAILED 0x3
-
-struct iwm_umac_notif_scan_complete {
- struct iwm_umac_notif_wifi_if mlme_hdr;
- __le32 type;
- __le32 result;
- u8 seq_num;
-} __packed;
-
-#define UMAC_OPCODE_ADD_MODIFY 0x0
-#define UMAC_OPCODE_REMOVE 0x1
-#define UMAC_OPCODE_CLEAR_ALL 0x2
-
-#define UMAC_STA_FLAG_QOS 0x1
-
-struct iwm_umac_notif_sta_info {
- struct iwm_umac_notif_wifi_if mlme_hdr;
- __le32 opcode;
- u8 mac_addr[ETH_ALEN];
- u8 sta_id; /* bits 0-3: station ID, bits 4-7: station color */
- u8 flags;
-} __packed;
-
-#define UMAC_BAND_2GHZ 0
-#define UMAC_BAND_5GHZ 1
-
-#define UMAC_CHANNEL_WIDTH_20MHZ 0
-#define UMAC_CHANNEL_WIDTH_40MHZ 1
-
-struct iwm_umac_notif_bss_info {
- struct iwm_umac_notif_wifi_if mlme_hdr;
- __le32 type;
- __le32 timestamp;
- __le16 table_idx;
- __le16 frame_len;
- u8 band;
- u8 channel;
- s8 rssi;
- u8 reserved;
- u8 frame_buf[1];
-} __packed;
-
-#define IWM_BSS_REMOVE_INDEX_MSK 0x0fff
-#define IWM_BSS_REMOVE_FLAGS_MSK 0xfc00
-
-#define IWM_BSS_REMOVE_FLG_AGE 0x1000
-#define IWM_BSS_REMOVE_FLG_TIMEOUT 0x2000
-#define IWM_BSS_REMOVE_FLG_TABLE_FULL 0x4000
-
-struct iwm_umac_notif_bss_removed {
- struct iwm_umac_notif_wifi_if mlme_hdr;
- __le32 count;
- __le16 entries[0];
-} __packed;
-
-struct iwm_umac_notif_mgt_frame {
- struct iwm_umac_notif_wifi_if mlme_hdr;
- __le16 len;
- u8 frame[1];
-} __packed;
-
-struct iwm_umac_notif_alive {
- struct iwm_umac_wifi_in_hdr hdr;
- __le16 status;
- __le16 reserved1;
- struct iwm_fw_alive_hdr alive_data;
- __le16 reserved2;
- __le16 page_grp_count;
- __le32 page_grp_state[IWM_MACS_OUT_GROUPS];
-} __packed;
-
-struct iwm_umac_notif_init_complete {
- struct iwm_umac_wifi_in_hdr hdr;
- __le16 status;
- __le16 reserved;
-} __packed;
-
-/* error categories */
-enum {
- UMAC_SYS_ERR_CAT_NONE = 0,
- UMAC_SYS_ERR_CAT_BOOT,
- UMAC_SYS_ERR_CAT_UMAC,
- UMAC_SYS_ERR_CAT_UAXM,
- UMAC_SYS_ERR_CAT_LMAC,
- UMAC_SYS_ERR_CAT_MAX
-};
-
-struct iwm_fw_error_hdr {
- __le32 category;
- __le32 status;
- __le32 pc;
- __le32 blink1;
- __le32 blink2;
- __le32 ilink1;
- __le32 ilink2;
- __le32 data1;
- __le32 data2;
- __le32 line_num;
- __le32 umac_status;
- __le32 lmac_status;
- __le32 sdio_status;
- __le32 dbm_sample_ctrl;
- __le32 dbm_buf_base;
- __le32 dbm_buf_end;
- __le32 dbm_buf_write_ptr;
- __le32 dbm_buf_cycle_cnt;
-} __packed;
-
-struct iwm_umac_notif_error {
- struct iwm_umac_wifi_in_hdr hdr;
- struct iwm_fw_error_hdr err;
-} __packed;
-
-#define UMAC_DEALLOC_NTFY_CHANGES_CNT_POS 0
-#define UMAC_DEALLOC_NTFY_CHANGES_CNT_SEED 0xff
-#define UMAC_DEALLOC_NTFY_CHANGES_MSK_POS 8
-#define UMAC_DEALLOC_NTFY_CHANGES_MSK_SEED 0xffffff
-#define UMAC_DEALLOC_NTFY_PAGE_CNT_POS 0
-#define UMAC_DEALLOC_NTFY_PAGE_CNT_SEED 0xffffff
-#define UMAC_DEALLOC_NTFY_GROUP_NUM_POS 24
-#define UMAC_DEALLOC_NTFY_GROUP_NUM_SEED 0xf
-
-struct iwm_umac_notif_page_dealloc {
- struct iwm_umac_wifi_in_hdr hdr;
- __le32 changes;
- __le32 grp_info[IWM_MACS_OUT_GROUPS];
-} __packed;
-
-struct iwm_umac_notif_wifi_status {
- struct iwm_umac_wifi_in_hdr hdr;
- __le16 status;
- __le16 reserved;
-} __packed;
-
-struct iwm_umac_notif_rx_ticket {
- struct iwm_umac_wifi_in_hdr hdr;
- u8 num_tickets;
- u8 reserved[3];
- struct iwm_rx_ticket tickets[1];
-} __packed;
-
-/* Tx/Rx rates window (number of max of last update window per second) */
-#define UMAC_NTF_RATE_SAMPLE_NR 4
-
-/* Max numbers of bits required to go through all antennae in bitmasks */
-#define UMAC_PHY_NUM_CHAINS 3
-
-#define IWM_UMAC_MGMT_TID 8
-#define IWM_UMAC_TID_NR 9 /* 8 TIDs + MGMT */
-
-struct iwm_umac_notif_stats {
- struct iwm_umac_wifi_in_hdr hdr;
- __le32 flags;
- __le32 timestamp;
- __le16 tid_load[IWM_UMAC_TID_NR + 1]; /* 1 non-QoS + 1 dword align */
- __le16 tx_rate[UMAC_NTF_RATE_SAMPLE_NR];
- __le16 rx_rate[UMAC_NTF_RATE_SAMPLE_NR];
- __le32 chain_energy[UMAC_PHY_NUM_CHAINS];
- s32 rssi_dbm;
- s32 noise_dbm;
- __le32 supp_rates;
- __le32 supp_ht_rates;
- __le32 missed_beacons;
- __le32 rx_beacons;
- __le32 rx_dir_pkts;
- __le32 rx_nondir_pkts;
- __le32 rx_multicast;
- __le32 rx_errors;
- __le32 rx_drop_other_bssid;
- __le32 rx_drop_decode;
- __le32 rx_drop_reassembly;
- __le32 rx_drop_bad_len;
- __le32 rx_drop_overflow;
- __le32 rx_drop_crc;
- __le32 rx_drop_missed;
- __le32 tx_dir_pkts;
- __le32 tx_nondir_pkts;
- __le32 tx_failure;
- __le32 tx_errors;
- __le32 tx_drop_max_retry;
- __le32 tx_err_abort;
- __le32 tx_err_carrier;
- __le32 rx_bytes;
- __le32 tx_bytes;
- __le32 tx_power;
- __le32 tx_max_power;
- __le32 roam_threshold;
- __le32 ap_assoc_nr;
- __le32 scan_full;
- __le32 scan_abort;
- __le32 ap_nr;
- __le32 roam_nr;
- __le32 roam_missed_beacons;
- __le32 roam_rssi;
- __le32 roam_unassoc;
- __le32 roam_deauth;
- __le32 roam_ap_loadblance;
-} __packed;
-
-#define UMAC_STOP_TX_FLAG 0x1
-#define UMAC_RESUME_TX_FLAG 0x2
-
-#define LAST_SEQ_NUM_INVALID 0xFFFF
-
-struct iwm_umac_notif_stop_resume_tx {
- struct iwm_umac_wifi_in_hdr hdr;
- u8 flags; /* UMAC_*_TX_FLAG_* */
- u8 sta_id;
- __le16 stop_resume_tid_msk; /* tid bitmask */
-} __packed;
-
-#define UMAC_MAX_NUM_PMKIDS 4
-
-/* WiFi interface wrapper header */
-struct iwm_umac_wifi_if {
- u8 oid;
- u8 flags;
- __le16 buf_size;
-} __packed;
-
-#define IWM_SEQ_NUM_HOST_MSK 0x0000
-#define IWM_SEQ_NUM_UMAC_MSK 0x4000
-#define IWM_SEQ_NUM_LMAC_MSK 0x8000
-#define IWM_SEQ_NUM_MSK 0xC000
-
-#endif
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index f4a203049fb4..706781316195 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -805,7 +805,6 @@ void lbs_scan_done(struct lbs_private *priv)
}
static int lbs_cfg_scan(struct wiphy *wiphy,
- struct net_device *dev,
struct cfg80211_scan_request *request)
{
struct lbs_private *priv = wiphy_priv(wiphy);
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index 2e2dbfa2ee50..96726f79a1dd 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -68,7 +68,6 @@
#define CMD_802_11_BEACON_STOP 0x0049
#define CMD_802_11_MAC_ADDRESS 0x004d
#define CMD_802_11_LED_GPIO_CTRL 0x004e
-#define CMD_802_11_EEPROM_ACCESS 0x0059
#define CMD_802_11_BAND_CONFIG 0x0058
#define CMD_GSPI_BUS_CONFIG 0x005a
#define CMD_802_11D_DOMAIN_INFO 0x005b
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index a0b7cfd34685..3f38d846b093 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -292,7 +292,7 @@ struct mac80211_hwsim_data {
struct list_head list;
struct ieee80211_hw *hw;
struct device *dev;
- struct ieee80211_supported_band bands[2];
+ struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)];
struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)];
struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)];
@@ -678,8 +678,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
continue;
if (data2->idle || !data2->started ||
- !hwsim_ps_rx_ok(data2, skb) ||
- !data->channel || !data2->channel ||
+ !hwsim_ps_rx_ok(data2, skb) || !data2->channel ||
data->channel->center_freq != data2->channel->center_freq ||
!(data->group & data2->group))
continue;
@@ -1083,6 +1082,8 @@ enum hwsim_testmode_attr {
enum hwsim_testmode_cmd {
HWSIM_TM_CMD_SET_PS = 0,
HWSIM_TM_CMD_GET_PS = 1,
+ HWSIM_TM_CMD_STOP_QUEUES = 2,
+ HWSIM_TM_CMD_WAKE_QUEUES = 3,
};
static const struct nla_policy hwsim_testmode_policy[HWSIM_TM_ATTR_MAX + 1] = {
@@ -1122,6 +1123,12 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw,
if (nla_put_u32(skb, HWSIM_TM_ATTR_PS, hwsim->ps))
goto nla_put_failure;
return cfg80211_testmode_reply(skb);
+ case HWSIM_TM_CMD_STOP_QUEUES:
+ ieee80211_stop_queues(hw);
+ return 0;
+ case HWSIM_TM_CMD_WAKE_QUEUES:
+ ieee80211_wake_queues(hw);
+ return 0;
default:
return -EOPNOTSUPP;
}
@@ -1486,7 +1493,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
struct mac80211_hwsim_data *data2;
struct ieee80211_tx_info *txi;
struct hwsim_tx_rate *tx_attempts;
- struct sk_buff __user *ret_skb;
+ unsigned long ret_skb_ptr;
struct sk_buff *skb, *tmp;
struct mac_address *src;
unsigned int hwsim_flags;
@@ -1504,8 +1511,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER]);
hwsim_flags = nla_get_u32(info->attrs[HWSIM_ATTR_FLAGS]);
- ret_skb = (struct sk_buff __user *)
- (unsigned long) nla_get_u64(info->attrs[HWSIM_ATTR_COOKIE]);
+ ret_skb_ptr = nla_get_u64(info->attrs[HWSIM_ATTR_COOKIE]);
data2 = get_hwsim_data_ref_from_addr(src);
@@ -1514,7 +1520,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
/* look for the skb matching the cookie passed back from user */
skb_queue_walk_safe(&data2->pending, skb, tmp) {
- if (skb == ret_skb) {
+ if ((unsigned long)skb == ret_skb_ptr) {
skb_unlink(skb, &data2->pending);
found = true;
break;
@@ -1857,7 +1863,7 @@ static int __init init_mac80211_hwsim(void)
sband->n_bitrates = ARRAY_SIZE(hwsim_rates) - 4;
break;
default:
- break;
+ continue;
}
sband->ht_cap.ht_supported = true;
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index 9c44088054dd..900ee129e825 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -256,7 +256,8 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
else
last_seq = priv->rx_seq[tid];
- if (last_seq >= new_node->start_win)
+ if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
+ last_seq >= new_node->start_win)
new_node->start_win = last_seq + 1;
new_node->win_size = win_size;
@@ -596,5 +597,5 @@ void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv)
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
- memset(priv->rx_seq, 0, sizeof(priv->rx_seq));
+ mwifiex_reset_11n_rx_seq_num(priv);
}
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
index f1bffebabc60..6c9815a0f5d8 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.h
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h
@@ -37,6 +37,13 @@
#define ADDBA_RSP_STATUS_ACCEPT 0
+#define MWIFIEX_DEF_11N_RX_SEQ_NUM 0xffff
+
+static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv)
+{
+ memset(priv->rx_seq, 0xff, sizeof(priv->rx_seq));
+}
+
int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *,
u16 seqNum,
u16 tid, u8 *ta,
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 015fec3371a0..e27b3168862c 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -170,7 +170,9 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
if (!priv->sec_info.wep_enabled)
return 0;
- if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) {
+ if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) {
+ priv->wep_key_curr_index = key_index;
+ } else if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) {
wiphy_err(wiphy, "set default Tx key index\n");
return -EFAULT;
}
@@ -187,9 +189,25 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
struct key_params *params)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
+ struct mwifiex_wep_key *wep_key;
const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
+ if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&
+ (params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+ params->cipher == WLAN_CIPHER_SUITE_WEP104)) {
+ if (params->key && params->key_len) {
+ wep_key = &priv->wep_key[key_index];
+ memset(wep_key, 0, sizeof(struct mwifiex_wep_key));
+ memcpy(wep_key->key_material, params->key,
+ params->key_len);
+ wep_key->key_index = key_index;
+ wep_key->key_length = params->key_len;
+ priv->sec_info.wep_enabled = 1;
+ }
+ return 0;
+ }
+
if (mwifiex_set_encode(priv, params->key, params->key_len,
key_index, peer_mac, 0)) {
wiphy_err(wiphy, "crypto keys added\n");
@@ -242,13 +260,13 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
flag = 1;
first_chan = (u32) ch->hw_value;
next_chan = first_chan;
- max_pwr = ch->max_power;
+ max_pwr = ch->max_reg_power;
no_of_parsed_chan = 1;
continue;
}
if (ch->hw_value == next_chan + 1 &&
- ch->max_power == max_pwr) {
+ ch->max_reg_power == max_pwr) {
next_chan++;
no_of_parsed_chan++;
} else {
@@ -259,7 +277,7 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
no_of_triplet++;
first_chan = (u32) ch->hw_value;
next_chan = first_chan;
- max_pwr = ch->max_power;
+ max_pwr = ch->max_reg_power;
no_of_parsed_chan = 1;
}
}
@@ -384,13 +402,13 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv,
cfp.freq = chan->center_freq;
cfp.channel = ieee80211_frequency_to_channel(chan->center_freq);
- if (mwifiex_bss_set_channel(priv, &cfp))
- return -EFAULT;
-
- if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
+ if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) {
+ if (mwifiex_bss_set_channel(priv, &cfp))
+ return -EFAULT;
return mwifiex_drv_change_adhoc_chan(priv, cfp.channel);
- else
- return mwifiex_uap_set_channel(priv, cfp.channel);
+ }
+
+ return 0;
}
/*
@@ -896,6 +914,69 @@ static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
return 0;
}
+/* cfg80211 operation handler for change_beacon.
+ * Function retrieves and sets modified management IEs to FW.
+ */
+static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_beacon_data *data)
+{
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+ if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
+ wiphy_err(wiphy, "%s: bss_type mismatched\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!priv->bss_started) {
+ wiphy_err(wiphy, "%s: bss not started\n", __func__);
+ return -EINVAL;
+ }
+
+ if (mwifiex_set_mgmt_ies(priv, data)) {
+ wiphy_err(wiphy, "%s: setting mgmt ies failed\n", __func__);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int
+mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
+{
+ struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
+ struct mwifiex_private *priv = mwifiex_get_priv(adapter,
+ MWIFIEX_BSS_ROLE_ANY);
+ struct mwifiex_ds_ant_cfg ant_cfg;
+
+ if (!tx_ant || !rx_ant)
+ return -EOPNOTSUPP;
+
+ if (adapter->hw_dev_mcs_support != HT_STREAM_2X2) {
+ /* Not a MIMO chip. User should provide specific antenna number
+ * for Tx/Rx path or enable all antennas for diversity
+ */
+ if (tx_ant != rx_ant)
+ return -EOPNOTSUPP;
+
+ if ((tx_ant & (tx_ant - 1)) &&
+ (tx_ant != BIT(adapter->number_of_antenna) - 1))
+ return -EOPNOTSUPP;
+
+ if ((tx_ant == BIT(adapter->number_of_antenna) - 1) &&
+ (priv->adapter->number_of_antenna > 1)) {
+ tx_ant = RF_ANTENNA_AUTO;
+ rx_ant = RF_ANTENNA_AUTO;
+ }
+ }
+
+ ant_cfg.tx_ant = tx_ant;
+ ant_cfg.rx_ant = rx_ant;
+
+ return mwifiex_send_cmd_sync(priv, HostCmd_CMD_RF_ANTENNA,
+ HostCmd_ACT_GEN_SET, 0, &ant_cfg);
+}
+
/* cfg80211 operation handler for stop ap.
* Function stops BSS running at uAP interface.
*/
@@ -929,7 +1010,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP)
return -1;
- if (mwifiex_set_mgmt_ies(priv, params))
+ if (mwifiex_set_mgmt_ies(priv, &params->beacon))
return -1;
bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);
@@ -958,15 +1039,29 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
/* firmware doesn't support this type of hidden SSID */
default:
+ kfree(bss_cfg);
return -EINVAL;
}
+ bss_cfg->channel =
+ (u8)ieee80211_frequency_to_channel(params->channel->center_freq);
+ bss_cfg->band_cfg = BAND_CONFIG_MANUAL;
+
+ if (mwifiex_set_rf_channel(priv, params->channel,
+ params->channel_type)) {
+ kfree(bss_cfg);
+ wiphy_err(wiphy, "Failed to set band config information!\n");
+ return -1;
+ }
+
if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
kfree(bss_cfg);
wiphy_err(wiphy, "Failed to parse secuirty parameters!\n");
return -1;
}
+ mwifiex_set_ht_params(priv, bss_cfg, params);
+
if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP,
HostCmd_ACT_GEN_SET, 0, NULL)) {
wiphy_err(wiphy, "Failed to stop the BSS\n");
@@ -990,6 +1085,16 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
return -1;
}
+ if (priv->sec_info.wep_enabled)
+ priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
+ else
+ priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
+
+ if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL,
+ HostCmd_ACT_GEN_SET, 0,
+ &priv->curr_pkt_filter))
+ return -1;
+
return 0;
}
@@ -1335,9 +1440,10 @@ mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
* it also informs the results.
*/
static int
-mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev,
+mwifiex_cfg80211_scan(struct wiphy *wiphy,
struct cfg80211_scan_request *request)
{
+ struct net_device *dev = request->wdev->netdev;
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
int i;
struct ieee80211_channel *chan;
@@ -1381,7 +1487,7 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev,
priv->user_scan_cfg->chan_list[i].scan_time = 0;
}
- if (mwifiex_set_user_scan_ioctl(priv, priv->user_scan_cfg))
+ if (mwifiex_scan_networks(priv, priv->user_scan_cfg))
return -EFAULT;
if (request->ie && request->ie_len) {
@@ -1471,11 +1577,11 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,
/*
* create a new virtual interface with the given name
*/
-struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
- char *name,
- enum nl80211_iftype type,
- u32 *flags,
- struct vif_params *params)
+struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
+ char *name,
+ enum nl80211_iftype type,
+ u32 *flags,
+ struct vif_params *params)
{
struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
struct mwifiex_private *priv;
@@ -1484,7 +1590,7 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
struct wireless_dev *wdev;
if (!adapter)
- return NULL;
+ return ERR_PTR(-EFAULT);
switch (type) {
case NL80211_IFTYPE_UNSPECIFIED:
@@ -1494,12 +1600,12 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
if (priv->bss_mode) {
wiphy_err(wiphy,
"cannot create multiple sta/adhoc ifaces\n");
- return NULL;
+ return ERR_PTR(-EINVAL);
}
wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
if (!wdev)
- return NULL;
+ return ERR_PTR(-ENOMEM);
wdev->wiphy = wiphy;
priv->wdev = wdev;
@@ -1522,12 +1628,12 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
if (priv->bss_mode) {
wiphy_err(wiphy, "Can't create multiple AP interfaces");
- return NULL;
+ return ERR_PTR(-EINVAL);
}
wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
if (!wdev)
- return NULL;
+ return ERR_PTR(-ENOMEM);
priv->wdev = wdev;
wdev->wiphy = wiphy;
@@ -1544,14 +1650,15 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
break;
default:
wiphy_err(wiphy, "type not supported\n");
- return NULL;
+ return ERR_PTR(-EINVAL);
}
dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), name,
ether_setup, 1);
if (!dev) {
wiphy_err(wiphy, "no memory available for netdevice\n");
- goto error;
+ priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+ return ERR_PTR(-ENOMEM);
}
mwifiex_init_priv_params(priv, dev);
@@ -1582,7 +1689,9 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
/* Register network device */
if (register_netdevice(dev)) {
wiphy_err(wiphy, "cannot register virtual network device\n");
- goto error;
+ free_netdev(dev);
+ priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+ return ERR_PTR(-EFAULT);
}
sema_init(&priv->async_sem, 1);
@@ -1593,22 +1702,16 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
#ifdef CONFIG_DEBUG_FS
mwifiex_dev_debugfs_init(priv);
#endif
- return dev;
-error:
- if (dev && (dev->reg_state == NETREG_UNREGISTERED))
- free_netdev(dev);
- priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-
- return NULL;
+ return wdev;
}
EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
/*
* del_virtual_intf: remove the virtual interface determined by dev
*/
-int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev)
+int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
{
- struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
#ifdef CONFIG_DEBUG_FS
mwifiex_dev_debugfs_remove(priv);
@@ -1620,11 +1723,11 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev)
if (netif_carrier_ok(priv->netdev))
netif_carrier_off(priv->netdev);
- if (dev->reg_state == NETREG_REGISTERED)
- unregister_netdevice(dev);
+ if (wdev->netdev->reg_state == NETREG_REGISTERED)
+ unregister_netdevice(wdev->netdev);
- if (dev->reg_state == NETREG_UNREGISTERED)
- free_netdev(dev);
+ if (wdev->netdev->reg_state == NETREG_UNREGISTERED)
+ free_netdev(wdev->netdev);
/* Clear the priv in adapter */
priv->netdev = NULL;
@@ -1658,7 +1761,9 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
.set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask,
.start_ap = mwifiex_cfg80211_start_ap,
.stop_ap = mwifiex_cfg80211_stop_ap,
+ .change_beacon = mwifiex_cfg80211_change_beacon,
.set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,
+ .set_antenna = mwifiex_cfg80211_set_antenna,
};
/*
@@ -1705,7 +1810,14 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
- wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_CUSTOM_REGULATORY;
+ wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
+ WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+
+ wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
+ NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2;
+
+ wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
+ wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
/* Reserve space for mwifiex specific private data for BSS */
wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 51e023ec1de4..c68adec3cc8b 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -578,6 +578,7 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
} else {
adapter->cmd_queued = cmd_node;
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
+ queue_work(adapter->workqueue, &adapter->main_work);
}
return ret;
@@ -1102,7 +1103,8 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
&resp->params.opt_hs_cfg;
uint32_t conditions = le32_to_cpu(phs_cfg->params.hs_config.conditions);
- if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE)) {
+ if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE) &&
+ adapter->iface_type == MWIFIEX_SDIO) {
mwifiex_hs_activated_event(priv, true);
return 0;
} else {
@@ -1114,6 +1116,9 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
}
if (conditions != HOST_SLEEP_CFG_CANCEL) {
adapter->is_hs_configured = true;
+ if (adapter->iface_type == MWIFIEX_USB ||
+ adapter->iface_type == MWIFIEX_PCIE)
+ mwifiex_hs_activated_event(priv, true);
} else {
adapter->is_hs_configured = false;
if (adapter->hs_activated)
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 561452a5c818..14e985d01dee 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -124,6 +124,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45)
#define TLV_TYPE_UAP_BCAST_SSID (PROPRIETARY_TLV_BASE_ID + 48)
#define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51)
+#define TLV_TYPE_UAP_WEP_KEY (PROPRIETARY_TLV_BASE_ID + 59)
#define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60)
#define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64)
#define TLV_TYPE_UAP_AKMP (PROPRIETARY_TLV_BASE_ID + 65)
@@ -162,6 +163,12 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11))
+#define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \
+ (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \
+ IEEE80211_HT_CAP_SM_PS)
+
+#define MWIFIEX_DEF_AMPDU IEEE80211_HT_AMPDU_PARM_FACTOR
+
/* dev_cap bitmap
* BIT
* 0-16 reserved
@@ -219,6 +226,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define HostCmd_CMD_RF_REG_ACCESS 0x001b
#define HostCmd_CMD_PMIC_REG_ACCESS 0x00ad
#define HostCmd_CMD_802_11_RF_CHANNEL 0x001d
+#define HostCmd_CMD_RF_TX_PWR 0x001e
+#define HostCmd_CMD_RF_ANTENNA 0x0020
#define HostCmd_CMD_802_11_DEAUTHENTICATE 0x0024
#define HostCmd_CMD_MAC_CONTROL 0x0028
#define HostCmd_CMD_802_11_AD_HOC_START 0x002b
@@ -314,6 +323,12 @@ enum ENH_PS_MODES {
#define HostCmd_BSS_TYPE_MASK 0xf000
+#define HostCmd_ACT_SET_RX 0x0001
+#define HostCmd_ACT_SET_TX 0x0002
+#define HostCmd_ACT_SET_BOTH 0x0003
+
+#define RF_ANTENNA_AUTO 0xFFFF
+
#define HostCmd_SET_SEQ_NO_BSS_INFO(seq, num, type) { \
(((seq) & 0x00ff) | \
(((num) & 0x000f) << 8)) | \
@@ -869,6 +884,25 @@ struct host_cmd_ds_txpwr_cfg {
__le32 mode;
} __packed;
+struct host_cmd_ds_rf_tx_pwr {
+ __le16 action;
+ __le16 cur_level;
+ u8 max_power;
+ u8 min_power;
+} __packed;
+
+struct host_cmd_ds_rf_ant_mimo {
+ __le16 action_tx;
+ __le16 tx_ant_mode;
+ __le16 action_rx;
+ __le16 rx_ant_mode;
+};
+
+struct host_cmd_ds_rf_ant_siso {
+ __le16 action;
+ __le16 ant_mode;
+};
+
struct mwifiex_bcn_param {
u8 bssid[ETH_ALEN];
u8 rssi;
@@ -1195,6 +1229,13 @@ struct host_cmd_tlv_passphrase {
u8 passphrase[0];
} __packed;
+struct host_cmd_tlv_wep_key {
+ struct host_cmd_tlv tlv;
+ u8 key_index;
+ u8 is_default;
+ u8 key[1];
+};
+
struct host_cmd_tlv_auth_type {
struct host_cmd_tlv tlv;
u8 auth_type;
@@ -1347,6 +1388,9 @@ struct host_cmd_ds_command {
struct host_cmd_ds_tx_rate_query tx_rate;
struct host_cmd_ds_tx_rate_cfg tx_rate_cfg;
struct host_cmd_ds_txpwr_cfg txp_cfg;
+ struct host_cmd_ds_rf_tx_pwr txp;
+ struct host_cmd_ds_rf_ant_mimo ant_mimo;
+ struct host_cmd_ds_rf_ant_siso ant_siso;
struct host_cmd_ds_802_11_ps_mode_enh psmode_enh;
struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg;
struct host_cmd_ds_802_11_scan scan;
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c
index ceb82cd749cc..1d8dd003e396 100644
--- a/drivers/net/wireless/mwifiex/ie.c
+++ b/drivers/net/wireless/mwifiex/ie.c
@@ -51,8 +51,7 @@ mwifiex_ie_get_autoidx(struct mwifiex_private *priv, u16 subtype_mask,
for (i = 0; i < priv->adapter->max_mgmt_ie_index; i++) {
mask = le16_to_cpu(priv->mgmt_ie[i].mgmt_subtype_mask);
- len = le16_to_cpu(priv->mgmt_ie[i].ie_length) +
- le16_to_cpu(ie->ie_length);
+ len = le16_to_cpu(ie->ie_length);
if (mask == MWIFIEX_AUTO_IDX_MASK)
continue;
@@ -108,10 +107,8 @@ mwifiex_update_autoindex_ies(struct mwifiex_private *priv,
return -1;
tmp = (u8 *)&priv->mgmt_ie[index].ie_buffer;
- tmp += le16_to_cpu(priv->mgmt_ie[index].ie_length);
memcpy(tmp, &ie->ie_buffer, le16_to_cpu(ie->ie_length));
- le16_add_cpu(&priv->mgmt_ie[index].ie_length,
- le16_to_cpu(ie->ie_length));
+ priv->mgmt_ie[index].ie_length = ie->ie_length;
priv->mgmt_ie[index].ie_index = cpu_to_le16(index);
priv->mgmt_ie[index].mgmt_subtype_mask =
cpu_to_le16(mask);
@@ -213,95 +210,67 @@ mwifiex_update_uap_custom_ie(struct mwifiex_private *priv,
/* save assoc resp ie index after auto-indexing */
*assoc_idx = *((u16 *)pos);
+ kfree(ap_custom_ie);
return ret;
}
-/* This function parses different IEs- Tail IEs, beacon IEs, probe response IEs,
- * association response IEs from cfg80211_ap_settings function and sets these IE
- * to FW.
+/* This function checks if WPS IE is present in passed buffer and copies it to
+ * mwifiex_ie structure.
+ * Function takes pointer to struct mwifiex_ie pointer as argument.
+ * If WPS IE is present memory is allocated for mwifiex_ie pointer and filled
+ * in with WPS IE. Caller should take care of freeing this memory.
*/
-int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
- struct cfg80211_ap_settings *params)
+static int mwifiex_update_wps_ie(const u8 *ies, int ies_len,
+ struct mwifiex_ie **ie_ptr, u16 mask)
{
- struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL;
- struct mwifiex_ie *ar_ie = NULL, *rsn_ie = NULL;
- struct ieee_types_header *ie = NULL;
- u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK;
- u16 ar_idx = MWIFIEX_AUTO_IDX_MASK, rsn_idx = MWIFIEX_AUTO_IDX_MASK;
- u16 mask;
- int ret = 0;
-
- if (params->beacon.tail && params->beacon.tail_len) {
- ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, params->beacon.tail,
- params->beacon.tail_len);
- if (ie) {
- rsn_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
- if (!rsn_ie)
- return -ENOMEM;
-
- rsn_ie->ie_index = cpu_to_le16(rsn_idx);
- mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP |
- MGMT_MASK_ASSOC_RESP;
- rsn_ie->mgmt_subtype_mask = cpu_to_le16(mask);
- rsn_ie->ie_length = cpu_to_le16(ie->len + 2);
- memcpy(rsn_ie->ie_buffer, ie, ie->len + 2);
-
- if (mwifiex_update_uap_custom_ie(priv, rsn_ie, &rsn_idx,
- NULL, NULL,
- NULL, NULL)) {
- ret = -1;
- goto done;
- }
+ struct ieee_types_header *wps_ie;
+ struct mwifiex_ie *ie = NULL;
+ const u8 *vendor_ie;
+
+ vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+ WLAN_OUI_TYPE_MICROSOFT_WPS,
+ ies, ies_len);
+ if (vendor_ie) {
+ ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
+ if (!ie)
+ return -ENOMEM;
- priv->rsn_idx = rsn_idx;
- }
+ wps_ie = (struct ieee_types_header *)vendor_ie;
+ memcpy(ie->ie_buffer, wps_ie, wps_ie->len + 2);
+ ie->ie_length = cpu_to_le16(wps_ie->len + 2);
+ ie->mgmt_subtype_mask = cpu_to_le16(mask);
+ ie->ie_index = cpu_to_le16(MWIFIEX_AUTO_IDX_MASK);
}
- if (params->beacon.beacon_ies && params->beacon.beacon_ies_len) {
- beacon_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
- if (!beacon_ie) {
- ret = -ENOMEM;
- goto done;
- }
-
- beacon_ie->ie_index = cpu_to_le16(beacon_idx);
- beacon_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON);
- beacon_ie->ie_length =
- cpu_to_le16(params->beacon.beacon_ies_len);
- memcpy(beacon_ie->ie_buffer, params->beacon.beacon_ies,
- params->beacon.beacon_ies_len);
- }
+ *ie_ptr = ie;
+ return 0;
+}
- if (params->beacon.proberesp_ies && params->beacon.proberesp_ies_len) {
- pr_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
- if (!pr_ie) {
- ret = -ENOMEM;
- goto done;
- }
+/* This function parses beacon IEs, probe response IEs, association response IEs
+ * from cfg80211_ap_settings->beacon and sets these IE to FW.
+ */
+static int mwifiex_set_mgmt_beacon_data_ies(struct mwifiex_private *priv,
+ struct cfg80211_beacon_data *data)
+{
+ struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL, *ar_ie = NULL;
+ u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK;
+ u16 ar_idx = MWIFIEX_AUTO_IDX_MASK;
+ int ret = 0;
- pr_ie->ie_index = cpu_to_le16(pr_idx);
- pr_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_PROBE_RESP);
- pr_ie->ie_length =
- cpu_to_le16(params->beacon.proberesp_ies_len);
- memcpy(pr_ie->ie_buffer, params->beacon.proberesp_ies,
- params->beacon.proberesp_ies_len);
- }
+ if (data->beacon_ies && data->beacon_ies_len)
+ mwifiex_update_wps_ie(data->beacon_ies, data->beacon_ies_len,
+ &beacon_ie, MGMT_MASK_BEACON);
- if (params->beacon.assocresp_ies && params->beacon.assocresp_ies_len) {
- ar_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
- if (!ar_ie) {
- ret = -ENOMEM;
- goto done;
- }
+ if (data->proberesp_ies && data->proberesp_ies_len)
+ mwifiex_update_wps_ie(data->proberesp_ies,
+ data->proberesp_ies_len, &pr_ie,
+ MGMT_MASK_PROBE_RESP);
- ar_ie->ie_index = cpu_to_le16(ar_idx);
- mask = MGMT_MASK_ASSOC_RESP | MGMT_MASK_REASSOC_RESP;
- ar_ie->mgmt_subtype_mask = cpu_to_le16(mask);
- ar_ie->ie_length =
- cpu_to_le16(params->beacon.assocresp_ies_len);
- memcpy(ar_ie->ie_buffer, params->beacon.assocresp_ies,
- params->beacon.assocresp_ies_len);
- }
+ if (data->assocresp_ies && data->assocresp_ies_len)
+ mwifiex_update_wps_ie(data->assocresp_ies,
+ data->assocresp_ies_len, &ar_ie,
+ MGMT_MASK_ASSOC_RESP |
+ MGMT_MASK_REASSOC_RESP);
if (beacon_ie || pr_ie || ar_ie) {
ret = mwifiex_update_uap_custom_ie(priv, beacon_ie,
@@ -319,11 +288,67 @@ done:
kfree(beacon_ie);
kfree(pr_ie);
kfree(ar_ie);
- kfree(rsn_ie);
return ret;
}
+/* This function parses different IEs-tail IEs, beacon IEs, probe response IEs,
+ * association response IEs from cfg80211_ap_settings function and sets these IE
+ * to FW.
+ */
+int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
+ struct cfg80211_beacon_data *info)
+{
+ struct mwifiex_ie *gen_ie;
+ struct ieee_types_header *rsn_ie, *wpa_ie = NULL;
+ u16 rsn_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
+ const u8 *vendor_ie;
+
+ if (info->tail && info->tail_len) {
+ gen_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
+ if (!gen_ie)
+ return -ENOMEM;
+ gen_ie->ie_index = cpu_to_le16(rsn_idx);
+ gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
+ MGMT_MASK_PROBE_RESP |
+ MGMT_MASK_ASSOC_RESP);
+
+ rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN,
+ info->tail, info->tail_len);
+ if (rsn_ie) {
+ memcpy(gen_ie->ie_buffer, rsn_ie, rsn_ie->len + 2);
+ ie_len = rsn_ie->len + 2;
+ gen_ie->ie_length = cpu_to_le16(ie_len);
+ }
+
+ vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+ WLAN_OUI_TYPE_MICROSOFT_WPA,
+ info->tail,
+ info->tail_len);
+ if (vendor_ie) {
+ wpa_ie = (struct ieee_types_header *)vendor_ie;
+ memcpy(gen_ie->ie_buffer + ie_len,
+ wpa_ie, wpa_ie->len + 2);
+ ie_len += wpa_ie->len + 2;
+ gen_ie->ie_length = cpu_to_le16(ie_len);
+ }
+
+ if (rsn_ie || wpa_ie) {
+ if (mwifiex_update_uap_custom_ie(priv, gen_ie, &rsn_idx,
+ NULL, NULL,
+ NULL, NULL)) {
+ kfree(gen_ie);
+ return -1;
+ }
+ priv->rsn_idx = rsn_idx;
+ }
+
+ kfree(gen_ie);
+ }
+
+ return mwifiex_set_mgmt_beacon_data_ies(priv, info);
+}
+
/* This function removes management IE set */
int mwifiex_del_mgmt_ies(struct mwifiex_private *priv)
{
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 0f18ef6a30c8..b543a4d82ff3 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -103,6 +103,7 @@ static void scan_delay_timer_fn(unsigned long data)
msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
adapter->scan_delay_cnt++;
}
+ queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
} else {
/*
* Tx data queue is empty. Get scan command from scan_pending_q
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index e6be6ee75951..e121294cc1ac 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -21,6 +21,7 @@
#define _MWIFIEX_IOCTL_H_
#include <net/mac80211.h>
+#include <net/lib80211.h>
enum {
MWIFIEX_SCAN_TYPE_UNCHANGED = 0,
@@ -71,6 +72,13 @@ struct wpa_param {
u8 passphrase[MWIFIEX_WPA_PASSHPHRASE_LEN];
};
+struct wep_key {
+ u8 key_index;
+ u8 is_default;
+ u16 length;
+ u8 key[WLAN_KEY_LEN_WEP104];
+};
+
#define KEY_MGMT_ON_HOST 0x03
#define MWIFIEX_AUTH_MODE_AUTO 0xFF
#define BAND_CONFIG_MANUAL 0x00
@@ -90,6 +98,8 @@ struct mwifiex_uap_bss_param {
u16 key_mgmt;
u16 key_mgmt_operation;
struct wpa_param wpa_cfg;
+ struct wep_key wep_cfg[NUM_WEP_KEYS];
+ struct ieee80211_ht_cap ht_cap;
};
enum {
@@ -267,6 +277,11 @@ struct mwifiex_ds_11n_amsdu_aggr_ctrl {
u16 curr_buf_size;
};
+struct mwifiex_ds_ant_cfg {
+ u32 tx_ant;
+ u32 rx_ant;
+};
+
#define MWIFIEX_NUM_OF_CMD_BUFFER 20
#define MWIFIEX_SIZE_OF_CMD_BUFFER 2048
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 0f06f07a70e6..46803621d015 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -190,7 +190,8 @@ process_start:
adapter->tx_lock_flag)
break;
- if (adapter->scan_processing || adapter->data_sent ||
+ if ((adapter->scan_processing &&
+ !adapter->scan_delay_cnt) || adapter->data_sent ||
mwifiex_wmm_lists_empty(adapter)) {
if (adapter->cmd_sent || adapter->curr_cmd ||
(!is_command_pending(adapter)))
@@ -376,7 +377,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
goto done;
err_add_intf:
- mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev);
+ mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
rtnl_unlock();
err_init_fw:
pr_debug("info: %s: unregister device\n", __func__);
@@ -843,7 +844,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
rtnl_lock();
if (priv->wdev && priv->netdev)
- mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev);
+ mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
rtnl_unlock();
}
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 5b32221077c4..774880d5cb56 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -840,6 +840,9 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
int mwifiex_set_secure_params(struct mwifiex_private *priv,
struct mwifiex_uap_bss_param *bss_config,
struct cfg80211_ap_settings *params);
+void mwifiex_set_ht_params(struct mwifiex_private *priv,
+ struct mwifiex_uap_bss_param *bss_cfg,
+ struct cfg80211_ap_settings *params);
/*
* This function checks if the queuing is RA based or not.
@@ -946,8 +949,8 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
struct mwifiex_rate_cfg *rate);
int mwifiex_request_scan(struct mwifiex_private *priv,
struct cfg80211_ssid *req_ssid);
-int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
- struct mwifiex_user_scan_cfg *scan_req);
+int mwifiex_scan_networks(struct mwifiex_private *priv,
+ const struct mwifiex_user_scan_cfg *user_scan_in);
int mwifiex_set_radio(struct mwifiex_private *priv, u8 option);
int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel);
@@ -990,7 +993,6 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,
int mwifiex_main_process(struct mwifiex_adapter *);
-int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel);
int mwifiex_bss_set_channel(struct mwifiex_private *,
struct mwifiex_chan_freq_power *cfp);
int mwifiex_get_bss_info(struct mwifiex_private *,
@@ -1003,15 +1005,17 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc);
-struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
- char *name, enum nl80211_iftype type,
- u32 *flags, struct vif_params *params);
-int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev);
+struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
+ char *name,
+ enum nl80211_iftype type,
+ u32 *flags,
+ struct vif_params *params);
+int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev);
void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config);
int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
- struct cfg80211_ap_settings *params);
+ struct cfg80211_beacon_data *data);
int mwifiex_del_mgmt_ies(struct mwifiex_private *priv);
u8 *mwifiex_11d_code_2_region(u8 code);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index efaf26ccd6ba..884ed6377003 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1296,8 +1296,8 @@ mwifiex_radio_type_to_band(u8 radio_type)
* order to send the appropriate scan commands to firmware to populate or
* update the internal driver scan table.
*/
-static int mwifiex_scan_networks(struct mwifiex_private *priv,
- const struct mwifiex_user_scan_cfg *user_scan_in)
+int mwifiex_scan_networks(struct mwifiex_private *priv,
+ const struct mwifiex_user_scan_cfg *user_scan_in)
{
int ret = 0;
struct mwifiex_adapter *adapter = priv->adapter;
@@ -1362,6 +1362,7 @@ static int mwifiex_scan_networks(struct mwifiex_private *priv,
adapter->cmd_queued = cmd_node;
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
true);
+ queue_work(adapter->workqueue, &adapter->main_work);
} else {
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
flags);
@@ -1378,26 +1379,6 @@ static int mwifiex_scan_networks(struct mwifiex_private *priv,
}
/*
- * Sends IOCTL request to start a scan with user configurations.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- *
- * Upon completion, it also generates a wireless event to notify
- * applications.
- */
-int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
- struct mwifiex_user_scan_cfg *scan_req)
-{
- int status;
-
- status = mwifiex_scan_networks(priv, scan_req);
- queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
-
- return status;
-}
-
-/*
* This function prepares a scan command to be sent to the firmware.
*
* This uses the scan command configuration sent to the command processing
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index e0377473282f..fc8a9bfa1248 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -978,10 +978,10 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
dev_dbg(adapter->dev, "info: --- Rx: Event ---\n");
adapter->event_cause = *(u32 *) skb->data;
- skb_pull(skb, MWIFIEX_EVENT_HEADER_LEN);
-
if ((skb->len > 0) && (skb->len < MAX_EVENT_SIZE))
- memcpy(adapter->event_body, skb->data, skb->len);
+ memcpy(adapter->event_body,
+ skb->data + MWIFIEX_EVENT_HEADER_LEN,
+ skb->len);
/* event cause has been saved to adapter->event_cause */
adapter->event_received = true;
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index 40e025da6bc2..75eaa6f877fa 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -260,6 +260,56 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
}
/*
+ * This function prepares command to get RF Tx power.
+ */
+static int mwifiex_cmd_rf_tx_power(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *cmd,
+ u16 cmd_action, void *data_buf)
+{
+ struct host_cmd_ds_rf_tx_pwr *txp = &cmd->params.txp;
+
+ cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_tx_pwr)
+ + S_DS_GEN);
+ cmd->command = cpu_to_le16(HostCmd_CMD_RF_TX_PWR);
+ txp->action = cpu_to_le16(cmd_action);
+
+ return 0;
+}
+
+/*
+ * This function prepares command to set rf antenna.
+ */
+static int mwifiex_cmd_rf_antenna(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *cmd,
+ u16 cmd_action,
+ struct mwifiex_ds_ant_cfg *ant_cfg)
+{
+ struct host_cmd_ds_rf_ant_mimo *ant_mimo = &cmd->params.ant_mimo;
+ struct host_cmd_ds_rf_ant_siso *ant_siso = &cmd->params.ant_siso;
+
+ cmd->command = cpu_to_le16(HostCmd_CMD_RF_ANTENNA);
+
+ if (cmd_action != HostCmd_ACT_GEN_SET)
+ return 0;
+
+ if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) {
+ cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_mimo) +
+ S_DS_GEN);
+ ant_mimo->action_tx = cpu_to_le16(HostCmd_ACT_SET_TX);
+ ant_mimo->tx_ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant);
+ ant_mimo->action_rx = cpu_to_le16(HostCmd_ACT_SET_RX);
+ ant_mimo->rx_ant_mode = cpu_to_le16((u16)ant_cfg->rx_ant);
+ } else {
+ cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_siso) +
+ S_DS_GEN);
+ ant_siso->action = cpu_to_le16(HostCmd_ACT_SET_BOTH);
+ ant_siso->ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant);
+ }
+
+ return 0;
+}
+
+/*
* This function prepares command to set Host Sleep configuration.
*
* Preparation includes -
@@ -1055,6 +1105,14 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
ret = mwifiex_cmd_tx_power_cfg(cmd_ptr, cmd_action,
data_buf);
break;
+ case HostCmd_CMD_RF_TX_PWR:
+ ret = mwifiex_cmd_rf_tx_power(priv, cmd_ptr, cmd_action,
+ data_buf);
+ break;
+ case HostCmd_CMD_RF_ANTENNA:
+ ret = mwifiex_cmd_rf_antenna(priv, cmd_ptr, cmd_action,
+ data_buf);
+ break;
case HostCmd_CMD_802_11_PS_MODE_ENH:
ret = mwifiex_cmd_enh_power_mode(priv, cmd_ptr, cmd_action,
(uint16_t)cmd_oid, data_buf);
@@ -1283,7 +1341,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
priv->data_rate = 0;
/* get tx power */
- ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_TXPWR_CFG,
+ ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_RF_TX_PWR,
HostCmd_ACT_GEN_GET, 0, NULL);
if (ret)
return -1;
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index a79ed9bd9695..71c9b5b92e6d 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -451,6 +451,57 @@ static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
}
/*
+ * This function handles the command response of get RF Tx power.
+ */
+static int mwifiex_ret_rf_tx_power(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *resp)
+{
+ struct host_cmd_ds_rf_tx_pwr *txp = &resp->params.txp;
+ u16 action = le16_to_cpu(txp->action);
+
+ priv->tx_power_level = le16_to_cpu(txp->cur_level);
+
+ if (action == HostCmd_ACT_GEN_GET) {
+ priv->max_tx_power_level = txp->max_power;
+ priv->min_tx_power_level = txp->min_power;
+ }
+
+ dev_dbg(priv->adapter->dev,
+ "Current TxPower Level=%d, Max Power=%d, Min Power=%d\n",
+ priv->tx_power_level, priv->max_tx_power_level,
+ priv->min_tx_power_level);
+
+ return 0;
+}
+
+/*
+ * This function handles the command response of set rf antenna
+ */
+static int mwifiex_ret_rf_antenna(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *resp)
+{
+ struct host_cmd_ds_rf_ant_mimo *ant_mimo = &resp->params.ant_mimo;
+ struct host_cmd_ds_rf_ant_siso *ant_siso = &resp->params.ant_siso;
+ struct mwifiex_adapter *adapter = priv->adapter;
+
+ if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
+ dev_dbg(adapter->dev,
+ "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x"
+ " Rx action = 0x%x, Rx Mode = 0x%04x\n",
+ le16_to_cpu(ant_mimo->action_tx),
+ le16_to_cpu(ant_mimo->tx_ant_mode),
+ le16_to_cpu(ant_mimo->action_rx),
+ le16_to_cpu(ant_mimo->rx_ant_mode));
+ else
+ dev_dbg(adapter->dev,
+ "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n",
+ le16_to_cpu(ant_siso->action),
+ le16_to_cpu(ant_siso->ant_mode));
+
+ return 0;
+}
+
+/*
* This function handles the command response of set/get MAC address.
*
* Handling includes saving the MAC address in driver.
@@ -847,6 +898,12 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
case HostCmd_CMD_TXPWR_CFG:
ret = mwifiex_ret_tx_power_cfg(priv, resp);
break;
+ case HostCmd_CMD_RF_TX_PWR:
+ ret = mwifiex_ret_rf_tx_power(priv, resp);
+ break;
+ case HostCmd_CMD_RF_ANTENNA:
+ ret = mwifiex_ret_rf_antenna(priv, resp);
+ break;
case HostCmd_CMD_802_11_PS_MODE_ENH:
ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf);
break;
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index 4ace5a3dcd23..11e731f3581c 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -406,9 +406,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
break;
case EVENT_UAP_STA_ASSOC:
- skb_pull(adapter->event_skb, MWIFIEX_UAP_EVENT_EXTRA_HEADER);
memset(&sinfo, 0, sizeof(sinfo));
- event = (struct mwifiex_assoc_event *)adapter->event_skb->data;
+ event = (struct mwifiex_assoc_event *)
+ (adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER);
if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) {
len = -1;
@@ -433,9 +433,8 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
GFP_KERNEL);
break;
case EVENT_UAP_STA_DEAUTH:
- skb_pull(adapter->event_skb, MWIFIEX_UAP_EVENT_EXTRA_HEADER);
- cfg80211_del_sta(priv->netdev, adapter->event_skb->data,
- GFP_KERNEL);
+ cfg80211_del_sta(priv->netdev, adapter->event_body +
+ MWIFIEX_UAP_EVENT_EXTRA_HEADER, GFP_KERNEL);
break;
case EVENT_UAP_BSS_IDLE:
priv->media_connected = false;
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 106c449477b2..f2fd2423214f 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -66,9 +66,6 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
dev_dbg(adapter->dev, "cmd pending\n");
atomic_inc(&adapter->cmd_pending);
- /* Status pending, wake up main process */
- queue_work(adapter->workqueue, &adapter->main_work);
-
/* Wait for completion */
wait_event_interruptible(adapter->cmd_wait_q.wait,
*(cmd_queued->condition));
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index e2faec4db108..cecb27283196 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -161,15 +161,11 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
goto done;
for (i = 0; i < adapter->priv_num; i++) {
-
tpriv = adapter->priv[i];
- if ((GET_BSS_ROLE(tpriv) == MWIFIEX_BSS_ROLE_STA) &&
- (tpriv->media_connected)) {
- if (netif_queue_stopped(tpriv->netdev))
- mwifiex_wake_up_net_dev_queue(tpriv->netdev,
- adapter);
- }
+ if (tpriv->media_connected &&
+ netif_queue_stopped(tpriv->netdev))
+ mwifiex_wake_up_net_dev_queue(tpriv->netdev, adapter);
}
done:
dev_kfree_skb_any(skb);
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
index 8173ab66066d..f40e93fe894a 100644
--- a/drivers/net/wireless/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/mwifiex/uap_cmd.c
@@ -26,6 +26,18 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
struct mwifiex_uap_bss_param *bss_config,
struct cfg80211_ap_settings *params) {
int i;
+ struct mwifiex_wep_key wep_key;
+
+ if (!params->privacy) {
+ bss_config->protocol = PROTOCOL_NO_SECURITY;
+ bss_config->key_mgmt = KEY_MGMT_NONE;
+ bss_config->wpa_cfg.length = 0;
+ priv->sec_info.wep_enabled = 0;
+ priv->sec_info.wpa_enabled = 0;
+ priv->sec_info.wpa2_enabled = 0;
+
+ return 0;
+ }
switch (params->auth_type) {
case NL80211_AUTHTYPE_OPEN_SYSTEM:
@@ -54,7 +66,7 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
}
if (params->crypto.wpa_versions &
NL80211_WPA_VERSION_2) {
- bss_config->protocol = PROTOCOL_WPA2;
+ bss_config->protocol |= PROTOCOL_WPA2;
bss_config->key_mgmt = KEY_MGMT_EAP;
}
break;
@@ -66,7 +78,7 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
}
if (params->crypto.wpa_versions &
NL80211_WPA_VERSION_2) {
- bss_config->protocol = PROTOCOL_WPA2;
+ bss_config->protocol |= PROTOCOL_WPA2;
bss_config->key_mgmt = KEY_MGMT_PSK;
}
break;
@@ -80,10 +92,19 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
case WLAN_CIPHER_SUITE_WEP104:
break;
case WLAN_CIPHER_SUITE_TKIP:
- bss_config->wpa_cfg.pairwise_cipher_wpa = CIPHER_TKIP;
+ if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
+ bss_config->wpa_cfg.pairwise_cipher_wpa |=
+ CIPHER_TKIP;
+ if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+ bss_config->wpa_cfg.pairwise_cipher_wpa2 |=
+ CIPHER_TKIP;
break;
case WLAN_CIPHER_SUITE_CCMP:
- bss_config->wpa_cfg.pairwise_cipher_wpa2 =
+ if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
+ bss_config->wpa_cfg.pairwise_cipher_wpa |=
+ CIPHER_AES_CCMP;
+ if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+ bss_config->wpa_cfg.pairwise_cipher_wpa2 |=
CIPHER_AES_CCMP;
default:
break;
@@ -93,6 +114,27 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
switch (params->crypto.cipher_group) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
+ if (priv->sec_info.wep_enabled) {
+ bss_config->protocol = PROTOCOL_STATIC_WEP;
+ bss_config->key_mgmt = KEY_MGMT_NONE;
+ bss_config->wpa_cfg.length = 0;
+
+ for (i = 0; i < NUM_WEP_KEYS; i++) {
+ wep_key = priv->wep_key[i];
+ bss_config->wep_cfg[i].key_index = i;
+
+ if (priv->wep_key_curr_index == i)
+ bss_config->wep_cfg[i].is_default = 1;
+ else
+ bss_config->wep_cfg[i].is_default = 0;
+
+ bss_config->wep_cfg[i].length =
+ wep_key.key_length;
+ memcpy(&bss_config->wep_cfg[i].key,
+ &wep_key.key_material,
+ wep_key.key_length);
+ }
+ }
break;
case WLAN_CIPHER_SUITE_TKIP:
bss_config->wpa_cfg.group_cipher = CIPHER_TKIP;
@@ -107,6 +149,33 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
return 0;
}
+/* This function updates 11n related parameters from IE and sets them into
+ * bss_config structure.
+ */
+void
+mwifiex_set_ht_params(struct mwifiex_private *priv,
+ struct mwifiex_uap_bss_param *bss_cfg,
+ struct cfg80211_ap_settings *params)
+{
+ const u8 *ht_ie;
+
+ if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info))
+ return;
+
+ ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail,
+ params->beacon.tail_len);
+ if (ht_ie) {
+ memcpy(&bss_cfg->ht_cap, ht_ie + 2,
+ sizeof(struct ieee80211_ht_cap));
+ } else {
+ memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap));
+ bss_cfg->ht_cap.cap_info = cpu_to_le16(MWIFIEX_DEF_HT_CAP);
+ bss_cfg->ht_cap.ampdu_params_info = MWIFIEX_DEF_AMPDU;
+ }
+
+ return;
+}
+
/* This function initializes some of mwifiex_uap_bss_param variables.
* This helps FW in ignoring invalid values. These values may or may not
* be get updated to valid ones at later stage.
@@ -124,6 +193,120 @@ void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config)
}
/* This function parses BSS related parameters from structure
+ * and prepares TLVs specific to WPA/WPA2 security.
+ * These TLVs are appended to command buffer.
+ */
+static void
+mwifiex_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
+{
+ struct host_cmd_tlv_pwk_cipher *pwk_cipher;
+ struct host_cmd_tlv_gwk_cipher *gwk_cipher;
+ struct host_cmd_tlv_passphrase *passphrase;
+ struct host_cmd_tlv_akmp *tlv_akmp;
+ struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
+ u16 cmd_size = *param_size;
+ u8 *tlv = *tlv_buf;
+
+ tlv_akmp = (struct host_cmd_tlv_akmp *)tlv;
+ tlv_akmp->tlv.type = cpu_to_le16(TLV_TYPE_UAP_AKMP);
+ tlv_akmp->tlv.len = cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) -
+ sizeof(struct host_cmd_tlv));
+ tlv_akmp->key_mgmt_operation = cpu_to_le16(bss_cfg->key_mgmt_operation);
+ tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt);
+ cmd_size += sizeof(struct host_cmd_tlv_akmp);
+ tlv += sizeof(struct host_cmd_tlv_akmp);
+
+ if (bss_cfg->wpa_cfg.pairwise_cipher_wpa & VALID_CIPHER_BITMAP) {
+ pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
+ pwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
+ pwk_cipher->tlv.len =
+ cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
+ sizeof(struct host_cmd_tlv));
+ pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA);
+ pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa;
+ cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
+ tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
+ }
+
+ if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 & VALID_CIPHER_BITMAP) {
+ pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
+ pwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
+ pwk_cipher->tlv.len =
+ cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
+ sizeof(struct host_cmd_tlv));
+ pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2);
+ pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa2;
+ cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
+ tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
+ }
+
+ if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) {
+ gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv;
+ gwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER);
+ gwk_cipher->tlv.len =
+ cpu_to_le16(sizeof(struct host_cmd_tlv_gwk_cipher) -
+ sizeof(struct host_cmd_tlv));
+ gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher;
+ cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher);
+ tlv += sizeof(struct host_cmd_tlv_gwk_cipher);
+ }
+
+ if (bss_cfg->wpa_cfg.length) {
+ passphrase = (struct host_cmd_tlv_passphrase *)tlv;
+ passphrase->tlv.type = cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE);
+ passphrase->tlv.len = cpu_to_le16(bss_cfg->wpa_cfg.length);
+ memcpy(passphrase->passphrase, bss_cfg->wpa_cfg.passphrase,
+ bss_cfg->wpa_cfg.length);
+ cmd_size += sizeof(struct host_cmd_tlv) +
+ bss_cfg->wpa_cfg.length;
+ tlv += sizeof(struct host_cmd_tlv) + bss_cfg->wpa_cfg.length;
+ }
+
+ *param_size = cmd_size;
+ *tlv_buf = tlv;
+
+ return;
+}
+
+/* This function parses BSS related parameters from structure
+ * and prepares TLVs specific to WEP encryption.
+ * These TLVs are appended to command buffer.
+ */
+static void
+mwifiex_uap_bss_wep(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
+{
+ struct host_cmd_tlv_wep_key *wep_key;
+ u16 cmd_size = *param_size;
+ int i;
+ u8 *tlv = *tlv_buf;
+ struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
+
+ for (i = 0; i < NUM_WEP_KEYS; i++) {
+ if (bss_cfg->wep_cfg[i].length &&
+ (bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP40 ||
+ bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP104)) {
+ wep_key = (struct host_cmd_tlv_wep_key *)tlv;
+ wep_key->tlv.type = cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
+ wep_key->tlv.len =
+ cpu_to_le16(bss_cfg->wep_cfg[i].length + 2);
+ wep_key->key_index = bss_cfg->wep_cfg[i].key_index;
+ wep_key->is_default = bss_cfg->wep_cfg[i].is_default;
+ memcpy(wep_key->key, bss_cfg->wep_cfg[i].key,
+ bss_cfg->wep_cfg[i].length);
+ cmd_size += sizeof(struct host_cmd_tlv) + 2 +
+ bss_cfg->wep_cfg[i].length;
+ tlv += sizeof(struct host_cmd_tlv) + 2 +
+ bss_cfg->wep_cfg[i].length;
+ }
+ }
+
+ *param_size = cmd_size;
+ *tlv_buf = tlv;
+
+ return;
+}
+
+/* This function parses BSS related parameters from structure
* and prepares TLVs. These TLVs are appended to command buffer.
*/
static int
@@ -137,12 +320,9 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
struct host_cmd_tlv_frag_threshold *frag_threshold;
struct host_cmd_tlv_rts_threshold *rts_threshold;
struct host_cmd_tlv_retry_limit *retry_limit;
- struct host_cmd_tlv_pwk_cipher *pwk_cipher;
- struct host_cmd_tlv_gwk_cipher *gwk_cipher;
struct host_cmd_tlv_encrypt_protocol *encrypt_protocol;
struct host_cmd_tlv_auth_type *auth_type;
- struct host_cmd_tlv_passphrase *passphrase;
- struct host_cmd_tlv_akmp *tlv_akmp;
+ struct mwifiex_ie_types_htcap *htcap;
struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
u16 cmd_size = *param_size;
@@ -232,70 +412,11 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
}
if ((bss_cfg->protocol & PROTOCOL_WPA) ||
(bss_cfg->protocol & PROTOCOL_WPA2) ||
- (bss_cfg->protocol & PROTOCOL_EAP)) {
- tlv_akmp = (struct host_cmd_tlv_akmp *)tlv;
- tlv_akmp->tlv.type = cpu_to_le16(TLV_TYPE_UAP_AKMP);
- tlv_akmp->tlv.len =
- cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) -
- sizeof(struct host_cmd_tlv));
- tlv_akmp->key_mgmt_operation =
- cpu_to_le16(bss_cfg->key_mgmt_operation);
- tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt);
- cmd_size += sizeof(struct host_cmd_tlv_akmp);
- tlv += sizeof(struct host_cmd_tlv_akmp);
-
- if (bss_cfg->wpa_cfg.pairwise_cipher_wpa &
- VALID_CIPHER_BITMAP) {
- pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
- pwk_cipher->tlv.type =
- cpu_to_le16(TLV_TYPE_PWK_CIPHER);
- pwk_cipher->tlv.len = cpu_to_le16(
- sizeof(struct host_cmd_tlv_pwk_cipher) -
- sizeof(struct host_cmd_tlv));
- pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA);
- pwk_cipher->cipher =
- bss_cfg->wpa_cfg.pairwise_cipher_wpa;
- cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
- tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
- }
- if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 &
- VALID_CIPHER_BITMAP) {
- pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
- pwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
- pwk_cipher->tlv.len = cpu_to_le16(
- sizeof(struct host_cmd_tlv_pwk_cipher) -
- sizeof(struct host_cmd_tlv));
- pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2);
- pwk_cipher->cipher =
- bss_cfg->wpa_cfg.pairwise_cipher_wpa2;
- cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
- tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
- }
- if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) {
- gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv;
- gwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER);
- gwk_cipher->tlv.len = cpu_to_le16(
- sizeof(struct host_cmd_tlv_gwk_cipher) -
- sizeof(struct host_cmd_tlv));
- gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher;
- cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher);
- tlv += sizeof(struct host_cmd_tlv_gwk_cipher);
- }
- if (bss_cfg->wpa_cfg.length) {
- passphrase = (struct host_cmd_tlv_passphrase *)tlv;
- passphrase->tlv.type =
- cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE);
- passphrase->tlv.len =
- cpu_to_le16(bss_cfg->wpa_cfg.length);
- memcpy(passphrase->passphrase,
- bss_cfg->wpa_cfg.passphrase,
- bss_cfg->wpa_cfg.length);
- cmd_size += sizeof(struct host_cmd_tlv) +
- bss_cfg->wpa_cfg.length;
- tlv += sizeof(struct host_cmd_tlv) +
- bss_cfg->wpa_cfg.length;
- }
- }
+ (bss_cfg->protocol & PROTOCOL_EAP))
+ mwifiex_uap_bss_wpa(&tlv, cmd_buf, &cmd_size);
+ else
+ mwifiex_uap_bss_wep(&tlv, cmd_buf, &cmd_size);
+
if ((bss_cfg->auth_mode <= WLAN_AUTH_SHARED_KEY) ||
(bss_cfg->auth_mode == MWIFIEX_AUTH_MODE_AUTO)) {
auth_type = (struct host_cmd_tlv_auth_type *)tlv;
@@ -319,6 +440,25 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
tlv += sizeof(struct host_cmd_tlv_encrypt_protocol);
}
+ if (bss_cfg->ht_cap.cap_info) {
+ htcap = (struct mwifiex_ie_types_htcap *)tlv;
+ htcap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
+ htcap->header.len =
+ cpu_to_le16(sizeof(struct ieee80211_ht_cap));
+ htcap->ht_cap.cap_info = bss_cfg->ht_cap.cap_info;
+ htcap->ht_cap.ampdu_params_info =
+ bss_cfg->ht_cap.ampdu_params_info;
+ memcpy(&htcap->ht_cap.mcs, &bss_cfg->ht_cap.mcs,
+ sizeof(struct ieee80211_mcs_info));
+ htcap->ht_cap.extended_ht_cap_info =
+ bss_cfg->ht_cap.extended_ht_cap_info;
+ htcap->ht_cap.tx_BF_cap_info = bss_cfg->ht_cap.tx_BF_cap_info;
+ htcap->ht_cap.antenna_selection_info =
+ bss_cfg->ht_cap.antenna_selection_info;
+ cmd_size += sizeof(struct mwifiex_ie_types_htcap);
+ tlv += sizeof(struct mwifiex_ie_types_htcap);
+ }
+
*param_size = cmd_size;
return 0;
@@ -410,33 +550,3 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
return 0;
}
-
-/* This function sets the RF channel for AP.
- *
- * This function populates channel information in AP config structure
- * and sends command to configure channel information in AP.
- */
-int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel)
-{
- struct mwifiex_uap_bss_param *bss_cfg;
- struct wiphy *wiphy = priv->wdev->wiphy;
-
- bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);
- if (!bss_cfg)
- return -ENOMEM;
-
- mwifiex_set_sys_config_invalid_data(bss_cfg);
- bss_cfg->band_cfg = BAND_CONFIG_MANUAL;
- bss_cfg->channel = channel;
-
- if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG,
- HostCmd_ACT_GEN_SET,
- UAP_BSS_PARAMS_I, bss_cfg)) {
- wiphy_err(wiphy, "Failed to set the uAP channel\n");
- kfree(bss_cfg);
- return -1;
- }
-
- kfree(bss_cfg);
- return 0;
-}
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c
index 49ebf20c56eb..22a5916564b8 100644
--- a/drivers/net/wireless/mwifiex/usb.c
+++ b/drivers/net/wireless/mwifiex/usb.c
@@ -49,6 +49,7 @@ static int mwifiex_usb_recv(struct mwifiex_adapter *adapter,
struct device *dev = adapter->dev;
u32 recv_type;
__le32 tmp;
+ int ret;
if (adapter->hs_activated)
mwifiex_process_hs_config(adapter);
@@ -69,16 +70,19 @@ static int mwifiex_usb_recv(struct mwifiex_adapter *adapter,
case MWIFIEX_USB_TYPE_CMD:
if (skb->len > MWIFIEX_SIZE_OF_CMD_BUFFER) {
dev_err(dev, "CMD: skb->len too large\n");
- return -1;
+ ret = -1;
+ goto exit_restore_skb;
} else if (!adapter->curr_cmd) {
dev_dbg(dev, "CMD: no curr_cmd\n");
if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
mwifiex_process_sleep_confirm_resp(
adapter, skb->data,
skb->len);
- return 0;
+ ret = 0;
+ goto exit_restore_skb;
}
- return -1;
+ ret = -1;
+ goto exit_restore_skb;
}
adapter->curr_cmd->resp_skb = skb;
@@ -87,20 +91,22 @@ static int mwifiex_usb_recv(struct mwifiex_adapter *adapter,
case MWIFIEX_USB_TYPE_EVENT:
if (skb->len < sizeof(u32)) {
dev_err(dev, "EVENT: skb->len too small\n");
- return -1;
+ ret = -1;
+ goto exit_restore_skb;
}
skb_copy_from_linear_data(skb, &tmp, sizeof(u32));
adapter->event_cause = le32_to_cpu(tmp);
- skb_pull(skb, sizeof(u32));
dev_dbg(dev, "event_cause %#x\n", adapter->event_cause);
if (skb->len > MAX_EVENT_SIZE) {
dev_err(dev, "EVENT: event body too large\n");
- return -1;
+ ret = -1;
+ goto exit_restore_skb;
}
- skb_copy_from_linear_data(skb, adapter->event_body,
- skb->len);
+ memcpy(adapter->event_body, skb->data +
+ MWIFIEX_EVENT_HEADER_LEN, skb->len);
+
adapter->event_received = true;
adapter->event_skb = skb;
break;
@@ -124,6 +130,12 @@ static int mwifiex_usb_recv(struct mwifiex_adapter *adapter,
}
return -EINPROGRESS;
+
+exit_restore_skb:
+ /* The buffer will be reused for further cmds/events */
+ skb_push(skb, INTF_HEADER_LEN);
+
+ return ret;
}
static void mwifiex_usb_rx_complete(struct urb *urb)
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index f3fc65515857..3fa4d4176993 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -404,6 +404,8 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter)
priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE;
priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE;
+ mwifiex_reset_11n_rx_seq_num(priv);
+
atomic_set(&priv->wmm.tx_pkts_queued, 0);
atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
}
@@ -1221,6 +1223,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
if (!ptr->is_11n_enabled ||
mwifiex_is_ba_stream_setup(priv, ptr, tid) ||
+ priv->wps.session_enable ||
((priv->sec_info.wpa_enabled ||
priv->sec_info.wpa2_enabled) &&
!priv->wpa_is_gtk_set)) {
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
index e15675585fb1..7b751fba7e1f 100644
--- a/drivers/net/wireless/orinoco/cfg.c
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -138,7 +138,7 @@ static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev,
return err;
}
-static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev,
+static int orinoco_scan(struct wiphy *wiphy,
struct cfg80211_scan_request *request)
{
struct orinoco_private *priv = wiphy_priv(wiphy);
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index 82a1cac920bd..f38786e02623 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -422,11 +422,11 @@ static void p54_rx_frame_sent(struct p54_common *priv, struct sk_buff *skb)
* Clear manually, ieee80211_tx_info_clear_status would
* clear the counts too and we need them.
*/
- memset(&info->status.ampdu_ack_len, 0,
+ memset(&info->status.ack_signal, 0,
sizeof(struct ieee80211_tx_info) -
- offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
+ offsetof(struct ieee80211_tx_info, status.ack_signal));
BUILD_BUG_ON(offsetof(struct ieee80211_tx_info,
- status.ampdu_ack_len) != 23);
+ status.ack_signal) != 20);
if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
pad = entry_data->align[0];
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 2e9e6af21362..241162e8111d 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -484,7 +484,7 @@ static int rndis_change_virtual_intf(struct wiphy *wiphy,
enum nl80211_iftype type, u32 *flags,
struct vif_params *params);
-static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
+static int rndis_scan(struct wiphy *wiphy,
struct cfg80211_scan_request *request);
static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed);
@@ -1941,9 +1941,10 @@ static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm)
}
#define SCAN_DELAY_JIFFIES (6 * HZ)
-static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
+static int rndis_scan(struct wiphy *wiphy,
struct cfg80211_scan_request *request)
{
+ struct net_device *dev = request->wdev->netdev;
struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
int ret;
@@ -2110,7 +2111,7 @@ resize_buf:
while (check_bssid_list_item(bssid, bssid_len, buf, len)) {
if (rndis_bss_info_update(usbdev, bssid) && match_bssid &&
matched) {
- if (!ether_addr_equal(bssid->mac, match_bssid))
+ if (ether_addr_equal(bssid->mac, match_bssid))
*matched = true;
}
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index 299c3879582d..c7548da6573d 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -99,6 +99,14 @@ config RT2800PCI_RT53XX
rt2800pci driver.
Supported chips: RT5390
+config RT2800PCI_RT3290
+ bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ default y
+ ---help---
+ This adds support for rt3290 wireless chipset family to the
+ rt2800pci driver.
+ Supported chips: RT3290
endif
config RT2500USB
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index 1ca88cdc6ece..e252e9bafd0e 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -68,6 +68,7 @@
#define RF3320 0x000b
#define RF3322 0x000c
#define RF3053 0x000d
+#define RF3290 0x3290
#define RF5360 0x5360
#define RF5370 0x5370
#define RF5372 0x5372
@@ -117,6 +118,12 @@
* Registers.
*/
+
+/*
+ * MAC_CSR0_3290: MAC_CSR0 for RT3290 to identity MAC version number.
+ */
+#define MAC_CSR0_3290 0x0000
+
/*
* E2PROM_CSR: PCI EEPROM control register.
* RELOAD: Write 1 to reload eeprom content.
@@ -133,6 +140,150 @@
#define E2PROM_CSR_RELOAD FIELD32(0x00000080)
/*
+ * CMB_CTRL_CFG
+ */
+#define CMB_CTRL 0x0020
+#define AUX_OPT_BIT0 FIELD32(0x00000001)
+#define AUX_OPT_BIT1 FIELD32(0x00000002)
+#define AUX_OPT_BIT2 FIELD32(0x00000004)
+#define AUX_OPT_BIT3 FIELD32(0x00000008)
+#define AUX_OPT_BIT4 FIELD32(0x00000010)
+#define AUX_OPT_BIT5 FIELD32(0x00000020)
+#define AUX_OPT_BIT6 FIELD32(0x00000040)
+#define AUX_OPT_BIT7 FIELD32(0x00000080)
+#define AUX_OPT_BIT8 FIELD32(0x00000100)
+#define AUX_OPT_BIT9 FIELD32(0x00000200)
+#define AUX_OPT_BIT10 FIELD32(0x00000400)
+#define AUX_OPT_BIT11 FIELD32(0x00000800)
+#define AUX_OPT_BIT12 FIELD32(0x00001000)
+#define AUX_OPT_BIT13 FIELD32(0x00002000)
+#define AUX_OPT_BIT14 FIELD32(0x00004000)
+#define AUX_OPT_BIT15 FIELD32(0x00008000)
+#define LDO25_LEVEL FIELD32(0x00030000)
+#define LDO25_LARGEA FIELD32(0x00040000)
+#define LDO25_FRC_ON FIELD32(0x00080000)
+#define CMB_RSV FIELD32(0x00300000)
+#define XTAL_RDY FIELD32(0x00400000)
+#define PLL_LD FIELD32(0x00800000)
+#define LDO_CORE_LEVEL FIELD32(0x0F000000)
+#define LDO_BGSEL FIELD32(0x30000000)
+#define LDO3_EN FIELD32(0x40000000)
+#define LDO0_EN FIELD32(0x80000000)
+
+/*
+ * EFUSE_CSR_3290: RT3290 EEPROM
+ */
+#define EFUSE_CTRL_3290 0x0024
+
+/*
+ * EFUSE_DATA3 of 3290
+ */
+#define EFUSE_DATA3_3290 0x0028
+
+/*
+ * EFUSE_DATA2 of 3290
+ */
+#define EFUSE_DATA2_3290 0x002c
+
+/*
+ * EFUSE_DATA1 of 3290
+ */
+#define EFUSE_DATA1_3290 0x0030
+
+/*
+ * EFUSE_DATA0 of 3290
+ */
+#define EFUSE_DATA0_3290 0x0034
+
+/*
+ * OSC_CTRL_CFG
+ * Ring oscillator configuration
+ */
+#define OSC_CTRL 0x0038
+#define OSC_REF_CYCLE FIELD32(0x00001fff)
+#define OSC_RSV FIELD32(0x0000e000)
+#define OSC_CAL_CNT FIELD32(0x0fff0000)
+#define OSC_CAL_ACK FIELD32(0x10000000)
+#define OSC_CLK_32K_VLD FIELD32(0x20000000)
+#define OSC_CAL_REQ FIELD32(0x40000000)
+#define OSC_ROSC_EN FIELD32(0x80000000)
+
+/*
+ * COEX_CFG_0
+ */
+#define COEX_CFG0 0x0040
+#define COEX_CFG_ANT FIELD32(0xff000000)
+/*
+ * COEX_CFG_1
+ */
+#define COEX_CFG1 0x0044
+
+/*
+ * COEX_CFG_2
+ */
+#define COEX_CFG2 0x0048
+#define BT_COEX_CFG1 FIELD32(0xff000000)
+#define BT_COEX_CFG0 FIELD32(0x00ff0000)
+#define WL_COEX_CFG1 FIELD32(0x0000ff00)
+#define WL_COEX_CFG0 FIELD32(0x000000ff)
+/*
+ * PLL_CTRL_CFG
+ * PLL configuration register
+ */
+#define PLL_CTRL 0x0050
+#define PLL_RESERVED_INPUT1 FIELD32(0x000000ff)
+#define PLL_RESERVED_INPUT2 FIELD32(0x0000ff00)
+#define PLL_CONTROL FIELD32(0x00070000)
+#define PLL_LPF_R1 FIELD32(0x00080000)
+#define PLL_LPF_C1_CTRL FIELD32(0x00300000)
+#define PLL_LPF_C2_CTRL FIELD32(0x00c00000)
+#define PLL_CP_CURRENT_CTRL FIELD32(0x03000000)
+#define PLL_PFD_DELAY_CTRL FIELD32(0x0c000000)
+#define PLL_LOCK_CTRL FIELD32(0x70000000)
+#define PLL_VBGBK_EN FIELD32(0x80000000)
+
+
+/*
+ * WLAN_CTRL_CFG
+ * RT3290 wlan configuration
+ */
+#define WLAN_FUN_CTRL 0x0080
+#define WLAN_EN FIELD32(0x00000001)
+#define WLAN_CLK_EN FIELD32(0x00000002)
+#define WLAN_RSV1 FIELD32(0x00000004)
+#define WLAN_RESET FIELD32(0x00000008)
+#define PCIE_APP0_CLK_REQ FIELD32(0x00000010)
+#define FRC_WL_ANT_SET FIELD32(0x00000020)
+#define INV_TR_SW0 FIELD32(0x00000040)
+#define WLAN_GPIO_IN_BIT0 FIELD32(0x00000100)
+#define WLAN_GPIO_IN_BIT1 FIELD32(0x00000200)
+#define WLAN_GPIO_IN_BIT2 FIELD32(0x00000400)
+#define WLAN_GPIO_IN_BIT3 FIELD32(0x00000800)
+#define WLAN_GPIO_IN_BIT4 FIELD32(0x00001000)
+#define WLAN_GPIO_IN_BIT5 FIELD32(0x00002000)
+#define WLAN_GPIO_IN_BIT6 FIELD32(0x00004000)
+#define WLAN_GPIO_IN_BIT7 FIELD32(0x00008000)
+#define WLAN_GPIO_IN_BIT_ALL FIELD32(0x0000ff00)
+#define WLAN_GPIO_OUT_BIT0 FIELD32(0x00010000)
+#define WLAN_GPIO_OUT_BIT1 FIELD32(0x00020000)
+#define WLAN_GPIO_OUT_BIT2 FIELD32(0x00040000)
+#define WLAN_GPIO_OUT_BIT3 FIELD32(0x00050000)
+#define WLAN_GPIO_OUT_BIT4 FIELD32(0x00100000)
+#define WLAN_GPIO_OUT_BIT5 FIELD32(0x00200000)
+#define WLAN_GPIO_OUT_BIT6 FIELD32(0x00400000)
+#define WLAN_GPIO_OUT_BIT7 FIELD32(0x00800000)
+#define WLAN_GPIO_OUT_BIT_ALL FIELD32(0x00ff0000)
+#define WLAN_GPIO_OUT_OE_BIT0 FIELD32(0x01000000)
+#define WLAN_GPIO_OUT_OE_BIT1 FIELD32(0x02000000)
+#define WLAN_GPIO_OUT_OE_BIT2 FIELD32(0x04000000)
+#define WLAN_GPIO_OUT_OE_BIT3 FIELD32(0x08000000)
+#define WLAN_GPIO_OUT_OE_BIT4 FIELD32(0x10000000)
+#define WLAN_GPIO_OUT_OE_BIT5 FIELD32(0x20000000)
+#define WLAN_GPIO_OUT_OE_BIT6 FIELD32(0x40000000)
+#define WLAN_GPIO_OUT_OE_BIT7 FIELD32(0x80000000)
+#define WLAN_GPIO_OUT_OE_BIT_ALL FIELD32(0xff000000)
+
+/*
* AUX_CTRL: Aux/PCI-E related configuration
*/
#define AUX_CTRL 0x10c
@@ -1763,9 +1914,11 @@ struct mac_iveiv_entry {
/*
* BBP 3: RX Antenna
*/
-#define BBP3_RX_ADC FIELD8(0x03)
+#define BBP3_RX_ADC FIELD8(0x03)
#define BBP3_RX_ANTENNA FIELD8(0x18)
#define BBP3_HT40_MINUS FIELD8(0x20)
+#define BBP3_ADC_MODE_SWITCH FIELD8(0x40)
+#define BBP3_ADC_INIT_MODE FIELD8(0x80)
/*
* BBP 4: Bandwidth
@@ -1775,6 +1928,14 @@ struct mac_iveiv_entry {
#define BBP4_MAC_IF_CTRL FIELD8(0x40)
/*
+ * BBP 47: Bandwidth
+ */
+#define BBP47_TSSI_REPORT_SEL FIELD8(0x03)
+#define BBP47_TSSI_UPDATE_REQ FIELD8(0x04)
+#define BBP47_TSSI_TSSI_MODE FIELD8(0x18)
+#define BBP47_TSSI_ADC6 FIELD8(0x80)
+
+/*
* BBP 109
*/
#define BBP109_TX0_POWER FIELD8(0x0f)
@@ -1917,6 +2078,16 @@ struct mac_iveiv_entry {
#define RFCSR27_R4 FIELD8(0x40)
/*
+ * RFCSR 29:
+ */
+#define RFCSR29_ADC6_TEST FIELD8(0x01)
+#define RFCSR29_ADC6_INT_TEST FIELD8(0x02)
+#define RFCSR29_RSSI_RESET FIELD8(0x04)
+#define RFCSR29_RSSI_ON FIELD8(0x08)
+#define RFCSR29_RSSI_RIP_CTRL FIELD8(0x30)
+#define RFCSR29_RSSI_GAIN FIELD8(0xc0)
+
+/*
* RFCSR 30:
*/
#define RFCSR30_TX_H20M FIELD8(0x02)
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 4d3747c3010b..e76f03c9b468 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -354,16 +354,15 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
* of 4kb. Certain USB chipsets however require different firmware,
* which Ralink only provides attached to the original firmware
* file. Thus for USB devices, firmware files have a length
- * which is a multiple of 4kb.
+ * which is a multiple of 4kb. The firmware for rt3290 chip also
+ * have a length which is a multiple of 4kb.
*/
- if (rt2x00_is_usb(rt2x00dev)) {
+ if (rt2x00_is_usb(rt2x00dev) || rt2x00_rt(rt2x00dev, RT3290))
fw_len = 4096;
- multiple = true;
- } else {
+ else
fw_len = 8192;
- multiple = true;
- }
+ multiple = true;
/*
* Validate the firmware length
*/
@@ -415,7 +414,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
return -EBUSY;
if (rt2x00_is_pci(rt2x00dev)) {
- if (rt2x00_rt(rt2x00dev, RT3572) ||
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
+ rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
@@ -851,8 +851,13 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
- return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
+ if (rt2x00_rt(rt2x00dev, RT3290)) {
+ rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+ return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
+ } else {
+ rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+ return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
+ }
}
EXPORT_SYMBOL_GPL(rt2800_rfkill_poll);
@@ -1935,8 +1940,50 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
}
-#define RT5390_POWER_BOUND 0x27
-#define RT5390_FREQ_OFFSET_BOUND 0x5f
+#define POWER_BOUND 0x27
+#define FREQ_OFFSET_BOUND 0x5f
+
+static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_conf *conf,
+ struct rf_channel *rf,
+ struct channel_info *info)
+{
+ u8 rfcsr;
+
+ rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
+ rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
+ rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
+ rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+ if (info->default_power1 > POWER_BOUND)
+ rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND);
+ else
+ rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
+ rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+ if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND)
+ rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND);
+ else
+ rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
+ rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+
+ if (rf->channel <= 14) {
+ if (rf->channel == 6)
+ rt2800_bbp_write(rt2x00dev, 68, 0x0c);
+ else
+ rt2800_bbp_write(rt2x00dev, 68, 0x0b);
+
+ if (rf->channel >= 1 && rf->channel <= 6)
+ rt2800_bbp_write(rt2x00dev, 59, 0x0f);
+ else if (rf->channel >= 7 && rf->channel <= 11)
+ rt2800_bbp_write(rt2x00dev, 59, 0x0e);
+ else if (rf->channel >= 12 && rf->channel <= 14)
+ rt2800_bbp_write(rt2x00dev, 59, 0x0d);
+ }
+}
static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf,
@@ -1952,17 +1999,16 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
- if (info->default_power1 > RT5390_POWER_BOUND)
- rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT5390_POWER_BOUND);
+ if (info->default_power1 > POWER_BOUND)
+ rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND);
else
rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
if (rt2x00_rt(rt2x00dev, RT5392)) {
rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
- if (info->default_power1 > RT5390_POWER_BOUND)
- rt2x00_set_field8(&rfcsr, RFCSR50_TX,
- RT5390_POWER_BOUND);
+ if (info->default_power1 > POWER_BOUND)
+ rt2x00_set_field8(&rfcsr, RFCSR50_TX, POWER_BOUND);
else
rt2x00_set_field8(&rfcsr, RFCSR50_TX,
info->default_power2);
@@ -1981,9 +2027,8 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
- if (rt2x00dev->freq_offset > RT5390_FREQ_OFFSET_BOUND)
- rt2x00_set_field8(&rfcsr, RFCSR17_CODE,
- RT5390_FREQ_OFFSET_BOUND);
+ if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND)
+ rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND);
else
rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
@@ -2036,15 +2081,6 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
}
}
}
-
- rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
- rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
- rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
-
- rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
- rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
}
static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
@@ -2054,7 +2090,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
unsigned int tx_pin;
- u8 bbp;
+ u8 bbp, rfcsr;
if (rf->channel <= 14) {
info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1);
@@ -2075,6 +2111,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
case RF3052:
rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info);
break;
+ case RF3290:
+ rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
+ break;
case RF5360:
case RF5370:
case RF5372:
@@ -2086,6 +2125,22 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
}
+ if (rt2x00_rf(rt2x00dev, RF3290) ||
+ rt2x00_rf(rt2x00dev, RF5360) ||
+ rt2x00_rf(rt2x00dev, RF5370) ||
+ rt2x00_rf(rt2x00dev, RF5372) ||
+ rt2x00_rf(rt2x00dev, RF5390) ||
+ rt2x00_rf(rt2x00dev, RF5392)) {
+ rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
+ rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
+ rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+ }
+
/*
* Change BBP settings
*/
@@ -2566,6 +2621,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
break;
+ case RF3290:
case RF5360:
case RF5370:
case RF5372:
@@ -2701,6 +2757,7 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt(rt2x00dev, RT3070) ||
rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
+ rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3390) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
@@ -2797,10 +2854,54 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
+ if (rt2x00_rt(rt2x00dev, RT3290)) {
+ rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+ if (rt2x00_get_field32(reg, WLAN_EN) == 1) {
+ rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 1);
+ rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
+ }
+
+ rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
+ if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) {
+ rt2x00_set_field32(&reg, LDO0_EN, 1);
+ rt2x00_set_field32(&reg, LDO_BGSEL, 3);
+ rt2800_register_write(rt2x00dev, CMB_CTRL, reg);
+ }
+
+ rt2800_register_read(rt2x00dev, OSC_CTRL, &reg);
+ rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
+ rt2x00_set_field32(&reg, OSC_CAL_REQ, 1);
+ rt2x00_set_field32(&reg, OSC_REF_CYCLE, 0x27);
+ rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
+
+ rt2800_register_read(rt2x00dev, COEX_CFG0, &reg);
+ rt2x00_set_field32(&reg, COEX_CFG_ANT, 0x5e);
+ rt2800_register_write(rt2x00dev, COEX_CFG0, reg);
+
+ rt2800_register_read(rt2x00dev, COEX_CFG2, &reg);
+ rt2x00_set_field32(&reg, BT_COEX_CFG1, 0x00);
+ rt2x00_set_field32(&reg, BT_COEX_CFG0, 0x17);
+ rt2x00_set_field32(&reg, WL_COEX_CFG1, 0x93);
+ rt2x00_set_field32(&reg, WL_COEX_CFG0, 0x7f);
+ rt2800_register_write(rt2x00dev, COEX_CFG2, reg);
+
+ rt2800_register_read(rt2x00dev, PLL_CTRL, &reg);
+ rt2x00_set_field32(&reg, PLL_CONTROL, 1);
+ rt2800_register_write(rt2x00dev, PLL_CTRL, reg);
+ }
+
if (rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
+ rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3390)) {
- rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
+
+ if (rt2x00_rt(rt2x00dev, RT3290))
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0,
+ 0x00000404);
+ else
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0,
+ 0x00000400);
+
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
@@ -3209,14 +3310,16 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_wait_bbp_ready(rt2x00dev)))
return -EACCES;
- if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392)) {
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392)) {
rt2800_bbp_read(rt2x00dev, 4, &value);
rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
rt2800_bbp_write(rt2x00dev, 4, value);
}
if (rt2800_is_305x_soc(rt2x00dev) ||
+ rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
@@ -3225,20 +3328,26 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 65, 0x2c);
rt2800_bbp_write(rt2x00dev, 66, 0x38);
- if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 68, 0x0b);
if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
rt2800_bbp_write(rt2x00dev, 69, 0x16);
rt2800_bbp_write(rt2x00dev, 73, 0x12);
- } else if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392)) {
+ } else if (rt2x00_rt(rt2x00dev, RT3290) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392)) {
rt2800_bbp_write(rt2x00dev, 69, 0x12);
rt2800_bbp_write(rt2x00dev, 73, 0x13);
rt2800_bbp_write(rt2x00dev, 75, 0x46);
rt2800_bbp_write(rt2x00dev, 76, 0x28);
- rt2800_bbp_write(rt2x00dev, 77, 0x59);
+
+ if (rt2x00_rt(rt2x00dev, RT3290))
+ rt2800_bbp_write(rt2x00dev, 77, 0x58);
+ else
+ rt2800_bbp_write(rt2x00dev, 77, 0x59);
} else {
rt2800_bbp_write(rt2x00dev, 69, 0x12);
rt2800_bbp_write(rt2x00dev, 73, 0x10);
@@ -3263,23 +3372,33 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 81, 0x37);
}
+ if (rt2x00_rt(rt2x00dev, RT3290)) {
+ rt2800_bbp_write(rt2x00dev, 74, 0x0b);
+ rt2800_bbp_write(rt2x00dev, 79, 0x18);
+ rt2800_bbp_write(rt2x00dev, 80, 0x09);
+ rt2800_bbp_write(rt2x00dev, 81, 0x33);
+ }
+
rt2800_bbp_write(rt2x00dev, 82, 0x62);
- if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 83, 0x7a);
else
rt2800_bbp_write(rt2x00dev, 83, 0x6a);
if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
rt2800_bbp_write(rt2x00dev, 84, 0x19);
- else if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ else if (rt2x00_rt(rt2x00dev, RT3290) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 84, 0x9a);
else
rt2800_bbp_write(rt2x00dev, 84, 0x99);
- if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 86, 0x38);
else
rt2800_bbp_write(rt2x00dev, 86, 0x00);
@@ -3289,8 +3408,9 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 91, 0x04);
- if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 92, 0x02);
else
rt2800_bbp_write(rt2x00dev, 92, 0x00);
@@ -3304,6 +3424,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||
rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) ||
rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) ||
+ rt2x00_rt(rt2x00dev, RT3290) ||
rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392) ||
@@ -3312,27 +3433,32 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
else
rt2800_bbp_write(rt2x00dev, 103, 0x00);
- if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 104, 0x92);
if (rt2800_is_305x_soc(rt2x00dev))
rt2800_bbp_write(rt2x00dev, 105, 0x01);
+ else if (rt2x00_rt(rt2x00dev, RT3290))
+ rt2800_bbp_write(rt2x00dev, 105, 0x1c);
else if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 105, 0x3c);
else
rt2800_bbp_write(rt2x00dev, 105, 0x05);
- if (rt2x00_rt(rt2x00dev, RT5390))
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
+ rt2x00_rt(rt2x00dev, RT5390))
rt2800_bbp_write(rt2x00dev, 106, 0x03);
else if (rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 106, 0x12);
else
rt2800_bbp_write(rt2x00dev, 106, 0x35);
- if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 128, 0x12);
if (rt2x00_rt(rt2x00dev, RT5392)) {
@@ -3357,6 +3483,29 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 138, value);
}
+ if (rt2x00_rt(rt2x00dev, RT3290)) {
+ rt2800_bbp_write(rt2x00dev, 67, 0x24);
+ rt2800_bbp_write(rt2x00dev, 143, 0x04);
+ rt2800_bbp_write(rt2x00dev, 142, 0x99);
+ rt2800_bbp_write(rt2x00dev, 150, 0x30);
+ rt2800_bbp_write(rt2x00dev, 151, 0x2e);
+ rt2800_bbp_write(rt2x00dev, 152, 0x20);
+ rt2800_bbp_write(rt2x00dev, 153, 0x34);
+ rt2800_bbp_write(rt2x00dev, 154, 0x40);
+ rt2800_bbp_write(rt2x00dev, 155, 0x3b);
+ rt2800_bbp_write(rt2x00dev, 253, 0x04);
+
+ rt2800_bbp_read(rt2x00dev, 47, &value);
+ rt2x00_set_field8(&value, BBP47_TSSI_ADC6, 1);
+ rt2800_bbp_write(rt2x00dev, 47, value);
+
+ /* Use 5-bit ADC for Acquisition and 8-bit ADC for data */
+ rt2800_bbp_read(rt2x00dev, 3, &value);
+ rt2x00_set_field8(&value, BBP3_ADC_MODE_SWITCH, 1);
+ rt2x00_set_field8(&value, BBP3_ADC_INIT_MODE, 1);
+ rt2800_bbp_write(rt2x00dev, 3, value);
+ }
+
if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
int ant, div_mode;
@@ -3489,6 +3638,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
if (!rt2x00_rt(rt2x00dev, RT3070) &&
!rt2x00_rt(rt2x00dev, RT3071) &&
!rt2x00_rt(rt2x00dev, RT3090) &&
+ !rt2x00_rt(rt2x00dev, RT3290) &&
!rt2x00_rt(rt2x00dev, RT3390) &&
!rt2x00_rt(rt2x00dev, RT3572) &&
!rt2x00_rt(rt2x00dev, RT5390) &&
@@ -3499,8 +3649,9 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
/*
* Init RF calibration.
*/
- if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392)) {
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392)) {
rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
@@ -3538,6 +3689,53 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);
+ } else if (rt2x00_rt(rt2x00dev, RT3290)) {
+ rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
+ rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
+ rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
+ rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
+ rt2800_rfcsr_write(rt2x00dev, 8, 0xf3);
+ rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
+ rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
+ rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
+ rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
+ rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
+ rt2800_rfcsr_write(rt2x00dev, 18, 0x02);
+ rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x83);
+ rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
+ rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
+ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+ rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
+ rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 34, 0x05);
+ rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
+ rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
+ rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
+ rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
+ rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
+ rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
+ rt2800_rfcsr_write(rt2x00dev, 43, 0x7b);
+ rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
+ rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
+ rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
+ rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
+ rt2800_rfcsr_write(rt2x00dev, 49, 0x98);
+ rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
+ rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
+ rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
+ rt2800_rfcsr_write(rt2x00dev, 56, 0x02);
+ rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
+ rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
+ rt2800_rfcsr_write(rt2x00dev, 59, 0x09);
+ rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
+ rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
} else if (rt2x00_rt(rt2x00dev, RT3390)) {
rt2800_rfcsr_write(rt2x00dev, 0, 0xa0);
rt2800_rfcsr_write(rt2x00dev, 1, 0xe1);
@@ -3946,6 +4144,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 27, rfcsr);
}
+ if (rt2x00_rt(rt2x00dev, RT3290)) {
+ rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR29_RSSI_GAIN, 3);
+ rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
+ }
+
if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr);
@@ -4052,9 +4256,14 @@ EXPORT_SYMBOL_GPL(rt2800_disable_radio);
int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
+ u16 efuse_ctrl_reg;
- rt2800_register_read(rt2x00dev, EFUSE_CTRL, &reg);
+ if (rt2x00_rt(rt2x00dev, RT3290))
+ efuse_ctrl_reg = EFUSE_CTRL_3290;
+ else
+ efuse_ctrl_reg = EFUSE_CTRL;
+ rt2800_register_read(rt2x00dev, efuse_ctrl_reg, &reg);
return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
}
EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
@@ -4062,27 +4271,44 @@ EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
{
u32 reg;
-
+ u16 efuse_ctrl_reg;
+ u16 efuse_data0_reg;
+ u16 efuse_data1_reg;
+ u16 efuse_data2_reg;
+ u16 efuse_data3_reg;
+
+ if (rt2x00_rt(rt2x00dev, RT3290)) {
+ efuse_ctrl_reg = EFUSE_CTRL_3290;
+ efuse_data0_reg = EFUSE_DATA0_3290;
+ efuse_data1_reg = EFUSE_DATA1_3290;
+ efuse_data2_reg = EFUSE_DATA2_3290;
+ efuse_data3_reg = EFUSE_DATA3_3290;
+ } else {
+ efuse_ctrl_reg = EFUSE_CTRL;
+ efuse_data0_reg = EFUSE_DATA0;
+ efuse_data1_reg = EFUSE_DATA1;
+ efuse_data2_reg = EFUSE_DATA2;
+ efuse_data3_reg = EFUSE_DATA3;
+ }
mutex_lock(&rt2x00dev->csr_mutex);
- rt2800_register_read_lock(rt2x00dev, EFUSE_CTRL, &reg);
+ rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, &reg);
rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
- rt2800_register_write_lock(rt2x00dev, EFUSE_CTRL, reg);
+ rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);
/* Wait until the EEPROM has been loaded */
- rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, &reg);
-
+ rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, &reg);
/* Apparently the data is read from end to start */
- rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, &reg);
+ rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, &reg);
/* The returned value is in CPU order, but eeprom is le */
*(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
- rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, &reg);
+ rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, &reg);
*(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
- rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, &reg);
+ rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, &reg);
*(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
- rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, &reg);
+ rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, &reg);
*(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);
mutex_unlock(&rt2x00dev->csr_mutex);
@@ -4244,9 +4470,14 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
* RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field
* RT53xx: defined in "EEPROM_CHIP_ID" field
*/
- rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
- if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 ||
- rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392)
+ if (rt2x00_rt(rt2x00dev, RT3290))
+ rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
+ else
+ rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+
+ if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT3290 ||
+ rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 ||
+ rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392)
rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value);
else
value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
@@ -4261,6 +4492,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
case RT3070:
case RT3071:
case RT3090:
+ case RT3290:
case RT3390:
case RT3572:
case RT5390:
@@ -4281,6 +4513,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
case RF3021:
case RF3022:
case RF3052:
+ case RF3290:
case RF3320:
case RF5360:
case RF5370:
@@ -4597,6 +4830,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
rt2x00_rf(rt2x00dev, RF2020) ||
rt2x00_rf(rt2x00dev, RF3021) ||
rt2x00_rf(rt2x00dev, RF3022) ||
+ rt2x00_rf(rt2x00dev, RF3290) ||
rt2x00_rf(rt2x00dev, RF3320) ||
rt2x00_rf(rt2x00dev, RF5360) ||
rt2x00_rf(rt2x00dev, RF5370) ||
@@ -4685,6 +4919,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
case RF3022:
case RF3320:
case RF3052:
+ case RF3290:
case RF5360:
case RF5370:
case RF5372:
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 206158b67426..235376e9cb04 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -280,7 +280,13 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
*/
static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
{
- return FIRMWARE_RT2860;
+ /*
+ * Chip rt3290 use specific 4KB firmware named rt3290.bin.
+ */
+ if (rt2x00_rt(rt2x00dev, RT3290))
+ return FIRMWARE_RT3290;
+ else
+ return FIRMWARE_RT2860;
}
static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
@@ -974,6 +980,66 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
return rt2800_validate_eeprom(rt2x00dev);
}
+static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
+{
+ u32 reg;
+ int i, count;
+
+ rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+ if (rt2x00_get_field32(reg, WLAN_EN))
+ return 0;
+
+ rt2x00_set_field32(&reg, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
+ rt2x00_set_field32(&reg, FRC_WL_ANT_SET, 1);
+ rt2x00_set_field32(&reg, WLAN_CLK_EN, 0);
+ rt2x00_set_field32(&reg, WLAN_EN, 1);
+ rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
+
+ udelay(REGISTER_BUSY_DELAY);
+
+ count = 0;
+ do {
+ /*
+ * Check PLL_LD & XTAL_RDY.
+ */
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+ rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
+ if (rt2x00_get_field32(reg, PLL_LD) &&
+ rt2x00_get_field32(reg, XTAL_RDY))
+ break;
+ udelay(REGISTER_BUSY_DELAY);
+ }
+
+ if (i >= REGISTER_BUSY_COUNT) {
+
+ if (count >= 10)
+ return -EIO;
+
+ rt2800_register_write(rt2x00dev, 0x58, 0x018);
+ udelay(REGISTER_BUSY_DELAY);
+ rt2800_register_write(rt2x00dev, 0x58, 0x418);
+ udelay(REGISTER_BUSY_DELAY);
+ rt2800_register_write(rt2x00dev, 0x58, 0x618);
+ udelay(REGISTER_BUSY_DELAY);
+ count++;
+ } else {
+ count = 0;
+ }
+
+ rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+ rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 0);
+ rt2x00_set_field32(&reg, WLAN_CLK_EN, 1);
+ rt2x00_set_field32(&reg, WLAN_RESET, 1);
+ rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
+ udelay(10);
+ rt2x00_set_field32(&reg, WLAN_RESET, 0);
+ rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
+ udelay(10);
+ rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff);
+ } while (count != 0);
+
+ return 0;
+}
static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
@@ -997,6 +1063,17 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
return retval;
/*
+ * In probe phase call rt2800_enable_wlan_rt3290 to enable wlan
+ * clk for rt3290. That avoid the MCU fail in start phase.
+ */
+ if (rt2x00_rt(rt2x00dev, RT3290)) {
+ retval = rt2800_enable_wlan_rt3290(rt2x00dev);
+
+ if (retval)
+ return retval;
+ }
+
+ /*
* This device has multiple filters for control frames
* and has a separate filter for PS Poll frames.
*/
@@ -1175,6 +1252,9 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
{ PCI_DEVICE(0x1432, 0x7768) },
{ PCI_DEVICE(0x1462, 0x891a) },
{ PCI_DEVICE(0x1a3b, 0x1059) },
+#ifdef CONFIG_RT2800PCI_RT3290
+ { PCI_DEVICE(0x1814, 0x3290) },
+#endif
#ifdef CONFIG_RT2800PCI_RT33XX
{ PCI_DEVICE(0x1814, 0x3390) },
#endif
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h
index 70e050d904c8..ab22a087c50d 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.h
+++ b/drivers/net/wireless/rt2x00/rt2800pci.h
@@ -47,6 +47,7 @@
* 8051 firmware image.
*/
#define FIRMWARE_RT2860 "rt2860.bin"
+#define FIRMWARE_RT3290 "rt3290.bin"
#define FIRMWARE_IMAGE_BASE 0x2000
/*
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 20a504072895..6cf336595e25 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -971,6 +971,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0411, 0x015d) },
{ USB_DEVICE(0x0411, 0x016f) },
{ USB_DEVICE(0x0411, 0x01a2) },
+ { USB_DEVICE(0x0411, 0x01ee) },
/* Corega */
{ USB_DEVICE(0x07aa, 0x002f) },
{ USB_DEVICE(0x07aa, 0x003c) },
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 8f754025b06e..8afb546c2b2d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -187,6 +187,7 @@ struct rt2x00_chip {
#define RT3070 0x3070
#define RT3071 0x3071
#define RT3090 0x3090 /* 2.4GHz PCIe */
+#define RT3290 0x3290
#define RT3390 0x3390
#define RT3572 0x3572
#define RT3593 0x3593
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index e7361d913e8e..49a63e973934 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -102,7 +102,7 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
/* Update the AID, this is needed for dynamic PS support */
rt2x00dev->aid = bss_conf->assoc ? bss_conf->aid : 0;
- rt2x00dev->last_beacon = bss_conf->last_tsf;
+ rt2x00dev->last_beacon = bss_conf->sync_tsf;
/* Update global beacon interval time, this is needed for PS support */
rt2x00dev->beacon_int = bss_conf->beacon_int;
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 0a4653a92cab..a0c8caef3b0a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -256,6 +256,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
struct ieee80211_hw *hw;
struct rt2x00_dev *rt2x00dev;
int retval;
+ u16 chip;
retval = pci_enable_device(pci_dev);
if (retval) {
@@ -305,6 +306,14 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
if (retval)
goto exit_free_device;
+ /*
+ * Because rt3290 chip use different efuse offset to read efuse data.
+ * So before read efuse it need to indicate it is the
+ * rt3290 or not.
+ */
+ pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip);
+ rt2x00dev->chip.rt = chip;
+
retval = rt2x00lib_probe_dev(rt2x00dev);
if (retval)
goto exit_free_reg;
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 2fd830103415..f7e74a0a7759 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -774,9 +774,7 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
bool rt2x00queue_for_each_entry(struct data_queue *queue,
enum queue_index start,
enum queue_index end,
- void *data,
- bool (*fn)(struct queue_entry *entry,
- void *data))
+ bool (*fn)(struct queue_entry *entry))
{
unsigned long irqflags;
unsigned int index_start;
@@ -807,17 +805,17 @@ bool rt2x00queue_for_each_entry(struct data_queue *queue,
*/
if (index_start < index_end) {
for (i = index_start; i < index_end; i++) {
- if (fn(&queue->entries[i], data))
+ if (fn(&queue->entries[i]))
return true;
}
} else {
for (i = index_start; i < queue->limit; i++) {
- if (fn(&queue->entries[i], data))
+ if (fn(&queue->entries[i]))
return true;
}
for (i = 0; i < index_end; i++) {
- if (fn(&queue->entries[i], data))
+ if (fn(&queue->entries[i]))
return true;
}
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 5f1392c72673..9b8c10a86dee 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -584,7 +584,6 @@ struct data_queue_desc {
* @queue: Pointer to @data_queue
* @start: &enum queue_index Pointer to start index
* @end: &enum queue_index Pointer to end index
- * @data: Data to pass to the callback function
* @fn: The function to call for each &struct queue_entry
*
* This will walk through all entries in the queue, in chronological
@@ -597,9 +596,7 @@ struct data_queue_desc {
bool rt2x00queue_for_each_entry(struct data_queue *queue,
enum queue_index start,
enum queue_index end,
- void *data,
- bool (*fn)(struct queue_entry *entry,
- void *data));
+ bool (*fn)(struct queue_entry *entry));
/**
* rt2x00queue_empty - Check if the queue is empty.
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index d357d1ed92f6..40ea80725a96 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -285,7 +285,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
}
-static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data)
+static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
@@ -390,7 +390,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work);
}
-static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data)
+static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
@@ -427,18 +427,12 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
case QID_AC_BE:
case QID_AC_BK:
if (!rt2x00queue_empty(queue))
- rt2x00queue_for_each_entry(queue,
- Q_INDEX_DONE,
- Q_INDEX,
- NULL,
+ rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
rt2x00usb_kick_tx_entry);
break;
case QID_RX:
if (!rt2x00queue_full(queue))
- rt2x00queue_for_each_entry(queue,
- Q_INDEX_DONE,
- Q_INDEX,
- NULL,
+ rt2x00queue_for_each_entry(queue, Q_INDEX, Q_INDEX_DONE,
rt2x00usb_kick_rx_entry);
break;
default:
@@ -447,7 +441,7 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
}
EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue);
-static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data)
+static bool rt2x00usb_flush_entry(struct queue_entry *entry)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
@@ -474,7 +468,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue, bool drop)
unsigned int i;
if (drop)
- rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL,
+ rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
rt2x00usb_flush_entry);
/*
@@ -565,7 +559,7 @@ void rt2x00usb_clear_entry(struct queue_entry *entry)
entry->flags = 0;
if (entry->queue->qid == QID_RX)
- rt2x00usb_kick_rx_entry(entry, NULL);
+ rt2x00usb_kick_rx_entry(entry);
}
EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index 2bebcb71a1e9..3b505395d869 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -47,6 +47,8 @@ static DEFINE_PCI_DEVICE_TABLE(rtl8180_table) = {
{ PCI_DEVICE(0x1799, 0x6001) },
{ PCI_DEVICE(0x1799, 0x6020) },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x3300) },
+ { PCI_DEVICE(0x1186, 0x3301) },
+ { PCI_DEVICE(0x1432, 0x7106) },
{ }
};
diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c
index 3d8cc4a0c86d..6a2d72beb00d 100644
--- a/drivers/net/wireless/rtlwifi/cam.c
+++ b/drivers/net/wireless/rtlwifi/cam.c
@@ -128,7 +128,7 @@ u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr,
u32 us_config;
struct rtl_priv *rtlpriv = rtl_priv(hw);
- RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
"EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, ulUseDK=%x MacAddr %pM\n",
ul_entry_idx, ul_key_id, ul_enc_alg,
ul_default_key, mac_addr);
@@ -342,7 +342,8 @@ void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr)
/* Remove from HW Security CAM */
memset(rtlpriv->sec.hwsec_cam_sta_addr[i], 0, ETH_ALEN);
rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i);
- pr_info("&&&&&&&&&del entry %d\n", i);
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+ "del CAM entry %d\n", i);
}
}
return;
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 2062ea1d7c80..36bffbc4519e 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -1273,17 +1273,18 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
*after reset, release previous pending packet,
*and force the tx idx to the first one
*/
- spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) {
if (rtlpci->tx_ring[i].desc) {
struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[i];
while (skb_queue_len(&ring->queue)) {
- struct rtl_tx_desc *entry =
- &ring->desc[ring->idx];
- struct sk_buff *skb =
- __skb_dequeue(&ring->queue);
+ struct rtl_tx_desc *entry;
+ struct sk_buff *skb;
+ spin_lock_irqsave(&rtlpriv->locks.irq_th_lock,
+ flags);
+ entry = &ring->desc[ring->idx];
+ skb = __skb_dequeue(&ring->queue);
pci_unmap_single(rtlpci->pdev,
rtlpriv->cfg->ops->
get_desc((u8 *)
@@ -1291,15 +1292,15 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
true,
HW_DESC_TXBUFF_ADDR),
skb->len, PCI_DMA_TODEVICE);
- kfree_skb(skb);
ring->idx = (ring->idx + 1) % ring->entries;
+ spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock,
+ flags);
+ kfree_skb(skb);
}
ring->idx = 0;
}
}
- spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
-
return 0;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
index d228358e6a40..9970c2b1b199 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
@@ -301,9 +301,11 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
{RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
{RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
{RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/
+ {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/
{RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
{RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
{RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/
+ {RTL_USB_DEVICE(0x4856, 0x0091, rtl92cu_hal_cfg)}, /*NetweeN - Feixun*/
/* HP - Lite-On ,8188CUS Slim Combo */
{RTL_USB_DEVICE(0x103c, 0x1629, rtl92cu_hal_cfg)},
{RTL_USB_DEVICE(0x13d3, 0x3357, rtl92cu_hal_cfg)}, /* AzureWave */
@@ -346,6 +348,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
{RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Funai -Abocom*/
{RTL_USB_DEVICE(0x0846, 0x9021, rtl92cu_hal_cfg)}, /*Netgear-Sercomm*/
{RTL_USB_DEVICE(0x0b05, 0x17ab, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/
+ {RTL_USB_DEVICE(0x0bda, 0x8186, rtl92cu_hal_cfg)}, /*Realtek 92CE-VAU*/
{RTL_USB_DEVICE(0x0df6, 0x0061, rtl92cu_hal_cfg)}, /*Sitecom-Edimax*/
{RTL_USB_DEVICE(0x0e66, 0x0019, rtl92cu_hal_cfg)}, /*Hawking-Edimax*/
{RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
index 8d7099bc472c..b917a2a3caf7 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
@@ -1247,6 +1247,9 @@ static void _rtl92s_phy_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
/* Read HT 40 OFDM TX power */
ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_2s[0][index];
ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_2s[1][index];
+ } else {
+ ofdmpowerLevel[0] = 0;
+ ofdmpowerLevel[1] = 0;
}
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
index 730bcc919529..ad4b4803482d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
@@ -29,7 +29,6 @@
#include "../wifi.h"
#include "../core.h"
-#include "../pci.h"
#include "../base.h"
#include "../pci.h"
#include "reg.h"
diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
index ad87a1ac6462..db6430c1a084 100644
--- a/drivers/net/wireless/ti/wl1251/acx.c
+++ b/drivers/net/wireless/ti/wl1251/acx.c
@@ -869,7 +869,7 @@ int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime)
}
*mactime = tsf_info->current_tsf_lsb |
- (tsf_info->current_tsf_msb << 31);
+ ((u64)tsf_info->current_tsf_msb << 32);
out:
kfree(tsf_info);
diff --git a/drivers/net/wireless/ti/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c
index d14d69d733a0..6822b845efc1 100644
--- a/drivers/net/wireless/ti/wl1251/cmd.c
+++ b/drivers/net/wireless/ti/wl1251/cmd.c
@@ -277,15 +277,6 @@ int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
join->rx_config_options = wl->rx_config;
join->rx_filter_options = wl->rx_filter;
- /*
- * FIXME: disable temporarily all filters because after commit
- * 9cef8737 "mac80211: fix managed mode BSSID handling" broke
- * association. The filter logic needs to be implemented properly
- * and once that is done, this hack can be removed.
- */
- join->rx_config_options = 0;
- join->rx_filter_options = WL1251_DEFAULT_RX_FILTER;
-
join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;
diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c
index 9f15ccaf8f05..5ec50a476a69 100644
--- a/drivers/net/wireless/ti/wl1251/event.c
+++ b/drivers/net/wireless/ti/wl1251/event.c
@@ -76,8 +76,7 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
}
}
- if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID &&
- wl->station_mode != STATION_ACTIVE_MODE) {
+ if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) {
wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");
/* indicate to the stack, that beacons have been lost */
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index d1afb8e3b2ef..3118c425bcf1 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -334,6 +334,12 @@ static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel,
if (ret < 0)
goto out;
+ /*
+ * Join command applies filters, and if we are not associated,
+ * BSSID filter must be disabled for association to work.
+ */
+ if (is_zero_ether_addr(wl->bssid))
+ wl->rx_config &= ~CFG_BSSID_FILTER_EN;
ret = wl1251_cmd_join(wl, bss_type, channel, beacon_interval,
dtim_period);
@@ -348,33 +354,6 @@ out:
return ret;
}
-static void wl1251_filter_work(struct work_struct *work)
-{
- struct wl1251 *wl =
- container_of(work, struct wl1251, filter_work);
- int ret;
-
- mutex_lock(&wl->mutex);
-
- if (wl->state == WL1251_STATE_OFF)
- goto out;
-
- ret = wl1251_ps_elp_wakeup(wl);
- if (ret < 0)
- goto out;
-
- ret = wl1251_join(wl, wl->bss_type, wl->channel, wl->beacon_int,
- wl->dtim_period);
- if (ret < 0)
- goto out_sleep;
-
-out_sleep:
- wl1251_ps_elp_sleep(wl);
-
-out:
- mutex_unlock(&wl->mutex);
-}
-
static void wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct wl1251 *wl = hw->priv;
@@ -478,7 +457,6 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
cancel_work_sync(&wl->irq_work);
cancel_work_sync(&wl->tx_work);
- cancel_work_sync(&wl->filter_work);
cancel_delayed_work_sync(&wl->elp_work);
mutex_lock(&wl->mutex);
@@ -681,13 +659,15 @@ out:
FIF_FCSFAIL | \
FIF_BCN_PRBRESP_PROMISC | \
FIF_CONTROL | \
- FIF_OTHER_BSS)
+ FIF_OTHER_BSS | \
+ FIF_PROBE_REQ)
static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed,
unsigned int *total,u64 multicast)
{
struct wl1251 *wl = hw->priv;
+ int ret;
wl1251_debug(DEBUG_MAC80211, "mac80211 configure filter");
@@ -698,7 +678,7 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
/* no filters which we support changed */
return;
- /* FIXME: wl->rx_config and wl->rx_filter are not protected */
+ mutex_lock(&wl->mutex);
wl->rx_config = WL1251_DEFAULT_RX_CONFIG;
wl->rx_filter = WL1251_DEFAULT_RX_FILTER;
@@ -721,15 +701,25 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
}
if (*total & FIF_CONTROL)
wl->rx_filter |= CFG_RX_CTL_EN;
- if (*total & FIF_OTHER_BSS)
- wl->rx_filter &= ~CFG_BSSID_FILTER_EN;
+ if (*total & FIF_OTHER_BSS || is_zero_ether_addr(wl->bssid))
+ wl->rx_config &= ~CFG_BSSID_FILTER_EN;
+ if (*total & FIF_PROBE_REQ)
+ wl->rx_filter |= CFG_RX_PREQ_EN;
- /*
- * FIXME: workqueues need to be properly cancelled on stop(), for
- * now let's just disable changing the filter settings. They will
- * be updated any on config().
- */
- /* schedule_work(&wl->filter_work); */
+ if (wl->state == WL1251_STATE_OFF)
+ goto out;
+
+ ret = wl1251_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ /* send filters to firmware */
+ wl1251_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
+
+ wl1251_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
}
/* HW encryption */
@@ -1390,7 +1380,6 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
skb_queue_head_init(&wl->tx_queue);
- INIT_WORK(&wl->filter_work, wl1251_filter_work);
INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work);
wl->channel = WL1251_DEFAULT_CHANNEL;
wl->scanning = false;
diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c
index 87f6305bda2c..567660cd2fcd 100644
--- a/drivers/net/wireless/ti/wl1251/spi.c
+++ b/drivers/net/wireless/ti/wl1251/spi.c
@@ -73,6 +73,8 @@ static void wl1251_spi_reset(struct wl1251 *wl)
spi_sync(wl_to_spi(wl), &m);
wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
+
+ kfree(cmd);
}
static void wl1251_spi_wake(struct wl1251 *wl)
@@ -127,6 +129,8 @@ static void wl1251_spi_wake(struct wl1251 *wl)
spi_sync(wl_to_spi(wl), &m);
wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
+
+ kfree(cmd);
}
static void wl1251_spi_reset_wake(struct wl1251 *wl)
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h
index 9d8f5816c6f9..fd02060038de 100644
--- a/drivers/net/wireless/ti/wl1251/wl1251.h
+++ b/drivers/net/wireless/ti/wl1251/wl1251.h
@@ -315,7 +315,6 @@ struct wl1251 {
bool tx_queue_stopped;
struct work_struct tx_work;
- struct work_struct filter_work;
/* Pending TX frames */
struct sk_buff *tx_frames[16];
diff --git a/drivers/net/wireless/ti/wl12xx/cmd.c b/drivers/net/wireless/ti/wl12xx/cmd.c
index 50ba7480b790..30be784a40d8 100644
--- a/drivers/net/wireless/ti/wl12xx/cmd.c
+++ b/drivers/net/wireless/ti/wl12xx/cmd.c
@@ -174,7 +174,7 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs;
struct wl1271_radio_parms_cmd *radio_parms;
struct wl1271_ini_general_params *gp = &nvs->general_params;
- int ret;
+ int ret, fem_idx;
if (!wl->nvs)
return -ENODEV;
@@ -185,11 +185,13 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
+ fem_idx = WL12XX_FEM_TO_NVS_ENTRY(gp->tx_bip_fem_manufacturer);
+
/* 2.4GHz parameters */
memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2,
sizeof(struct wl1271_ini_band_params_2));
memcpy(&radio_parms->dyn_params_2,
- &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params,
+ &nvs->dyn_radio_params_2[fem_idx].params,
sizeof(struct wl1271_ini_fem_params_2));
/* 5GHz parameters */
@@ -197,7 +199,7 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
&nvs->stat_radio_params_5,
sizeof(struct wl1271_ini_band_params_5));
memcpy(&radio_parms->dyn_params_5,
- &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params,
+ &nvs->dyn_radio_params_5[fem_idx].params,
sizeof(struct wl1271_ini_fem_params_5));
wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
@@ -216,7 +218,7 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl)
struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs;
struct wl128x_radio_parms_cmd *radio_parms;
struct wl128x_ini_general_params *gp = &nvs->general_params;
- int ret;
+ int ret, fem_idx;
if (!wl->nvs)
return -ENODEV;
@@ -227,11 +229,13 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl)
radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
+ fem_idx = WL12XX_FEM_TO_NVS_ENTRY(gp->tx_bip_fem_manufacturer);
+
/* 2.4GHz parameters */
memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2,
sizeof(struct wl128x_ini_band_params_2));
memcpy(&radio_parms->dyn_params_2,
- &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params,
+ &nvs->dyn_radio_params_2[fem_idx].params,
sizeof(struct wl128x_ini_fem_params_2));
/* 5GHz parameters */
@@ -239,7 +243,7 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl)
&nvs->stat_radio_params_5,
sizeof(struct wl128x_ini_band_params_5));
memcpy(&radio_parms->dyn_params_5,
- &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params,
+ &nvs->dyn_radio_params_5[fem_idx].params,
sizeof(struct wl128x_ini_fem_params_5));
radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options;
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 85d1600ee340..3d6c71b7a3c7 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -242,10 +242,11 @@ static struct wlcore_conf wl12xx_conf = {
.psm_entry_retries = 8,
.psm_exit_retries = 16,
.psm_entry_nullfunc_retries = 3,
- .dynamic_ps_timeout = 200,
+ .dynamic_ps_timeout = 1500,
.forced_ps = false,
.keep_alive_interval = 55000,
.max_listen_interval = 20,
+ .sta_sleep_auth = WL1271_PSM_ILLEGAL,
},
.itrim = {
.enable = false,
@@ -589,16 +590,18 @@ static const int wl12xx_rtable[REG_TABLE_LEN] = {
};
/* TODO: maybe move to a new header file? */
-#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin"
-#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin"
-#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin"
+#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-5-mr.bin"
+#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-5-sr.bin"
+#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-5-plt.bin"
-#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin"
-#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin"
-#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin"
+#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-5-mr.bin"
+#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-5-sr.bin"
+#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-5-plt.bin"
-static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
+static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
{
+ int ret;
+
if (wl->chip.id != CHIP_ID_1283_PG20) {
struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
struct wl127x_rx_mem_pool_addr rx_mem_addr;
@@ -615,9 +618,13 @@ static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
rx_mem_addr.addr_extra = rx_mem_addr.addr + 4;
- wl1271_write(wl, WL1271_SLV_REG_DATA,
- &rx_mem_addr, sizeof(rx_mem_addr), false);
+ ret = wlcore_write(wl, WL1271_SLV_REG_DATA, &rx_mem_addr,
+ sizeof(rx_mem_addr), false);
+ if (ret < 0)
+ return ret;
}
+
+ return 0;
}
static int wl12xx_identify_chip(struct wl1271 *wl)
@@ -630,6 +637,7 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
wl->chip.id);
wl->quirks |= WLCORE_QUIRK_LEGACY_NVS |
+ WLCORE_QUIRK_DUAL_PROBE_TMPL |
WLCORE_QUIRK_TKIP_HEADER_SPACE;
wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
wl->mr_fw_name = WL127X_FW_NAME_MULTI;
@@ -639,6 +647,9 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
/* read data preparation is only needed by wl127x */
wl->ops->prepare_read = wl127x_prepare_read;
+ wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_VER,
+ WL127X_MAJOR_VER, WL127X_SUBTYPE_VER,
+ WL127X_MINOR_VER);
break;
case CHIP_ID_1271_PG20:
@@ -646,6 +657,7 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
wl->chip.id);
wl->quirks |= WLCORE_QUIRK_LEGACY_NVS |
+ WLCORE_QUIRK_DUAL_PROBE_TMPL |
WLCORE_QUIRK_TKIP_HEADER_SPACE;
wl->plt_fw_name = WL127X_PLT_FW_NAME;
wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
@@ -656,6 +668,9 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
/* read data preparation is only needed by wl127x */
wl->ops->prepare_read = wl127x_prepare_read;
+ wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_VER,
+ WL127X_MAJOR_VER, WL127X_SUBTYPE_VER,
+ WL127X_MINOR_VER);
break;
case CHIP_ID_1283_PG20:
@@ -667,8 +682,12 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
/* wl128x requires TX blocksize alignment */
wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN |
+ WLCORE_QUIRK_DUAL_PROBE_TMPL |
WLCORE_QUIRK_TKIP_HEADER_SPACE;
+ wlcore_set_min_fw_ver(wl, WL128X_CHIP_VER, WL128X_IFTYPE_VER,
+ WL128X_MAJOR_VER, WL128X_SUBTYPE_VER,
+ WL128X_MINOR_VER);
break;
case CHIP_ID_1283_PG10:
default:
@@ -681,64 +700,95 @@ out:
return ret;
}
-static void wl12xx_top_reg_write(struct wl1271 *wl, int addr, u16 val)
+static int __must_check wl12xx_top_reg_write(struct wl1271 *wl, int addr,
+ u16 val)
{
+ int ret;
+
/* write address >> 1 + 0x30000 to OCP_POR_CTR */
addr = (addr >> 1) + 0x30000;
- wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr);
+ ret = wlcore_write32(wl, WL12XX_OCP_POR_CTR, addr);
+ if (ret < 0)
+ goto out;
/* write value to OCP_POR_WDATA */
- wl1271_write32(wl, WL12XX_OCP_DATA_WRITE, val);
+ ret = wlcore_write32(wl, WL12XX_OCP_DATA_WRITE, val);
+ if (ret < 0)
+ goto out;
/* write 1 to OCP_CMD */
- wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE);
+ ret = wlcore_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE);
+ if (ret < 0)
+ goto out;
+
+out:
+ return ret;
}
-static u16 wl12xx_top_reg_read(struct wl1271 *wl, int addr)
+static int __must_check wl12xx_top_reg_read(struct wl1271 *wl, int addr,
+ u16 *out)
{
u32 val;
int timeout = OCP_CMD_LOOP;
+ int ret;
/* write address >> 1 + 0x30000 to OCP_POR_CTR */
addr = (addr >> 1) + 0x30000;
- wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr);
+ ret = wlcore_write32(wl, WL12XX_OCP_POR_CTR, addr);
+ if (ret < 0)
+ return ret;
/* write 2 to OCP_CMD */
- wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ);
+ ret = wlcore_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ);
+ if (ret < 0)
+ return ret;
/* poll for data ready */
do {
- val = wl1271_read32(wl, WL12XX_OCP_DATA_READ);
+ ret = wlcore_read32(wl, WL12XX_OCP_DATA_READ, &val);
+ if (ret < 0)
+ return ret;
} while (!(val & OCP_READY_MASK) && --timeout);
if (!timeout) {
wl1271_warning("Top register access timed out.");
- return 0xffff;
+ return -ETIMEDOUT;
}
/* check data status and return if OK */
- if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK)
- return val & 0xffff;
- else {
+ if ((val & OCP_STATUS_MASK) != OCP_STATUS_OK) {
wl1271_warning("Top register access returned error.");
- return 0xffff;
+ return -EIO;
}
+
+ if (out)
+ *out = val & 0xffff;
+
+ return 0;
}
static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
{
u16 spare_reg;
+ int ret;
/* Mask bits [2] & [8:4] in the sys_clk_cfg register */
- spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG);
+ ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, &spare_reg);
+ if (ret < 0)
+ return ret;
+
if (spare_reg == 0xFFFF)
return -EFAULT;
spare_reg |= (BIT(3) | BIT(5) | BIT(6));
- wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
+ ret = wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
+ if (ret < 0)
+ return ret;
/* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */
- wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG,
- WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF);
+ ret = wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG,
+ WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF);
+ if (ret < 0)
+ return ret;
/* Delay execution for 15msec, to let the HW settle */
mdelay(15);
@@ -749,8 +799,12 @@ static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
static bool wl128x_is_tcxo_valid(struct wl1271 *wl)
{
u16 tcxo_detection;
+ int ret;
+
+ ret = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG, &tcxo_detection);
+ if (ret < 0)
+ return false;
- tcxo_detection = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG);
if (tcxo_detection & TCXO_DET_FAILED)
return false;
@@ -760,8 +814,12 @@ static bool wl128x_is_tcxo_valid(struct wl1271 *wl)
static bool wl128x_is_fref_valid(struct wl1271 *wl)
{
u16 fref_detection;
+ int ret;
+
+ ret = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG, &fref_detection);
+ if (ret < 0)
+ return false;
- fref_detection = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG);
if (fref_detection & FREF_CLK_DETECT_FAIL)
return false;
@@ -770,11 +828,21 @@ static bool wl128x_is_fref_valid(struct wl1271 *wl)
static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl)
{
- wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL);
- wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL);
- wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL);
+ int ret;
- return 0;
+ ret = wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL);
+ if (ret < 0)
+ goto out;
+
+ ret = wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL);
+ if (ret < 0)
+ goto out;
+
+ ret = wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG,
+ MCS_PLL_CONFIG_REG_VAL);
+
+out:
+ return ret;
}
static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
@@ -783,13 +851,19 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
u16 pll_config;
u8 input_freq;
struct wl12xx_priv *priv = wl->priv;
+ int ret;
/* Mask bits [3:1] in the sys_clk_cfg register */
- spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG);
+ ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, &spare_reg);
+ if (ret < 0)
+ return ret;
+
if (spare_reg == 0xFFFF)
return -EFAULT;
spare_reg |= BIT(2);
- wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
+ ret = wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
+ if (ret < 0)
+ return ret;
/* Handle special cases of the TCXO clock */
if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_8 ||
@@ -799,14 +873,17 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
/* Set the input frequency according to the selected clock source */
input_freq = (clk & 1) + 1;
- pll_config = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG);
+ ret = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG, &pll_config);
+ if (ret < 0)
+ return ret;
+
if (pll_config == 0xFFFF)
return -EFAULT;
pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT);
pll_config |= MCS_PLL_ENABLE_HP;
- wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config);
+ ret = wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config);
- return 0;
+ return ret;
}
/*
@@ -820,6 +897,7 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
{
struct wl12xx_priv *priv = wl->priv;
u16 sys_clk_cfg;
+ int ret;
/* For XTAL-only modes, FREF will be used after switching from TCXO */
if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
@@ -830,7 +908,10 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
}
/* Query the HW, to determine which clock source we should use */
- sys_clk_cfg = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG);
+ ret = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG, &sys_clk_cfg);
+ if (ret < 0)
+ return ret;
+
if (sys_clk_cfg == 0xFFFF)
return -EINVAL;
if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF)
@@ -865,6 +946,7 @@ static int wl127x_boot_clk(struct wl1271 *wl)
struct wl12xx_priv *priv = wl->priv;
u32 pause;
u32 clk;
+ int ret;
if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION;
@@ -885,48 +967,74 @@ static int wl127x_boot_clk(struct wl1271 *wl)
if (priv->ref_clock != CONF_REF_CLK_19_2_E) {
u16 val;
/* Set clock type (open drain) */
- val = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE);
+ ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE, &val);
+ if (ret < 0)
+ goto out;
+
val &= FREF_CLK_TYPE_BITS;
- wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val);
+ ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val);
+ if (ret < 0)
+ goto out;
/* Set clock pull mode (no pull) */
- val = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL);
+ ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL, &val);
+ if (ret < 0)
+ goto out;
+
val |= NO_PULL;
- wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val);
+ ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val);
+ if (ret < 0)
+ goto out;
} else {
u16 val;
/* Set clock polarity */
- val = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY);
+ ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY, &val);
+ if (ret < 0)
+ goto out;
+
val &= FREF_CLK_POLARITY_BITS;
val |= CLK_REQ_OUTN_SEL;
- wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
+ ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
+ if (ret < 0)
+ goto out;
}
- wl1271_write32(wl, WL12XX_PLL_PARAMETERS, clk);
+ ret = wlcore_write32(wl, WL12XX_PLL_PARAMETERS, clk);
+ if (ret < 0)
+ goto out;
- pause = wl1271_read32(wl, WL12XX_PLL_PARAMETERS);
+ ret = wlcore_read32(wl, WL12XX_PLL_PARAMETERS, &pause);
+ if (ret < 0)
+ goto out;
wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
pause &= ~(WU_COUNTER_PAUSE_VAL);
pause |= WU_COUNTER_PAUSE_VAL;
- wl1271_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause);
+ ret = wlcore_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause);
- return 0;
+out:
+ return ret;
}
static int wl1271_boot_soft_reset(struct wl1271 *wl)
{
unsigned long timeout;
u32 boot_data;
+ int ret = 0;
/* perform soft reset */
- wl1271_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
+ ret = wlcore_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
+ if (ret < 0)
+ goto out;
/* SOFT_RESET is self clearing */
timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
while (1) {
- boot_data = wl1271_read32(wl, WL12XX_SLV_SOFT_RESET);
+ ret = wlcore_read32(wl, WL12XX_SLV_SOFT_RESET, &boot_data);
+ if (ret < 0)
+ goto out;
+
wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
break;
@@ -942,12 +1050,15 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
}
/* disable Rx/Tx */
- wl1271_write32(wl, WL12XX_ENABLE, 0x0);
+ ret = wlcore_write32(wl, WL12XX_ENABLE, 0x0);
+ if (ret < 0)
+ goto out;
/* disable auto calibration on start*/
- wl1271_write32(wl, WL12XX_SPARE_A2, 0xffff);
+ ret = wlcore_write32(wl, WL12XX_SPARE_A2, 0xffff);
- return 0;
+out:
+ return ret;
}
static int wl12xx_pre_boot(struct wl1271 *wl)
@@ -968,16 +1079,23 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
}
/* Continue the ELP wake up sequence */
- wl1271_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
+ ret = wlcore_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
+ if (ret < 0)
+ goto out;
+
udelay(500);
- wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
+ if (ret < 0)
+ goto out;
/* Read-modify-write DRPW_SCRATCH_START register (see next state)
to be used by DRPw FW. The RTRIM value will be added by the FW
before taking DRPw out of reset */
- clk = wl1271_read32(wl, WL12XX_DRPW_SCRATCH_START);
+ ret = wlcore_read32(wl, WL12XX_DRPW_SCRATCH_START, &clk);
+ if (ret < 0)
+ goto out;
wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
@@ -986,12 +1104,18 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
else
clk |= (priv->ref_clock << 1) << 4;
- wl1271_write32(wl, WL12XX_DRPW_SCRATCH_START, clk);
+ ret = wlcore_write32(wl, WL12XX_DRPW_SCRATCH_START, clk);
+ if (ret < 0)
+ goto out;
- wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
+ if (ret < 0)
+ goto out;
/* Disable interrupts */
- wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
+ ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
+ if (ret < 0)
+ goto out;
ret = wl1271_boot_soft_reset(wl);
if (ret < 0)
@@ -1001,47 +1125,72 @@ out:
return ret;
}
-static void wl12xx_pre_upload(struct wl1271 *wl)
+static int wl12xx_pre_upload(struct wl1271 *wl)
{
- u32 tmp, polarity;
+ u32 tmp;
+ u16 polarity;
+ int ret;
/* write firmware's last address (ie. it's length) to
* ACX_EEPROMLESS_IND_REG */
wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");
- wl1271_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND);
+ ret = wlcore_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND);
+ if (ret < 0)
+ goto out;
- tmp = wlcore_read_reg(wl, REG_CHIP_ID_B);
+ ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &tmp);
+ if (ret < 0)
+ goto out;
wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
/* 6. read the EEPROM parameters */
- tmp = wl1271_read32(wl, WL12XX_SCR_PAD2);
+ ret = wlcore_read32(wl, WL12XX_SCR_PAD2, &tmp);
+ if (ret < 0)
+ goto out;
/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
* to upload_fw) */
- if (wl->chip.id == CHIP_ID_1283_PG20)
- wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);
+ if (wl->chip.id == CHIP_ID_1283_PG20) {
+ ret = wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);
+ if (ret < 0)
+ goto out;
+ }
/* polarity must be set before the firmware is loaded */
- polarity = wl12xx_top_reg_read(wl, OCP_REG_POLARITY);
+ ret = wl12xx_top_reg_read(wl, OCP_REG_POLARITY, &polarity);
+ if (ret < 0)
+ goto out;
/* We use HIGH polarity, so unset the LOW bit */
polarity &= ~POLARITY_LOW;
- wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity);
+ ret = wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity);
+out:
+ return ret;
}
-static void wl12xx_enable_interrupts(struct wl1271 *wl)
+static int wl12xx_enable_interrupts(struct wl1271 *wl)
{
- wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL12XX_ACX_ALL_EVENTS_VECTOR);
+ int ret;
+
+ ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK,
+ WL12XX_ACX_ALL_EVENTS_VECTOR);
+ if (ret < 0)
+ goto out;
wlcore_enable_interrupts(wl);
- wlcore_write_reg(wl, REG_INTERRUPT_MASK,
- WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK));
+ ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK,
+ WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK));
+ if (ret < 0)
+ goto out;
- wl1271_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL);
+ ret = wlcore_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL);
+
+out:
+ return ret;
}
static int wl12xx_boot(struct wl1271 *wl)
@@ -1056,7 +1205,9 @@ static int wl12xx_boot(struct wl1271 *wl)
if (ret < 0)
goto out;
- wl12xx_pre_upload(wl);
+ ret = wl12xx_pre_upload(wl);
+ if (ret < 0)
+ goto out;
ret = wlcore_boot_upload_firmware(wl);
if (ret < 0)
@@ -1066,22 +1217,30 @@ static int wl12xx_boot(struct wl1271 *wl)
if (ret < 0)
goto out;
- wl12xx_enable_interrupts(wl);
+ ret = wl12xx_enable_interrupts(wl);
out:
return ret;
}
-static void wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
+static int wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
void *buf, size_t len)
{
- wl1271_write(wl, cmd_box_addr, buf, len, false);
- wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD);
+ int ret;
+
+ ret = wlcore_write(wl, cmd_box_addr, buf, len, false);
+ if (ret < 0)
+ return ret;
+
+ ret = wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD);
+
+ return ret;
}
-static void wl12xx_ack_event(struct wl1271 *wl)
+static int wl12xx_ack_event(struct wl1271 *wl)
{
- wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_EVENT_ACK);
+ return wlcore_write_reg(wl, REG_INTERRUPT_TRIG,
+ WL12XX_INTR_TRIG_EVENT_ACK);
}
static u32 wl12xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks)
@@ -1161,13 +1320,13 @@ static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,
return data_len - sizeof(*desc) - desc->pad_len;
}
-static void wl12xx_tx_delayed_compl(struct wl1271 *wl)
+static int wl12xx_tx_delayed_compl(struct wl1271 *wl)
{
if (wl->fw_status_1->tx_results_counter ==
(wl->tx_results_count & 0xff))
- return;
+ return 0;
- wl1271_tx_complete(wl);
+ return wlcore_tx_complete(wl);
}
static int wl12xx_hw_init(struct wl1271 *wl)
@@ -1268,39 +1427,58 @@ static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
return supported;
}
-static void wl12xx_get_fuse_mac(struct wl1271 *wl)
+static int wl12xx_get_fuse_mac(struct wl1271 *wl)
{
u32 mac1, mac2;
+ int ret;
- wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
+ if (ret < 0)
+ goto out;
- mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1);
- mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2);
+ ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1, &mac1);
+ if (ret < 0)
+ goto out;
+
+ ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2, &mac2);
+ if (ret < 0)
+ goto out;
/* these are the two parts of the BD_ADDR */
wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
((mac1 & 0xff000000) >> 24);
wl->fuse_nic_addr = mac1 & 0xffffff;
- wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
+
+out:
+ return ret;
}
-static s8 wl12xx_get_pg_ver(struct wl1271 *wl)
+static int wl12xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
{
- u32 die_info;
+ u16 die_info;
+ int ret;
if (wl->chip.id == CHIP_ID_1283_PG20)
- die_info = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1);
+ ret = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1,
+ &die_info);
else
- die_info = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1);
+ ret = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1,
+ &die_info);
- return (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET;
+ if (ret >= 0 && ver)
+ *ver = (s8)((die_info & PG_VER_MASK) >> PG_VER_OFFSET);
+
+ return ret;
}
-static void wl12xx_get_mac(struct wl1271 *wl)
+static int wl12xx_get_mac(struct wl1271 *wl)
{
if (wl12xx_mac_in_fuse(wl))
- wl12xx_get_fuse_mac(wl);
+ return wl12xx_get_fuse_mac(wl);
+
+ return 0;
}
static void wl12xx_set_tx_desc_csum(struct wl1271 *wl,
@@ -1448,10 +1626,8 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0;
wl->fw_status_priv_len = 0;
wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics);
- memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], &wl12xx_ht_cap,
- sizeof(wl12xx_ht_cap));
- memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], &wl12xx_ht_cap,
- sizeof(wl12xx_ht_cap));
+ wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, &wl12xx_ht_cap);
+ wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, &wl12xx_ht_cap);
wl12xx_conf_init(wl);
if (!fref_param) {
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h
index de1132410876..26990fb4edea 100644
--- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
@@ -24,6 +24,20 @@
#include "conf.h"
+/* minimum FW required for driver for wl127x */
+#define WL127X_CHIP_VER 6
+#define WL127X_IFTYPE_VER 3
+#define WL127X_MAJOR_VER 10
+#define WL127X_SUBTYPE_VER 2
+#define WL127X_MINOR_VER 115
+
+/* minimum FW required for driver for wl128x */
+#define WL128X_CHIP_VER 7
+#define WL128X_IFTYPE_VER 3
+#define WL128X_MAJOR_VER 10
+#define WL128X_SUBTYPE_VER 2
+#define WL128X_MINOR_VER 115
+
struct wl127x_rx_mem_pool_addr {
u32 addr;
u32 addr_extra;
diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h
index ebbaf611e97b..e2609a6b7341 100644
--- a/drivers/net/wireless/ti/wl18xx/acx.h
+++ b/drivers/net/wireless/ti/wl18xx/acx.h
@@ -32,25 +32,21 @@ enum {
/* numbers of bits the length field takes (add 1 for the actual number) */
#define WL18XX_HOST_IF_LEN_SIZE_FIELD 15
-#define WL18XX_ACX_EVENTS_VECTOR_PG1 (WL1271_ACX_INTR_WATCHDOG | \
- WL1271_ACX_INTR_INIT_COMPLETE | \
- WL1271_ACX_INTR_EVENT_A | \
- WL1271_ACX_INTR_EVENT_B | \
- WL1271_ACX_INTR_CMD_COMPLETE | \
- WL1271_ACX_INTR_HW_AVAILABLE | \
- WL1271_ACX_INTR_DATA)
-
-#define WL18XX_ACX_EVENTS_VECTOR_PG2 (WL18XX_ACX_EVENTS_VECTOR_PG1 | \
- WL1271_ACX_SW_INTR_WATCHDOG)
-
-#define WL18XX_INTR_MASK_PG1 (WL1271_ACX_INTR_WATCHDOG | \
- WL1271_ACX_INTR_EVENT_A | \
- WL1271_ACX_INTR_EVENT_B | \
- WL1271_ACX_INTR_HW_AVAILABLE | \
- WL1271_ACX_INTR_DATA)
-
-#define WL18XX_INTR_MASK_PG2 (WL18XX_INTR_MASK_PG1 | \
- WL1271_ACX_SW_INTR_WATCHDOG)
+#define WL18XX_ACX_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \
+ WL1271_ACX_INTR_INIT_COMPLETE | \
+ WL1271_ACX_INTR_EVENT_A | \
+ WL1271_ACX_INTR_EVENT_B | \
+ WL1271_ACX_INTR_CMD_COMPLETE | \
+ WL1271_ACX_INTR_HW_AVAILABLE | \
+ WL1271_ACX_INTR_DATA | \
+ WL1271_ACX_SW_INTR_WATCHDOG)
+
+#define WL18XX_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \
+ WL1271_ACX_INTR_EVENT_A | \
+ WL1271_ACX_INTR_EVENT_B | \
+ WL1271_ACX_INTR_HW_AVAILABLE | \
+ WL1271_ACX_INTR_DATA | \
+ WL1271_ACX_SW_INTR_WATCHDOG)
struct wl18xx_acx_host_config_bitmap {
struct acx_header header;
diff --git a/drivers/net/wireless/ti/wl18xx/io.c b/drivers/net/wireless/ti/wl18xx/io.c
index 598c057e722b..0c06ccfd1b8c 100644
--- a/drivers/net/wireless/ti/wl18xx/io.c
+++ b/drivers/net/wireless/ti/wl18xx/io.c
@@ -24,37 +24,52 @@
#include "io.h"
-void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val)
+int wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val)
{
u32 tmp;
+ int ret;
if (WARN_ON(addr % 2))
- return;
+ return -EINVAL;
if ((addr % 4) == 0) {
- tmp = wl1271_read32(wl, addr);
+ ret = wlcore_read32(wl, addr, &tmp);
+ if (ret < 0)
+ goto out;
+
tmp = (tmp & 0xffff0000) | val;
- wl1271_write32(wl, addr, tmp);
+ ret = wlcore_write32(wl, addr, tmp);
} else {
- tmp = wl1271_read32(wl, addr - 2);
+ ret = wlcore_read32(wl, addr - 2, &tmp);
+ if (ret < 0)
+ goto out;
+
tmp = (tmp & 0xffff) | (val << 16);
- wl1271_write32(wl, addr - 2, tmp);
+ ret = wlcore_write32(wl, addr - 2, tmp);
}
+
+out:
+ return ret;
}
-u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr)
+int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out)
{
u32 val;
+ int ret;
if (WARN_ON(addr % 2))
- return 0;
+ return -EINVAL;
if ((addr % 4) == 0) {
/* address is 4-bytes aligned */
- val = wl1271_read32(wl, addr);
- return val & 0xffff;
+ ret = wlcore_read32(wl, addr, &val);
+ if (ret >= 0 && out)
+ *out = val & 0xffff;
} else {
- val = wl1271_read32(wl, addr - 2);
- return (val & 0xffff0000) >> 16;
+ ret = wlcore_read32(wl, addr - 2, &val);
+ if (ret >= 0 && out)
+ *out = (val & 0xffff0000) >> 16;
}
+
+ return ret;
}
diff --git a/drivers/net/wireless/ti/wl18xx/io.h b/drivers/net/wireless/ti/wl18xx/io.h
index be4e126ff617..c32ae30277df 100644
--- a/drivers/net/wireless/ti/wl18xx/io.h
+++ b/drivers/net/wireless/ti/wl18xx/io.h
@@ -22,7 +22,7 @@
#ifndef __WL18XX_IO_H__
#define __WL18XX_IO_H__
-void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val);
-u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr);
+int __must_check wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val);
+int __must_check wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out);
#endif /* __WL18XX_IO_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index ed9c3650e08a..b378b34c4a6a 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -43,10 +43,11 @@
#define WL18XX_RX_CHECKSUM_MASK 0x40
-static char *ht_mode_param = "wide";
+static char *ht_mode_param = "default";
static char *board_type_param = "hdk";
static bool checksum_param = false;
static bool enable_11a_param = true;
+static int num_rx_desc_param = -1;
/* phy paramters */
static int dc2dc_param = -1;
@@ -368,10 +369,11 @@ static struct wlcore_conf wl18xx_conf = {
.psm_entry_retries = 8,
.psm_exit_retries = 16,
.psm_entry_nullfunc_retries = 3,
- .dynamic_ps_timeout = 200,
+ .dynamic_ps_timeout = 1500,
.forced_ps = false,
.keep_alive_interval = 55000,
.max_listen_interval = 20,
+ .sta_sleep_auth = WL1271_PSM_ILLEGAL,
},
.itrim = {
.enable = false,
@@ -606,24 +608,20 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
wl->plt_fw_name = WL18XX_FW_NAME;
wl->quirks |= WLCORE_QUIRK_NO_ELP |
WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN |
+ WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN |
+ WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN |
WLCORE_QUIRK_TX_PAD_LAST_FRAME;
+ wlcore_set_min_fw_ver(wl, WL18XX_CHIP_VER, WL18XX_IFTYPE_VER,
+ WL18XX_MAJOR_VER, WL18XX_SUBTYPE_VER,
+ WL18XX_MINOR_VER);
break;
case CHIP_ID_185x_PG10:
- wl1271_debug(DEBUG_BOOT, "chip id 0x%x (185x PG10)",
- wl->chip.id);
- wl->sr_fw_name = WL18XX_FW_NAME;
- /* wl18xx uses the same firmware for PLT */
- wl->plt_fw_name = WL18XX_FW_NAME;
- wl->quirks |= WLCORE_QUIRK_NO_ELP |
- WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED |
- WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN |
- WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN;
-
- /* PG 1.0 has some problems with MCS_13, so disable it */
- wl->ht_cap[IEEE80211_BAND_2GHZ].mcs.rx_mask[1] &= ~BIT(5);
+ wl1271_warning("chip id 0x%x (185x PG10) is deprecated",
+ wl->chip.id);
+ ret = -ENODEV;
+ goto out;
- break;
default:
wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
ret = -ENODEV;
@@ -634,123 +632,178 @@ out:
return ret;
}
-static void wl18xx_set_clk(struct wl1271 *wl)
+static int wl18xx_set_clk(struct wl1271 *wl)
{
- u32 clk_freq;
+ u16 clk_freq;
+ int ret;
- wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
+ if (ret < 0)
+ goto out;
/* TODO: PG2: apparently we need to read the clk type */
- clk_freq = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT);
+ ret = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT, &clk_freq);
+ if (ret < 0)
+ goto out;
+
wl1271_debug(DEBUG_BOOT, "clock freq %d (%d, %d, %d, %d, %s)", clk_freq,
wl18xx_clk_table[clk_freq].n, wl18xx_clk_table[clk_freq].m,
wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q,
wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit");
- wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N, wl18xx_clk_table[clk_freq].n);
- wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M, wl18xx_clk_table[clk_freq].m);
+ ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N,
+ wl18xx_clk_table[clk_freq].n);
+ if (ret < 0)
+ goto out;
+
+ ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M,
+ wl18xx_clk_table[clk_freq].m);
+ if (ret < 0)
+ goto out;
if (wl18xx_clk_table[clk_freq].swallow) {
/* first the 16 lower bits */
- wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1,
- wl18xx_clk_table[clk_freq].q &
- PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK);
+ ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1,
+ wl18xx_clk_table[clk_freq].q &
+ PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK);
+ if (ret < 0)
+ goto out;
+
/* then the 16 higher bits, masked out */
- wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2,
- (wl18xx_clk_table[clk_freq].q >> 16) &
- PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK);
+ ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2,
+ (wl18xx_clk_table[clk_freq].q >> 16) &
+ PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK);
+ if (ret < 0)
+ goto out;
/* first the 16 lower bits */
- wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1,
- wl18xx_clk_table[clk_freq].p &
- PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK);
+ ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1,
+ wl18xx_clk_table[clk_freq].p &
+ PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK);
+ if (ret < 0)
+ goto out;
+
/* then the 16 higher bits, masked out */
- wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2,
- (wl18xx_clk_table[clk_freq].p >> 16) &
- PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK);
+ ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2,
+ (wl18xx_clk_table[clk_freq].p >> 16) &
+ PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK);
} else {
- wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN,
- PLLSH_WCS_PLL_SWALLOW_EN_VAL2);
+ ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN,
+ PLLSH_WCS_PLL_SWALLOW_EN_VAL2);
}
+
+out:
+ return ret;
}
-static void wl18xx_boot_soft_reset(struct wl1271 *wl)
+static int wl18xx_boot_soft_reset(struct wl1271 *wl)
{
+ int ret;
+
/* disable Rx/Tx */
- wl1271_write32(wl, WL18XX_ENABLE, 0x0);
+ ret = wlcore_write32(wl, WL18XX_ENABLE, 0x0);
+ if (ret < 0)
+ goto out;
/* disable auto calibration on start*/
- wl1271_write32(wl, WL18XX_SPARE_A2, 0xffff);
+ ret = wlcore_write32(wl, WL18XX_SPARE_A2, 0xffff);
+
+out:
+ return ret;
}
static int wl18xx_pre_boot(struct wl1271 *wl)
{
- wl18xx_set_clk(wl);
+ int ret;
+
+ ret = wl18xx_set_clk(wl);
+ if (ret < 0)
+ goto out;
/* Continue the ELP wake up sequence */
- wl1271_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
+ ret = wlcore_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
+ if (ret < 0)
+ goto out;
+
udelay(500);
- wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
+ if (ret < 0)
+ goto out;
/* Disable interrupts */
- wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
+ ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
+ if (ret < 0)
+ goto out;
- wl18xx_boot_soft_reset(wl);
+ ret = wl18xx_boot_soft_reset(wl);
- return 0;
+out:
+ return ret;
}
-static void wl18xx_pre_upload(struct wl1271 *wl)
+static int wl18xx_pre_upload(struct wl1271 *wl)
{
u32 tmp;
+ int ret;
- wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
+ if (ret < 0)
+ goto out;
/* TODO: check if this is all needed */
- wl1271_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND);
+ ret = wlcore_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND);
+ if (ret < 0)
+ goto out;
- tmp = wlcore_read_reg(wl, REG_CHIP_ID_B);
+ ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &tmp);
+ if (ret < 0)
+ goto out;
wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
- tmp = wl1271_read32(wl, WL18XX_SCR_PAD2);
+ ret = wlcore_read32(wl, WL18XX_SCR_PAD2, &tmp);
+
+out:
+ return ret;
}
-static void wl18xx_set_mac_and_phy(struct wl1271 *wl)
+static int wl18xx_set_mac_and_phy(struct wl1271 *wl)
{
struct wl18xx_priv *priv = wl->priv;
- size_t len;
+ int ret;
- /* the parameters struct is smaller for PG1 */
- if (wl->chip.id == CHIP_ID_185x_PG10)
- len = offsetof(struct wl18xx_mac_and_phy_params, psat) + 1;
- else
- len = sizeof(struct wl18xx_mac_and_phy_params);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
+ if (ret < 0)
+ goto out;
- wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
- wl1271_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy, len,
- false);
+ ret = wlcore_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy,
+ sizeof(struct wl18xx_mac_and_phy_params), false);
+
+out:
+ return ret;
}
-static void wl18xx_enable_interrupts(struct wl1271 *wl)
+static int wl18xx_enable_interrupts(struct wl1271 *wl)
{
u32 event_mask, intr_mask;
+ int ret;
- if (wl->chip.id == CHIP_ID_185x_PG10) {
- event_mask = WL18XX_ACX_EVENTS_VECTOR_PG1;
- intr_mask = WL18XX_INTR_MASK_PG1;
- } else {
- event_mask = WL18XX_ACX_EVENTS_VECTOR_PG2;
- intr_mask = WL18XX_INTR_MASK_PG2;
- }
+ event_mask = WL18XX_ACX_EVENTS_VECTOR;
+ intr_mask = WL18XX_INTR_MASK;
- wlcore_write_reg(wl, REG_INTERRUPT_MASK, event_mask);
+ ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, event_mask);
+ if (ret < 0)
+ goto out;
wlcore_enable_interrupts(wl);
- wlcore_write_reg(wl, REG_INTERRUPT_MASK,
- WL1271_ACX_INTR_ALL & ~intr_mask);
+
+ ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK,
+ WL1271_ACX_INTR_ALL & ~intr_mask);
+
+out:
+ return ret;
}
static int wl18xx_boot(struct wl1271 *wl)
@@ -761,25 +814,29 @@ static int wl18xx_boot(struct wl1271 *wl)
if (ret < 0)
goto out;
- wl18xx_pre_upload(wl);
+ ret = wl18xx_pre_upload(wl);
+ if (ret < 0)
+ goto out;
ret = wlcore_boot_upload_firmware(wl);
if (ret < 0)
goto out;
- wl18xx_set_mac_and_phy(wl);
+ ret = wl18xx_set_mac_and_phy(wl);
+ if (ret < 0)
+ goto out;
ret = wlcore_boot_run_firmware(wl);
if (ret < 0)
goto out;
- wl18xx_enable_interrupts(wl);
+ ret = wl18xx_enable_interrupts(wl);
out:
return ret;
}
-static void wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
+static int wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
void *buf, size_t len)
{
struct wl18xx_priv *priv = wl->priv;
@@ -787,13 +844,14 @@ static void wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
memcpy(priv->cmd_buf, buf, len);
memset(priv->cmd_buf + len, 0, WL18XX_CMD_MAX_SIZE - len);
- wl1271_write(wl, cmd_box_addr, priv->cmd_buf, WL18XX_CMD_MAX_SIZE,
- false);
+ return wlcore_write(wl, cmd_box_addr, priv->cmd_buf,
+ WL18XX_CMD_MAX_SIZE, false);
}
-static void wl18xx_ack_event(struct wl1271 *wl)
+static int wl18xx_ack_event(struct wl1271 *wl)
{
- wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL18XX_INTR_TRIG_EVENT_ACK);
+ return wlcore_write_reg(wl, REG_INTERRUPT_TRIG,
+ WL18XX_INTR_TRIG_EVENT_ACK);
}
static u32 wl18xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks)
@@ -967,42 +1025,50 @@ static u32 wl18xx_sta_get_ap_rate_mask(struct wl1271 *wl,
static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
struct wl12xx_vif *wlvif)
{
- if ((wlvif->channel_type == NL80211_CHAN_HT40MINUS ||
- wlvif->channel_type == NL80211_CHAN_HT40PLUS) &&
- !strcmp(ht_mode_param, "wide")) {
+ struct wl18xx_priv *priv = wl->priv;
+
+ if (wlvif->channel_type == NL80211_CHAN_HT40MINUS ||
+ wlvif->channel_type == NL80211_CHAN_HT40PLUS) {
wl1271_debug(DEBUG_ACX, "using wide channel rate mask");
+
+ /* sanity check - we don't support this */
+ if (WARN_ON(wlvif->band != IEEE80211_BAND_5GHZ))
+ return 0;
+
return CONF_TX_RATE_USE_WIDE_CHAN;
- } else if (!strcmp(ht_mode_param, "mimo")) {
+ } else if (priv->conf.phy.number_of_assembled_ant2_4 >= 2 &&
+ wlvif->band == IEEE80211_BAND_2GHZ) {
wl1271_debug(DEBUG_ACX, "using MIMO rate mask");
-
/*
- * PG 1.0 has some problems with MCS_13, so disable it
- *
- * TODO: instead of hacking this in here, we should
- * make it more general and change a bit in the
- * wlvif->rate_set instead.
+ * we don't care about HT channel here - if a peer doesn't
+ * support MIMO, we won't enable it in its rates
*/
- if (wl->chip.id == CHIP_ID_185x_PG10)
- return CONF_TX_MIMO_RATES & ~CONF_HW_BIT_RATE_MCS_13;
-
return CONF_TX_MIMO_RATES;
} else {
return 0;
}
}
-static s8 wl18xx_get_pg_ver(struct wl1271 *wl)
+static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
{
u32 fuse;
+ int ret;
- wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
+ if (ret < 0)
+ goto out;
- fuse = wl1271_read32(wl, WL18XX_REG_FUSE_DATA_1_3);
- fuse = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET;
+ ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_1_3, &fuse);
+ if (ret < 0)
+ goto out;
+
+ if (ver)
+ *ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET;
- wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
- return (s8)fuse;
+out:
+ return ret;
}
#define WL18XX_CONF_FILE_NAME "ti-connectivity/wl18xx-conf.bin"
@@ -1021,8 +1087,7 @@ static int wl18xx_conf_init(struct wl1271 *wl, struct device *dev)
}
if (fw->size != WL18XX_CONF_SIZE) {
- wl1271_error("configuration binary file size is wrong, "
- "expected %ld got %zd",
+ wl1271_error("configuration binary file size is wrong, expected %zu got %zu",
WL18XX_CONF_SIZE, fw->size);
ret = -EINVAL;
goto out;
@@ -1069,26 +1134,41 @@ out:
static int wl18xx_plt_init(struct wl1271 *wl)
{
- wl1271_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT);
+ int ret;
+
+ ret = wlcore_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT);
+ if (ret < 0)
+ return ret;
return wl->ops->boot(wl);
}
-static void wl18xx_get_mac(struct wl1271 *wl)
+static int wl18xx_get_mac(struct wl1271 *wl)
{
u32 mac1, mac2;
+ int ret;
- wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
+ if (ret < 0)
+ goto out;
- mac1 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1);
- mac2 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2);
+ ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1, &mac1);
+ if (ret < 0)
+ goto out;
+
+ ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2, &mac2);
+ if (ret < 0)
+ goto out;
/* these are the two parts of the BD_ADDR */
wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
((mac1 & 0xff000000) >> 24);
wl->fuse_nic_addr = (mac1 & 0xffffff);
- wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
+
+out:
+ return ret;
}
static int wl18xx_handle_static_data(struct wl1271 *wl,
@@ -1214,8 +1294,8 @@ static struct wlcore_ops wl18xx_ops = {
.pre_pkt_send = wl18xx_pre_pkt_send,
};
-/* HT cap appropriate for wide channels */
-static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap = {
+/* HT cap appropriate for wide channels in 2Ghz */
+static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_2ghz = {
.cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_DSSSCCK40,
.ht_supported = true,
@@ -1228,40 +1308,42 @@ static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap = {
},
};
-/* HT cap appropriate for SISO 20 */
-static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = {
- .cap = IEEE80211_HT_CAP_SGI_20,
+/* HT cap appropriate for wide channels in 5Ghz */
+static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_5ghz = {
+ .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
+ IEEE80211_HT_CAP_SUP_WIDTH_20_40,
.ht_supported = true,
.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K,
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
.mcs = {
.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- .rx_highest = cpu_to_le16(72),
+ .rx_highest = cpu_to_le16(150),
.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
},
};
-/* HT cap appropriate for MIMO rates in 20mhz channel */
-static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = {
+/* HT cap appropriate for SISO 20 */
+static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = {
.cap = IEEE80211_HT_CAP_SGI_20,
.ht_supported = true,
.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K,
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
.mcs = {
- .rx_mask = { 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, },
- .rx_highest = cpu_to_le16(144),
+ .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
+ .rx_highest = cpu_to_le16(72),
.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
},
};
-static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_5ghz = {
+/* HT cap appropriate for MIMO rates in 20mhz channel */
+static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = {
.cap = IEEE80211_HT_CAP_SGI_20,
.ht_supported = true,
.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K,
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
.mcs = {
- .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- .rx_highest = cpu_to_le16(72),
+ .rx_mask = { 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, },
+ .rx_highest = cpu_to_le16(144),
.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
},
};
@@ -1286,7 +1368,7 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
wl->ptable = wl18xx_ptable;
wl->rtable = wl18xx_rtable;
wl->num_tx_desc = 32;
- wl->num_rx_desc = 16;
+ wl->num_rx_desc = 32;
wl->band_rate_to_idx = wl18xx_band_rate_to_idx;
wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX;
wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0;
@@ -1294,32 +1376,8 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics);
wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv);
- if (!strcmp(ht_mode_param, "wide")) {
- memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ],
- &wl18xx_siso40_ht_cap,
- sizeof(wl18xx_siso40_ht_cap));
- memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ],
- &wl18xx_siso40_ht_cap,
- sizeof(wl18xx_siso40_ht_cap));
- } else if (!strcmp(ht_mode_param, "mimo")) {
- memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ],
- &wl18xx_mimo_ht_cap_2ghz,
- sizeof(wl18xx_mimo_ht_cap_2ghz));
- memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ],
- &wl18xx_mimo_ht_cap_5ghz,
- sizeof(wl18xx_mimo_ht_cap_5ghz));
- } else if (!strcmp(ht_mode_param, "siso20")) {
- memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ],
- &wl18xx_siso20_ht_cap,
- sizeof(wl18xx_siso20_ht_cap));
- memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ],
- &wl18xx_siso20_ht_cap,
- sizeof(wl18xx_siso20_ht_cap));
- } else {
- wl1271_error("invalid ht_mode '%s'", ht_mode_param);
- ret = -EINVAL;
- goto out_free;
- }
+ if (num_rx_desc_param != -1)
+ wl->num_rx_desc = num_rx_desc_param;
ret = wl18xx_conf_init(wl, &pdev->dev);
if (ret < 0)
@@ -1366,6 +1424,37 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
if (dc2dc_param != -1)
priv->conf.phy.external_pa_dc2dc = dc2dc_param;
+ if (!strcmp(ht_mode_param, "default")) {
+ /*
+ * Only support mimo with multiple antennas. Fall back to
+ * siso20.
+ */
+ if (priv->conf.phy.number_of_assembled_ant2_4 >= 2)
+ wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
+ &wl18xx_mimo_ht_cap_2ghz);
+ else
+ wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
+ &wl18xx_siso20_ht_cap);
+
+ /* 5Ghz is always wide */
+ wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,
+ &wl18xx_siso40_ht_cap_5ghz);
+ } else if (!strcmp(ht_mode_param, "wide")) {
+ wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
+ &wl18xx_siso40_ht_cap_2ghz);
+ wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,
+ &wl18xx_siso40_ht_cap_5ghz);
+ } else if (!strcmp(ht_mode_param, "siso20")) {
+ wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
+ &wl18xx_siso20_ht_cap);
+ wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,
+ &wl18xx_siso20_ht_cap);
+ } else {
+ wl1271_error("invalid ht_mode '%s'", ht_mode_param);
+ ret = -EINVAL;
+ goto out_free;
+ }
+
if (!checksum_param) {
wl18xx_ops.set_rx_csum = NULL;
wl18xx_ops.init_vif = NULL;
@@ -1410,7 +1499,7 @@ static void __exit wl18xx_exit(void)
module_exit(wl18xx_exit);
module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR);
-MODULE_PARM_DESC(ht_mode, "Force HT mode: wide (default), mimo or siso20");
+MODULE_PARM_DESC(ht_mode, "Force HT mode: wide or siso20");
module_param_named(board_type, board_type_param, charp, S_IRUSR);
MODULE_PARM_DESC(board_type, "Board type: fpga, hdk (default), evb, com8 or "
@@ -1458,6 +1547,11 @@ module_param_named(pwr_limit_reference_11_abg,
MODULE_PARM_DESC(pwr_limit_reference_11_abg, "Power limit reference: u8 "
"(default is 0xc8)");
+module_param_named(num_rx_desc,
+ num_rx_desc_param, int, S_IRUSR);
+MODULE_PARM_DESC(num_rx_desc_param,
+ "Number of Rx descriptors: u8 (default is 32)");
+
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
MODULE_FIRMWARE(WL18XX_FW_NAME);
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index bc67a4750615..6452396fa1d4 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -24,6 +24,13 @@
#include "conf.h"
+/* minimum FW required for driver */
+#define WL18XX_CHIP_VER 8
+#define WL18XX_IFTYPE_VER 2
+#define WL18XX_MAJOR_VER 0
+#define WL18XX_SUBTYPE_VER 0
+#define WL18XX_MINOR_VER 100
+
#define WL18XX_CMD_MAX_SIZE 740
struct wl18xx_priv {
diff --git a/drivers/net/wireless/ti/wlcore/Kconfig b/drivers/net/wireless/ti/wlcore/Kconfig
index 54156b0b5c2d..d7b907e67170 100644
--- a/drivers/net/wireless/ti/wlcore/Kconfig
+++ b/drivers/net/wireless/ti/wlcore/Kconfig
@@ -1,7 +1,6 @@
config WLCORE
tristate "TI wlcore support"
depends on WL_TI && GENERIC_HARDIRQS && MAC80211
- depends on INET
select FW_LOADER
---help---
This module contains the main code for TI WLAN chips. It abstracts
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c
index b9ec42c83757..ce108a736bd0 100644
--- a/drivers/net/wireless/ti/wlcore/acx.c
+++ b/drivers/net/wireless/ti/wlcore/acx.c
@@ -70,7 +70,7 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth)
struct acx_sleep_auth *auth;
int ret;
- wl1271_debug(DEBUG_ACX, "acx sleep auth");
+ wl1271_debug(DEBUG_ACX, "acx sleep auth %d", sleep_auth);
auth = kzalloc(sizeof(*auth), GFP_KERNEL);
if (!auth) {
@@ -81,7 +81,13 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth)
auth->sleep_auth = sleep_auth;
ret = wl1271_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
+ if (ret < 0) {
+ wl1271_error("could not configure sleep_auth to %d: %d",
+ sleep_auth, ret);
+ goto out;
+ }
+ wl->sleep_auth = sleep_auth;
out:
kfree(auth);
return ret;
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h
index c0181258b722..d03215d6b3bd 100644
--- a/drivers/net/wireless/ti/wlcore/acx.h
+++ b/drivers/net/wireless/ti/wlcore/acx.h
@@ -118,6 +118,11 @@ enum wl1271_psm_mode {
/* Extreme low power */
WL1271_PSM_ELP = 2,
+
+ WL1271_PSM_MAX = WL1271_PSM_ELP,
+
+ /* illegal out of band value of PSM mode */
+ WL1271_PSM_ILLEGAL = 0xff
};
struct acx_sleep_auth {
diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c
index 0fda500c01c9..375ea574eafb 100644
--- a/drivers/net/wireless/ti/wlcore/boot.c
+++ b/drivers/net/wireless/ti/wlcore/boot.c
@@ -33,16 +33,22 @@
#include "rx.h"
#include "hw_ops.h"
-static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
+static int wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
{
u32 cpu_ctrl;
+ int ret;
/* 10.5.0 run the firmware (I) */
- cpu_ctrl = wlcore_read_reg(wl, REG_ECPU_CONTROL);
+ ret = wlcore_read_reg(wl, REG_ECPU_CONTROL, &cpu_ctrl);
+ if (ret < 0)
+ goto out;
/* 10.5.1 run the firmware (II) */
cpu_ctrl |= flag;
- wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl);
+ ret = wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl);
+
+out:
+ return ret;
}
static int wlcore_boot_parse_fw_ver(struct wl1271 *wl,
@@ -75,6 +81,53 @@ out:
return ret;
}
+static int wlcore_validate_fw_ver(struct wl1271 *wl)
+{
+ unsigned int *fw_ver = wl->chip.fw_ver;
+ unsigned int *min_ver = wl->min_fw_ver;
+
+ /* the chip must be exactly equal */
+ if (min_ver[FW_VER_CHIP] != fw_ver[FW_VER_CHIP])
+ goto fail;
+
+ /* always check the next digit if all previous ones are equal */
+
+ if (min_ver[FW_VER_IF_TYPE] < fw_ver[FW_VER_IF_TYPE])
+ goto out;
+ else if (min_ver[FW_VER_IF_TYPE] > fw_ver[FW_VER_IF_TYPE])
+ goto fail;
+
+ if (min_ver[FW_VER_MAJOR] < fw_ver[FW_VER_MAJOR])
+ goto out;
+ else if (min_ver[FW_VER_MAJOR] > fw_ver[FW_VER_MAJOR])
+ goto fail;
+
+ if (min_ver[FW_VER_SUBTYPE] < fw_ver[FW_VER_SUBTYPE])
+ goto out;
+ else if (min_ver[FW_VER_SUBTYPE] > fw_ver[FW_VER_SUBTYPE])
+ goto fail;
+
+ if (min_ver[FW_VER_MINOR] < fw_ver[FW_VER_MINOR])
+ goto out;
+ else if (min_ver[FW_VER_MINOR] > fw_ver[FW_VER_MINOR])
+ goto fail;
+
+out:
+ return 0;
+
+fail:
+ wl1271_error("Your WiFi FW version (%u.%u.%u.%u.%u) is outdated.\n"
+ "Please use at least FW %u.%u.%u.%u.%u.\n"
+ "You can get more information at:\n"
+ "http://wireless.kernel.org/en/users/Drivers/wl12xx",
+ fw_ver[FW_VER_CHIP], fw_ver[FW_VER_IF_TYPE],
+ fw_ver[FW_VER_MAJOR], fw_ver[FW_VER_SUBTYPE],
+ fw_ver[FW_VER_MINOR], min_ver[FW_VER_CHIP],
+ min_ver[FW_VER_IF_TYPE], min_ver[FW_VER_MAJOR],
+ min_ver[FW_VER_SUBTYPE], min_ver[FW_VER_MINOR]);
+ return -EINVAL;
+}
+
static int wlcore_boot_static_data(struct wl1271 *wl)
{
struct wl1271_static_data *static_data;
@@ -87,12 +140,18 @@ static int wlcore_boot_static_data(struct wl1271 *wl)
goto out;
}
- wl1271_read(wl, wl->cmd_box_addr, static_data, len, false);
+ ret = wlcore_read(wl, wl->cmd_box_addr, static_data, len, false);
+ if (ret < 0)
+ goto out_free;
ret = wlcore_boot_parse_fw_ver(wl, static_data);
if (ret < 0)
goto out_free;
+ ret = wlcore_validate_fw_ver(wl);
+ if (ret < 0)
+ goto out_free;
+
ret = wlcore_handle_static_data(wl, static_data);
if (ret < 0)
goto out_free;
@@ -109,6 +168,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
struct wlcore_partition_set partition;
int addr, chunk_num, partition_limit;
u8 *p, *chunk;
+ int ret;
/* whal_FwCtrl_LoadFwImageSm() */
@@ -130,7 +190,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
memcpy(&partition, &wl->ptable[PART_DOWN], sizeof(partition));
partition.mem.start = dest;
- wlcore_set_partition(wl, &partition);
+ ret = wlcore_set_partition(wl, &partition);
+ if (ret < 0)
+ goto out;
/* 10.1 set partition limit and chunk num */
chunk_num = 0;
@@ -144,7 +206,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
partition_limit = chunk_num * CHUNK_SIZE +
wl->ptable[PART_DOWN].mem.size;
partition.mem.start = addr;
- wlcore_set_partition(wl, &partition);
+ ret = wlcore_set_partition(wl, &partition);
+ if (ret < 0)
+ goto out;
}
/* 10.3 upload the chunk */
@@ -153,7 +217,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
memcpy(chunk, p, CHUNK_SIZE);
wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
p, addr);
- wl1271_write(wl, addr, chunk, CHUNK_SIZE, false);
+ ret = wlcore_write(wl, addr, chunk, CHUNK_SIZE, false);
+ if (ret < 0)
+ goto out;
chunk_num++;
}
@@ -164,10 +230,11 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
memcpy(chunk, p, fw_data_len % CHUNK_SIZE);
wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
fw_data_len % CHUNK_SIZE, p, addr);
- wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false);
+ ret = wlcore_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false);
+out:
kfree(chunk);
- return 0;
+ return ret;
}
int wlcore_boot_upload_firmware(struct wl1271 *wl)
@@ -210,6 +277,7 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
int i;
u32 dest_addr, val;
u8 *nvs_ptr, *nvs_aligned;
+ int ret;
if (wl->nvs == NULL) {
wl1271_error("NVS file is needed during boot");
@@ -307,7 +375,9 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
wl1271_debug(DEBUG_BOOT,
"nvs burst write 0x%x: 0x%x",
dest_addr, val);
- wl1271_write32(wl, dest_addr, val);
+ ret = wlcore_write32(wl, dest_addr, val);
+ if (ret < 0)
+ return ret;
nvs_ptr += 4;
dest_addr += 4;
@@ -333,7 +403,9 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
nvs_len -= nvs_ptr - (u8 *)wl->nvs;
/* Now we must set the partition correctly */
- wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
+ if (ret < 0)
+ return ret;
/* Copy the NVS tables to a new block to ensure alignment */
nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
@@ -341,11 +413,11 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
return -ENOMEM;
/* And finally we upload the NVS tables */
- wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS,
- nvs_aligned, nvs_len, false);
+ ret = wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS, nvs_aligned, nvs_len,
+ false);
kfree(nvs_aligned);
- return 0;
+ return ret;
out_badnvs:
wl1271_error("nvs data is malformed");
@@ -359,11 +431,17 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
u32 chip_id, intr;
/* Make sure we have the boot partition */
- wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
+ if (ret < 0)
+ return ret;
- wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
+ ret = wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
+ if (ret < 0)
+ return ret;
- chip_id = wlcore_read_reg(wl, REG_CHIP_ID_B);
+ ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &chip_id);
+ if (ret < 0)
+ return ret;
wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
@@ -376,7 +454,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
loop = 0;
while (loop++ < INIT_LOOP) {
udelay(INIT_LOOP_DELAY);
- intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR);
+ ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr);
+ if (ret < 0)
+ return ret;
if (intr == 0xffffffff) {
wl1271_error("error reading hardware complete "
@@ -385,8 +465,10 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
}
/* check that ACX_INTR_INIT_COMPLETE is enabled */
else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) {
- wlcore_write_reg(wl, REG_INTERRUPT_ACK,
- WL1271_ACX_INTR_INIT_COMPLETE);
+ ret = wlcore_write_reg(wl, REG_INTERRUPT_ACK,
+ WL1271_ACX_INTR_INIT_COMPLETE);
+ if (ret < 0)
+ return ret;
break;
}
}
@@ -398,12 +480,17 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
}
/* get hardware config command mail box */
- wl->cmd_box_addr = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR);
+ ret = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR, &wl->cmd_box_addr);
+ if (ret < 0)
+ return ret;
wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x", wl->cmd_box_addr);
/* get hardware config event mail box */
- wl->mbox_ptr[0] = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR);
+ ret = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR, &wl->mbox_ptr[0]);
+ if (ret < 0)
+ return ret;
+
wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x",
@@ -445,9 +532,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
}
/* set the working partition to its "running" mode offset */
- wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
/* firmware startup completed */
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(wlcore_boot_run_firmware);
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 885364ca4344..a23949cdaebc 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -39,6 +39,7 @@
#include "hw_ops.h"
#define WL1271_CMD_FAST_POLL_COUNT 50
+#define WL1271_WAIT_EVENT_FAST_POLL_COUNT 20
/*
* send command to firmware
@@ -65,17 +66,24 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
WARN_ON(len % 4 != 0);
WARN_ON(test_bit(WL1271_FLAG_IN_ELP, &wl->flags));
- wl1271_write(wl, wl->cmd_box_addr, buf, len, false);
+ ret = wlcore_write(wl, wl->cmd_box_addr, buf, len, false);
+ if (ret < 0)
+ goto fail;
/*
* TODO: we just need this because one bit is in a different
* place. Is there any better way?
*/
- wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len);
+ ret = wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len);
+ if (ret < 0)
+ goto fail;
timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT);
- intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR);
+ ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr);
+ if (ret < 0)
+ goto fail;
+
while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) {
if (time_after(jiffies, timeout)) {
wl1271_error("command complete timeout");
@@ -89,13 +97,18 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
else
msleep(1);
- intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR);
+ ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr);
+ if (ret < 0)
+ goto fail;
}
/* read back the status code of the command */
if (res_len == 0)
res_len = sizeof(struct wl1271_cmd_header);
- wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false);
+
+ ret = wlcore_read(wl, wl->cmd_box_addr, cmd, res_len, false);
+ if (ret < 0)
+ goto fail;
status = le16_to_cpu(cmd->status);
if (status != CMD_STATUS_SUCCESS) {
@@ -104,11 +117,14 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
goto fail;
}
- wlcore_write_reg(wl, REG_INTERRUPT_ACK, WL1271_ACX_INTR_CMD_COMPLETE);
+ ret = wlcore_write_reg(wl, REG_INTERRUPT_ACK,
+ WL1271_ACX_INTR_CMD_COMPLETE);
+ if (ret < 0)
+ goto fail;
+
return 0;
fail:
- WARN_ON(1);
wl12xx_queue_recovery_work(wl);
return ret;
}
@@ -117,35 +133,50 @@ fail:
* Poll the mailbox event field until any of the bits in the mask is set or a
* timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
*/
-static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask)
+static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl,
+ u32 mask, bool *timeout)
{
u32 *events_vector;
u32 event;
- unsigned long timeout;
+ unsigned long timeout_time;
+ u16 poll_count = 0;
int ret = 0;
+ *timeout = false;
+
events_vector = kmalloc(sizeof(*events_vector), GFP_KERNEL | GFP_DMA);
if (!events_vector)
return -ENOMEM;
- timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT);
+ timeout_time = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT);
do {
- if (time_after(jiffies, timeout)) {
+ if (time_after(jiffies, timeout_time)) {
wl1271_debug(DEBUG_CMD, "timeout waiting for event %d",
(int)mask);
- ret = -ETIMEDOUT;
+ *timeout = true;
goto out;
}
- msleep(1);
+ poll_count++;
+ if (poll_count < WL1271_WAIT_EVENT_FAST_POLL_COUNT)
+ usleep_range(50, 51);
+ else
+ usleep_range(1000, 5000);
/* read from both event fields */
- wl1271_read(wl, wl->mbox_ptr[0], events_vector,
- sizeof(*events_vector), false);
+ ret = wlcore_read(wl, wl->mbox_ptr[0], events_vector,
+ sizeof(*events_vector), false);
+ if (ret < 0)
+ goto out;
+
event = *events_vector & mask;
- wl1271_read(wl, wl->mbox_ptr[1], events_vector,
- sizeof(*events_vector), false);
+
+ ret = wlcore_read(wl, wl->mbox_ptr[1], events_vector,
+ sizeof(*events_vector), false);
+ if (ret < 0)
+ goto out;
+
event |= *events_vector & mask;
} while (!event);
@@ -157,9 +188,10 @@ out:
static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
{
int ret;
+ bool timeout = false;
- ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask);
- if (ret != 0) {
+ ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask, &timeout);
+ if (ret != 0 || timeout) {
wl12xx_queue_recovery_work(wl);
return ret;
}
@@ -981,12 +1013,14 @@ out:
int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 role_id, u8 band,
const u8 *ssid, size_t ssid_len,
- const u8 *ie, size_t ie_len)
+ const u8 *ie, size_t ie_len, bool sched_scan)
{
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
struct sk_buff *skb;
int ret;
u32 rate;
+ u16 template_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4;
+ u16 template_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5;
skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len,
ie, ie_len);
@@ -997,14 +1031,20 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len);
+ if (!sched_scan &&
+ (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL)) {
+ template_id_2_4 = CMD_TEMPL_APP_PROBE_REQ_2_4;
+ template_id_5 = CMD_TEMPL_APP_PROBE_REQ_5;
+ }
+
rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
if (band == IEEE80211_BAND_2GHZ)
ret = wl1271_cmd_template_set(wl, role_id,
- CMD_TEMPL_CFG_PROBE_REQ_2_4,
+ template_id_2_4,
skb->data, skb->len, 0, rate);
else
ret = wl1271_cmd_template_set(wl, role_id,
- CMD_TEMPL_CFG_PROBE_REQ_5,
+ template_id_5,
skb->data, skb->len, 0, rate);
out:
@@ -1412,6 +1452,7 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
{
struct wl12xx_cmd_remove_peer *cmd;
int ret;
+ bool timeout = false;
wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid);
@@ -1432,12 +1473,16 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
goto out_free;
}
+ ret = wl1271_cmd_wait_for_event_or_timeout(wl,
+ PEER_REMOVE_COMPLETE_EVENT_ID,
+ &timeout);
/*
* We are ok with a timeout here. The event is sometimes not sent
- * due to a firmware bug.
+ * due to a firmware bug. In case of another error (like SDIO timeout)
+ * queue a recovery.
*/
- wl1271_cmd_wait_for_event_or_timeout(wl,
- PEER_REMOVE_COMPLETE_EVENT_ID);
+ if (ret)
+ wl12xx_queue_recovery_work(wl);
out_free:
kfree(cmd);
@@ -1754,7 +1799,9 @@ int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
return -EINVAL;
/* flush all pending packets */
- wl1271_tx_work_locked(wl);
+ ret = wlcore_tx_work_locked(wl);
+ if (ret < 0)
+ goto out;
if (test_bit(wlvif->dev_role_id, wl->roc_map)) {
ret = wl12xx_croc(wl, wlvif->dev_role_id);
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h
index 85171f2bf68e..d7d9f801e506 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.h
+++ b/drivers/net/wireless/ti/wlcore/cmd.h
@@ -58,7 +58,7 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 role_id, u8 band,
const u8 *ssid, size_t ssid_len,
- const u8 *ie, size_t ie_len);
+ const u8 *ie, size_t ie_len, bool sched_scan);
struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct sk_buff *skb);
@@ -172,8 +172,8 @@ enum cmd_templ {
CMD_TEMPL_PS_POLL,
CMD_TEMPL_KLV,
CMD_TEMPL_DISCONNECT,
- CMD_TEMPL_PROBE_REQ_2_4, /* for firmware internal use only */
- CMD_TEMPL_PROBE_REQ_5, /* for firmware internal use only */
+ CMD_TEMPL_APP_PROBE_REQ_2_4,
+ CMD_TEMPL_APP_PROBE_REQ_5,
CMD_TEMPL_BAR, /* for firmware internal use only */
CMD_TEMPL_CTS, /*
* For CTS-to-self (FastCTS) mechanism
@@ -652,4 +652,25 @@ struct wl12xx_cmd_stop_channel_switch {
struct wl1271_cmd_header header;
} __packed;
+/* Used to check radio status after calibration */
+#define MAX_TLV_LENGTH 500
+#define TEST_CMD_P2G_CAL 2 /* TX BiP */
+
+struct wl1271_cmd_cal_p2g {
+ struct wl1271_cmd_header header;
+
+ struct wl1271_cmd_test_header test;
+
+ __le32 ver;
+ __le16 len;
+ u8 buf[MAX_TLV_LENGTH];
+ u8 type;
+ u8 padding;
+
+ __le16 radio_status;
+
+ u8 sub_band_mask;
+ u8 padding2;
+} __packed;
+
#endif /* __WL1271_CMD_H__ */
diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h
index 03c635872335..d77224f2ac6b 100644
--- a/drivers/net/wireless/ti/wlcore/conf.h
+++ b/drivers/net/wireless/ti/wlcore/conf.h
@@ -951,6 +951,12 @@ struct conf_conn_settings {
* Range: u16
*/
u8 max_listen_interval;
+
+ /*
+ * Default sleep authorization for a new STA interface. This determines
+ * whether we can go to ELP.
+ */
+ u8 sta_sleep_auth;
} __packed;
enum {
@@ -1276,7 +1282,7 @@ struct conf_hangover_settings {
* version, the two LSB are the lower driver's private conf
* version.
*/
-#define WLCORE_CONF_VERSION (0x0001 << 16)
+#define WLCORE_CONF_VERSION (0x0002 << 16)
#define WLCORE_CONF_MASK 0xffff0000
#define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \
sizeof(struct wlcore_conf))
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c
index 689a847005c9..80dbc5304fac 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@ -38,6 +38,8 @@
/* ms */
#define WL1271_DEBUGFS_STATS_LIFETIME 1000
+#define WLCORE_MAX_BLOCK_SIZE ((size_t)(4*PAGE_SIZE))
+
/* debugfs macros idea from mac80211 */
int wl1271_format_buffer(char __user *userbuf, size_t count,
loff_t *ppos, char *fmt, ...)
@@ -963,6 +965,257 @@ static const struct file_operations fw_stats_raw_ops = {
.llseek = default_llseek,
};
+static ssize_t sleep_auth_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+
+ return wl1271_format_buffer(user_buf, count,
+ ppos, "%d\n",
+ wl->sleep_auth);
+}
+
+static ssize_t sleep_auth_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+ unsigned long value;
+ int ret;
+
+ ret = kstrtoul_from_user(user_buf, count, 0, &value);
+ if (ret < 0) {
+ wl1271_warning("illegal value in sleep_auth");
+ return -EINVAL;
+ }
+
+ if (value < 0 || value > WL1271_PSM_MAX) {
+ wl1271_warning("sleep_auth must be between 0 and %d",
+ WL1271_PSM_MAX);
+ return -ERANGE;
+ }
+
+ mutex_lock(&wl->mutex);
+
+ wl->conf.conn.sta_sleep_auth = value;
+
+ if (wl->state == WL1271_STATE_OFF) {
+ /* this will show up on "read" in case we are off */
+ wl->sleep_auth = value;
+ goto out;
+ }
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_acx_sleep_auth(wl, value);
+ if (ret < 0)
+ goto out_sleep;
+
+out_sleep:
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+ return count;
+}
+
+static const struct file_operations sleep_auth_ops = {
+ .read = sleep_auth_read,
+ .write = sleep_auth_write,
+ .open = simple_open,
+ .llseek = default_llseek,
+};
+
+static ssize_t dev_mem_read(struct file *file,
+ char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+ struct wlcore_partition_set part, old_part;
+ size_t bytes = count;
+ int ret;
+ char *buf;
+
+ /* only requests of dword-aligned size and offset are supported */
+ if (bytes % 4)
+ return -EINVAL;
+
+ if (*ppos % 4)
+ return -EINVAL;
+
+ /* function should return in reasonable time */
+ bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE);
+
+ if (bytes == 0)
+ return -EINVAL;
+
+ memset(&part, 0, sizeof(part));
+ part.mem.start = file->f_pos;
+ part.mem.size = bytes;
+
+ buf = kmalloc(bytes, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ mutex_lock(&wl->mutex);
+
+ if (wl->state == WL1271_STATE_OFF) {
+ ret = -EFAULT;
+ goto skip_read;
+ }
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto skip_read;
+
+ /* store current partition and switch partition */
+ memcpy(&old_part, &wl->curr_part, sizeof(old_part));
+ ret = wlcore_set_partition(wl, &part);
+ if (ret < 0)
+ goto part_err;
+
+ ret = wlcore_raw_read(wl, 0, buf, bytes, false);
+ if (ret < 0)
+ goto read_err;
+
+read_err:
+ /* recover partition */
+ ret = wlcore_set_partition(wl, &old_part);
+ if (ret < 0)
+ goto part_err;
+
+part_err:
+ wl1271_ps_elp_sleep(wl);
+
+skip_read:
+ mutex_unlock(&wl->mutex);
+
+ if (ret == 0) {
+ ret = copy_to_user(user_buf, buf, bytes);
+ if (ret < bytes) {
+ bytes -= ret;
+ *ppos += bytes;
+ ret = 0;
+ } else {
+ ret = -EFAULT;
+ }
+ }
+
+ kfree(buf);
+
+ return ((ret == 0) ? bytes : ret);
+}
+
+static ssize_t dev_mem_write(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+ struct wlcore_partition_set part, old_part;
+ size_t bytes = count;
+ int ret;
+ char *buf;
+
+ /* only requests of dword-aligned size and offset are supported */
+ if (bytes % 4)
+ return -EINVAL;
+
+ if (*ppos % 4)
+ return -EINVAL;
+
+ /* function should return in reasonable time */
+ bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE);
+
+ if (bytes == 0)
+ return -EINVAL;
+
+ memset(&part, 0, sizeof(part));
+ part.mem.start = file->f_pos;
+ part.mem.size = bytes;
+
+ buf = kmalloc(bytes, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = copy_from_user(buf, user_buf, bytes);
+ if (ret) {
+ ret = -EFAULT;
+ goto err_out;
+ }
+
+ mutex_lock(&wl->mutex);
+
+ if (wl->state == WL1271_STATE_OFF) {
+ ret = -EFAULT;
+ goto skip_write;
+ }
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto skip_write;
+
+ /* store current partition and switch partition */
+ memcpy(&old_part, &wl->curr_part, sizeof(old_part));
+ ret = wlcore_set_partition(wl, &part);
+ if (ret < 0)
+ goto part_err;
+
+ ret = wlcore_raw_write(wl, 0, buf, bytes, false);
+ if (ret < 0)
+ goto write_err;
+
+write_err:
+ /* recover partition */
+ ret = wlcore_set_partition(wl, &old_part);
+ if (ret < 0)
+ goto part_err;
+
+part_err:
+ wl1271_ps_elp_sleep(wl);
+
+skip_write:
+ mutex_unlock(&wl->mutex);
+
+ if (ret == 0)
+ *ppos += bytes;
+
+err_out:
+ kfree(buf);
+
+ return ((ret == 0) ? bytes : ret);
+}
+
+static loff_t dev_mem_seek(struct file *file, loff_t offset, int orig)
+{
+ loff_t ret;
+
+ /* only requests of dword-aligned size and offset are supported */
+ if (offset % 4)
+ return -EINVAL;
+
+ switch (orig) {
+ case SEEK_SET:
+ file->f_pos = offset;
+ ret = file->f_pos;
+ break;
+ case SEEK_CUR:
+ file->f_pos += offset;
+ ret = file->f_pos;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static const struct file_operations dev_mem_ops = {
+ .open = simple_open,
+ .read = dev_mem_read,
+ .write = dev_mem_write,
+ .llseek = dev_mem_seek,
+};
+
static int wl1271_debugfs_add_files(struct wl1271 *wl,
struct dentry *rootdir)
{
@@ -988,6 +1241,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD(irq_blk_threshold, rootdir);
DEBUGFS_ADD(irq_timeout, rootdir);
DEBUGFS_ADD(fw_stats_raw, rootdir);
+ DEBUGFS_ADD(sleep_auth, rootdir);
streaming = debugfs_create_dir("rx_streaming", rootdir);
if (!streaming || IS_ERR(streaming))
@@ -996,6 +1250,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming);
DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming);
+ DEBUGFS_ADD_PREFIX(dev, mem, rootdir);
return 0;
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c
index c976f0409865..48907054d493 100644
--- a/drivers/net/wireless/ti/wlcore/event.c
+++ b/drivers/net/wireless/ti/wlcore/event.c
@@ -105,6 +105,7 @@ static int wl1271_event_process(struct wl1271 *wl)
u32 vector;
bool disconnect_sta = false;
unsigned long sta_bitmap = 0;
+ int ret;
wl1271_event_mbox_dump(mbox);
@@ -228,7 +229,9 @@ static int wl1271_event_process(struct wl1271 *wl)
if ((vector & DUMMY_PACKET_EVENT_ID)) {
wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
- wl1271_tx_dummy_packet(wl);
+ ret = wl1271_tx_dummy_packet(wl);
+ if (ret < 0)
+ return ret;
}
/*
@@ -301,8 +304,10 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
return -EINVAL;
/* first we read the mbox descriptor */
- wl1271_read(wl, wl->mbox_ptr[mbox_num], wl->mbox,
- sizeof(*wl->mbox), false);
+ ret = wlcore_read(wl, wl->mbox_ptr[mbox_num], wl->mbox,
+ sizeof(*wl->mbox), false);
+ if (ret < 0)
+ return ret;
/* process the descriptor */
ret = wl1271_event_process(wl);
@@ -313,7 +318,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
* TODO: we just need this because one bit is in a different
* place. Is there any better way?
*/
- wl->ops->ack_event(wl);
+ ret = wl->ops->ack_event(wl);
- return 0;
+ return ret;
}
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
index 9e7787ba9610..2673d783ec1e 100644
--- a/drivers/net/wireless/ti/wlcore/hw_ops.h
+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
@@ -65,11 +65,13 @@ wlcore_hw_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
return wl->ops->get_rx_buf_align(wl, rx_desc);
}
-static inline void
+static inline int
wlcore_hw_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
{
if (wl->ops->prepare_read)
- wl->ops->prepare_read(wl, rx_desc, len);
+ return wl->ops->prepare_read(wl, rx_desc, len);
+
+ return 0;
}
static inline u32
@@ -81,10 +83,12 @@ wlcore_hw_get_rx_packet_len(struct wl1271 *wl, void *rx_data, u32 data_len)
return wl->ops->get_rx_packet_len(wl, rx_data, data_len);
}
-static inline void wlcore_hw_tx_delayed_compl(struct wl1271 *wl)
+static inline int wlcore_hw_tx_delayed_compl(struct wl1271 *wl)
{
if (wl->ops->tx_delayed_compl)
- wl->ops->tx_delayed_compl(wl);
+ return wl->ops->tx_delayed_compl(wl);
+
+ return 0;
}
static inline void wlcore_hw_tx_immediate_compl(struct wl1271 *wl)
diff --git a/drivers/net/wireless/ti/wlcore/ini.h b/drivers/net/wireless/ti/wlcore/ini.h
index 4cf9ecc56212..d24fe3bbc672 100644
--- a/drivers/net/wireless/ti/wlcore/ini.h
+++ b/drivers/net/wireless/ti/wlcore/ini.h
@@ -172,7 +172,19 @@ struct wl128x_ini_fem_params_5 {
/* NVS data structure */
#define WL1271_INI_NVS_SECTION_SIZE 468
-#define WL1271_INI_FEM_MODULE_COUNT 2
+
+/* We have four FEM module types: 0-RFMD, 1-TQS, 2-SKW, 3-TQS_HP */
+#define WL1271_INI_FEM_MODULE_COUNT 4
+
+/*
+ * In NVS we only store two FEM module entries -
+ * FEM modules 0,2,3 are stored in entry 0
+ * FEM module 1 is stored in entry 1
+ */
+#define WL12XX_NVS_FEM_MODULE_COUNT 2
+
+#define WL12XX_FEM_TO_NVS_ENTRY(ini_fem_module) \
+ ((ini_fem_module) == 1 ? 1 : 0)
#define WL1271_INI_LEGACY_NVS_FILE_SIZE 800
@@ -188,13 +200,13 @@ struct wl1271_nvs_file {
struct {
struct wl1271_ini_fem_params_2 params;
u8 padding;
- } dyn_radio_params_2[WL1271_INI_FEM_MODULE_COUNT];
+ } dyn_radio_params_2[WL12XX_NVS_FEM_MODULE_COUNT];
struct wl1271_ini_band_params_5 stat_radio_params_5;
u8 padding3;
struct {
struct wl1271_ini_fem_params_5 params;
u8 padding;
- } dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT];
+ } dyn_radio_params_5[WL12XX_NVS_FEM_MODULE_COUNT];
} __packed;
struct wl128x_nvs_file {
@@ -209,12 +221,12 @@ struct wl128x_nvs_file {
struct {
struct wl128x_ini_fem_params_2 params;
u8 padding;
- } dyn_radio_params_2[WL1271_INI_FEM_MODULE_COUNT];
+ } dyn_radio_params_2[WL12XX_NVS_FEM_MODULE_COUNT];
struct wl128x_ini_band_params_5 stat_radio_params_5;
u8 padding3;
struct {
struct wl128x_ini_fem_params_5 params;
u8 padding;
- } dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT];
+ } dyn_radio_params_5[WL12XX_NVS_FEM_MODULE_COUNT];
} __packed;
#endif
diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c
index 645abd4b660d..a3c867786df8 100644
--- a/drivers/net/wireless/ti/wlcore/init.c
+++ b/drivers/net/wireless/ti/wlcore/init.c
@@ -54,6 +54,22 @@ int wl1271_init_templates_config(struct wl1271 *wl)
if (ret < 0)
return ret;
+ if (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL) {
+ ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
+ CMD_TEMPL_APP_PROBE_REQ_2_4, NULL,
+ WL1271_CMD_TEMPL_MAX_SIZE,
+ 0, WL1271_RATE_AUTOMATIC);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
+ CMD_TEMPL_APP_PROBE_REQ_5, NULL,
+ WL1271_CMD_TEMPL_MAX_SIZE,
+ 0, WL1271_RATE_AUTOMATIC);
+ if (ret < 0)
+ return ret;
+ }
+
ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
CMD_TEMPL_NULL_DATA, NULL,
sizeof(struct wl12xx_null_data_template),
@@ -554,29 +570,28 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
int ret, i;
- /*
- * consider all existing roles before configuring psm.
- * TODO: reconfigure on interface removal.
- */
- if (!wl->ap_count) {
- if (is_ap) {
- /* Configure for power always on */
+ /* consider all existing roles before configuring psm. */
+
+ if (wl->ap_count == 0 && is_ap) { /* first AP */
+ /* Configure for power always on */
+ ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
+ if (ret < 0)
+ return ret;
+ /* first STA, no APs */
+ } else if (wl->sta_count == 0 && wl->ap_count == 0 && !is_ap) {
+ u8 sta_auth = wl->conf.conn.sta_sleep_auth;
+ /* Configure for power according to debugfs */
+ if (sta_auth != WL1271_PSM_ILLEGAL)
+ ret = wl1271_acx_sleep_auth(wl, sta_auth);
+ /* Configure for power always on */
+ else if (wl->quirks & WLCORE_QUIRK_NO_ELP)
ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
- if (ret < 0)
- return ret;
- } else if (!wl->sta_count) {
- if (wl->quirks & WLCORE_QUIRK_NO_ELP) {
- /* Configure for power always on */
- ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
- if (ret < 0)
- return ret;
- } else {
- /* Configure for ELP power saving */
- ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
- if (ret < 0)
- return ret;
- }
- }
+ /* Configure for ELP power saving */
+ else
+ ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
+
+ if (ret < 0)
+ return ret;
}
/* Mode specific init */
diff --git a/drivers/net/wireless/ti/wlcore/io.c b/drivers/net/wireless/ti/wlcore/io.c
index 7cd0081aede5..68e74eefd296 100644
--- a/drivers/net/wireless/ti/wlcore/io.c
+++ b/drivers/net/wireless/ti/wlcore/io.c
@@ -48,12 +48,24 @@ void wlcore_disable_interrupts(struct wl1271 *wl)
}
EXPORT_SYMBOL_GPL(wlcore_disable_interrupts);
+void wlcore_disable_interrupts_nosync(struct wl1271 *wl)
+{
+ disable_irq_nosync(wl->irq);
+}
+EXPORT_SYMBOL_GPL(wlcore_disable_interrupts_nosync);
+
void wlcore_enable_interrupts(struct wl1271 *wl)
{
enable_irq(wl->irq);
}
EXPORT_SYMBOL_GPL(wlcore_enable_interrupts);
+void wlcore_synchronize_interrupts(struct wl1271 *wl)
+{
+ synchronize_irq(wl->irq);
+}
+EXPORT_SYMBOL_GPL(wlcore_synchronize_interrupts);
+
int wlcore_translate_addr(struct wl1271 *wl, int addr)
{
struct wlcore_partition_set *part = &wl->curr_part;
@@ -122,9 +134,11 @@ EXPORT_SYMBOL_GPL(wlcore_translate_addr);
* | |
*
*/
-void wlcore_set_partition(struct wl1271 *wl,
- const struct wlcore_partition_set *p)
+int wlcore_set_partition(struct wl1271 *wl,
+ const struct wlcore_partition_set *p)
{
+ int ret;
+
/* copy partition info */
memcpy(&wl->curr_part, p, sizeof(*p));
@@ -137,28 +151,41 @@ void wlcore_set_partition(struct wl1271 *wl,
wl1271_debug(DEBUG_IO, "mem3_start %08X mem3_size %08X",
p->mem3.start, p->mem3.size);
- wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start);
- wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
- wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start);
- wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
- wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
- wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
+ ret = wlcore_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start);
+ if (ret < 0)
+ goto out;
+
+ ret = wlcore_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
+ if (ret < 0)
+ goto out;
+
+ ret = wlcore_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start);
+ if (ret < 0)
+ goto out;
+
+ ret = wlcore_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
+ if (ret < 0)
+ goto out;
+
+ ret = wlcore_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
+ if (ret < 0)
+ goto out;
+
+ ret = wlcore_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
+ if (ret < 0)
+ goto out;
+
/*
* We don't need the size of the last partition, as it is
* automatically calculated based on the total memory size and
* the sizes of the previous partitions.
*/
- wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
-}
-EXPORT_SYMBOL_GPL(wlcore_set_partition);
-
-void wlcore_select_partition(struct wl1271 *wl, u8 part)
-{
- wl1271_debug(DEBUG_IO, "setting partition %d", part);
+ ret = wlcore_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
- wlcore_set_partition(wl, &wl->ptable[part]);
+out:
+ return ret;
}
-EXPORT_SYMBOL_GPL(wlcore_select_partition);
+EXPORT_SYMBOL_GPL(wlcore_set_partition);
void wl1271_io_reset(struct wl1271 *wl)
{
diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h
index 8942954b56a0..259149f36fae 100644
--- a/drivers/net/wireless/ti/wlcore/io.h
+++ b/drivers/net/wireless/ti/wlcore/io.h
@@ -45,86 +45,122 @@
struct wl1271;
void wlcore_disable_interrupts(struct wl1271 *wl);
+void wlcore_disable_interrupts_nosync(struct wl1271 *wl);
void wlcore_enable_interrupts(struct wl1271 *wl);
+void wlcore_synchronize_interrupts(struct wl1271 *wl);
void wl1271_io_reset(struct wl1271 *wl);
void wl1271_io_init(struct wl1271 *wl);
int wlcore_translate_addr(struct wl1271 *wl, int addr);
/* Raw target IO, address is not translated */
-static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
- size_t len, bool fixed)
+static inline int __must_check wlcore_raw_write(struct wl1271 *wl, int addr,
+ void *buf, size_t len,
+ bool fixed)
{
- wl->if_ops->write(wl->dev, addr, buf, len, fixed);
+ int ret;
+
+ if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags))
+ return -EIO;
+
+ ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed);
+ if (ret && wl->state != WL1271_STATE_OFF)
+ set_bit(WL1271_FLAG_IO_FAILED, &wl->flags);
+
+ return ret;
}
-static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
- size_t len, bool fixed)
+static inline int __must_check wlcore_raw_read(struct wl1271 *wl, int addr,
+ void *buf, size_t len,
+ bool fixed)
{
- wl->if_ops->read(wl->dev, addr, buf, len, fixed);
+ int ret;
+
+ if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags))
+ return -EIO;
+
+ ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed);
+ if (ret && wl->state != WL1271_STATE_OFF)
+ set_bit(WL1271_FLAG_IO_FAILED, &wl->flags);
+
+ return ret;
}
-static inline void wlcore_raw_read_data(struct wl1271 *wl, int reg, void *buf,
- size_t len, bool fixed)
+static inline int __must_check wlcore_raw_read_data(struct wl1271 *wl, int reg,
+ void *buf, size_t len,
+ bool fixed)
{
- wl1271_raw_read(wl, wl->rtable[reg], buf, len, fixed);
+ return wlcore_raw_read(wl, wl->rtable[reg], buf, len, fixed);
}
-static inline void wlcore_raw_write_data(struct wl1271 *wl, int reg, void *buf,
- size_t len, bool fixed)
+static inline int __must_check wlcore_raw_write_data(struct wl1271 *wl, int reg,
+ void *buf, size_t len,
+ bool fixed)
{
- wl1271_raw_write(wl, wl->rtable[reg], buf, len, fixed);
+ return wlcore_raw_write(wl, wl->rtable[reg], buf, len, fixed);
}
-static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr)
+static inline int __must_check wlcore_raw_read32(struct wl1271 *wl, int addr,
+ u32 *val)
{
- wl1271_raw_read(wl, addr, &wl->buffer_32,
- sizeof(wl->buffer_32), false);
+ int ret;
+
+ ret = wlcore_raw_read(wl, addr, &wl->buffer_32,
+ sizeof(wl->buffer_32), false);
+ if (ret < 0)
+ return ret;
+
+ if (val)
+ *val = le32_to_cpu(wl->buffer_32);
- return le32_to_cpu(wl->buffer_32);
+ return 0;
}
-static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val)
+static inline int __must_check wlcore_raw_write32(struct wl1271 *wl, int addr,
+ u32 val)
{
wl->buffer_32 = cpu_to_le32(val);
- wl1271_raw_write(wl, addr, &wl->buffer_32,
- sizeof(wl->buffer_32), false);
+ return wlcore_raw_write(wl, addr, &wl->buffer_32,
+ sizeof(wl->buffer_32), false);
}
-static inline void wl1271_read(struct wl1271 *wl, int addr, void *buf,
- size_t len, bool fixed)
+static inline int __must_check wlcore_read(struct wl1271 *wl, int addr,
+ void *buf, size_t len, bool fixed)
{
int physical;
physical = wlcore_translate_addr(wl, addr);
- wl1271_raw_read(wl, physical, buf, len, fixed);
+ return wlcore_raw_read(wl, physical, buf, len, fixed);
}
-static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf,
- size_t len, bool fixed)
+static inline int __must_check wlcore_write(struct wl1271 *wl, int addr,
+ void *buf, size_t len, bool fixed)
{
int physical;
physical = wlcore_translate_addr(wl, addr);
- wl1271_raw_write(wl, physical, buf, len, fixed);
+ return wlcore_raw_write(wl, physical, buf, len, fixed);
}
-static inline void wlcore_write_data(struct wl1271 *wl, int reg, void *buf,
- size_t len, bool fixed)
+static inline int __must_check wlcore_write_data(struct wl1271 *wl, int reg,
+ void *buf, size_t len,
+ bool fixed)
{
- wl1271_write(wl, wl->rtable[reg], buf, len, fixed);
+ return wlcore_write(wl, wl->rtable[reg], buf, len, fixed);
}
-static inline void wlcore_read_data(struct wl1271 *wl, int reg, void *buf,
- size_t len, bool fixed)
+static inline int __must_check wlcore_read_data(struct wl1271 *wl, int reg,
+ void *buf, size_t len,
+ bool fixed)
{
- wl1271_read(wl, wl->rtable[reg], buf, len, fixed);
+ return wlcore_read(wl, wl->rtable[reg], buf, len, fixed);
}
-static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr,
- void *buf, size_t len, bool fixed)
+static inline int __must_check wlcore_read_hwaddr(struct wl1271 *wl, int hwaddr,
+ void *buf, size_t len,
+ bool fixed)
{
int physical;
int addr;
@@ -134,34 +170,47 @@ static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr,
physical = wlcore_translate_addr(wl, addr);
- wl1271_raw_read(wl, physical, buf, len, fixed);
+ return wlcore_raw_read(wl, physical, buf, len, fixed);
}
-static inline u32 wl1271_read32(struct wl1271 *wl, int addr)
+static inline int __must_check wlcore_read32(struct wl1271 *wl, int addr,
+ u32 *val)
{
- return wl1271_raw_read32(wl, wlcore_translate_addr(wl, addr));
+ return wlcore_raw_read32(wl, wlcore_translate_addr(wl, addr), val);
}
-static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
+static inline int __must_check wlcore_write32(struct wl1271 *wl, int addr,
+ u32 val)
{
- wl1271_raw_write32(wl, wlcore_translate_addr(wl, addr), val);
+ return wlcore_raw_write32(wl, wlcore_translate_addr(wl, addr), val);
}
-static inline u32 wlcore_read_reg(struct wl1271 *wl, int reg)
+static inline int __must_check wlcore_read_reg(struct wl1271 *wl, int reg,
+ u32 *val)
{
- return wl1271_raw_read32(wl,
- wlcore_translate_addr(wl, wl->rtable[reg]));
+ return wlcore_raw_read32(wl,
+ wlcore_translate_addr(wl, wl->rtable[reg]),
+ val);
}
-static inline void wlcore_write_reg(struct wl1271 *wl, int reg, u32 val)
+static inline int __must_check wlcore_write_reg(struct wl1271 *wl, int reg,
+ u32 val)
{
- wl1271_raw_write32(wl, wlcore_translate_addr(wl, wl->rtable[reg]), val);
+ return wlcore_raw_write32(wl,
+ wlcore_translate_addr(wl, wl->rtable[reg]),
+ val);
}
static inline void wl1271_power_off(struct wl1271 *wl)
{
- wl->if_ops->power(wl->dev, false);
- clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+ int ret;
+
+ if (!test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags))
+ return;
+
+ ret = wl->if_ops->power(wl->dev, false);
+ if (!ret)
+ clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
}
static inline int wl1271_power_on(struct wl1271 *wl)
@@ -173,8 +222,8 @@ static inline int wl1271_power_on(struct wl1271 *wl)
return ret;
}
-void wlcore_set_partition(struct wl1271 *wl,
- const struct wlcore_partition_set *p);
+int wlcore_set_partition(struct wl1271 *wl,
+ const struct wlcore_partition_set *p);
bool wl1271_set_block_size(struct wl1271 *wl);
@@ -182,6 +231,4 @@ bool wl1271_set_block_size(struct wl1271 *wl);
int wl1271_tx_dummy_packet(struct wl1271 *wl);
-void wlcore_select_partition(struct wl1271 *wl, u8 part);
-
#endif
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 1156e3f578c1..9f04b64dfa33 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -62,7 +62,7 @@ static bool no_recovery;
static void __wl1271_op_remove_interface(struct wl1271 *wl,
struct ieee80211_vif *vif,
bool reset_tx_queues);
-static void wl1271_op_stop(struct ieee80211_hw *hw);
+static void wlcore_op_stop_locked(struct wl1271 *wl);
static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif);
static int wl12xx_set_authorized(struct wl1271 *wl,
@@ -378,9 +378,9 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
}
}
-static void wl12xx_fw_status(struct wl1271 *wl,
- struct wl_fw_status_1 *status_1,
- struct wl_fw_status_2 *status_2)
+static int wlcore_fw_status(struct wl1271 *wl,
+ struct wl_fw_status_1 *status_1,
+ struct wl_fw_status_2 *status_2)
{
struct wl12xx_vif *wlvif;
struct timespec ts;
@@ -388,12 +388,15 @@ static void wl12xx_fw_status(struct wl1271 *wl,
int avail, freed_blocks;
int i;
size_t status_len;
+ int ret;
status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) +
sizeof(*status_2) + wl->fw_status_priv_len;
- wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1,
- status_len, false);
+ ret = wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1,
+ status_len, false);
+ if (ret < 0)
+ return ret;
wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
"drv_rx_counter = %d, tx_results_counter = %d)",
@@ -462,6 +465,8 @@ static void wl12xx_fw_status(struct wl1271 *wl,
getnstimeofday(&ts);
wl->time_offset = (timespec_to_ns(&ts) >> 10) -
(s64)le32_to_cpu(status_2->fw_localtime);
+
+ return 0;
}
static void wl1271_flush_deferred_work(struct wl1271 *wl)
@@ -489,20 +494,15 @@ static void wl1271_netstack_work(struct work_struct *work)
#define WL1271_IRQ_MAX_LOOPS 256
-static irqreturn_t wl1271_irq(int irq, void *cookie)
+static int wlcore_irq_locked(struct wl1271 *wl)
{
- int ret;
+ int ret = 0;
u32 intr;
int loopcount = WL1271_IRQ_MAX_LOOPS;
- struct wl1271 *wl = (struct wl1271 *)cookie;
bool done = false;
unsigned int defer_count;
unsigned long flags;
- /* TX might be handled here, avoid redundant work */
- set_bit(WL1271_FLAG_TX_PENDING, &wl->flags);
- cancel_work_sync(&wl->tx_work);
-
/*
* In case edge triggered interrupt must be used, we cannot iterate
* more than once without introducing race conditions with the hardirq.
@@ -510,8 +510,6 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ)
loopcount = 1;
- mutex_lock(&wl->mutex);
-
wl1271_debug(DEBUG_IRQ, "IRQ work");
if (unlikely(wl->state == WL1271_STATE_OFF))
@@ -530,7 +528,9 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
smp_mb__after_clear_bit();
- wl12xx_fw_status(wl, wl->fw_status_1, wl->fw_status_2);
+ ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2);
+ if (ret < 0)
+ goto out;
wlcore_hw_tx_immediate_compl(wl);
@@ -544,7 +544,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) {
wl1271_error("HW watchdog interrupt received! starting recovery.");
wl->watchdog_recovery = true;
- wl12xx_queue_recovery_work(wl);
+ ret = -EIO;
/* restarting the chip. ignore any other interrupt. */
goto out;
@@ -554,7 +554,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
wl1271_error("SW watchdog interrupt received! "
"starting recovery.");
wl->watchdog_recovery = true;
- wl12xx_queue_recovery_work(wl);
+ ret = -EIO;
/* restarting the chip. ignore any other interrupt. */
goto out;
@@ -563,7 +563,9 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
if (likely(intr & WL1271_ACX_INTR_DATA)) {
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
- wl12xx_rx(wl, wl->fw_status_1);
+ ret = wlcore_rx(wl, wl->fw_status_1);
+ if (ret < 0)
+ goto out;
/* Check if any tx blocks were freed */
spin_lock_irqsave(&wl->wl_lock, flags);
@@ -574,13 +576,17 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
* In order to avoid starvation of the TX path,
* call the work function directly.
*/
- wl1271_tx_work_locked(wl);
+ ret = wlcore_tx_work_locked(wl);
+ if (ret < 0)
+ goto out;
} else {
spin_unlock_irqrestore(&wl->wl_lock, flags);
}
/* check for tx results */
- wlcore_hw_tx_delayed_compl(wl);
+ ret = wlcore_hw_tx_delayed_compl(wl);
+ if (ret < 0)
+ goto out;
/* Make sure the deferred queues don't get too long */
defer_count = skb_queue_len(&wl->deferred_tx_queue) +
@@ -591,12 +597,16 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
if (intr & WL1271_ACX_INTR_EVENT_A) {
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A");
- wl1271_event_handle(wl, 0);
+ ret = wl1271_event_handle(wl, 0);
+ if (ret < 0)
+ goto out;
}
if (intr & WL1271_ACX_INTR_EVENT_B) {
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B");
- wl1271_event_handle(wl, 1);
+ ret = wl1271_event_handle(wl, 1);
+ if (ret < 0)
+ goto out;
}
if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
@@ -610,6 +620,25 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
wl1271_ps_elp_sleep(wl);
out:
+ return ret;
+}
+
+static irqreturn_t wlcore_irq(int irq, void *cookie)
+{
+ int ret;
+ unsigned long flags;
+ struct wl1271 *wl = cookie;
+
+ /* TX might be handled here, avoid redundant work */
+ set_bit(WL1271_FLAG_TX_PENDING, &wl->flags);
+ cancel_work_sync(&wl->tx_work);
+
+ mutex_lock(&wl->mutex);
+
+ ret = wlcore_irq_locked(wl);
+ if (ret)
+ wl12xx_queue_recovery_work(wl);
+
spin_lock_irqsave(&wl->wl_lock, flags);
/* In case TX was not handled here, queue TX work */
clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags);
@@ -743,8 +772,13 @@ out:
void wl12xx_queue_recovery_work(struct wl1271 *wl)
{
- if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
+ WARN_ON(!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));
+
+ /* Avoid a recursive recovery */
+ if (!test_and_set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) {
+ wlcore_disable_interrupts_nosync(wl);
ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ }
}
size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen)
@@ -770,14 +804,17 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen)
return len;
}
+#define WLCORE_FW_LOG_END 0x2000000
+
static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
{
u32 addr;
- u32 first_addr;
+ u32 offset;
+ u32 end_of_log;
u8 *block;
+ int ret;
if ((wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED) ||
- (wl->conf.fwlog.mode != WL12XX_FWLOG_ON_DEMAND) ||
(wl->conf.fwlog.mem_blocks == 0))
return;
@@ -791,34 +828,47 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
* Make sure the chip is awake and the logger isn't active.
* Do not send a stop fwlog command if the fw is hanged.
*/
- if (!wl1271_ps_elp_wakeup(wl) && !wl->watchdog_recovery)
- wl12xx_cmd_stop_fwlog(wl);
- else
+ if (wl1271_ps_elp_wakeup(wl))
goto out;
+ if (!wl->watchdog_recovery)
+ wl12xx_cmd_stop_fwlog(wl);
/* Read the first memory block address */
- wl12xx_fw_status(wl, wl->fw_status_1, wl->fw_status_2);
- first_addr = le32_to_cpu(wl->fw_status_2->log_start_addr);
- if (!first_addr)
+ ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2);
+ if (ret < 0)
+ goto out;
+
+ addr = le32_to_cpu(wl->fw_status_2->log_start_addr);
+ if (!addr)
goto out;
+ if (wl->conf.fwlog.mode == WL12XX_FWLOG_CONTINUOUS) {
+ offset = sizeof(addr) + sizeof(struct wl1271_rx_descriptor);
+ end_of_log = WLCORE_FW_LOG_END;
+ } else {
+ offset = sizeof(addr);
+ end_of_log = addr;
+ }
+
/* Traverse the memory blocks linked list */
- addr = first_addr;
do {
memset(block, 0, WL12XX_HW_BLOCK_SIZE);
- wl1271_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE,
- false);
+ ret = wlcore_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE,
+ false);
+ if (ret < 0)
+ goto out;
/*
* Memory blocks are linked to one another. The first 4 bytes
* of each memory block hold the hardware address of the next
- * one. The last memory block points to the first one.
+ * one. The last memory block points to the first one in
+ * on demand mode and is equal to 0x2000000 in continuous mode.
*/
addr = le32_to_cpup((__le32 *)block);
- if (!wl12xx_copy_fwlog(wl, block + sizeof(addr),
- WL12XX_HW_BLOCK_SIZE - sizeof(addr)))
+ if (!wl12xx_copy_fwlog(wl, block + offset,
+ WL12XX_HW_BLOCK_SIZE - offset))
break;
- } while (addr && (addr != first_addr));
+ } while (addr && (addr != end_of_log));
wake_up_interruptible(&wl->fwlog_waitq);
@@ -826,6 +876,34 @@ out:
kfree(block);
}
+static void wlcore_print_recovery(struct wl1271 *wl)
+{
+ u32 pc = 0;
+ u32 hint_sts = 0;
+ int ret;
+
+ wl1271_info("Hardware recovery in progress. FW ver: %s",
+ wl->chip.fw_ver_str);
+
+ /* change partitions momentarily so we can read the FW pc */
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
+ if (ret < 0)
+ return;
+
+ ret = wlcore_read_reg(wl, REG_PC_ON_RECOVERY, &pc);
+ if (ret < 0)
+ return;
+
+ ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &hint_sts);
+ if (ret < 0)
+ return;
+
+ wl1271_info("pc: 0x%x, hint_sts: 0x%08x", pc, hint_sts);
+
+ wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
+}
+
+
static void wl1271_recovery_work(struct work_struct *work)
{
struct wl1271 *wl =
@@ -838,26 +916,16 @@ static void wl1271_recovery_work(struct work_struct *work)
if (wl->state != WL1271_STATE_ON || wl->plt)
goto out_unlock;
- /* Avoid a recursive recovery */
- set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
-
- wl12xx_read_fwlog_panic(wl);
-
- /* change partitions momentarily so we can read the FW pc */
- wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
- wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x "
- "hint_sts: 0x%08x",
- wl->chip.fw_ver_str,
- wlcore_read_reg(wl, REG_PC_ON_RECOVERY),
- wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR));
- wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
+ if (!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) {
+ wl12xx_read_fwlog_panic(wl);
+ wlcore_print_recovery(wl);
+ }
BUG_ON(bug_on_recovery &&
!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));
if (no_recovery) {
wl1271_info("No recovery (chosen on module load). Fw will remain stuck.");
- clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
goto out_unlock;
}
@@ -888,11 +956,8 @@ static void wl1271_recovery_work(struct work_struct *work)
vif = wl12xx_wlvif_to_vif(wlvif);
__wl1271_op_remove_interface(wl, vif, false);
}
- wl->watchdog_recovery = false;
- mutex_unlock(&wl->mutex);
- wl1271_op_stop(wl->hw);
- clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
+ wlcore_op_stop_locked(wl);
ieee80211_restart_hw(wl->hw);
@@ -901,15 +966,16 @@ static void wl1271_recovery_work(struct work_struct *work)
* to restart the HW.
*/
wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART);
- return;
+
out_unlock:
- wl->watchdog_recovery = false;
+ wl->watchdog_recovery = false;
+ clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
mutex_unlock(&wl->mutex);
}
-static void wl1271_fw_wakeup(struct wl1271 *wl)
+static int wlcore_fw_wakeup(struct wl1271 *wl)
{
- wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
+ return wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
}
static int wl1271_setup(struct wl1271 *wl)
@@ -945,13 +1011,21 @@ static int wl12xx_set_power_on(struct wl1271 *wl)
wl1271_io_reset(wl);
wl1271_io_init(wl);
- wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
+ ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
+ if (ret < 0)
+ goto fail;
/* ELP module wake up */
- wl1271_fw_wakeup(wl);
+ ret = wlcore_fw_wakeup(wl);
+ if (ret < 0)
+ goto fail;
out:
return ret;
+
+fail:
+ wl1271_power_off(wl);
+ return ret;
}
static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt)
@@ -1082,6 +1156,7 @@ int wl1271_plt_stop(struct wl1271 *wl)
mutex_lock(&wl->mutex);
wl1271_power_off(wl);
wl->flags = 0;
+ wl->sleep_auth = WL1271_PSM_ILLEGAL;
wl->state = WL1271_STATE_OFF;
wl->plt = false;
wl->rx_counter = 0;
@@ -1136,7 +1211,9 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
* The workqueue is slow to process the tx_queue and we need stop
* the queue here, otherwise the queue will get too long.
*/
- if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
+ if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK &&
+ !wlcore_is_queue_stopped_by_reason(wl, q,
+ WLCORE_QUEUE_STOP_REASON_WATERMARK)) {
wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q);
wlcore_stop_queue_locked(wl, q,
WLCORE_QUEUE_STOP_REASON_WATERMARK);
@@ -1173,7 +1250,7 @@ int wl1271_tx_dummy_packet(struct wl1271 *wl)
/* The FW is low on RX memory blocks, so send the dummy packet asap */
if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags))
- wl1271_tx_work_locked(wl);
+ return wlcore_tx_work_locked(wl);
/*
* If the FW TX is busy, TX work will be scheduled by the threaded
@@ -1440,8 +1517,15 @@ static int wl1271_configure_wowlan(struct wl1271 *wl,
int i, ret;
if (!wow || wow->any || !wow->n_patterns) {
- wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL);
- wl1271_rx_filter_clear_all(wl);
+ ret = wl1271_acx_default_rx_filter_enable(wl, 0,
+ FILTER_SIGNAL);
+ if (ret)
+ goto out;
+
+ ret = wl1271_rx_filter_clear_all(wl);
+ if (ret)
+ goto out;
+
return 0;
}
@@ -1457,8 +1541,13 @@ static int wl1271_configure_wowlan(struct wl1271 *wl,
}
}
- wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL);
- wl1271_rx_filter_clear_all(wl);
+ ret = wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL);
+ if (ret)
+ goto out;
+
+ ret = wl1271_rx_filter_clear_all(wl);
+ if (ret)
+ goto out;
/* Translate WoWLAN patterns into filters */
for (i = 0; i < wow->n_patterns; i++) {
@@ -1500,7 +1589,10 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
if (ret < 0)
goto out;
- wl1271_configure_wowlan(wl, wow);
+ ret = wl1271_configure_wowlan(wl, wow);
+ if (ret < 0)
+ goto out_sleep;
+
ret = wl1271_acx_wake_up_conditions(wl, wlvif,
wl->conf.conn.suspend_wake_up_event,
wl->conf.conn.suspend_listen_interval);
@@ -1508,8 +1600,8 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
if (ret < 0)
wl1271_error("suspend: set wake up conditions failed: %d", ret);
+out_sleep:
wl1271_ps_elp_sleep(wl);
-
out:
return ret;
@@ -1588,6 +1680,12 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow);
WARN_ON(!wow);
+ /* we want to perform the recovery before suspending */
+ if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) {
+ wl1271_warning("postponing suspend to perform recovery");
+ return -EBUSY;
+ }
+
wl1271_tx_flush(wl);
mutex_lock(&wl->mutex);
@@ -1628,7 +1726,8 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
struct wl1271 *wl = hw->priv;
struct wl12xx_vif *wlvif;
unsigned long flags;
- bool run_irq_work = false;
+ bool run_irq_work = false, pending_recovery;
+ int ret;
wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d",
wl->wow_enabled);
@@ -1644,17 +1743,37 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
run_irq_work = true;
spin_unlock_irqrestore(&wl->wl_lock, flags);
+ mutex_lock(&wl->mutex);
+
+ /* test the recovery flag before calling any SDIO functions */
+ pending_recovery = test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS,
+ &wl->flags);
+
if (run_irq_work) {
wl1271_debug(DEBUG_MAC80211,
"run postponed irq_work directly");
- wl1271_irq(0, wl);
+
+ /* don't talk to the HW if recovery is pending */
+ if (!pending_recovery) {
+ ret = wlcore_irq_locked(wl);
+ if (ret)
+ wl12xx_queue_recovery_work(wl);
+ }
+
wlcore_enable_interrupts(wl);
}
- mutex_lock(&wl->mutex);
+ if (pending_recovery) {
+ wl1271_warning("queuing forgotten recovery on resume");
+ ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ goto out;
+ }
+
wl12xx_for_each_wlvif(wl, wlvif) {
wl1271_configure_resume(wl, wlvif);
}
+
+out:
wl->wow_enabled = false;
mutex_unlock(&wl->mutex);
@@ -1680,29 +1799,15 @@ static int wl1271_op_start(struct ieee80211_hw *hw)
return 0;
}
-static void wl1271_op_stop(struct ieee80211_hw *hw)
+static void wlcore_op_stop_locked(struct wl1271 *wl)
{
- struct wl1271 *wl = hw->priv;
int i;
- wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
-
- /*
- * Interrupts must be disabled before setting the state to OFF.
- * Otherwise, the interrupt handler might be called and exit without
- * reading the interrupt status.
- */
- wlcore_disable_interrupts(wl);
- mutex_lock(&wl->mutex);
if (wl->state == WL1271_STATE_OFF) {
- mutex_unlock(&wl->mutex);
+ if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS,
+ &wl->flags))
+ wlcore_enable_interrupts(wl);
- /*
- * This will not necessarily enable interrupts as interrupts
- * may have been disabled when op_stop was called. It will,
- * however, balance the above call to disable_interrupts().
- */
- wlcore_enable_interrupts(wl);
return;
}
@@ -1711,8 +1816,16 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
* functions don't perform further work.
*/
wl->state = WL1271_STATE_OFF;
+
+ /*
+ * Use the nosync variant to disable interrupts, so the mutex could be
+ * held while doing so without deadlocking.
+ */
+ wlcore_disable_interrupts_nosync(wl);
+
mutex_unlock(&wl->mutex);
+ wlcore_synchronize_interrupts(wl);
wl1271_flush_deferred_work(wl);
cancel_delayed_work_sync(&wl->scan_complete_work);
cancel_work_sync(&wl->netstack_work);
@@ -1726,6 +1839,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
mutex_lock(&wl->mutex);
wl1271_power_off(wl);
+ /*
+ * In case a recovery was scheduled, interrupts were disabled to avoid
+ * an interrupt storm. Now that the power is down, it is safe to
+ * re-enable interrupts to balance the disable depth
+ */
+ if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
+ wlcore_enable_interrupts(wl);
wl->band = IEEE80211_BAND_2GHZ;
@@ -1740,6 +1860,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl->ap_fw_ps_map = 0;
wl->ap_ps_map = 0;
wl->sched_scanning = false;
+ wl->sleep_auth = WL1271_PSM_ILLEGAL;
memset(wl->roles_map, 0, sizeof(wl->roles_map));
memset(wl->links_map, 0, sizeof(wl->links_map));
memset(wl->roc_map, 0, sizeof(wl->roc_map));
@@ -1771,6 +1892,17 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl->tx_res_if = NULL;
kfree(wl->target_mem_map);
wl->target_mem_map = NULL;
+}
+
+static void wlcore_op_stop(struct ieee80211_hw *hw)
+{
+ struct wl1271 *wl = hw->priv;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
+
+ mutex_lock(&wl->mutex);
+
+ wlcore_op_stop_locked(wl);
mutex_unlock(&wl->mutex);
}
@@ -2146,6 +2278,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
{
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
int i, ret;
+ bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
@@ -2226,11 +2359,25 @@ deinit:
wlvif->role_id = WL12XX_INVALID_ROLE_ID;
wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID;
- if (wlvif->bss_type == BSS_TYPE_AP_BSS)
+ if (is_ap)
wl->ap_count--;
else
wl->sta_count--;
+ /* Last AP, have more stations. Configure according to STA. */
+ if (wl->ap_count == 0 && is_ap && wl->sta_count) {
+ u8 sta_auth = wl->conf.conn.sta_sleep_auth;
+ /* Configure for power according to debugfs */
+ if (sta_auth != WL1271_PSM_ILLEGAL)
+ wl1271_acx_sleep_auth(wl, sta_auth);
+ /* Configure for power always on */
+ else if (wl->quirks & WLCORE_QUIRK_NO_ELP)
+ wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
+ /* Configure for ELP power saving */
+ else
+ wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
+ }
+
mutex_unlock(&wl->mutex);
del_timer_sync(&wlvif->rx_streaming_timer);
@@ -2448,12 +2595,16 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif,
(wlvif->channel != channel) ||
(wlvif->channel_type != conf->channel_type))) {
/* send all pending packets */
- wl1271_tx_work_locked(wl);
+ ret = wlcore_tx_work_locked(wl);
+ if (ret < 0)
+ return ret;
+
wlvif->band = conf->channel->band;
wlvif->channel = channel;
wlvif->channel_type = conf->channel_type;
if (is_ap) {
+ wl1271_set_band_rate(wl, wlvif);
ret = wl1271_init_ap_rates(wl, wlvif);
if (ret < 0)
wl1271_error("AP rate policy change failed %d",
@@ -4090,16 +4241,13 @@ out:
static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey)
{
- struct wl1271 *wl = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
if (idx != 0)
return -ENOENT;
survey->channel = conf->channel;
- survey->filled = SURVEY_INFO_NOISE_DBM;
- survey->noise = wl->noise;
-
+ survey->filled = 0;
return 0;
}
@@ -4365,9 +4513,14 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_RX_STOP:
if (!(*ba_bitmap & BIT(tid))) {
- ret = -EINVAL;
- wl1271_error("no active RX BA session on tid: %d",
+ /*
+ * this happens on reconfig - so only output a debug
+ * message for now, and don't fail the function.
+ */
+ wl1271_debug(DEBUG_MAC80211,
+ "no active RX BA session on tid: %d",
tid);
+ ret = 0;
break;
}
@@ -4416,7 +4569,7 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw,
mutex_lock(&wl->mutex);
- for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+ for (i = 0; i < WLCORE_NUM_BANDS; i++)
wlvif->bitrate_masks[i] =
wl1271_tx_enabled_rates_get(wl,
mask->control[i].legacy,
@@ -4484,6 +4637,13 @@ out:
mutex_unlock(&wl->mutex);
}
+static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop)
+{
+ struct wl1271 *wl = hw->priv;
+
+ wl1271_tx_flush(wl);
+}
+
static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
{
struct wl1271 *wl = hw->priv;
@@ -4646,7 +4806,7 @@ static struct ieee80211_supported_band wl1271_band_5ghz = {
static const struct ieee80211_ops wl1271_ops = {
.start = wl1271_op_start,
- .stop = wl1271_op_stop,
+ .stop = wlcore_op_stop,
.add_interface = wl1271_op_add_interface,
.remove_interface = wl1271_op_remove_interface,
.change_interface = wl12xx_op_change_interface,
@@ -4674,6 +4834,7 @@ static const struct ieee80211_ops wl1271_ops = {
.tx_frames_pending = wl1271_tx_frames_pending,
.set_bitrate_mask = wl12xx_set_bitrate_mask,
.channel_switch = wl12xx_op_channel_switch,
+ .flush = wlcore_op_flush,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
};
@@ -4904,18 +5065,22 @@ static int wl12xx_get_hw_info(struct wl1271 *wl)
if (ret < 0)
goto out;
- wl->chip.id = wlcore_read_reg(wl, REG_CHIP_ID_B);
+ ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &wl->chip.id);
+ if (ret < 0)
+ goto out;
wl->fuse_oui_addr = 0;
wl->fuse_nic_addr = 0;
- wl->hw_pg_ver = wl->ops->get_pg_ver(wl);
+ ret = wl->ops->get_pg_ver(wl, &wl->hw_pg_ver);
+ if (ret < 0)
+ goto out;
if (wl->ops->get_mac)
- wl->ops->get_mac(wl);
+ ret = wl->ops->get_mac(wl);
- wl1271_power_off(wl);
out:
+ wl1271_power_off(wl);
return ret;
}
@@ -4976,6 +5141,29 @@ static void wl1271_unregister_hw(struct wl1271 *wl)
}
+static const struct ieee80211_iface_limit wlcore_iface_limits[] = {
+ {
+ .max = 2,
+ .types = BIT(NL80211_IFTYPE_STATION),
+ },
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_P2P_GO) |
+ BIT(NL80211_IFTYPE_P2P_CLIENT),
+ },
+};
+
+static const struct ieee80211_iface_combination
+wlcore_iface_combinations[] = {
+ {
+ .num_different_channels = 1,
+ .max_interfaces = 2,
+ .limits = wlcore_iface_limits,
+ .n_limits = ARRAY_SIZE(wlcore_iface_limits),
+ },
+};
+
static int wl1271_init_ieee80211(struct wl1271 *wl)
{
static const u32 cipher_suites[] = {
@@ -5069,6 +5257,11 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
+ /* allowed interface combinations */
+ wl->hw->wiphy->iface_combinations = wlcore_iface_combinations;
+ wl->hw->wiphy->n_iface_combinations =
+ ARRAY_SIZE(wlcore_iface_combinations);
+
SET_IEEE80211_DEV(wl->hw, wl->dev);
wl->hw->sta_data_size = sizeof(struct wl1271_station);
@@ -5140,6 +5333,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size)
wl->channel_type = NL80211_CHAN_NO_HT;
wl->flags = 0;
wl->sg_enabled = true;
+ wl->sleep_auth = WL1271_PSM_ILLEGAL;
wl->hw_pg_ver = -1;
wl->ap_ps_map = 0;
wl->ap_fw_ps_map = 0;
@@ -5313,7 +5507,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
else
irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
- ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wl1271_irq,
+ ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wlcore_irq,
irqflags,
pdev->name, wl);
if (ret < 0) {
@@ -5321,6 +5515,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
goto out_free_hw;
}
+#ifdef CONFIG_PM
ret = enable_irq_wake(wl->irq);
if (!ret) {
wl->irq_wake_enabled = true;
@@ -5334,17 +5529,18 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
WL1271_RX_FILTER_MAX_PATTERN_SIZE;
}
}
+#endif
disable_irq(wl->irq);
ret = wl12xx_get_hw_info(wl);
if (ret < 0) {
wl1271_error("couldn't get hw info");
- goto out;
+ goto out_irq;
}
ret = wl->ops->identify_chip(wl);
if (ret < 0)
- goto out;
+ goto out_irq;
ret = wl1271_init_ieee80211(wl);
if (ret)
@@ -5358,7 +5554,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
ret = device_create_file(wl->dev, &dev_attr_bt_coex_state);
if (ret < 0) {
wl1271_error("failed to create sysfs file bt_coex_state");
- goto out_irq;
+ goto out_unreg;
}
/* Create sysfs file to get HW PG version */
@@ -5383,6 +5579,9 @@ out_hw_pg_ver:
out_bt_coex_state:
device_remove_file(wl->dev, &dev_attr_bt_coex_state);
+out_unreg:
+ wl1271_unregister_hw(wl);
+
out_irq:
free_irq(wl->irq, wl);
diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c
index 47e81b32f7da..46d36fd30eba 100644
--- a/drivers/net/wireless/ti/wlcore/ps.c
+++ b/drivers/net/wireless/ti/wlcore/ps.c
@@ -35,6 +35,7 @@ void wl1271_elp_work(struct work_struct *work)
struct delayed_work *dwork;
struct wl1271 *wl;
struct wl12xx_vif *wlvif;
+ int ret;
dwork = container_of(work, struct delayed_work, work);
wl = container_of(dwork, struct wl1271, elp_work);
@@ -63,7 +64,12 @@ void wl1271_elp_work(struct work_struct *work)
}
wl1271_debug(DEBUG_PSM, "chip to elp");
- wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP);
+ ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP);
+ if (ret < 0) {
+ wl12xx_queue_recovery_work(wl);
+ goto out;
+ }
+
set_bit(WL1271_FLAG_IN_ELP, &wl->flags);
out:
@@ -76,7 +82,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
struct wl12xx_vif *wlvif;
u32 timeout;
- if (wl->quirks & WLCORE_QUIRK_NO_ELP)
+ if (wl->sleep_auth != WL1271_PSM_ELP)
return;
/* we shouldn't get consecutive sleep requests */
@@ -135,7 +141,11 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
wl->elp_compl = &compl;
spin_unlock_irqrestore(&wl->wl_lock, flags);
- wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
+ ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
+ if (ret < 0) {
+ wl12xx_queue_recovery_work(wl);
+ goto err;
+ }
if (!pending) {
ret = wait_for_completion_timeout(
diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c
index 78200dcacfca..f55e2f9e7ac5 100644
--- a/drivers/net/wireless/ti/wlcore/rx.c
+++ b/drivers/net/wireless/ti/wlcore/rx.c
@@ -127,7 +127,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
}
if (rx_align == WLCORE_RX_BUF_UNALIGNED)
- reserved = NET_IP_ALIGN;
+ reserved = RX_BUF_ALIGN;
/* the data read starts with the descriptor */
desc = (struct wl1271_rx_descriptor *) data;
@@ -175,7 +175,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
*/
memcpy(buf, data + sizeof(*desc), pkt_data_len);
if (rx_align == WLCORE_RX_BUF_PADDED)
- skb_pull(skb, NET_IP_ALIGN);
+ skb_pull(skb, RX_BUF_ALIGN);
*hlid = desc->hlid;
@@ -200,7 +200,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
return is_data;
}
-void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
+int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
{
unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
u32 buf_size;
@@ -211,6 +211,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
u32 pkt_offset, des;
u8 hlid;
enum wl_rx_buf_align rx_align;
+ int ret = 0;
while (drv_rx_counter != fw_rx_counter) {
buf_size = 0;
@@ -234,9 +235,14 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
/* Read all available packets at once */
des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]);
- wlcore_hw_prepare_read(wl, des, buf_size);
- wlcore_read_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
- buf_size, true);
+ ret = wlcore_hw_prepare_read(wl, des, buf_size);
+ if (ret < 0)
+ goto out;
+
+ ret = wlcore_read_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
+ buf_size, true);
+ if (ret < 0)
+ goto out;
/* Split data into separate packets */
pkt_offset = 0;
@@ -273,11 +279,17 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
* Write the driver's packet counter to the FW. This is only required
* for older hardware revisions
*/
- if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION)
- wl1271_write32(wl, WL12XX_REG_RX_DRIVER_COUNTER,
- wl->rx_counter);
+ if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) {
+ ret = wlcore_write32(wl, WL12XX_REG_RX_DRIVER_COUNTER,
+ wl->rx_counter);
+ if (ret < 0)
+ goto out;
+ }
wl12xx_rearm_rx_streaming(wl, active_hlids);
+
+out:
+ return ret;
}
#ifdef CONFIG_PM
@@ -306,14 +318,19 @@ int wl1271_rx_filter_enable(struct wl1271 *wl,
return 0;
}
-void wl1271_rx_filter_clear_all(struct wl1271 *wl)
+int wl1271_rx_filter_clear_all(struct wl1271 *wl)
{
- int i;
+ int i, ret = 0;
for (i = 0; i < WL1271_MAX_RX_FILTERS; i++) {
if (!wl->rx_filter_enabled[i])
continue;
- wl1271_rx_filter_enable(wl, i, 0, NULL);
+ ret = wl1271_rx_filter_enable(wl, i, 0, NULL);
+ if (ret)
+ goto out;
}
+
+out:
+ return ret;
}
#endif /* CONFIG_PM */
diff --git a/drivers/net/wireless/ti/wlcore/rx.h b/drivers/net/wireless/ti/wlcore/rx.h
index 9be780179456..71eba1899915 100644
--- a/drivers/net/wireless/ti/wlcore/rx.h
+++ b/drivers/net/wireless/ti/wlcore/rx.h
@@ -103,6 +103,12 @@
/* If set, the buffer was padded by the FW to be 4 bytes aligned */
#define RX_BUF_PADDED_PAYLOAD BIT(30)
+/*
+ * Account for the padding inserted by the FW in case of RX_ALIGNMENT
+ * or for fixing alignment in case the packet wasn't aligned.
+ */
+#define RX_BUF_ALIGN 2
+
/* Describes the alignment state of a Rx buffer */
enum wl_rx_buf_align {
WLCORE_RX_BUF_ALIGNED,
@@ -137,11 +143,11 @@ struct wl1271_rx_descriptor {
u8 reserved;
} __packed;
-void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status);
+int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status);
u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
int wl1271_rx_filter_enable(struct wl1271 *wl,
int index, bool enable,
struct wl12xx_rx_filter *filter);
-void wl1271_rx_filter_clear_all(struct wl1271 *wl);
+int wl1271_rx_filter_clear_all(struct wl1271 *wl);
#endif
diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c
index d9daed53ceb7..dbeca1bfbb2c 100644
--- a/drivers/net/wireless/ti/wlcore/scan.c
+++ b/drivers/net/wireless/ti/wlcore/scan.c
@@ -226,7 +226,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif,
cmd->params.role_id, band,
wl->scan.ssid, wl->scan.ssid_len,
wl->scan.req->ie,
- wl->scan.req->ie_len);
+ wl->scan.req->ie_len, false);
if (ret < 0) {
wl1271_error("PROBE request template failed");
goto out;
@@ -633,7 +633,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
for (j = 0; j < cmd->n_ssids; j++)
if ((req->ssids[i].ssid_len ==
- req->ssids[j].ssid_len) &&
+ cmd->ssids[j].len) &&
!memcmp(req->ssids[i].ssid,
cmd->ssids[j].ssid,
req->ssids[i].ssid_len)) {
@@ -722,7 +722,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
req->ssids[0].ssid,
req->ssids[0].ssid_len,
ies->ie[band],
- ies->len[band]);
+ ies->len[band], true);
if (ret < 0) {
wl1271_error("2.4GHz PROBE request template failed");
goto out;
@@ -736,7 +736,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
req->ssids[0].ssid,
req->ssids[0].ssid_len,
ies->ie[band],
- ies->len[band]);
+ ies->len[band], true);
if (ret < 0) {
wl1271_error("5GHz PROBE request template failed");
goto out;
@@ -766,7 +766,8 @@ int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif)
if (wlvif->bss_type != BSS_TYPE_STA_BSS)
return -EOPNOTSUPP;
- if (test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags))
+ if ((wl->quirks & WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN) &&
+ test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags))
return -EBUSY;
start = kzalloc(sizeof(*start), GFP_KERNEL);
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index c67ec482e445..73ace4b2604e 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -71,8 +71,8 @@ static void wl1271_sdio_set_block_size(struct device *child,
sdio_release_host(func);
}
-static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf,
- size_t len, bool fixed)
+static int __must_check wl12xx_sdio_raw_read(struct device *child, int addr,
+ void *buf, size_t len, bool fixed)
{
int ret;
struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
@@ -103,12 +103,14 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf,
sdio_release_host(func);
- if (ret)
+ if (WARN_ON(ret))
dev_err(child->parent, "sdio read failed (%d)\n", ret);
+
+ return ret;
}
-static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf,
- size_t len, bool fixed)
+static int __must_check wl12xx_sdio_raw_write(struct device *child, int addr,
+ void *buf, size_t len, bool fixed)
{
int ret;
struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
@@ -139,25 +141,30 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf,
sdio_release_host(func);
- if (ret)
+ if (WARN_ON(ret))
dev_err(child->parent, "sdio write failed (%d)\n", ret);
+
+ return ret;
}
static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue)
{
int ret;
struct sdio_func *func = dev_to_sdio_func(glue->dev);
+ struct mmc_card *card = func->card;
- /* If enabled, tell runtime PM not to power off the card */
- if (pm_runtime_enabled(&func->dev)) {
- ret = pm_runtime_get_sync(&func->dev);
- if (ret < 0)
- goto out;
- } else {
- /* Runtime PM is disabled: power up the card manually */
- ret = mmc_power_restore_host(func->card->host);
- if (ret < 0)
+ ret = pm_runtime_get_sync(&card->dev);
+ if (ret) {
+ /*
+ * Runtime PM might be temporarily disabled, or the device
+ * might have a positive reference counter. Make sure it is
+ * really powered on.
+ */
+ ret = mmc_power_restore_host(card->host);
+ if (ret < 0) {
+ pm_runtime_put_sync(&card->dev);
goto out;
+ }
}
sdio_claim_host(func);
@@ -172,20 +179,21 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue)
{
int ret;
struct sdio_func *func = dev_to_sdio_func(glue->dev);
+ struct mmc_card *card = func->card;
sdio_claim_host(func);
sdio_disable_func(func);
sdio_release_host(func);
- /* Power off the card manually, even if runtime PM is enabled. */
- ret = mmc_power_save_host(func->card->host);
+ /* Power off the card manually in case it wasn't powered off above */
+ ret = mmc_power_save_host(card->host);
if (ret < 0)
- return ret;
+ goto out;
- /* If enabled, let runtime PM know the card is powered off */
- if (pm_runtime_enabled(&func->dev))
- ret = pm_runtime_put_sync(&func->dev);
+ /* Let runtime PM know the card is powered off */
+ pm_runtime_put_sync(&card->dev);
+out:
return ret;
}
@@ -403,9 +411,3 @@ MODULE_PARM_DESC(dump, "Enable sdio read/write dumps.");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
-MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
-MODULE_FIRMWARE(WL127X_FW_NAME_MULTI);
-MODULE_FIRMWARE(WL127X_PLT_FW_NAME);
-MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE);
-MODULE_FIRMWARE(WL128X_FW_NAME_MULTI);
-MODULE_FIRMWARE(WL128X_PLT_FW_NAME);
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c
index 553cd3cbb98c..8da4ed243ebc 100644
--- a/drivers/net/wireless/ti/wlcore/spi.c
+++ b/drivers/net/wireless/ti/wlcore/spi.c
@@ -193,8 +193,8 @@ static int wl12xx_spi_read_busy(struct device *child)
return -ETIMEDOUT;
}
-static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf,
- size_t len, bool fixed)
+static int __must_check wl12xx_spi_raw_read(struct device *child, int addr,
+ void *buf, size_t len, bool fixed)
{
struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
struct wl1271 *wl = dev_get_drvdata(child);
@@ -238,7 +238,7 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf,
if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) &&
wl12xx_spi_read_busy(child)) {
memset(buf, 0, chunk_len);
- return;
+ return 0;
}
spi_message_init(&m);
@@ -256,10 +256,12 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf,
buf += chunk_len;
len -= chunk_len;
}
+
+ return 0;
}
-static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf,
- size_t len, bool fixed)
+static int __must_check wl12xx_spi_raw_write(struct device *child, int addr,
+ void *buf, size_t len, bool fixed)
{
struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS];
@@ -304,6 +306,8 @@ static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf,
}
spi_sync(to_spi_device(glue->dev), &m);
+
+ return 0;
}
static struct wl1271_if_operations spi_ops = {
@@ -431,10 +435,4 @@ module_exit(wl1271_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
-MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
-MODULE_FIRMWARE(WL127X_FW_NAME_MULTI);
-MODULE_FIRMWARE(WL127X_PLT_FW_NAME);
-MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE);
-MODULE_FIRMWARE(WL128X_FW_NAME_MULTI);
-MODULE_FIRMWARE(WL128X_PLT_FW_NAME);
MODULE_ALIAS("spi:wl1271");
diff --git a/drivers/net/wireless/ti/wlcore/testmode.c b/drivers/net/wireless/ti/wlcore/testmode.c
index 0e59ea2cdd39..d6f57e2c03cf 100644
--- a/drivers/net/wireless/ti/wlcore/testmode.c
+++ b/drivers/net/wireless/ti/wlcore/testmode.c
@@ -40,7 +40,7 @@ enum wl1271_tm_commands {
WL1271_TM_CMD_CONFIGURE,
WL1271_TM_CMD_NVS_PUSH, /* Not in use. Keep to not break ABI */
WL1271_TM_CMD_SET_PLT_MODE,
- WL1271_TM_CMD_RECOVER,
+ WL1271_TM_CMD_RECOVER, /* Not in use. Keep to not break ABI */
WL1271_TM_CMD_GET_MAC,
__WL1271_TM_CMD_AFTER_LAST
@@ -108,6 +108,20 @@ static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[])
}
if (answer) {
+ /* If we got bip calibration answer print radio status */
+ struct wl1271_cmd_cal_p2g *params =
+ (struct wl1271_cmd_cal_p2g *) buf;
+
+ s16 radio_status = (s16) le16_to_cpu(params->radio_status);
+
+ if (params->test.id == TEST_CMD_P2G_CAL &&
+ radio_status < 0)
+ wl1271_warning("testmode cmd: radio status=%d",
+ radio_status);
+ else
+ wl1271_info("testmode cmd: radio status=%d",
+ radio_status);
+
len = nla_total_size(buf_len);
skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len);
if (!skb) {
@@ -258,15 +272,6 @@ static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[])
return ret;
}
-static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[])
-{
- wl1271_debug(DEBUG_TESTMODE, "testmode cmd recover");
-
- wl12xx_queue_recovery_work(wl);
-
- return 0;
-}
-
static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[])
{
struct sk_buff *skb;
@@ -336,8 +341,6 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
return wl1271_tm_cmd_configure(wl, tb);
case WL1271_TM_CMD_SET_PLT_MODE:
return wl1271_tm_cmd_set_plt_mode(wl, tb);
- case WL1271_TM_CMD_RECOVER:
- return wl1271_tm_cmd_recover(wl, tb);
case WL1271_TM_CMD_GET_MAC:
return wl12xx_tm_cmd_get_mac(wl, tb);
default:
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index 6983e7a829d0..6a28aeecf004 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -305,11 +305,15 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if (is_dummy || !wlvif)
rate_idx = 0;
else if (wlvif->bss_type != BSS_TYPE_AP_BSS) {
- /* if the packets are destined for AP (have a STA entry)
- send them with AP rate policies, otherwise use default
- basic rates */
+ /*
+ * if the packets are destined for AP (have a STA entry)
+ * send them with AP rate policies (EAPOLs are an exception),
+ * otherwise use default basic rates
+ */
if (control->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
rate_idx = wlvif->sta.p2p_rate_idx;
+ else if (skb->protocol == cpu_to_be16(ETH_P_PAE))
+ rate_idx = wlvif->sta.basic_rate_idx;
else if (control->control.sta)
rate_idx = wlvif->sta.ap_rate_idx;
else
@@ -348,8 +352,10 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
bool is_dummy;
bool is_gem = false;
- if (!skb)
+ if (!skb) {
+ wl1271_error("discarding null skb");
return -EINVAL;
+ }
info = IEEE80211_SKB_CB(skb);
@@ -658,7 +664,17 @@ void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids)
}
}
-void wl1271_tx_work_locked(struct wl1271 *wl)
+/*
+ * Returns failure values only in case of failed bus ops within this function.
+ * wl1271_prepare_tx_frame retvals won't be returned in order to avoid
+ * triggering recovery by higher layers when not necessary.
+ * In case a FW command fails within wl1271_prepare_tx_frame fails a recovery
+ * will be queued in wl1271_cmd_send. -EAGAIN/-EBUSY from prepare_tx_frame
+ * can occur and are legitimate so don't propagate. -EINVAL will emit a WARNING
+ * within prepare_tx_frame code but there's nothing we should do about those
+ * as well.
+ */
+int wlcore_tx_work_locked(struct wl1271 *wl)
{
struct wl12xx_vif *wlvif;
struct sk_buff *skb;
@@ -666,10 +682,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
u32 buf_offset = 0, last_len = 0;
bool sent_packets = false;
unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
- int ret;
+ int ret = 0;
+ int bus_ret = 0;
if (unlikely(wl->state == WL1271_STATE_OFF))
- return;
+ return 0;
while ((skb = wl1271_skb_dequeue(wl))) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -690,8 +707,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset,
last_len);
- wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
- buf_offset, true);
+ bus_ret = wlcore_write_data(wl, REG_SLV_MEM_DATA,
+ wl->aggr_buf, buf_offset, true);
+ if (bus_ret < 0)
+ goto out;
+
sent_packets = true;
buf_offset = 0;
continue;
@@ -727,8 +747,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
out_ack:
if (buf_offset) {
buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, last_len);
- wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
- buf_offset, true);
+ bus_ret = wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
+ buf_offset, true);
+ if (bus_ret < 0)
+ goto out;
+
sent_packets = true;
}
if (sent_packets) {
@@ -736,13 +759,19 @@ out_ack:
* Interrupt the firmware with the new packets. This is only
* required for older hardware revisions
*/
- if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION)
- wl1271_write32(wl, WL12XX_HOST_WR_ACCESS,
- wl->tx_packets_count);
+ if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) {
+ bus_ret = wlcore_write32(wl, WL12XX_HOST_WR_ACCESS,
+ wl->tx_packets_count);
+ if (bus_ret < 0)
+ goto out;
+ }
wl1271_handle_tx_low_watermark(wl);
}
wl12xx_rearm_rx_streaming(wl, active_hlids);
+
+out:
+ return bus_ret;
}
void wl1271_tx_work(struct work_struct *work)
@@ -755,7 +784,11 @@ void wl1271_tx_work(struct work_struct *work)
if (ret < 0)
goto out;
- wl1271_tx_work_locked(wl);
+ ret = wlcore_tx_work_locked(wl);
+ if (ret < 0) {
+ wl12xx_queue_recovery_work(wl);
+ goto out;
+ }
wl1271_ps_elp_sleep(wl);
out:
@@ -877,22 +910,28 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
}
/* Called upon reception of a TX complete interrupt */
-void wl1271_tx_complete(struct wl1271 *wl)
+int wlcore_tx_complete(struct wl1271 *wl)
{
struct wl1271_acx_mem_map *memmap =
(struct wl1271_acx_mem_map *)wl->target_mem_map;
u32 count, fw_counter;
u32 i;
+ int ret;
/* read the tx results from the chipset */
- wl1271_read(wl, le32_to_cpu(memmap->tx_result),
- wl->tx_res_if, sizeof(*wl->tx_res_if), false);
+ ret = wlcore_read(wl, le32_to_cpu(memmap->tx_result),
+ wl->tx_res_if, sizeof(*wl->tx_res_if), false);
+ if (ret < 0)
+ goto out;
+
fw_counter = le32_to_cpu(wl->tx_res_if->tx_result_fw_counter);
/* write host counter to chipset (to ack) */
- wl1271_write32(wl, le32_to_cpu(memmap->tx_result) +
- offsetof(struct wl1271_tx_hw_res_if,
- tx_result_host_counter), fw_counter);
+ ret = wlcore_write32(wl, le32_to_cpu(memmap->tx_result) +
+ offsetof(struct wl1271_tx_hw_res_if,
+ tx_result_host_counter), fw_counter);
+ if (ret < 0)
+ goto out;
count = fw_counter - wl->tx_results_count;
wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count);
@@ -912,8 +951,11 @@ void wl1271_tx_complete(struct wl1271 *wl)
wl->tx_results_count++;
}
+
+out:
+ return ret;
}
-EXPORT_SYMBOL(wl1271_tx_complete);
+EXPORT_SYMBOL(wlcore_tx_complete);
void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
{
diff --git a/drivers/net/wireless/ti/wlcore/tx.h b/drivers/net/wireless/ti/wlcore/tx.h
index fa4be1b91135..1e939b016155 100644
--- a/drivers/net/wireless/ti/wlcore/tx.h
+++ b/drivers/net/wireless/ti/wlcore/tx.h
@@ -234,8 +234,8 @@ static inline int wl1271_tx_total_queue_count(struct wl1271 *wl)
}
void wl1271_tx_work(struct work_struct *work);
-void wl1271_tx_work_locked(struct wl1271 *wl);
-void wl1271_tx_complete(struct wl1271 *wl);
+int wlcore_tx_work_locked(struct wl1271 *wl);
+int wlcore_tx_complete(struct wl1271 *wl);
void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif);
void wl12xx_tx_reset(struct wl1271 *wl);
void wl1271_tx_flush(struct wl1271 *wl);
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 761a72f4b8d1..27ccc275a1c1 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -41,9 +41,9 @@ struct wlcore_ops {
int (*identify_fw)(struct wl1271 *wl);
int (*boot)(struct wl1271 *wl);
int (*plt_init)(struct wl1271 *wl);
- void (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr,
- void *buf, size_t len);
- void (*ack_event)(struct wl1271 *wl);
+ int (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr,
+ void *buf, size_t len);
+ int (*ack_event)(struct wl1271 *wl);
u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks);
void (*set_tx_desc_blocks)(struct wl1271 *wl,
struct wl1271_tx_hw_descr *desc,
@@ -53,17 +53,17 @@ struct wlcore_ops {
struct sk_buff *skb);
enum wl_rx_buf_align (*get_rx_buf_align)(struct wl1271 *wl,
u32 rx_desc);
- void (*prepare_read)(struct wl1271 *wl, u32 rx_desc, u32 len);
+ int (*prepare_read)(struct wl1271 *wl, u32 rx_desc, u32 len);
u32 (*get_rx_packet_len)(struct wl1271 *wl, void *rx_data,
u32 data_len);
- void (*tx_delayed_compl)(struct wl1271 *wl);
+ int (*tx_delayed_compl)(struct wl1271 *wl);
void (*tx_immediate_compl)(struct wl1271 *wl);
int (*hw_init)(struct wl1271 *wl);
int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl,
struct wl12xx_vif *wlvif);
- s8 (*get_pg_ver)(struct wl1271 *wl);
- void (*get_mac)(struct wl1271 *wl);
+ int (*get_pg_ver)(struct wl1271 *wl, s8 *ver);
+ int (*get_mac)(struct wl1271 *wl);
void (*set_tx_desc_csum)(struct wl1271 *wl,
struct wl1271_tx_hw_descr *desc,
struct sk_buff *skb);
@@ -304,7 +304,7 @@ struct wl1271 {
s8 noise;
/* bands supported by this instance of wl12xx */
- struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+ struct ieee80211_supported_band bands[WLCORE_NUM_BANDS];
/*
* wowlan trigger was configured during suspend.
@@ -371,7 +371,7 @@ struct wl1271 {
u8 hw_min_ht_rate;
/* HW HT (11n) capabilities */
- struct ieee80211_sta_ht_cap ht_cap[IEEE80211_NUM_BANDS];
+ struct ieee80211_sta_ht_cap ht_cap[WLCORE_NUM_BANDS];
/* size of the private FW status data */
size_t fw_status_priv_len;
@@ -387,6 +387,12 @@ struct wl1271 {
/* mutex for protecting the tx_flush function */
struct mutex flush_mutex;
+
+ /* sleep auth value currently configured to FW */
+ int sleep_auth;
+
+ /* the minimum FW version required for the driver to work */
+ unsigned int min_fw_ver[NUM_FW_VER];
};
int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
@@ -398,6 +404,25 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key_conf);
+static inline void
+wlcore_set_ht_cap(struct wl1271 *wl, enum ieee80211_band band,
+ struct ieee80211_sta_ht_cap *ht_cap)
+{
+ memcpy(&wl->ht_cap[band], ht_cap, sizeof(*ht_cap));
+}
+
+static inline void
+wlcore_set_min_fw_ver(struct wl1271 *wl, unsigned int chip,
+ unsigned int iftype, unsigned int major,
+ unsigned int subtype, unsigned int minor)
+{
+ wl->min_fw_ver[FW_VER_CHIP] = chip;
+ wl->min_fw_ver[FW_VER_IF_TYPE] = iftype;
+ wl->min_fw_ver[FW_VER_MAJOR] = major;
+ wl->min_fw_ver[FW_VER_SUBTYPE] = subtype;
+ wl->min_fw_ver[FW_VER_MINOR] = minor;
+}
+
/* Firmware image load chunk size */
#define CHUNK_SIZE 16384
@@ -427,6 +452,12 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
/* extra header space is required for TKIP */
#define WLCORE_QUIRK_TKIP_HEADER_SPACE BIT(8)
+/* Some firmwares not support sched scans while connected */
+#define WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN BIT(9)
+
+/* separate probe response templates for one-shot and sched scans */
+#define WLCORE_QUIRK_DUAL_PROBE_TMPL BIT(10)
+
/* TODO: move to the lower drivers when all usages are abstracted */
#define CHIP_ID_1271_PG10 (0x4030101)
#define CHIP_ID_1271_PG20 (0x4030111)
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 8260b1e9288a..0187eef4fb07 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -35,15 +35,6 @@
#include "conf.h"
#include "ini.h"
-#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin"
-#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin"
-
-#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin"
-#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin"
-
-#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin"
-#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin"
-
/*
* wl127x and wl128x are using the same NVS file name. However, the
* ini parameters between them are different. The driver validates
@@ -71,6 +62,9 @@
#define WL12XX_INVALID_ROLE_ID 0xff
#define WL12XX_INVALID_LINK_ID 0xff
+/* the driver supports the 2.4Ghz and 5Ghz bands */
+#define WLCORE_NUM_BANDS 2
+
#define WL12XX_MAX_RATE_POLICIES 16
/* Defined by FW as 0. Will not be freed or allocated. */
@@ -209,10 +203,10 @@ struct wl1271_scan {
};
struct wl1271_if_operations {
- void (*read)(struct device *child, int addr, void *buf, size_t len,
- bool fixed);
- void (*write)(struct device *child, int addr, void *buf, size_t len,
- bool fixed);
+ int __must_check (*read)(struct device *child, int addr, void *buf,
+ size_t len, bool fixed);
+ int __must_check (*write)(struct device *child, int addr, void *buf,
+ size_t len, bool fixed);
void (*reset)(struct device *child);
void (*init)(struct device *child);
int (*power)(struct device *child, bool enable);
@@ -247,6 +241,7 @@ enum wl12xx_flags {
WL1271_FLAG_RECOVERY_IN_PROGRESS,
WL1271_FLAG_VIF_CHANGE_IN_PROGRESS,
WL1271_FLAG_INTENDED_FW_RECOVERY,
+ WL1271_FLAG_IO_FAILED,
};
enum wl12xx_vif_flags {
@@ -368,7 +363,7 @@ struct wl12xx_vif {
int channel;
enum nl80211_channel_type channel_type;
- u32 bitrate_masks[IEEE80211_NUM_BANDS];
+ u32 bitrate_masks[WLCORE_NUM_BANDS];
u32 basic_rate_set;
/*
diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c
index 1f74a77d040d..e7fd4938f9bc 100644
--- a/drivers/nfc/nfcwilink.c
+++ b/drivers/nfc/nfcwilink.c
@@ -535,9 +535,10 @@ static int nfcwilink_probe(struct platform_device *pdev)
drv->pdev = pdev;
protocols = NFC_PROTO_JEWEL_MASK
- | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK
- | NFC_PROTO_ISO14443_MASK
- | NFC_PROTO_NFC_DEP_MASK;
+ | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK
+ | NFC_PROTO_ISO14443_MASK
+ | NFC_PROTO_ISO14443_B_MASK
+ | NFC_PROTO_NFC_DEP_MASK;
drv->ndev = nci_allocate_device(&nfcwilink_ops,
protocols,
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 9ac829e22e73..d606f52fec84 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -38,9 +38,44 @@
#define SCM_VENDOR_ID 0x4E6
#define SCL3711_PRODUCT_ID 0x5591
+#define SONY_VENDOR_ID 0x054c
+#define PASORI_PRODUCT_ID 0x02e1
+
+#define PN533_QUIRKS_TYPE_A BIT(0)
+#define PN533_QUIRKS_TYPE_F BIT(1)
+#define PN533_QUIRKS_DEP BIT(2)
+#define PN533_QUIRKS_RAW_EXCHANGE BIT(3)
+
+#define PN533_DEVICE_STD 0x1
+#define PN533_DEVICE_PASORI 0x2
+
+#define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\
+ NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\
+ NFC_PROTO_NFC_DEP_MASK |\
+ NFC_PROTO_ISO14443_B_MASK)
+
+#define PN533_NO_TYPE_B_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \
+ NFC_PROTO_MIFARE_MASK | \
+ NFC_PROTO_FELICA_MASK | \
+ NFC_PROTO_ISO14443_MASK | \
+ NFC_PROTO_NFC_DEP_MASK)
+
static const struct usb_device_id pn533_table[] = {
- { USB_DEVICE(PN533_VENDOR_ID, PN533_PRODUCT_ID) },
- { USB_DEVICE(SCM_VENDOR_ID, SCL3711_PRODUCT_ID) },
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = PN533_VENDOR_ID,
+ .idProduct = PN533_PRODUCT_ID,
+ .driver_info = PN533_DEVICE_STD,
+ },
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = SCM_VENDOR_ID,
+ .idProduct = SCL3711_PRODUCT_ID,
+ .driver_info = PN533_DEVICE_STD,
+ },
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = SONY_VENDOR_ID,
+ .idProduct = PASORI_PRODUCT_ID,
+ .driver_info = PN533_DEVICE_PASORI,
+ },
{ }
};
MODULE_DEVICE_TABLE(usb, pn533_table);
@@ -72,6 +107,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
#define PN533_CMD_GET_FIRMWARE_VERSION 0x02
#define PN533_CMD_RF_CONFIGURATION 0x32
#define PN533_CMD_IN_DATA_EXCHANGE 0x40
+#define PN533_CMD_IN_COMM_THRU 0x42
#define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A
#define PN533_CMD_IN_ATR 0x50
#define PN533_CMD_IN_RELEASE 0x52
@@ -109,6 +145,7 @@ struct pn533_fw_version {
/* PN533_CMD_RF_CONFIGURATION */
#define PN533_CFGITEM_TIMING 0x02
#define PN533_CFGITEM_MAX_RETRIES 0x05
+#define PN533_CFGITEM_PASORI 0x82
#define PN533_CONFIG_TIMING_102 0xb
#define PN533_CONFIG_TIMING_204 0xc
@@ -344,6 +381,8 @@ struct pn533 {
u8 tgt_available_prots;
u8 tgt_active_prot;
u8 tgt_mode;
+
+ u32 device_type;
};
struct pn533_frame {
@@ -950,7 +989,7 @@ static int pn533_target_found_type_b(struct nfc_target *nfc_tgt, u8 *tgt_data,
if (!pn533_target_type_b_is_valid(tgt_type_b, tgt_data_len))
return -EPROTO;
- nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_MASK;
+ nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_B_MASK;
return 0;
}
@@ -1057,7 +1096,7 @@ static void pn533_poll_create_mod_list(struct pn533 *dev,
if (im_protocols & NFC_PROTO_JEWEL_MASK)
pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL);
- if (im_protocols & NFC_PROTO_ISO14443_MASK)
+ if (im_protocols & NFC_PROTO_ISO14443_B_MASK)
pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B);
if (tm_protocols)
@@ -1768,13 +1807,30 @@ static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb,
}
if (target == true) {
- skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
- out_frame = (struct pn533_frame *) skb->data;
+ switch (dev->device_type) {
+ case PN533_DEVICE_PASORI:
+ if (dev->tgt_active_prot == NFC_PROTO_FELICA) {
+ skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1);
+ out_frame = (struct pn533_frame *) skb->data;
+ pn533_tx_frame_init(out_frame,
+ PN533_CMD_IN_COMM_THRU);
+
+ break;
+ }
+
+ default:
+ skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
+ out_frame = (struct pn533_frame *) skb->data;
+ pn533_tx_frame_init(out_frame,
+ PN533_CMD_IN_DATA_EXCHANGE);
+ tg = 1;
+ memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame),
+ &tg, sizeof(u8));
+ out_frame->datalen += sizeof(u8);
+
+ break;
+ }
- pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE);
- tg = 1;
- memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8));
- out_frame->datalen += sizeof(u8);
} else {
skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1);
out_frame = (struct pn533_frame *) skb->data;
@@ -2101,7 +2157,28 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
return rc;
}
-struct nfc_ops pn533_nfc_ops = {
+static int pn533_fw_reset(struct pn533 *dev)
+{
+ int rc;
+ u8 *params;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ pn533_tx_frame_init(dev->out_frame, 0x18);
+
+ params = PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame);
+ params[0] = 0x1;
+ dev->out_frame->datalen += 1;
+
+ pn533_tx_frame_finish(dev->out_frame);
+
+ rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame,
+ dev->in_maxlen);
+
+ return rc;
+}
+
+static struct nfc_ops pn533_nfc_ops = {
.dev_up = NULL,
.dev_down = NULL,
.dep_link_up = pn533_dep_link_up,
@@ -2114,6 +2191,84 @@ struct nfc_ops pn533_nfc_ops = {
.tm_send = pn533_tm_send,
};
+static int pn533_setup(struct pn533 *dev)
+{
+ struct pn533_config_max_retries max_retries;
+ struct pn533_config_timing timing;
+ u8 pasori_cfg[3] = {0x08, 0x01, 0x08};
+ int rc;
+
+ switch (dev->device_type) {
+ case PN533_DEVICE_STD:
+ max_retries.mx_rty_atr = PN533_CONFIG_MAX_RETRIES_ENDLESS;
+ max_retries.mx_rty_psl = 2;
+ max_retries.mx_rty_passive_act =
+ PN533_CONFIG_MAX_RETRIES_NO_RETRY;
+
+ timing.rfu = PN533_CONFIG_TIMING_102;
+ timing.atr_res_timeout = PN533_CONFIG_TIMING_204;
+ timing.dep_timeout = PN533_CONFIG_TIMING_409;
+
+ break;
+
+ case PN533_DEVICE_PASORI:
+ max_retries.mx_rty_atr = 0x2;
+ max_retries.mx_rty_psl = 0x1;
+ max_retries.mx_rty_passive_act =
+ PN533_CONFIG_MAX_RETRIES_NO_RETRY;
+
+ timing.rfu = PN533_CONFIG_TIMING_102;
+ timing.atr_res_timeout = PN533_CONFIG_TIMING_102;
+ timing.dep_timeout = PN533_CONFIG_TIMING_204;
+
+ break;
+
+ default:
+ nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n",
+ dev->device_type);
+ return -EINVAL;
+ }
+
+ rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES,
+ (u8 *)&max_retries, sizeof(max_retries));
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev,
+ "Error on setting MAX_RETRIES config");
+ return rc;
+ }
+
+
+ rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING,
+ (u8 *)&timing, sizeof(timing));
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev,
+ "Error on setting RF timings");
+ return rc;
+ }
+
+ switch (dev->device_type) {
+ case PN533_DEVICE_STD:
+ break;
+
+ case PN533_DEVICE_PASORI:
+ pn533_fw_reset(dev);
+
+ rc = pn533_set_configuration(dev, PN533_CFGITEM_PASORI,
+ pasori_cfg, 3);
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev,
+ "Error while settings PASORI config");
+ return rc;
+ }
+
+ pn533_fw_reset(dev);
+
+ break;
+ }
+
+ return 0;
+}
+
static int pn533_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
@@ -2121,8 +2276,6 @@ static int pn533_probe(struct usb_interface *interface,
struct pn533 *dev;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
- struct pn533_config_max_retries max_retries;
- struct pn533_config_timing timing;
int in_endpoint = 0;
int out_endpoint = 0;
int rc = -ENOMEM;
@@ -2208,10 +2361,22 @@ static int pn533_probe(struct usb_interface *interface,
nfc_dev_info(&dev->interface->dev, "NXP PN533 firmware ver %d.%d now"
" attached", fw_ver->ver, fw_ver->rev);
- protocols = NFC_PROTO_JEWEL_MASK
- | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK
- | NFC_PROTO_ISO14443_MASK
- | NFC_PROTO_NFC_DEP_MASK;
+ dev->device_type = id->driver_info;
+ switch (dev->device_type) {
+ case PN533_DEVICE_STD:
+ protocols = PN533_ALL_PROTOCOLS;
+ break;
+
+ case PN533_DEVICE_PASORI:
+ protocols = PN533_NO_TYPE_B_PROTOCOLS;
+ break;
+
+ default:
+ nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n",
+ dev->device_type);
+ rc = -EINVAL;
+ goto destroy_wq;
+ }
dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols,
PN533_CMD_DATAEXCH_HEAD_LEN,
@@ -2226,30 +2391,9 @@ static int pn533_probe(struct usb_interface *interface,
if (rc)
goto free_nfc_dev;
- max_retries.mx_rty_atr = PN533_CONFIG_MAX_RETRIES_ENDLESS;
- max_retries.mx_rty_psl = 2;
- max_retries.mx_rty_passive_act = PN533_CONFIG_MAX_RETRIES_NO_RETRY;
-
- rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES,
- (u8 *) &max_retries, sizeof(max_retries));
-
- if (rc) {
- nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES"
- " config");
- goto unregister_nfc_dev;
- }
-
- timing.rfu = PN533_CONFIG_TIMING_102;
- timing.atr_res_timeout = PN533_CONFIG_TIMING_204;
- timing.dep_timeout = PN533_CONFIG_TIMING_409;
-
- rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING,
- (u8 *) &timing, sizeof(timing));
- if (rc) {
- nfc_dev_err(&dev->interface->dev,
- "Error on setting RF timings");
+ rc = pn533_setup(dev);
+ if (rc)
goto unregister_nfc_dev;
- }
return 0;
diff --git a/drivers/nfc/pn544_hci.c b/drivers/nfc/pn544_hci.c
index 457eac35dc74..aa71807189ba 100644
--- a/drivers/nfc/pn544_hci.c
+++ b/drivers/nfc/pn544_hci.c
@@ -108,16 +108,22 @@ enum pn544_state {
#define PN544_NFC_WI_MGMT_GATE 0xA1
-static u8 pn544_custom_gates[] = {
- PN544_SYS_MGMT_GATE,
- PN544_SWP_MGMT_GATE,
- PN544_POLLING_LOOP_MGMT_GATE,
- PN544_NFC_WI_MGMT_GATE,
- PN544_RF_READER_F_GATE,
- PN544_RF_READER_JEWEL_GATE,
- PN544_RF_READER_ISO15693_GATE,
- PN544_RF_READER_NFCIP1_INITIATOR_GATE,
- PN544_RF_READER_NFCIP1_TARGET_GATE
+static struct nfc_hci_gate pn544_gates[] = {
+ {NFC_HCI_ADMIN_GATE, NFC_HCI_INVALID_PIPE},
+ {NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE},
+ {NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE},
+ {NFC_HCI_LINK_MGMT_GATE, NFC_HCI_INVALID_PIPE},
+ {NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE},
+ {NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE},
+ {PN544_SYS_MGMT_GATE, NFC_HCI_INVALID_PIPE},
+ {PN544_SWP_MGMT_GATE, NFC_HCI_INVALID_PIPE},
+ {PN544_POLLING_LOOP_MGMT_GATE, NFC_HCI_INVALID_PIPE},
+ {PN544_NFC_WI_MGMT_GATE, NFC_HCI_INVALID_PIPE},
+ {PN544_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE},
+ {PN544_RF_READER_JEWEL_GATE, NFC_HCI_INVALID_PIPE},
+ {PN544_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE},
+ {PN544_RF_READER_NFCIP1_INITIATOR_GATE, NFC_HCI_INVALID_PIPE},
+ {PN544_RF_READER_NFCIP1_TARGET_GATE, NFC_HCI_INVALID_PIPE}
};
/* Largest headroom needed for outgoing custom commands */
@@ -377,6 +383,9 @@ static int pn544_hci_open(struct nfc_shdlc *shdlc)
r = pn544_hci_enable(info, HCI_MODE);
+ if (r == 0)
+ info->state = PN544_ST_READY;
+
out:
mutex_unlock(&info->info_lock);
return r;
@@ -393,6 +402,8 @@ static void pn544_hci_close(struct nfc_shdlc *shdlc)
pn544_hci_disable(info);
+ info->state = PN544_ST_COLD;
+
out:
mutex_unlock(&info->info_lock);
}
@@ -844,10 +855,9 @@ static int __devinit pn544_hci_probe(struct i2c_client *client,
goto err_rti;
}
- init_data.gate_count = ARRAY_SIZE(pn544_custom_gates);
+ init_data.gate_count = ARRAY_SIZE(pn544_gates);
- memcpy(init_data.gates, pn544_custom_gates,
- ARRAY_SIZE(pn544_custom_gates));
+ memcpy(init_data.gates, pn544_gates, sizeof(pn544_gates));
/*
* TODO: Session id must include the driver name + some bus addr
@@ -859,6 +869,7 @@ static int __devinit pn544_hci_probe(struct i2c_client *client,
NFC_PROTO_MIFARE_MASK |
NFC_PROTO_FELICA_MASK |
NFC_PROTO_ISO14443_MASK |
+ NFC_PROTO_ISO14443_B_MASK |
NFC_PROTO_NFC_DEP_MASK;
info->shdlc = nfc_shdlc_allocate(&pn544_shdlc_ops,
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 8deaf6d050c3..03b2f30d2ace 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -70,6 +70,13 @@ struct bcma_host_ops {
/* Core-ID values. */
#define BCMA_CORE_OOB_ROUTER 0x367 /* Out of band */
+#define BCMA_CORE_4706_CHIPCOMMON 0x500
+#define BCMA_CORE_4706_SOC_RAM 0x50E
+#define BCMA_CORE_4706_MAC_GBIT 0x52D
+#define BCMA_CORE_AMEMC 0x52E /* DDR1/2 memory controller core */
+#define BCMA_CORE_ALTA 0x534 /* I2S core */
+#define BCMA_CORE_4706_MAC_GBIT_COMMON 0x5DC
+#define BCMA_CORE_DDR23_PHY 0x5DD
#define BCMA_CORE_INVALID 0x700
#define BCMA_CORE_CHIPCOMMON 0x800
#define BCMA_CORE_ILINE20 0x801
@@ -130,6 +137,36 @@ struct bcma_host_ops {
#define BCMA_MAX_NR_CORES 16
+/* Chip IDs of PCIe devices */
+#define BCMA_CHIP_ID_BCM4313 0x4313
+#define BCMA_CHIP_ID_BCM43224 43224
+#define BCMA_PKG_ID_BCM43224_FAB_CSM 0x8
+#define BCMA_PKG_ID_BCM43224_FAB_SMIC 0xa
+#define BCMA_CHIP_ID_BCM43225 43225
+#define BCMA_CHIP_ID_BCM43227 43227
+#define BCMA_CHIP_ID_BCM43228 43228
+#define BCMA_CHIP_ID_BCM43421 43421
+#define BCMA_CHIP_ID_BCM43428 43428
+#define BCMA_CHIP_ID_BCM43431 43431
+#define BCMA_CHIP_ID_BCM43460 43460
+#define BCMA_CHIP_ID_BCM4331 0x4331
+#define BCMA_CHIP_ID_BCM6362 0x6362
+#define BCMA_CHIP_ID_BCM4360 0x4360
+#define BCMA_CHIP_ID_BCM4352 0x4352
+
+/* Chip IDs of SoCs */
+#define BCMA_CHIP_ID_BCM4706 0x5300
+#define BCMA_CHIP_ID_BCM4716 0x4716
+#define BCMA_PKG_ID_BCM4716 8
+#define BCMA_PKG_ID_BCM4717 9
+#define BCMA_PKG_ID_BCM4718 10
+#define BCMA_CHIP_ID_BCM47162 47162
+#define BCMA_CHIP_ID_BCM4748 0x4748
+#define BCMA_CHIP_ID_BCM4749 0x4749
+#define BCMA_CHIP_ID_BCM5356 0x5356
+#define BCMA_CHIP_ID_BCM5357 0x5357
+#define BCMA_CHIP_ID_BCM53572 53572
+
struct bcma_device {
struct bcma_bus *bus;
struct bcma_device_id id;
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index 8bbfe31fbac8..fbd0d49dc4d2 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -88,6 +88,11 @@
#define BCMA_CC_CHIPST_4313_OTP_PRESENT 2
#define BCMA_CC_CHIPST_4331_SPROM_PRESENT 2
#define BCMA_CC_CHIPST_4331_OTP_PRESENT 4
+#define BCMA_CC_CHIPST_4706_PKG_OPTION BIT(0) /* 0: full-featured package 1: low-cost package */
+#define BCMA_CC_CHIPST_4706_SFLASH_PRESENT BIT(1) /* 0: parallel, 1: serial flash is present */
+#define BCMA_CC_CHIPST_4706_SFLASH_TYPE BIT(2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */
+#define BCMA_CC_CHIPST_4706_MIPS_BENDIAN BIT(3) /* 0: little, 1: big endian */
+#define BCMA_CC_CHIPST_4706_PCIE1_DISABLE BIT(5) /* PCIE1 enable strap pin */
#define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */
#define BCMA_CC_JCMD_START 0x80000000
#define BCMA_CC_JCMD_BUSY 0x80000000
@@ -280,6 +285,15 @@
/* 4706 PMU */
#define BCMA_CC_PMU4706_MAINPLL_PLL0 0
+#define BCMA_CC_PMU6_4706_PROCPLL_OFF 4 /* The CPU PLL */
+#define BCMA_CC_PMU6_4706_PROC_P2DIV_MASK 0x000f0000
+#define BCMA_CC_PMU6_4706_PROC_P2DIV_SHIFT 16
+#define BCMA_CC_PMU6_4706_PROC_P1DIV_MASK 0x0000f000
+#define BCMA_CC_PMU6_4706_PROC_P1DIV_SHIFT 12
+#define BCMA_CC_PMU6_4706_PROC_NDIV_INT_MASK 0x00000ff8
+#define BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT 3
+#define BCMA_CC_PMU6_4706_PROC_NDIV_MODE_MASK 0x00000007
+#define BCMA_CC_PMU6_4706_PROC_NDIV_MODE_SHIFT 0
/* ALP clock on pre-PMU chips */
#define BCMA_CC_PMU_ALP_CLOCK 20000000
@@ -308,6 +322,19 @@
#define BCMA_CC_PPL_PCHI_OFF 5
#define BCMA_CC_PPL_PCHI_MASK 0x0000003f
+#define BCMA_CC_PMU_PLL_CTL0 0
+#define BCMA_CC_PMU_PLL_CTL1 1
+#define BCMA_CC_PMU_PLL_CTL2 2
+#define BCMA_CC_PMU_PLL_CTL3 3
+#define BCMA_CC_PMU_PLL_CTL4 4
+#define BCMA_CC_PMU_PLL_CTL5 5
+
+#define BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000
+#define BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT 20
+
+#define BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000
+#define BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT 20
+
/* BCM4331 ChipControl numbers. */
#define BCMA_CHIPCTL_4331_BT_COEXIST BIT(0) /* 0 disable */
#define BCMA_CHIPCTL_4331_SECI BIT(1) /* 0 SECI is disabled (JATG functional) */
@@ -321,9 +348,18 @@
#define BCMA_CHIPCTL_4331_OVR_PIPEAUXPWRDOWN BIT(9) /* override core control on pipe_AuxPowerDown */
#define BCMA_CHIPCTL_4331_PCIE_AUXCLKEN BIT(10) /* pcie_auxclkenable */
#define BCMA_CHIPCTL_4331_PCIE_PIPE_PLLDOWN BIT(11) /* pcie_pipe_pllpowerdown */
+#define BCMA_CHIPCTL_4331_EXTPA_EN2 BIT(12) /* 0 ext pa disable, 1 ext pa enabled */
#define BCMA_CHIPCTL_4331_BT_SHD0_ON_GPIO4 BIT(16) /* enable bt_shd0 at gpio4 */
#define BCMA_CHIPCTL_4331_BT_SHD1_ON_GPIO5 BIT(17) /* enable bt_shd1 at gpio5 */
+/* 43224 chip-specific ChipControl register bits */
+#define BCMA_CCTRL_43224_GPIO_TOGGLE 0x8000 /* gpio[3:0] pins as btcoex or s/w gpio */
+#define BCMA_CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */
+#define BCMA_CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */
+
+/* 4313 Chip specific ChipControl register bits */
+#define BCMA_CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */
+
/* Data for the PMU, if available.
* Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
*/
@@ -411,5 +447,6 @@ extern void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
u32 offset, u32 mask, u32 set);
extern void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc,
u32 offset, u32 mask, u32 set);
+extern void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid);
#endif /* LINUX_BCMA_DRIVER_CC_H_ */
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index ce9af8918514..e02fc682bb68 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -47,6 +47,7 @@
#define IEEE80211_FCTL_MOREDATA 0x2000
#define IEEE80211_FCTL_PROTECTED 0x4000
#define IEEE80211_FCTL_ORDER 0x8000
+#define IEEE80211_FCTL_CTL_EXT 0x0f00
#define IEEE80211_SCTL_FRAG 0x000F
#define IEEE80211_SCTL_SEQ 0xFFF0
@@ -54,6 +55,7 @@
#define IEEE80211_FTYPE_MGMT 0x0000
#define IEEE80211_FTYPE_CTL 0x0004
#define IEEE80211_FTYPE_DATA 0x0008
+#define IEEE80211_FTYPE_EXT 0x000c
/* management */
#define IEEE80211_STYPE_ASSOC_REQ 0x0000
@@ -70,6 +72,7 @@
#define IEEE80211_STYPE_ACTION 0x00D0
/* control */
+#define IEEE80211_STYPE_CTL_EXT 0x0060
#define IEEE80211_STYPE_BACK_REQ 0x0080
#define IEEE80211_STYPE_BACK 0x0090
#define IEEE80211_STYPE_PSPOLL 0x00A0
@@ -97,6 +100,18 @@
#define IEEE80211_STYPE_QOS_CFPOLL 0x00E0
#define IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0
+/* extension, added by 802.11ad */
+#define IEEE80211_STYPE_DMG_BEACON 0x0000
+
+/* control extension - for IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTL_EXT */
+#define IEEE80211_CTL_EXT_POLL 0x2000
+#define IEEE80211_CTL_EXT_SPR 0x3000
+#define IEEE80211_CTL_EXT_GRANT 0x4000
+#define IEEE80211_CTL_EXT_DMG_CTS 0x5000
+#define IEEE80211_CTL_EXT_DMG_DTS 0x6000
+#define IEEE80211_CTL_EXT_SSW 0x8000
+#define IEEE80211_CTL_EXT_SSW_FBACK 0x9000
+#define IEEE80211_CTL_EXT_SSW_ACK 0xa000
/* miscellaneous IEEE 802.11 constants */
#define IEEE80211_MAX_FRAG_THRESHOLD 2352
@@ -568,6 +583,26 @@ struct ieee80211s_hdr {
#define MESH_FLAGS_PS_DEEP 0x4
/**
+ * enum ieee80211_preq_flags - mesh PREQ element flags
+ *
+ * @IEEE80211_PREQ_PROACTIVE_PREP_FLAG: proactive PREP subfield
+ */
+enum ieee80211_preq_flags {
+ IEEE80211_PREQ_PROACTIVE_PREP_FLAG = 1<<2,
+};
+
+/**
+ * enum ieee80211_preq_target_flags - mesh PREQ element per target flags
+ *
+ * @IEEE80211_PREQ_TO_FLAG: target only subfield
+ * @IEEE80211_PREQ_USN_FLAG: unknown target HWMP sequence number subfield
+ */
+enum ieee80211_preq_target_flags {
+ IEEE80211_PREQ_TO_FLAG = 1<<0,
+ IEEE80211_PREQ_USN_FLAG = 1<<2,
+};
+
+/**
* struct ieee80211_quiet_ie
*
* This structure refers to "Quiet information element"
@@ -1072,6 +1107,73 @@ struct ieee80211_ht_operation {
#define WLAN_HT_SMPS_CONTROL_STATIC 1
#define WLAN_HT_SMPS_CONTROL_DYNAMIC 3
+#define VHT_MCS_SUPPORTED_SET_SIZE 8
+
+struct ieee80211_vht_capabilities {
+ __le32 vht_capabilities_info;
+ u8 vht_supported_mcs_set[VHT_MCS_SUPPORTED_SET_SIZE];
+} __packed;
+
+struct ieee80211_vht_operation {
+ u8 vht_op_info_chwidth;
+ u8 vht_op_info_chan_center_freq_seg1_idx;
+ u8 vht_op_info_chan_center_freq_seg2_idx;
+ __le16 vht_basic_mcs_set;
+} __packed;
+
+/**
+ * struct ieee80211_vht_mcs_info - VHT MCS information
+ * @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams
+ * @rx_highest: Indicates highest long GI VHT PPDU data rate
+ * STA can receive. Rate expressed in units of 1 Mbps.
+ * If this field is 0 this value should not be used to
+ * consider the highest RX data rate supported.
+ * @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams
+ * @tx_highest: Indicates highest long GI VHT PPDU data rate
+ * STA can transmit. Rate expressed in units of 1 Mbps.
+ * If this field is 0 this value should not be used to
+ * consider the highest TX data rate supported.
+ */
+struct ieee80211_vht_mcs_info {
+ __le16 rx_mcs_map;
+ __le16 rx_highest;
+ __le16 tx_mcs_map;
+ __le16 tx_highest;
+} __packed;
+
+#define IEEE80211_VHT_MCS_ZERO_TO_SEVEN_SUPPORT 0
+#define IEEE80211_VHT_MCS_ZERO_TO_EIGHT_SUPPORT 1
+#define IEEE80211_VHT_MCS_ZERO_TO_NINE_SUPPORT 2
+#define IEEE80211_VHT_MCS_NOT_SUPPORTED 3
+
+/* 802.11ac VHT Capabilities */
+#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000
+#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001
+#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002
+#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004
+#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008
+#define IEEE80211_VHT_CAP_RXLDPC 0x00000010
+#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020
+#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040
+#define IEEE80211_VHT_CAP_TXSTBC 0x00000080
+#define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100
+#define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200
+#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300
+#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400
+#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800
+#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000
+#define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000
+#define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX 0x00030000
+#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000
+#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000
+#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000
+#define IEEE80211_VHT_CAP_HTC_VHT 0x00400000
+#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT 0x00800000
+#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000
+#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000
+#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000
+#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000
+
/* Authentication algorithms */
#define WLAN_AUTH_OPEN 0
#define WLAN_AUTH_SHARED_KEY 1
@@ -1104,6 +1206,21 @@ struct ieee80211_ht_operation {
#define WLAN_CAPABILITY_QOS (1<<9)
#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
+
+/* DMG (60gHz) 802.11ad */
+/* type - bits 0..1 */
+#define WLAN_CAPABILITY_DMG_TYPE_IBSS (1<<0) /* Tx by: STA */
+#define WLAN_CAPABILITY_DMG_TYPE_PBSS (2<<0) /* Tx by: PCP */
+#define WLAN_CAPABILITY_DMG_TYPE_AP (3<<0) /* Tx by: AP */
+
+#define WLAN_CAPABILITY_DMG_CBAP_ONLY (1<<2)
+#define WLAN_CAPABILITY_DMG_CBAP_SOURCE (1<<3)
+#define WLAN_CAPABILITY_DMG_PRIVACY (1<<4)
+#define WLAN_CAPABILITY_DMG_ECPAC (1<<5)
+
+#define WLAN_CAPABILITY_DMG_SPECTRUM_MGMT (1<<8)
+#define WLAN_CAPABILITY_DMG_RADIO_MEASURE (1<<12)
+
/* measurement */
#define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0)
#define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1)
@@ -1113,7 +1230,6 @@ struct ieee80211_ht_operation {
#define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1
#define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2
-
/* 802.11g ERP information element */
#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
#define WLAN_ERP_USE_PROTECTION (1<<1)
@@ -1125,6 +1241,16 @@ enum {
WLAN_ERP_PREAMBLE_LONG = 1,
};
+/* Band ID, 802.11ad #8.4.1.45 */
+enum {
+ IEEE80211_BANDID_TV_WS = 0, /* TV white spaces */
+ IEEE80211_BANDID_SUB1 = 1, /* Sub-1 GHz (excluding TV white spaces) */
+ IEEE80211_BANDID_2G = 2, /* 2.4 GHz */
+ IEEE80211_BANDID_3G = 3, /* 3.6 GHz */
+ IEEE80211_BANDID_5G = 4, /* 4.9 and 5 GHz */
+ IEEE80211_BANDID_60G = 5, /* 60 GHz */
+};
+
/* Status codes */
enum ieee80211_statuscode {
WLAN_STATUS_SUCCESS = 0,
@@ -1176,6 +1302,17 @@ enum ieee80211_statuscode {
WLAN_STATUS_ANTI_CLOG_REQUIRED = 76,
WLAN_STATUS_FCG_NOT_SUPP = 78,
WLAN_STATUS_STA_NO_TBTT = 78,
+ /* 802.11ad */
+ WLAN_STATUS_REJECTED_WITH_SUGGESTED_CHANGES = 39,
+ WLAN_STATUS_REJECTED_FOR_DELAY_PERIOD = 47,
+ WLAN_STATUS_REJECT_WITH_SCHEDULE = 83,
+ WLAN_STATUS_PENDING_ADMITTING_FST_SESSION = 86,
+ WLAN_STATUS_PERFORMING_FST_NOW = 87,
+ WLAN_STATUS_PENDING_GAP_IN_BA_WINDOW = 88,
+ WLAN_STATUS_REJECT_U_PID_SETTING = 89,
+ WLAN_STATUS_REJECT_DSE_BAND = 96,
+ WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL = 99,
+ WLAN_STATUS_DENIED_DUE_TO_SPECTRUM_MANAGEMENT = 103,
};
@@ -1332,6 +1469,43 @@ enum ieee80211_eid {
WLAN_EID_DSE_REGISTERED_LOCATION = 58,
WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59,
WLAN_EID_EXT_CHANSWITCH_ANN = 60,
+
+ WLAN_EID_VHT_CAPABILITY = 191,
+ WLAN_EID_VHT_OPERATION = 192,
+
+ /* 802.11ad */
+ WLAN_EID_NON_TX_BSSID_CAP = 83,
+ WLAN_EID_WAKEUP_SCHEDULE = 143,
+ WLAN_EID_EXT_SCHEDULE = 144,
+ WLAN_EID_STA_AVAILABILITY = 145,
+ WLAN_EID_DMG_TSPEC = 146,
+ WLAN_EID_DMG_AT = 147,
+ WLAN_EID_DMG_CAP = 148,
+ WLAN_EID_DMG_OPERATION = 151,
+ WLAN_EID_DMG_BSS_PARAM_CHANGE = 152,
+ WLAN_EID_DMG_BEAM_REFINEMENT = 153,
+ WLAN_EID_CHANNEL_MEASURE_FEEDBACK = 154,
+ WLAN_EID_AWAKE_WINDOW = 157,
+ WLAN_EID_MULTI_BAND = 158,
+ WLAN_EID_ADDBA_EXT = 159,
+ WLAN_EID_NEXT_PCP_LIST = 160,
+ WLAN_EID_PCP_HANDOVER = 161,
+ WLAN_EID_DMG_LINK_MARGIN = 162,
+ WLAN_EID_SWITCHING_STREAM = 163,
+ WLAN_EID_SESSION_TRANSITION = 164,
+ WLAN_EID_DYN_TONE_PAIRING_REPORT = 165,
+ WLAN_EID_CLUSTER_REPORT = 166,
+ WLAN_EID_RELAY_CAP = 167,
+ WLAN_EID_RELAY_XFER_PARAM_SET = 168,
+ WLAN_EID_BEAM_LINK_MAINT = 169,
+ WLAN_EID_MULTIPLE_MAC_ADDR = 170,
+ WLAN_EID_U_PID = 171,
+ WLAN_EID_DMG_LINK_ADAPT_ACK = 172,
+ WLAN_EID_QUIET_PERIOD_REQ = 175,
+ WLAN_EID_QUIET_PERIOD_RESP = 177,
+ WLAN_EID_EPAC_POLICY = 182,
+ WLAN_EID_CLISTER_TIME_OFF = 183,
+ WLAN_EID_ANTENNA_SECTOR_ID_PATTERN = 190,
};
/* Action category code */
@@ -1348,7 +1522,10 @@ enum ieee80211_category {
WLAN_CATEGORY_MESH_ACTION = 13,
WLAN_CATEGORY_MULTIHOP_ACTION = 14,
WLAN_CATEGORY_SELF_PROTECTED = 15,
+ WLAN_CATEGORY_DMG = 16,
WLAN_CATEGORY_WMM = 17,
+ WLAN_CATEGORY_FST = 18,
+ WLAN_CATEGORY_UNPROT_DMG = 20,
WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126,
WLAN_CATEGORY_VENDOR_SPECIFIC = 127,
};
@@ -1443,7 +1620,7 @@ enum ieee80211_tdls_actioncode {
*
* @IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET: the default synchronization method
* @IEEE80211_SYNC_METHOD_VENDOR: a vendor specific synchronization method
- * that will be specified in a vendor specific information element
+ * that will be specified in a vendor specific information element
*/
enum {
IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET = 1,
@@ -1455,7 +1632,7 @@ enum {
*
* @IEEE80211_PATH_PROTOCOL_HWMP: the default path selection protocol
* @IEEE80211_PATH_PROTOCOL_VENDOR: a vendor specific protocol that will
- * be specified in a vendor specific information element
+ * be specified in a vendor specific information element
*/
enum {
IEEE80211_PATH_PROTOCOL_HWMP = 1,
@@ -1467,13 +1644,35 @@ enum {
*
* @IEEE80211_PATH_METRIC_AIRTIME: the default path selection metric
* @IEEE80211_PATH_METRIC_VENDOR: a vendor specific metric that will be
- * specified in a vendor specific information element
+ * specified in a vendor specific information element
*/
enum {
IEEE80211_PATH_METRIC_AIRTIME = 1,
IEEE80211_PATH_METRIC_VENDOR = 255,
};
+/**
+ * enum ieee80211_root_mode_identifier - root mesh STA mode identifier
+ *
+ * These attribute are used by dot11MeshHWMPRootMode to set root mesh STA mode
+ *
+ * @IEEE80211_ROOTMODE_NO_ROOT: the mesh STA is not a root mesh STA (default)
+ * @IEEE80211_ROOTMODE_ROOT: the mesh STA is a root mesh STA if greater than
+ * this value
+ * @IEEE80211_PROACTIVE_PREQ_NO_PREP: the mesh STA is a root mesh STA supports
+ * the proactive PREQ with proactive PREP subfield set to 0
+ * @IEEE80211_PROACTIVE_PREQ_WITH_PREP: the mesh STA is a root mesh STA
+ * supports the proactive PREQ with proactive PREP subfield set to 1
+ * @IEEE80211_PROACTIVE_RANN: the mesh STA is a root mesh STA supports
+ * the proactive RANN
+ */
+enum ieee80211_root_mode_identifier {
+ IEEE80211_ROOTMODE_NO_ROOT = 0,
+ IEEE80211_ROOTMODE_ROOT = 1,
+ IEEE80211_PROACTIVE_PREQ_NO_PREP = 2,
+ IEEE80211_PROACTIVE_PREQ_WITH_PREP = 3,
+ IEEE80211_PROACTIVE_RANN = 4,
+};
/*
* IEEE 802.11-2007 7.3.2.9 Country information element
@@ -1574,6 +1773,7 @@ enum ieee80211_sa_query_action {
#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
+#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
#define WLAN_CIPHER_SUITE_SMS4 0x00147201
@@ -1589,6 +1789,10 @@ enum ieee80211_sa_query_action {
#define WLAN_OUI_WFA 0x506f9a
#define WLAN_OUI_TYPE_WFA_P2P 9
+#define WLAN_OUI_MICROSOFT 0x0050f2
+#define WLAN_OUI_TYPE_MICROSOFT_WPA 1
+#define WLAN_OUI_TYPE_MICROSOFT_WMM 2
+#define WLAN_OUI_TYPE_MICROSOFT_WPS 4
/*
* WMM/802.11e Tspec Element
diff --git a/include/linux/nfc.h b/include/linux/nfc.h
index f4e6dd915b1c..6189f27e305b 100644
--- a/include/linux/nfc.h
+++ b/include/linux/nfc.h
@@ -136,8 +136,9 @@ enum nfc_attrs {
#define NFC_PROTO_FELICA 3
#define NFC_PROTO_ISO14443 4
#define NFC_PROTO_NFC_DEP 5
+#define NFC_PROTO_ISO14443_B 6
-#define NFC_PROTO_MAX 6
+#define NFC_PROTO_MAX 7
/* NFC communication modes */
#define NFC_COMM_ACTIVE 0
@@ -149,11 +150,12 @@ enum nfc_attrs {
#define NFC_RF_NONE 2
/* NFC protocols masks used in bitsets */
-#define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL)
-#define NFC_PROTO_MIFARE_MASK (1 << NFC_PROTO_MIFARE)
-#define NFC_PROTO_FELICA_MASK (1 << NFC_PROTO_FELICA)
-#define NFC_PROTO_ISO14443_MASK (1 << NFC_PROTO_ISO14443)
-#define NFC_PROTO_NFC_DEP_MASK (1 << NFC_PROTO_NFC_DEP)
+#define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL)
+#define NFC_PROTO_MIFARE_MASK (1 << NFC_PROTO_MIFARE)
+#define NFC_PROTO_FELICA_MASK (1 << NFC_PROTO_FELICA)
+#define NFC_PROTO_ISO14443_MASK (1 << NFC_PROTO_ISO14443)
+#define NFC_PROTO_NFC_DEP_MASK (1 << NFC_PROTO_NFC_DEP)
+#define NFC_PROTO_ISO14443_B_MASK (1 << NFC_PROTO_ISO14443_B)
struct sockaddr_nfc {
sa_family_t sa_family;
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 970afdf5a605..e791487ead37 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -277,6 +277,12 @@
* @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to
* NL80211_CMD_GET_SURVEY and on the "scan" multicast group)
*
+ * @NL80211_CMD_SET_PMKSA: Add a PMKSA cache entry, using %NL80211_ATTR_MAC
+ * (for the BSSID) and %NL80211_ATTR_PMKID.
+ * @NL80211_CMD_DEL_PMKSA: Delete a PMKSA cache entry, using %NL80211_ATTR_MAC
+ * (for the BSSID) and %NL80211_ATTR_PMKID.
+ * @NL80211_CMD_FLUSH_PMKSA: Flush all PMKSA cache entries.
+ *
* @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain
* has been changed and provides details of the request information
* that caused the change such as who initiated the regulatory request
@@ -456,6 +462,10 @@
* the frame.
* @NL80211_CMD_ACTION_TX_STATUS: Alias for @NL80211_CMD_FRAME_TX_STATUS for
* backward compatibility.
+ *
+ * @NL80211_CMD_SET_POWER_SAVE: Set powersave, using %NL80211_ATTR_PS_STATE
+ * @NL80211_CMD_GET_POWER_SAVE: Get powersave status in %NL80211_ATTR_PS_STATE
+ *
* @NL80211_CMD_SET_CQM: Connection quality monitor configuration. This command
* is used to configure connection quality monitoring notification trigger
* levels.
@@ -761,6 +771,9 @@ enum nl80211_commands {
* @NL80211_ATTR_IFNAME: network interface name
* @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype
*
+ * @NL80211_ATTR_WDEV: wireless device identifier, used for pseudo-devices
+ * that don't have a netdev (u64)
+ *
* @NL80211_ATTR_MAC: MAC address (various uses)
*
* @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of
@@ -771,6 +784,13 @@ enum nl80211_commands {
* section 7.3.2.25.1, e.g. 0x000FAC04)
* @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and
* CCMP keys, each six bytes in little endian
+ * @NL80211_ATTR_KEY_DEFAULT: Flag attribute indicating the key is default key
+ * @NL80211_ATTR_KEY_DEFAULT_MGMT: Flag attribute indicating the key is the
+ * default management key
+ * @NL80211_ATTR_CIPHER_SUITES_PAIRWISE: For crypto settings for connect or
+ * other commands, indicates which pairwise cipher suites are used
+ * @NL80211_ATTR_CIPHER_SUITE_GROUP: For crypto settings for connect or
+ * other commands, indicates which group cipher suite is used
*
* @NL80211_ATTR_BEACON_INTERVAL: beacon interval in TU
* @NL80211_ATTR_DTIM_PERIOD: DTIM period for beaconing
@@ -1006,6 +1026,8 @@ enum nl80211_commands {
* @NL80211_ATTR_ACK: Flag attribute indicating that the frame was
* acknowledged by the recipient.
*
+ * @NL80211_ATTR_PS_STATE: powersave state, using &enum nl80211_ps_state values.
+ *
* @NL80211_ATTR_CQM: connection quality monitor configuration in a
* nested attribute with %NL80211_ATTR_CQM_* sub-attributes.
*
@@ -1063,7 +1085,7 @@ enum nl80211_commands {
* flag isn't set, the frame will be rejected. This is also used as an
* nl80211 capability flag.
*
- * @NL80211_ATTR_BSS_HTOPMODE: HT operation mode (u16)
+ * @NL80211_ATTR_BSS_HT_OPMODE: HT operation mode (u16)
*
* @NL80211_ATTR_KEY_DEFAULT_TYPES: A nested attribute containing flags
* attributes, specifying what a key should be set as default as.
@@ -1087,10 +1109,10 @@ enum nl80211_commands {
* indicate which WoW triggers should be enabled. This is also
* used by %NL80211_CMD_GET_WOWLAN to get the currently enabled WoWLAN
* triggers.
-
+ *
* @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan
* cycles, in msecs.
-
+ *
* @NL80211_ATTR_SCHED_SCAN_MATCH: Nested attribute with one or more
* sets of attributes to match during scheduled scans. Only BSSs
* that match any of the sets will be reported. These are
@@ -1117,7 +1139,7 @@ enum nl80211_commands {
* are managed in software: interfaces of these types aren't subject to
* any restrictions in their number or combinations.
*
- * @%NL80211_ATTR_REKEY_DATA: nested attribute containing the information
+ * @NL80211_ATTR_REKEY_DATA: nested attribute containing the information
* necessary for GTK rekeying in the device, see &enum nl80211_rekey_data.
*
* @NL80211_ATTR_SCAN_SUPP_RATES: rates per to be advertised as supported in scan,
@@ -1184,7 +1206,6 @@ enum nl80211_commands {
* @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from
* &enum nl80211_feature_flags and is advertised in wiphy information.
* @NL80211_ATTR_PROBE_RESP_OFFLOAD: Indicates that the HW responds to probe
- *
* requests while operating in AP-mode.
* This attribute holds a bitmap of the supported protocols for
* offloading (see &enum nl80211_probe_resp_offload_support_attr).
@@ -1475,6 +1496,8 @@ enum nl80211_attrs {
NL80211_ATTR_BG_SCAN_PERIOD,
+ NL80211_ATTR_WDEV,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -1524,6 +1547,9 @@ enum nl80211_attrs {
#define NL80211_MIN_REMAIN_ON_CHANNEL_TIME 10
+/* default RSSI threshold for scan results if none specified. */
+#define NL80211_SCAN_RSSI_THOLD_OFF -300
+
/**
* enum nl80211_iftype - (virtual) interface types
*
@@ -1617,12 +1643,20 @@ struct nl80211_sta_flag_update {
*
* These attribute types are used with %NL80211_STA_INFO_TXRATE
* when getting information about the bitrate of a station.
+ * There are 2 attributes for bitrate, a legacy one that represents
+ * a 16-bit value, and new one that represents a 32-bit value.
+ * If the rate value fits into 16 bit, both attributes are reported
+ * with the same value. If the rate is too high to fit into 16 bits
+ * (>6.5535Gbps) only 32-bit attribute is included.
+ * User space tools encouraged to use the 32-bit attribute and fall
+ * back to the 16-bit one for compatibility with older kernels.
*
* @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
* @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
* @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
* @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
* @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
+ * @NL80211_RATE_INFO_BITRATE32: total bitrate (u32, 100kbit/s)
* @NL80211_RATE_INFO_MAX: highest rate_info number currently defined
* @__NL80211_RATE_INFO_AFTER_LAST: internal use
*/
@@ -1632,6 +1666,7 @@ enum nl80211_rate_info {
NL80211_RATE_INFO_MCS,
NL80211_RATE_INFO_40_MHZ_WIDTH,
NL80211_RATE_INFO_SHORT_GI,
+ NL80211_RATE_INFO_BITRATE32,
/* keep last */
__NL80211_RATE_INFO_AFTER_LAST,
@@ -1792,6 +1827,9 @@ enum nl80211_mpath_info {
* @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE
* @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n
* @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n
+ * @NL80211_BAND_ATTR_VHT_MCS_SET: 32-byte attribute containing the MCS set as
+ * defined in 802.11ac
+ * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE
* @NL80211_BAND_ATTR_MAX: highest band attribute currently defined
* @__NL80211_BAND_ATTR_AFTER_LAST: internal use
*/
@@ -1805,6 +1843,9 @@ enum nl80211_band_attr {
NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
+ NL80211_BAND_ATTR_VHT_MCS_SET,
+ NL80211_BAND_ATTR_VHT_CAPA,
+
/* keep last */
__NL80211_BAND_ATTR_AFTER_LAST,
NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
@@ -1956,6 +1997,8 @@ enum nl80211_reg_rule_attr {
* @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved
* @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching,
* only report BSS with matching SSID.
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a
+ * BSS in scan results. Filtering is turned off if not specified.
* @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
* attribute number currently defined
* @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
@@ -1963,7 +2006,8 @@ enum nl80211_reg_rule_attr {
enum nl80211_sched_scan_match_attr {
__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID,
- NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
+ NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
+ NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
/* keep last */
__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
@@ -1971,6 +2015,9 @@ enum nl80211_sched_scan_match_attr {
__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST - 1
};
+/* only for backward compatibility */
+#define NL80211_ATTR_SCHED_SCAN_MATCH_SSID NL80211_SCHED_SCAN_MATCH_ATTR_SSID
+
/**
* enum nl80211_reg_rule_flags - regulatory rule flags
*
@@ -2090,78 +2137,91 @@ enum nl80211_mntr_flags {
* @__NL80211_MESHCONF_INVALID: internal use
*
* @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in
- * millisecond units, used by the Peer Link Open message
+ * millisecond units, used by the Peer Link Open message
*
* @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the initial confirm timeout, in
- * millisecond units, used by the peer link management to close a peer link
+ * millisecond units, used by the peer link management to close a peer link
*
* @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in
- * millisecond units
+ * millisecond units
*
* @NL80211_MESHCONF_MAX_PEER_LINKS: maximum number of peer links allowed
- * on this mesh interface
+ * on this mesh interface
*
* @NL80211_MESHCONF_MAX_RETRIES: specifies the maximum number of peer link
- * open retries that can be sent to establish a new peer link instance in a
- * mesh
+ * open retries that can be sent to establish a new peer link instance in a
+ * mesh
*
* @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh
- * point.
+ * point.
*
* @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically
- * open peer links when we detect compatible mesh peers.
+ * open peer links when we detect compatible mesh peers.
*
* @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames
- * containing a PREQ that an MP can send to a particular destination (path
- * target)
+ * containing a PREQ that an MP can send to a particular destination (path
+ * target)
*
* @NL80211_MESHCONF_PATH_REFRESH_TIME: how frequently to refresh mesh paths
- * (in milliseconds)
+ * (in milliseconds)
*
* @NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: minimum length of time to wait
- * until giving up on a path discovery (in milliseconds)
+ * until giving up on a path discovery (in milliseconds)
*
* @NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: The time (in TUs) for which mesh
- * points receiving a PREQ shall consider the forwarding information from the
- * root to be valid. (TU = time unit)
+ * points receiving a PREQ shall consider the forwarding information from
+ * the root to be valid. (TU = time unit)
*
* @NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: The minimum interval of time (in
- * TUs) during which an MP can send only one action frame containing a PREQ
- * reference element
+ * TUs) during which an MP can send only one action frame containing a PREQ
+ * reference element
*
* @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs)
- * that it takes for an HWMP information element to propagate across the mesh
+ * that it takes for an HWMP information element to propagate across the
+ * mesh
*
* @NL80211_MESHCONF_HWMP_ROOTMODE: whether root mode is enabled or not
*
* @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a
- * source mesh point for path selection elements.
+ * source mesh point for path selection elements.
*
* @NL80211_MESHCONF_HWMP_RANN_INTERVAL: The interval of time (in TUs) between
- * root announcements are transmitted.
+ * root announcements are transmitted.
*
* @NL80211_MESHCONF_GATE_ANNOUNCEMENTS: Advertise that this mesh station has
- * access to a broader network beyond the MBSS. This is done via Root
- * Announcement frames.
+ * access to a broader network beyond the MBSS. This is done via Root
+ * Announcement frames.
*
* @NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL: The minimum interval of time (in
- * TUs) during which a mesh STA can send only one Action frame containing a
- * PERR element.
+ * TUs) during which a mesh STA can send only one Action frame containing a
+ * PERR element.
*
* @NL80211_MESHCONF_FORWARDING: set Mesh STA as forwarding or non-forwarding
- * or forwarding entity (default is TRUE - forwarding entity)
+ * or forwarding entity (default is TRUE - forwarding entity)
*
* @NL80211_MESHCONF_RSSI_THRESHOLD: RSSI threshold in dBm. This specifies the
- * threshold for average signal strength of candidate station to establish
- * a peer link.
- *
- * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
+ * threshold for average signal strength of candidate station to establish
+ * a peer link.
*
* @NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR: maximum number of neighbors
- * to synchronize to for 11s default synchronization method (see 11C.12.2.2)
+ * to synchronize to for 11s default synchronization method
+ * (see 11C.12.2.2)
*
* @NL80211_MESHCONF_HT_OPMODE: set mesh HT protection mode.
*
+ * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
+ *
+ * @NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT: The time (in TUs) for
+ * which mesh STAs receiving a proactive PREQ shall consider the forwarding
+ * information to the root mesh STA to be valid.
+ *
+ * @NL80211_MESHCONF_HWMP_ROOT_INTERVAL: The interval of time (in TUs) between
+ * proactive PREQs are transmitted.
+ *
+ * @NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL: The minimum interval of time
+ * (in TUs) during which a mesh STA can send only one Action frame
+ * containing a PREQ element for root path confirmation.
+ *
* @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
*/
enum nl80211_meshconf_params {
@@ -2188,6 +2248,9 @@ enum nl80211_meshconf_params {
NL80211_MESHCONF_RSSI_THRESHOLD,
NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
NL80211_MESHCONF_HT_OPMODE,
+ NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
+ NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
+ NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
/* keep last */
__NL80211_MESHCONF_ATTR_AFTER_LAST,
@@ -2203,34 +2266,36 @@ enum nl80211_meshconf_params {
* @__NL80211_MESH_SETUP_INVALID: Internal use
*
* @NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL: Enable this option to use a
- * vendor specific path selection algorithm or disable it to use the default
- * HWMP.
+ * vendor specific path selection algorithm or disable it to use the
+ * default HWMP.
*
* @NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC: Enable this option to use a
- * vendor specific path metric or disable it to use the default Airtime
- * metric.
+ * vendor specific path metric or disable it to use the default Airtime
+ * metric.
*
* @NL80211_MESH_SETUP_IE: Information elements for this mesh, for instance, a
- * robust security network ie, or a vendor specific information element that
- * vendors will use to identify the path selection methods and metrics in use.
+ * robust security network ie, or a vendor specific information element
+ * that vendors will use to identify the path selection methods and
+ * metrics in use.
*
* @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication
- * daemon will be authenticating mesh candidates.
+ * daemon will be authenticating mesh candidates.
*
* @NL80211_MESH_SETUP_USERSPACE_AMPE: Enable this option if an authentication
- * daemon will be securing peer link frames. AMPE is a secured version of Mesh
- * Peering Management (MPM) and is implemented with the assistance of a
- * userspace daemon. When this flag is set, the kernel will send peer
- * management frames to a userspace daemon that will implement AMPE
- * functionality (security capabilities selection, key confirmation, and key
- * management). When the flag is unset (default), the kernel can autonomously
- * complete (unsecured) mesh peering without the need of a userspace daemon.
- *
- * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
+ * daemon will be securing peer link frames. AMPE is a secured version of
+ * Mesh Peering Management (MPM) and is implemented with the assistance of
+ * a userspace daemon. When this flag is set, the kernel will send peer
+ * management frames to a userspace daemon that will implement AMPE
+ * functionality (security capabilities selection, key confirmation, and
+ * key management). When the flag is unset (default), the kernel can
+ * autonomously complete (unsecured) mesh peering without the need of a
+ * userspace daemon.
*
* @NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC: Enable this option to use a
- * vendor specific synchronization method or disable it to use the default
- * neighbor offset synchronization
+ * vendor specific synchronization method or disable it to use the default
+ * neighbor offset synchronization
+ *
+ * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
*
* @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use
*/
@@ -2494,12 +2559,19 @@ enum nl80211_tx_rate_attributes {
* enum nl80211_band - Frequency band
* @NL80211_BAND_2GHZ: 2.4 GHz ISM band
* @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz)
+ * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz)
*/
enum nl80211_band {
NL80211_BAND_2GHZ,
NL80211_BAND_5GHZ,
+ NL80211_BAND_60GHZ,
};
+/**
+ * enum nl80211_ps_state - powersave state
+ * @NL80211_PS_DISABLED: powersave is disabled
+ * @NL80211_PS_ENABLED: powersave is enabled
+ */
enum nl80211_ps_state {
NL80211_PS_DISABLED,
NL80211_PS_ENABLED,
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
new file mode 100644
index 000000000000..6a76e0a0705e
--- /dev/null
+++ b/include/net/bluetooth/a2mp.h
@@ -0,0 +1,126 @@
+/*
+ Copyright (c) 2010,2011 Code Aurora Forum. All rights reserved.
+ Copyright (c) 2011,2012 Intel Corp.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 and
+ only version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
+#ifndef __A2MP_H
+#define __A2MP_H
+
+#include <net/bluetooth/l2cap.h>
+
+#define A2MP_FEAT_EXT 0x8000
+
+struct amp_mgr {
+ struct l2cap_conn *l2cap_conn;
+ struct l2cap_chan *a2mp_chan;
+ struct kref kref;
+ __u8 ident;
+ __u8 handle;
+ unsigned long flags;
+};
+
+struct a2mp_cmd {
+ __u8 code;
+ __u8 ident;
+ __le16 len;
+ __u8 data[0];
+} __packed;
+
+/* A2MP command codes */
+#define A2MP_COMMAND_REJ 0x01
+struct a2mp_cmd_rej {
+ __le16 reason;
+ __u8 data[0];
+} __packed;
+
+#define A2MP_DISCOVER_REQ 0x02
+struct a2mp_discov_req {
+ __le16 mtu;
+ __le16 ext_feat;
+} __packed;
+
+struct a2mp_cl {
+ __u8 id;
+ __u8 type;
+ __u8 status;
+} __packed;
+
+#define A2MP_DISCOVER_RSP 0x03
+struct a2mp_discov_rsp {
+ __le16 mtu;
+ __le16 ext_feat;
+ struct a2mp_cl cl[0];
+} __packed;
+
+#define A2MP_CHANGE_NOTIFY 0x04
+#define A2MP_CHANGE_RSP 0x05
+
+#define A2MP_GETINFO_REQ 0x06
+struct a2mp_info_req {
+ __u8 id;
+} __packed;
+
+#define A2MP_GETINFO_RSP 0x07
+struct a2mp_info_rsp {
+ __u8 id;
+ __u8 status;
+ __le32 total_bw;
+ __le32 max_bw;
+ __le32 min_latency;
+ __le16 pal_cap;
+ __le16 assoc_size;
+} __packed;
+
+#define A2MP_GETAMPASSOC_REQ 0x08
+struct a2mp_amp_assoc_req {
+ __u8 id;
+} __packed;
+
+#define A2MP_GETAMPASSOC_RSP 0x09
+struct a2mp_amp_assoc_rsp {
+ __u8 id;
+ __u8 status;
+ __u8 amp_assoc[0];
+} __packed;
+
+#define A2MP_CREATEPHYSLINK_REQ 0x0A
+#define A2MP_DISCONNPHYSLINK_REQ 0x0C
+struct a2mp_physlink_req {
+ __u8 local_id;
+ __u8 remote_id;
+ __u8 amp_assoc[0];
+} __packed;
+
+#define A2MP_CREATEPHYSLINK_RSP 0x0B
+#define A2MP_DISCONNPHYSLINK_RSP 0x0D
+struct a2mp_physlink_rsp {
+ __u8 local_id;
+ __u8 remote_id;
+ __u8 status;
+} __packed;
+
+/* A2MP response status */
+#define A2MP_STATUS_SUCCESS 0x00
+#define A2MP_STATUS_INVALID_CTRL_ID 0x01
+#define A2MP_STATUS_UNABLE_START_LINK_CREATION 0x02
+#define A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS 0x02
+#define A2MP_STATUS_COLLISION_OCCURED 0x03
+#define A2MP_STATUS_DISCONN_REQ_RECVD 0x04
+#define A2MP_STATUS_PHYS_LINK_EXISTS 0x05
+#define A2MP_STATUS_SECURITY_VIOLATION 0x06
+
+void amp_mgr_get(struct amp_mgr *mgr);
+int amp_mgr_put(struct amp_mgr *mgr);
+struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
+ struct sk_buff *skb);
+
+#endif /* __A2MP_H */
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 961669b648fd..565d4bee1e49 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -1,4 +1,4 @@
-/*
+/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
@@ -12,22 +12,19 @@
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#ifndef __BLUETOOTH_H
#define __BLUETOOTH_H
-#include <asm/types.h>
-#include <asm/byteorder.h>
-#include <linux/list.h>
#include <linux/poll.h>
#include <net/sock.h>
@@ -168,8 +165,8 @@ typedef struct {
#define BDADDR_LE_PUBLIC 0x01
#define BDADDR_LE_RANDOM 0x02
-#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}})
-#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})
+#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0} })
+#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff} })
/* Copy, swap, convert BD Address */
static inline int bacmp(bdaddr_t *ba1, bdaddr_t *ba2)
@@ -215,7 +212,7 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len, int flags);
int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len, int flags);
-uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
+uint bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait);
int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo);
@@ -225,12 +222,12 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock);
/* Skb helpers */
struct l2cap_ctrl {
- unsigned int sframe : 1,
- poll : 1,
- final : 1,
- fcs : 1,
- sar : 2,
- super : 2;
+ unsigned int sframe:1,
+ poll:1,
+ final:1,
+ fcs:1,
+ sar:2,
+ super:2;
__u16 reqseq;
__u16 txseq;
__u8 retries;
@@ -249,7 +246,8 @@ static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how)
{
struct sk_buff *skb;
- if ((skb = alloc_skb(len + BT_SKB_RESERVE, how))) {
+ skb = alloc_skb(len + BT_SKB_RESERVE, how);
+ if (skb) {
skb_reserve(skb, BT_SKB_RESERVE);
bt_cb(skb)->incoming = 0;
}
@@ -261,7 +259,8 @@ static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk,
{
struct sk_buff *skb;
- if ((skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err))) {
+ skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err);
+ if (skb) {
skb_reserve(skb, BT_SKB_RESERVE);
bt_cb(skb)->incoming = 0;
}
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 66a7b579e31c..2a6b0b8b7120 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -30,6 +30,9 @@
#define HCI_MAX_EVENT_SIZE 260
#define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4)
+#define HCI_LINK_KEY_SIZE 16
+#define HCI_AMP_LINK_KEY_SIZE (2 * HCI_LINK_KEY_SIZE)
+
/* HCI dev events */
#define HCI_DEV_REG 1
#define HCI_DEV_UNREG 2
@@ -56,9 +59,12 @@
#define HCI_BREDR 0x00
#define HCI_AMP 0x01
+/* First BR/EDR Controller shall have ID = 0 */
+#define HCI_BREDR_ID 0
+
/* HCI device quirks */
enum {
- HCI_QUIRK_NO_RESET,
+ HCI_QUIRK_RESET_ON_CLOSE,
HCI_QUIRK_RAW_DEVICE,
HCI_QUIRK_FIXUP_BUFFER_SIZE
};
@@ -133,10 +139,8 @@ enum {
#define HCIINQUIRY _IOR('H', 240, int)
/* HCI timeouts */
-#define HCI_CONNECT_TIMEOUT (40000) /* 40 seconds */
#define HCI_DISCONN_TIMEOUT (2000) /* 2 seconds */
#define HCI_PAIRING_TIMEOUT (60000) /* 60 seconds */
-#define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */
#define HCI_INIT_TIMEOUT (10000) /* 10 seconds */
#define HCI_CMD_TIMEOUT (1000) /* 1 seconds */
#define HCI_ACL_TX_TIMEOUT (45000) /* 45 seconds */
@@ -371,7 +375,7 @@ struct hci_cp_reject_conn_req {
#define HCI_OP_LINK_KEY_REPLY 0x040b
struct hci_cp_link_key_reply {
bdaddr_t bdaddr;
- __u8 link_key[16];
+ __u8 link_key[HCI_LINK_KEY_SIZE];
} __packed;
#define HCI_OP_LINK_KEY_NEG_REPLY 0x040c
@@ -523,6 +527,28 @@ struct hci_cp_io_capability_neg_reply {
__u8 reason;
} __packed;
+#define HCI_OP_CREATE_PHY_LINK 0x0435
+struct hci_cp_create_phy_link {
+ __u8 phy_handle;
+ __u8 key_len;
+ __u8 key_type;
+ __u8 key[HCI_AMP_LINK_KEY_SIZE];
+} __packed;
+
+#define HCI_OP_ACCEPT_PHY_LINK 0x0436
+struct hci_cp_accept_phy_link {
+ __u8 phy_handle;
+ __u8 key_len;
+ __u8 key_type;
+ __u8 key[HCI_AMP_LINK_KEY_SIZE];
+} __packed;
+
+#define HCI_OP_DISCONN_PHY_LINK 0x0437
+struct hci_cp_disconn_phy_link {
+ __u8 phy_handle;
+ __u8 reason;
+} __packed;
+
#define HCI_OP_SNIFF_MODE 0x0803
struct hci_cp_sniff_mode {
__le16 handle;
@@ -818,6 +844,31 @@ struct hci_rp_read_local_amp_info {
__le32 be_flush_to;
} __packed;
+#define HCI_OP_READ_LOCAL_AMP_ASSOC 0x140a
+struct hci_cp_read_local_amp_assoc {
+ __u8 phy_handle;
+ __le16 len_so_far;
+ __le16 max_len;
+} __packed;
+struct hci_rp_read_local_amp_assoc {
+ __u8 status;
+ __u8 phy_handle;
+ __le16 rem_len;
+ __u8 frag[0];
+} __packed;
+
+#define HCI_OP_WRITE_REMOTE_AMP_ASSOC 0x140b
+struct hci_cp_write_remote_amp_assoc {
+ __u8 phy_handle;
+ __le16 len_so_far;
+ __le16 rem_len;
+ __u8 frag[0];
+} __packed;
+struct hci_rp_write_remote_amp_assoc {
+ __u8 status;
+ __u8 phy_handle;
+} __packed;
+
#define HCI_OP_LE_SET_EVENT_MASK 0x2001
struct hci_cp_le_set_event_mask {
__u8 mask[8];
@@ -1048,7 +1099,7 @@ struct hci_ev_link_key_req {
#define HCI_EV_LINK_KEY_NOTIFY 0x18
struct hci_ev_link_key_notify {
bdaddr_t bdaddr;
- __u8 link_key[16];
+ __u8 link_key[HCI_LINK_KEY_SIZE];
__u8 key_type;
} __packed;
@@ -1144,6 +1195,12 @@ struct extended_inquiry_info {
__u8 data[240];
} __packed;
+#define HCI_EV_KEY_REFRESH_COMPLETE 0x30
+struct hci_ev_key_refresh_complete {
+ __u8 status;
+ __le16 handle;
+} __packed;
+
#define HCI_EV_IO_CAPA_REQUEST 0x31
struct hci_ev_io_capa_request {
bdaddr_t bdaddr;
@@ -1190,6 +1247,39 @@ struct hci_ev_le_meta {
__u8 subevent;
} __packed;
+#define HCI_EV_PHY_LINK_COMPLETE 0x40
+struct hci_ev_phy_link_complete {
+ __u8 status;
+ __u8 phy_handle;
+} __packed;
+
+#define HCI_EV_CHANNEL_SELECTED 0x41
+struct hci_ev_channel_selected {
+ __u8 phy_handle;
+} __packed;
+
+#define HCI_EV_DISCONN_PHY_LINK_COMPLETE 0x42
+struct hci_ev_disconn_phy_link_complete {
+ __u8 status;
+ __u8 phy_handle;
+ __u8 reason;
+} __packed;
+
+#define HCI_EV_LOGICAL_LINK_COMPLETE 0x45
+struct hci_ev_logical_link_complete {
+ __u8 status;
+ __le16 handle;
+ __u8 phy_handle;
+ __u8 flow_spec_id;
+} __packed;
+
+#define HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE 0x46
+struct hci_ev_disconn_logical_link_complete {
+ __u8 status;
+ __le16 handle;
+ __u8 reason;
+} __packed;
+
#define HCI_EV_NUM_COMP_BLOCKS 0x48
struct hci_comp_blocks_info {
__le16 handle;
@@ -1290,7 +1380,6 @@ struct hci_sco_hdr {
__u8 dlen;
} __packed;
-#include <linux/skbuff.h>
static inline struct hci_event_hdr *hci_event_hdr(const struct sk_buff *skb)
{
return (struct hci_event_hdr *) skb->data;
@@ -1307,12 +1396,12 @@ static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb)
}
/* Command opcode pack/unpack */
-#define hci_opcode_pack(ogf, ocf) (__u16) ((ocf & 0x03ff)|(ogf << 10))
+#define hci_opcode_pack(ogf, ocf) ((__u16) ((ocf & 0x03ff)|(ogf << 10)))
#define hci_opcode_ogf(op) (op >> 10)
#define hci_opcode_ocf(op) (op & 0x03ff)
/* ACL handle and flags pack/unpack */
-#define hci_handle_pack(h, f) (__u16) ((h & 0x0fff)|(f << 12))
+#define hci_handle_pack(h, f) ((__u16) ((h & 0x0fff)|(f << 12)))
#define hci_handle(h) (h & 0x0fff)
#define hci_flags(h) (h >> 12)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 9fc7728f94e4..20fd57367ddc 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -25,7 +25,6 @@
#ifndef __HCI_CORE_H
#define __HCI_CORE_H
-#include <linux/interrupt.h>
#include <net/bluetooth/hci.h>
/* HCI priority */
@@ -65,7 +64,7 @@ struct discovery_state {
DISCOVERY_RESOLVING,
DISCOVERY_STOPPING,
} state;
- struct list_head all; /* All devices found during inquiry */
+ struct list_head all; /* All devices found during inquiry */
struct list_head unknown; /* Name state not known */
struct list_head resolve; /* Name needs to be resolved */
__u32 timestamp;
@@ -105,7 +104,7 @@ struct link_key {
struct list_head list;
bdaddr_t bdaddr;
u8 type;
- u8 val[16];
+ u8 val[HCI_LINK_KEY_SIZE];
u8 pin_len;
};
@@ -333,6 +332,7 @@ struct hci_conn {
void *l2cap_data;
void *sco_data;
void *smp_conn;
+ struct amp_mgr *amp_mgr;
struct hci_conn *link;
@@ -360,7 +360,8 @@ extern int l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
extern int l2cap_disconn_ind(struct hci_conn *hcon);
extern int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
-extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags);
+extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb,
+ u16 flags);
extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
extern int sco_connect_cfm(struct hci_conn *hcon, __u8 status);
@@ -429,8 +430,8 @@ enum {
static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
- return (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
- test_bit(HCI_CONN_SSP_ENABLED, &conn->flags));
+ return test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
+ test_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
}
static inline void hci_conn_hash_init(struct hci_dev *hdev)
@@ -640,6 +641,19 @@ static inline void hci_set_drvdata(struct hci_dev *hdev, void *data)
dev_set_drvdata(&hdev->dev, data);
}
+/* hci_dev_list shall be locked */
+static inline uint8_t __hci_num_ctrl(void)
+{
+ uint8_t count = 0;
+ struct list_head *p;
+
+ list_for_each(p, &hci_dev_list) {
+ count++;
+ }
+
+ return count;
+}
+
struct hci_dev *hci_dev_get(int index);
struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst);
@@ -661,7 +675,8 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg);
int hci_get_auth_info(struct hci_dev *hdev, void __user *arg);
int hci_inquiry(void __user *arg);
-struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
+struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
+ bdaddr_t *bdaddr);
int hci_blacklist_clear(struct hci_dev *hdev);
int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 1c7d1cd5e679..d80e3f0691b4 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -40,11 +40,11 @@
#define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */
#define L2CAP_DEFAULT_MAX_PDU_SIZE 1009 /* Sized for 3-DH5 packet */
#define L2CAP_DEFAULT_ACK_TO 200
-#define L2CAP_LE_DEFAULT_MTU 23
#define L2CAP_DEFAULT_MAX_SDU_SIZE 0xFFFF
#define L2CAP_DEFAULT_SDU_ITIME 0xFFFFFFFF
#define L2CAP_DEFAULT_ACC_LAT 0xFFFFFFFF
#define L2CAP_BREDR_MAX_PAYLOAD 1019 /* 3-DH5 packet */
+#define L2CAP_LE_MIN_MTU 23
#define L2CAP_DISC_TIMEOUT msecs_to_jiffies(100)
#define L2CAP_DISC_REJ_TIMEOUT msecs_to_jiffies(5000)
@@ -52,6 +52,8 @@
#define L2CAP_CONN_TIMEOUT msecs_to_jiffies(40000)
#define L2CAP_INFO_TIMEOUT msecs_to_jiffies(4000)
+#define L2CAP_A2MP_DEFAULT_MTU 670
+
/* L2CAP socket address */
struct sockaddr_l2 {
sa_family_t l2_family;
@@ -229,9 +231,14 @@ struct l2cap_conn_rsp {
__le16 status;
} __packed;
+/* protocol/service multiplexer (PSM) */
+#define L2CAP_PSM_SDP 0x0001
+#define L2CAP_PSM_RFCOMM 0x0003
+
/* channel indentifier */
#define L2CAP_CID_SIGNALING 0x0001
#define L2CAP_CID_CONN_LESS 0x0002
+#define L2CAP_CID_A2MP 0x0003
#define L2CAP_CID_LE_DATA 0x0004
#define L2CAP_CID_LE_SIGNALING 0x0005
#define L2CAP_CID_SMP 0x0006
@@ -271,6 +278,9 @@ struct l2cap_conf_rsp {
#define L2CAP_CONF_PENDING 0x0004
#define L2CAP_CONF_EFS_REJECT 0x0005
+/* configuration req/rsp continuation flag */
+#define L2CAP_CONF_FLAG_CONTINUATION 0x0001
+
struct l2cap_conf_opt {
__u8 type;
__u8 len;
@@ -419,11 +429,6 @@ struct l2cap_seq_list {
#define L2CAP_SEQ_LIST_CLEAR 0xFFFF
#define L2CAP_SEQ_LIST_TAIL 0x8000
-struct srej_list {
- __u16 tx_seq;
- struct list_head list;
-};
-
struct l2cap_chan {
struct sock *sk;
@@ -475,14 +480,12 @@ struct l2cap_chan {
__u16 expected_ack_seq;
__u16 expected_tx_seq;
__u16 buffer_seq;
- __u16 buffer_seq_srej;
__u16 srej_save_reqseq;
__u16 last_acked_seq;
__u16 frames_sent;
__u16 unacked_frames;
__u8 retry_count;
__u16 srej_queue_next;
- __u8 num_acked;
__u16 sdu_len;
struct sk_buff *sdu;
struct sk_buff *sdu_last_frag;
@@ -515,7 +518,6 @@ struct l2cap_chan {
struct sk_buff_head srej_q;
struct l2cap_seq_list srej_list;
struct l2cap_seq_list retrans_list;
- struct list_head srej_l;
struct list_head list;
struct list_head global_l;
@@ -528,10 +530,14 @@ struct l2cap_chan {
struct l2cap_ops {
char *name;
- struct l2cap_chan *(*new_connection) (void *data);
- int (*recv) (void *data, struct sk_buff *skb);
- void (*close) (void *data);
- void (*state_change) (void *data, int state);
+ struct l2cap_chan *(*new_connection) (struct l2cap_chan *chan);
+ int (*recv) (struct l2cap_chan * chan,
+ struct sk_buff *skb);
+ void (*teardown) (struct l2cap_chan *chan, int err);
+ void (*close) (struct l2cap_chan *chan);
+ void (*state_change) (struct l2cap_chan *chan,
+ int state);
+ void (*ready) (struct l2cap_chan *chan);
struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan,
unsigned long len, int nb);
};
@@ -575,6 +581,7 @@ struct l2cap_conn {
#define L2CAP_CHAN_RAW 1
#define L2CAP_CHAN_CONN_LESS 2
#define L2CAP_CHAN_CONN_ORIENTED 3
+#define L2CAP_CHAN_CONN_FIX_A2MP 4
/* ----- L2CAP socket info ----- */
#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
@@ -597,6 +604,7 @@ enum {
CONF_EWS_RECV,
CONF_LOC_CONF_PEND,
CONF_REM_CONF_PEND,
+ CONF_NOT_COMPLETE,
};
#define L2CAP_CONF_MAX_CONF_REQ 2
@@ -713,11 +721,7 @@ static inline bool l2cap_clear_timer(struct l2cap_chan *chan,
#define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t))
#define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer)
-#define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \
- msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
#define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer)
-#define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \
- msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO));
#define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer)
#define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \
msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO));
@@ -736,173 +740,17 @@ static inline __u16 __next_seq(struct l2cap_chan *chan, __u16 seq)
return (seq + 1) % (chan->tx_win_max + 1);
}
-static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
-{
- int sub;
-
- sub = (ch->next_tx_seq - ch->expected_ack_seq) % 64;
-
- if (sub < 0)
- sub += 64;
-
- return sub == ch->remote_tx_win;
-}
-
-static inline __u16 __get_reqseq(struct l2cap_chan *chan, __u32 ctrl)
-{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return (ctrl & L2CAP_EXT_CTRL_REQSEQ) >>
- L2CAP_EXT_CTRL_REQSEQ_SHIFT;
- else
- return (ctrl & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
-}
-
-static inline __u32 __set_reqseq(struct l2cap_chan *chan, __u32 reqseq)
+static inline struct l2cap_chan *l2cap_chan_no_new_connection(struct l2cap_chan *chan)
{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return (reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT) &
- L2CAP_EXT_CTRL_REQSEQ;
- else
- return (reqseq << L2CAP_CTRL_REQSEQ_SHIFT) & L2CAP_CTRL_REQSEQ;
+ return NULL;
}
-static inline __u16 __get_txseq(struct l2cap_chan *chan, __u32 ctrl)
+static inline void l2cap_chan_no_teardown(struct l2cap_chan *chan, int err)
{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return (ctrl & L2CAP_EXT_CTRL_TXSEQ) >>
- L2CAP_EXT_CTRL_TXSEQ_SHIFT;
- else
- return (ctrl & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
}
-static inline __u32 __set_txseq(struct l2cap_chan *chan, __u32 txseq)
+static inline void l2cap_chan_no_ready(struct l2cap_chan *chan)
{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return (txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT) &
- L2CAP_EXT_CTRL_TXSEQ;
- else
- return (txseq << L2CAP_CTRL_TXSEQ_SHIFT) & L2CAP_CTRL_TXSEQ;
-}
-
-static inline bool __is_sframe(struct l2cap_chan *chan, __u32 ctrl)
-{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return ctrl & L2CAP_EXT_CTRL_FRAME_TYPE;
- else
- return ctrl & L2CAP_CTRL_FRAME_TYPE;
-}
-
-static inline __u32 __set_sframe(struct l2cap_chan *chan)
-{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return L2CAP_EXT_CTRL_FRAME_TYPE;
- else
- return L2CAP_CTRL_FRAME_TYPE;
-}
-
-static inline __u8 __get_ctrl_sar(struct l2cap_chan *chan, __u32 ctrl)
-{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return (ctrl & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
- else
- return (ctrl & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
-}
-
-static inline __u32 __set_ctrl_sar(struct l2cap_chan *chan, __u32 sar)
-{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return (sar << L2CAP_EXT_CTRL_SAR_SHIFT) & L2CAP_EXT_CTRL_SAR;
- else
- return (sar << L2CAP_CTRL_SAR_SHIFT) & L2CAP_CTRL_SAR;
-}
-
-static inline bool __is_sar_start(struct l2cap_chan *chan, __u32 ctrl)
-{
- return __get_ctrl_sar(chan, ctrl) == L2CAP_SAR_START;
-}
-
-static inline __u32 __get_sar_mask(struct l2cap_chan *chan)
-{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return L2CAP_EXT_CTRL_SAR;
- else
- return L2CAP_CTRL_SAR;
-}
-
-static inline __u8 __get_ctrl_super(struct l2cap_chan *chan, __u32 ctrl)
-{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return (ctrl & L2CAP_EXT_CTRL_SUPERVISE) >>
- L2CAP_EXT_CTRL_SUPER_SHIFT;
- else
- return (ctrl & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
-}
-
-static inline __u32 __set_ctrl_super(struct l2cap_chan *chan, __u32 super)
-{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return (super << L2CAP_EXT_CTRL_SUPER_SHIFT) &
- L2CAP_EXT_CTRL_SUPERVISE;
- else
- return (super << L2CAP_CTRL_SUPER_SHIFT) &
- L2CAP_CTRL_SUPERVISE;
-}
-
-static inline __u32 __set_ctrl_final(struct l2cap_chan *chan)
-{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return L2CAP_EXT_CTRL_FINAL;
- else
- return L2CAP_CTRL_FINAL;
-}
-
-static inline bool __is_ctrl_final(struct l2cap_chan *chan, __u32 ctrl)
-{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return ctrl & L2CAP_EXT_CTRL_FINAL;
- else
- return ctrl & L2CAP_CTRL_FINAL;
-}
-
-static inline __u32 __set_ctrl_poll(struct l2cap_chan *chan)
-{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return L2CAP_EXT_CTRL_POLL;
- else
- return L2CAP_CTRL_POLL;
-}
-
-static inline bool __is_ctrl_poll(struct l2cap_chan *chan, __u32 ctrl)
-{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return ctrl & L2CAP_EXT_CTRL_POLL;
- else
- return ctrl & L2CAP_CTRL_POLL;
-}
-
-static inline __u32 __get_control(struct l2cap_chan *chan, void *p)
-{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return get_unaligned_le32(p);
- else
- return get_unaligned_le16(p);
-}
-
-static inline void __put_control(struct l2cap_chan *chan, __u32 control,
- void *p)
-{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return put_unaligned_le32(control, p);
- else
- return put_unaligned_le16(control, p);
-}
-
-static inline __u8 __ctrl_size(struct l2cap_chan *chan)
-{
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- return L2CAP_EXT_HDR_SIZE - L2CAP_HDR_SIZE;
- else
- return L2CAP_ENH_HDR_SIZE - L2CAP_HDR_SIZE;
}
extern bool disable_ertm;
@@ -926,5 +774,8 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
void l2cap_chan_busy(struct l2cap_chan *chan, int busy);
int l2cap_chan_check_security(struct l2cap_chan *chan);
void l2cap_chan_set_defaults(struct l2cap_chan *chan);
+int l2cap_ertm_init(struct l2cap_chan *chan);
+void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
+void l2cap_chan_del(struct l2cap_chan *chan, int err);
#endif /* __L2CAP_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7319f25250b6..5a67165f3b19 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -70,11 +70,13 @@
*
* @IEEE80211_BAND_2GHZ: 2.4GHz ISM band
* @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7)
+ * @IEEE80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz)
* @IEEE80211_NUM_BANDS: number of defined bands
*/
enum ieee80211_band {
IEEE80211_BAND_2GHZ = NL80211_BAND_2GHZ,
IEEE80211_BAND_5GHZ = NL80211_BAND_5GHZ,
+ IEEE80211_BAND_60GHZ = NL80211_BAND_60GHZ,
/* keep last */
IEEE80211_NUM_BANDS
@@ -211,6 +213,22 @@ struct ieee80211_sta_ht_cap {
};
/**
+ * struct ieee80211_sta_vht_cap - STA's VHT capabilities
+ *
+ * This structure describes most essential parameters needed
+ * to describe 802.11ac VHT capabilities for an STA.
+ *
+ * @vht_supported: is VHT supported by the STA
+ * @cap: VHT capabilities map as described in 802.11ac spec
+ * @vht_mcs: Supported VHT MCS rates
+ */
+struct ieee80211_sta_vht_cap {
+ bool vht_supported;
+ u32 cap; /* use IEEE80211_VHT_CAP_ */
+ struct ieee80211_vht_mcs_info vht_mcs;
+};
+
+/**
* struct ieee80211_supported_band - frequency band definition
*
* This structure describes a frequency band a wiphy
@@ -233,6 +251,7 @@ struct ieee80211_supported_band {
int n_channels;
int n_bitrates;
struct ieee80211_sta_ht_cap ht_cap;
+ struct ieee80211_sta_vht_cap vht_cap;
};
/*
@@ -561,11 +580,13 @@ enum station_info_flags {
* @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
* @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
* @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
+ * @RATE_INFO_FLAGS_60G: 60gHz MCS
*/
enum rate_info_flags {
RATE_INFO_FLAGS_MCS = 1<<0,
RATE_INFO_FLAGS_40_MHZ_WIDTH = 1<<1,
RATE_INFO_FLAGS_SHORT_GI = 1<<2,
+ RATE_INFO_FLAGS_60G = 1<<3,
};
/**
@@ -627,10 +648,10 @@ struct sta_bss_parameters {
* @llid: mesh local link id
* @plid: mesh peer link id
* @plink_state: mesh peer link state
- * @signal: the signal strength, type depends on the wiphy's signal_type
- NOTE: For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
- * @signal_avg: avg signal strength, type depends on the wiphy's signal_type
- NOTE: For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
+ * @signal: The signal strength, type depends on the wiphy's signal_type.
+ * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
+ * @signal_avg: Average signal strength, type depends on the wiphy's signal_type.
+ * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
* @txrate: current unicast bitrate from this station
* @rxrate: current unicast bitrate to this station
* @rx_packets: packets received from this station
@@ -790,43 +811,95 @@ struct bss_parameters {
int ht_opmode;
};
-/*
+/**
* struct mesh_config - 802.11s mesh configuration
*
* These parameters can be changed while the mesh is active.
+ *
+ * @dot11MeshRetryTimeout: the initial retry timeout in millisecond units used
+ * by the Mesh Peering Open message
+ * @dot11MeshConfirmTimeout: the initial retry timeout in millisecond units
+ * used by the Mesh Peering Open message
+ * @dot11MeshHoldingTimeout: the confirm timeout in millisecond units used by
+ * the mesh peering management to close a mesh peering
+ * @dot11MeshMaxPeerLinks: the maximum number of peer links allowed on this
+ * mesh interface
+ * @dot11MeshMaxRetries: the maximum number of peer link open retries that can
+ * be sent to establish a new peer link instance in a mesh
+ * @dot11MeshTTL: the value of TTL field set at a source mesh STA
+ * @element_ttl: the value of TTL field set at a mesh STA for path selection
+ * elements
+ * @auto_open_plinks: whether we should automatically open peer links when we
+ * detect compatible mesh peers
+ * @dot11MeshNbrOffsetMaxNeighbor: the maximum number of neighbors to
+ * synchronize to for 11s default synchronization method
+ * @dot11MeshHWMPmaxPREQretries: the number of action frames containing a PREQ
+ * that an originator mesh STA can send to a particular path target
+ * @path_refresh_time: how frequently to refresh mesh paths in milliseconds
+ * @min_discovery_timeout: the minimum length of time to wait until giving up on
+ * a path discovery in milliseconds
+ * @dot11MeshHWMPactivePathTimeout: the time (in TUs) for which mesh STAs
+ * receiving a PREQ shall consider the forwarding information from the
+ * root to be valid. (TU = time unit)
+ * @dot11MeshHWMPpreqMinInterval: the minimum interval of time (in TUs) during
+ * which a mesh STA can send only one action frame containing a PREQ
+ * element
+ * @dot11MeshHWMPperrMinInterval: the minimum interval of time (in TUs) during
+ * which a mesh STA can send only one Action frame containing a PERR
+ * element
+ * @dot11MeshHWMPnetDiameterTraversalTime: the interval of time (in TUs) that
+ * it takes for an HWMP information element to propagate across the mesh
+ * @dot11MeshHWMPRootMode: the configuration of a mesh STA as root mesh STA
+ * @dot11MeshHWMPRannInterval: the interval of time (in TUs) between root
+ * announcements are transmitted
+ * @dot11MeshGateAnnouncementProtocol: whether to advertise that this mesh
+ * station has access to a broader network beyond the MBSS. (This is
+ * missnamed in draft 12.0: dot11MeshGateAnnouncementProtocol set to true
+ * only means that the station will announce others it's a mesh gate, but
+ * not necessarily using the gate announcement protocol. Still keeping the
+ * same nomenclature to be in sync with the spec)
+ * @dot11MeshForwarding: whether the Mesh STA is forwarding or non-forwarding
+ * entity (default is TRUE - forwarding entity)
+ * @rssi_threshold: the threshold for average signal strength of candidate
+ * station to establish a peer link
+ * @ht_opmode: mesh HT protection mode
+ *
+ * @dot11MeshHWMPactivePathToRootTimeout: The time (in TUs) for which mesh STAs
+ * receiving a proactive PREQ shall consider the forwarding information to
+ * the root mesh STA to be valid.
+ *
+ * @dot11MeshHWMProotInterval: The interval of time (in TUs) between proactive
+ * PREQs are transmitted.
+ * @dot11MeshHWMPconfirmationInterval: The minimum interval of time (in TUs)
+ * during which a mesh STA can send only one Action frame containing
+ * a PREQ element for root path confirmation.
*/
struct mesh_config {
- /* Timeouts in ms */
- /* Mesh plink management parameters */
u16 dot11MeshRetryTimeout;
u16 dot11MeshConfirmTimeout;
u16 dot11MeshHoldingTimeout;
u16 dot11MeshMaxPeerLinks;
- u8 dot11MeshMaxRetries;
- u8 dot11MeshTTL;
- /* ttl used in path selection information elements */
- u8 element_ttl;
+ u8 dot11MeshMaxRetries;
+ u8 dot11MeshTTL;
+ u8 element_ttl;
bool auto_open_plinks;
- /* neighbor offset synchronization */
u32 dot11MeshNbrOffsetMaxNeighbor;
- /* HWMP parameters */
- u8 dot11MeshHWMPmaxPREQretries;
+ u8 dot11MeshHWMPmaxPREQretries;
u32 path_refresh_time;
u16 min_discovery_timeout;
u32 dot11MeshHWMPactivePathTimeout;
u16 dot11MeshHWMPpreqMinInterval;
u16 dot11MeshHWMPperrMinInterval;
u16 dot11MeshHWMPnetDiameterTraversalTime;
- u8 dot11MeshHWMPRootMode;
+ u8 dot11MeshHWMPRootMode;
u16 dot11MeshHWMPRannInterval;
- /* This is missnamed in draft 12.0: dot11MeshGateAnnouncementProtocol
- * set to true only means that the station will announce others it's a
- * mesh gate, but not necessarily using the gate announcement protocol.
- * Still keeping the same nomenclature to be in sync with the spec. */
- bool dot11MeshGateAnnouncementProtocol;
+ bool dot11MeshGateAnnouncementProtocol;
bool dot11MeshForwarding;
s32 rssi_threshold;
u16 ht_opmode;
+ u32 dot11MeshHWMPactivePathToRootTimeout;
+ u16 dot11MeshHWMProotInterval;
+ u16 dot11MeshHWMPconfirmationInterval;
};
/**
@@ -926,7 +999,7 @@ struct cfg80211_ssid {
* @ie_len: length of ie in octets
* @rates: bitmap of rates to advertise for each band
* @wiphy: the wiphy this was for
- * @dev: the interface
+ * @wdev: the wireless device to scan for
* @aborted: (internal) scan request was notified as aborted
* @no_cck: used to send probe requests at non CCK rate in 2GHz band
*/
@@ -939,9 +1012,10 @@ struct cfg80211_scan_request {
u32 rates[IEEE80211_NUM_BANDS];
+ struct wireless_dev *wdev;
+
/* internal */
struct wiphy *wiphy;
- struct net_device *dev;
bool aborted;
bool no_cck;
@@ -975,6 +1049,7 @@ struct cfg80211_match_set {
* @wiphy: the wiphy this was for
* @dev: the interface
* @channels: channels to scan
+ * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
*/
struct cfg80211_sched_scan_request {
struct cfg80211_ssid *ssids;
@@ -985,6 +1060,7 @@ struct cfg80211_sched_scan_request {
size_t ie_len;
struct cfg80211_match_set *match_sets;
int n_match_sets;
+ s32 rssi_thold;
/* internal */
struct wiphy *wiphy;
@@ -1360,10 +1436,10 @@ struct cfg80211_gtk_rekey_data {
*
* @add_virtual_intf: create a new virtual interface with the given name,
* must set the struct wireless_dev's iftype. Beware: You must create
- * the new netdev in the wiphy's network namespace! Returns the netdev,
- * or an ERR_PTR.
+ * the new netdev in the wiphy's network namespace! Returns the struct
+ * wireless_dev, or an ERR_PTR.
*
- * @del_virtual_intf: remove the virtual interface determined by ifindex.
+ * @del_virtual_intf: remove the virtual interface
*
* @change_virtual_intf: change type/configuration of virtual interface,
* keep the struct wireless_dev's iftype updated.
@@ -1428,9 +1504,8 @@ struct cfg80211_gtk_rekey_data {
* interfaces are active this callback should reject the configuration.
* If no interfaces are active or the device is down, the channel should
* be stored for when a monitor interface becomes active.
- * @get_channel: Get the current operating channel, should return %NULL if
- * there's no single defined operating channel if for example the
- * device implements channel hopping for multi-channel virtual interfaces.
+ * @set_monitor_enabled: Notify driver that there are only monitor
+ * interfaces running.
*
* @scan: Request to do a scan. If returning zero, the scan request is given
* the driver, and will be valid until passed to cfg80211_scan_done().
@@ -1543,12 +1618,13 @@ struct cfg80211_ops {
int (*resume)(struct wiphy *wiphy);
void (*set_wakeup)(struct wiphy *wiphy, bool enabled);
- struct net_device * (*add_virtual_intf)(struct wiphy *wiphy,
- char *name,
- enum nl80211_iftype type,
- u32 *flags,
- struct vif_params *params);
- int (*del_virtual_intf)(struct wiphy *wiphy, struct net_device *dev);
+ struct wireless_dev * (*add_virtual_intf)(struct wiphy *wiphy,
+ char *name,
+ enum nl80211_iftype type,
+ u32 *flags,
+ struct vif_params *params);
+ int (*del_virtual_intf)(struct wiphy *wiphy,
+ struct wireless_dev *wdev);
int (*change_virtual_intf)(struct wiphy *wiphy,
struct net_device *dev,
enum nl80211_iftype type, u32 *flags,
@@ -1625,7 +1701,7 @@ struct cfg80211_ops {
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type);
- int (*scan)(struct wiphy *wiphy, struct net_device *dev,
+ int (*scan)(struct wiphy *wiphy,
struct cfg80211_scan_request *request);
int (*auth)(struct wiphy *wiphy, struct net_device *dev,
@@ -1679,23 +1755,23 @@ struct cfg80211_ops {
int (*flush_pmksa)(struct wiphy *wiphy, struct net_device *netdev);
int (*remain_on_channel)(struct wiphy *wiphy,
- struct net_device *dev,
+ struct wireless_dev *wdev,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration,
u64 *cookie);
int (*cancel_remain_on_channel)(struct wiphy *wiphy,
- struct net_device *dev,
+ struct wireless_dev *wdev,
u64 cookie);
- int (*mgmt_tx)(struct wiphy *wiphy, struct net_device *dev,
+ int (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type,
bool channel_type_valid, unsigned int wait,
const u8 *buf, size_t len, bool no_cck,
bool dont_wait_for_ack, u64 *cookie);
int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy,
- struct net_device *dev,
+ struct wireless_dev *wdev,
u64 cookie);
int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
@@ -1706,7 +1782,7 @@ struct cfg80211_ops {
s32 rssi_thold, u32 rssi_hyst);
void (*mgmt_frame_register)(struct wiphy *wiphy,
- struct net_device *dev,
+ struct wireless_dev *wdev,
u16 frame_type, bool reg);
int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);
@@ -1737,15 +1813,14 @@ struct cfg80211_ops {
struct net_device *dev,
u16 noack_map);
- struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy,
- enum nl80211_channel_type *type);
-
int (*get_et_sset_count)(struct wiphy *wiphy,
struct net_device *dev, int sset);
void (*get_et_stats)(struct wiphy *wiphy, struct net_device *dev,
struct ethtool_stats *stats, u64 *data);
void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev,
u32 sset, u8 *data);
+
+ void (*set_monitor_enabled)(struct wiphy *wiphy, bool enabled);
};
/*
@@ -2099,7 +2174,9 @@ struct wiphy {
char fw_version[ETHTOOL_BUSINFO_LEN];
u32 hw_version;
+#ifdef CONFIG_PM
struct wiphy_wowlan_support wowlan;
+#endif
u16 max_remain_on_channel_duration;
@@ -2266,17 +2343,25 @@ struct cfg80211_internal_bss;
struct cfg80211_cached_keys;
/**
- * struct wireless_dev - wireless per-netdev state
+ * struct wireless_dev - wireless device state
+ *
+ * For netdevs, this structure must be allocated by the driver
+ * that uses the ieee80211_ptr field in struct net_device (this
+ * is intentional so it can be allocated along with the netdev.)
+ * It need not be registered then as netdev registration will
+ * be intercepted by cfg80211 to see the new wireless device.
*
- * This structure must be allocated by the driver/stack
- * that uses the ieee80211_ptr field in struct net_device
- * (this is intentional so it can be allocated along with
- * the netdev.)
+ * For non-netdev uses, it must also be allocated by the driver
+ * in response to the cfg80211 callbacks that require it, as
+ * there's no netdev registration in that case it may not be
+ * allocated outside of callback operations that return it.
*
* @wiphy: pointer to hardware description
* @iftype: interface type
* @list: (private) Used to collect the interfaces
- * @netdev: (private) Used to reference back to the netdev
+ * @netdev: (private) Used to reference back to the netdev, may be %NULL
+ * @identifier: (private) Identifier used in nl80211 to identify this
+ * wireless device if it has no netdev
* @current_bss: (private) Used by the internal configuration code
* @channel: (private) Used by the internal configuration code to track
* the user-set AP, monitor and WDS channel
@@ -2308,6 +2393,8 @@ struct wireless_dev {
struct list_head list;
struct net_device *netdev;
+ u32 identifier;
+
struct list_head mgmt_registrations;
spinlock_t mgmt_registrations_lock;
@@ -2335,6 +2422,11 @@ struct wireless_dev {
struct ieee80211_channel *preset_chan;
enum nl80211_channel_type preset_chantype;
+ /* for AP and mesh channel tracking */
+ struct ieee80211_channel *channel;
+
+ bool ibss_fixed;
+
bool ps;
int ps_timeout;
@@ -3189,7 +3281,7 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason,
/**
* cfg80211_ready_on_channel - notification of remain_on_channel start
- * @dev: network device
+ * @wdev: wireless device
* @cookie: the request cookie
* @chan: The current channel (from remain_on_channel request)
* @channel_type: Channel type
@@ -3197,21 +3289,20 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason,
* channel
* @gfp: allocation flags
*/
-void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie,
+void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp);
/**
* cfg80211_remain_on_channel_expired - remain_on_channel duration expired
- * @dev: network device
+ * @wdev: wireless device
* @cookie: the request cookie
* @chan: The current channel (from remain_on_channel request)
* @channel_type: Channel type
* @gfp: allocation flags
*/
-void cfg80211_remain_on_channel_expired(struct net_device *dev,
- u64 cookie,
+void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
gfp_t gfp);
@@ -3239,7 +3330,7 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp);
/**
* cfg80211_rx_mgmt - notification of received, unprocessed management frame
- * @dev: network device
+ * @wdev: wireless device receiving the frame
* @freq: Frequency on which the frame was received in MHz
* @sig_dbm: signal strength in mBm, or 0 if unknown
* @buf: Management frame (header + body)
@@ -3254,12 +3345,12 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp);
* This function is called whenever an Action frame is received for a station
* mode interface, but is not processed in kernel.
*/
-bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_dbm,
+bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_dbm,
const u8 *buf, size_t len, gfp_t gfp);
/**
* cfg80211_mgmt_tx_status - notification of TX status for management frame
- * @dev: network device
+ * @wdev: wireless device receiving the frame
* @cookie: Cookie returned by cfg80211_ops::mgmt_tx()
* @buf: Management frame (header + body)
* @len: length of the frame data
@@ -3270,7 +3361,7 @@ bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_dbm,
* transmitted with cfg80211_ops::mgmt_tx() to report the TX status of the
* transmission attempt.
*/
-void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie,
+void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
const u8 *buf, size_t len, bool ack, gfp_t gfp);
@@ -3409,7 +3500,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
*
* return 0 if MCS index >= 32
*/
-u16 cfg80211_calculate_bitrate(struct rate_info *rate);
+u32 cfg80211_calculate_bitrate(struct rate_info *rate);
/* Logging, debugging and troubleshooting/diagnostic helpers. */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d152f54064fd..bb86aa6f98dd 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -233,8 +233,10 @@ enum ieee80211_rssi_event {
* valid in station mode only while @assoc is true and if also
* requested by %IEEE80211_HW_NEED_DTIM_PERIOD (cf. also hw conf
* @ps_dtim_period)
- * @last_tsf: last beacon's/probe response's TSF timestamp (could be old
+ * @sync_tsf: last beacon's/probe response's TSF timestamp (could be old
* as it may have been received during scanning long ago)
+ * @sync_device_ts: the device timestamp corresponding to the sync_tsf,
+ * the driver/device can use this to calculate synchronisation
* @beacon_int: beacon interval
* @assoc_capability: capabilities taken from assoc resp
* @basic_rates: bitmap of basic rates, each bit stands for an
@@ -281,7 +283,8 @@ struct ieee80211_bss_conf {
u8 dtim_period;
u16 beacon_int;
u16 assoc_capability;
- u64 last_tsf;
+ u64 sync_tsf;
+ u32 sync_device_ts;
u32 basic_rates;
int mcast_rate[IEEE80211_NUM_BANDS];
u16 ht_operation_mode;
@@ -475,7 +478,7 @@ enum mac80211_rate_control_flags {
#define IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE 24
/* maximum number of rate stages */
-#define IEEE80211_TX_MAX_RATES 5
+#define IEEE80211_TX_MAX_RATES 4
/**
* struct ieee80211_tx_rate - rate selection/status
@@ -563,11 +566,11 @@ struct ieee80211_tx_info {
} control;
struct {
struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
- u8 ampdu_ack_len;
int ack_signal;
+ u8 ampdu_ack_len;
u8 ampdu_len;
u8 antenna;
- /* 14 bytes free */
+ /* 21 bytes free */
} status;
struct {
struct ieee80211_tx_rate driver_rates[
@@ -634,7 +637,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
info->status.rates[i].count = 0;
BUILD_BUG_ON(
- offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23);
+ offsetof(struct ieee80211_tx_info, status.ack_signal) != 20);
memset(&info->status.ampdu_ack_len, 0,
sizeof(struct ieee80211_tx_info) -
offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
@@ -696,6 +699,8 @@ enum mac80211_rx_flags {
*
* @mactime: value in microseconds of the 64-bit Time Synchronization Function
* (TSF) timer when the first data symbol (MPDU) arrived at the hardware.
+ * @device_timestamp: arbitrary timestamp for the device, mac80211 doesn't use
+ * it but can store it and pass it back to the driver for synchronisation
* @band: the active band when this frame was received
* @freq: frequency the radio was tuned to when receiving this frame, in MHz
* @signal: signal strength when receiving this frame, either in dBm, in dB or
@@ -709,13 +714,14 @@ enum mac80211_rx_flags {
*/
struct ieee80211_rx_status {
u64 mactime;
- enum ieee80211_band band;
- int freq;
- int signal;
- int antenna;
- int rate_idx;
- int flag;
- unsigned int rx_flags;
+ u32 device_timestamp;
+ u16 flag;
+ u16 freq;
+ u8 rate_idx;
+ u8 rx_flags;
+ u8 band;
+ u8 antenna;
+ s8 signal;
};
/**
@@ -1896,19 +1902,6 @@ enum ieee80211_rate_control_changed {
* The low-level driver should send the frame out based on
* configuration in the TX control data. This handler should,
* preferably, never fail and stop queues appropriately.
- * This must be implemented if @tx_frags is not.
- * Must be atomic.
- *
- * @tx_frags: Called to transmit multiple fragments of a single MSDU.
- * This handler must consume all fragments, sending out some of
- * them only is useless and it can't ask for some of them to be
- * queued again. If the frame is not fragmented the queue has a
- * single SKB only. To avoid issues with the networking stack
- * when TX status is reported the frames should be removed from
- * the skb queue.
- * If this is used, the tx_info @vif and @sta pointers will be
- * invalid -- you must not use them in that case.
- * This must be implemented if @tx isn't.
* Must be atomic.
*
* @start: Called before the first netdevice attached to the hardware
@@ -1945,6 +1938,11 @@ enum ieee80211_rate_control_changed {
* to also unregister the device. If it returns 1, then mac80211
* will also go through the regular complete restart on resume.
*
+ * @set_wakeup: Enable or disable wakeup when WoWLAN configuration is
+ * modified. The reason is that device_set_wakeup_enable() is
+ * supposed to be called when the configuration changes, not only
+ * in suspend().
+ *
* @add_interface: Called when a netdevice attached to the hardware is
* enabled. Because it is not called for monitor mode devices, @start
* and @stop must be implemented.
@@ -2249,11 +2247,24 @@ enum ieee80211_rate_control_changed {
* @get_et_strings: Ethtool API to get a set of strings to describe stats
* and perhaps other supported types of ethtool data-sets.
*
+ * @get_rssi: Get current signal strength in dBm, the function is optional
+ * and can sleep.
+ *
+ * @mgd_prepare_tx: Prepare for transmitting a management frame for association
+ * before associated. In multi-channel scenarios, a virtual interface is
+ * bound to a channel before it is associated, but as it isn't associated
+ * yet it need not necessarily be given airtime, in particular since any
+ * transmission to a P2P GO needs to be synchronized against the GO's
+ * powersave state. mac80211 will call this function before transmitting a
+ * management frame prior to having successfully associated to allow the
+ * driver to give it channel time for the transmission, to get a response
+ * and to be able to synchronize with the GO.
+ * The callback will be called before each transmission and upon return
+ * mac80211 will transmit the frame right away.
+ * The callback is optional and can (should!) sleep.
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
- void (*tx_frags)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, struct sk_buff_head *skbs);
int (*start)(struct ieee80211_hw *hw);
void (*stop)(struct ieee80211_hw *hw);
#ifdef CONFIG_PM
@@ -2388,6 +2399,11 @@ struct ieee80211_ops {
void (*get_et_strings)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u32 sset, u8 *data);
+ int (*get_rssi)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, s8 *rssi_dbm);
+
+ void (*mgd_prepare_tx)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
};
/**
@@ -2974,6 +2990,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
* ieee80211_generic_frame_duration - Calculate the duration field for a frame
* @hw: pointer obtained from ieee80211_alloc_hw().
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @band: the band to calculate the frame duration on
* @frame_len: the length of the frame.
* @rate: the rate at which the frame is going to be transmitted.
*
@@ -3581,22 +3598,6 @@ void ieee80211_request_smps(struct ieee80211_vif *vif,
enum ieee80211_smps_mode smps_mode);
/**
- * ieee80211_key_removed - disable hw acceleration for key
- * @key_conf: The key hw acceleration should be disabled for
- *
- * This allows drivers to indicate that the given key has been
- * removed from hardware acceleration, due to a new key that
- * was added. Don't use this if the key can continue to be used
- * for TX, if the key restriction is on RX only it is permitted
- * to keep the key for TX only and not call this function.
- *
- * Due to locking constraints, it may only be called during
- * @set_key. This function must be allowed to sleep, and the
- * key it tries to disable may still be used until it returns.
- */
-void ieee80211_key_removed(struct ieee80211_key_conf *key_conf);
-
-/**
* ieee80211_ready_on_channel - notification of remain-on-channel start
* @hw: pointer as obtained from ieee80211_alloc_hw()
*/
@@ -3821,12 +3822,6 @@ void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif);
-int ieee80211_add_srates_ie(struct ieee80211_vif *vif,
- struct sk_buff *skb, bool need_basic);
-
-int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif,
- struct sk_buff *skb, bool need_basic);
-
/**
* ieee80211_ave_rssi - report the average rssi for the specified interface
*
@@ -3837,28 +3832,4 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif,
*/
int ieee80211_ave_rssi(struct ieee80211_vif *vif);
-/* Extra debugging macros */
-
-#ifdef CONFIG_MAC80211_HT_DEBUG
-#define ht_vdbg(fmt, ...) \
- pr_debug(fmt, ##__VA_ARGS__)
-#else
-#define ht_vdbg(fmt, ...) \
-do { \
- if (0) \
- pr_debug(fmt, ##__VA_ARGS__); \
-} while (0)
-#endif
-
-#ifdef CONFIG_MAC80211_IBSS_DEBUG
-#define ibss_vdbg(fmt, ...) \
- pr_debug(fmt, ##__VA_ARGS__)
-#else
-#define ibss_vdbg(fmt, ...) \
-do { \
- if (0) \
- pr_debug(fmt, ##__VA_ARGS__); \
-} while (0)
-#endif
-
#endif /* MAC80211_H */
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index e30e6a869714..f5169b04f082 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -44,10 +44,20 @@ struct nfc_hci_ops {
struct nfc_target *target);
};
-#define NFC_HCI_MAX_CUSTOM_GATES 15
+/* Pipes */
+#define NFC_HCI_INVALID_PIPE 0x80
+#define NFC_HCI_LINK_MGMT_PIPE 0x00
+#define NFC_HCI_ADMIN_PIPE 0x01
+
+struct nfc_hci_gate {
+ u8 gate;
+ u8 pipe;
+};
+
+#define NFC_HCI_MAX_CUSTOM_GATES 50
struct nfc_hci_init_data {
u8 gate_count;
- u8 gates[NFC_HCI_MAX_CUSTOM_GATES];
+ struct nfc_hci_gate gates[NFC_HCI_MAX_CUSTOM_GATES];
char session_id[9];
};
@@ -112,6 +122,8 @@ void nfc_hci_unregister_device(struct nfc_hci_dev *hdev);
void nfc_hci_set_clientdata(struct nfc_hci_dev *hdev, void *clientdata);
void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev);
+void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err);
+
/* Host IDs */
#define NFC_HCI_HOST_CONTROLLER_ID 0x00
#define NFC_HCI_TERMINAL_HOST_ID 0x01
@@ -180,7 +192,8 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb);
/* connecting to gates and sending hci instructions */
-int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate);
+int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate,
+ u8 pipe);
int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate);
int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev);
int nfc_hci_get_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx,
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 180964b954ab..6431f5e39022 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -204,4 +204,6 @@ int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode,
int nfc_tm_deactivated(struct nfc_dev *dev);
int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb);
+void nfc_driver_failure(struct nfc_dev *dev, int err);
+
#endif /* __NET_NFC_H */
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index 2dc5a5700f53..fa6d94a4602a 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_BT_CMTP) += cmtp/
obj-$(CONFIG_BT_HIDP) += hidp/
bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
- hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o
+ hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
+ a2mp.o
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
new file mode 100644
index 000000000000..fb93250b3938
--- /dev/null
+++ b/net/bluetooth/a2mp.c
@@ -0,0 +1,568 @@
+/*
+ Copyright (c) 2010,2011 Code Aurora Forum. All rights reserved.
+ Copyright (c) 2011,2012 Intel Corp.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 and
+ only version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/a2mp.h>
+
+/* A2MP build & send command helper functions */
+static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
+{
+ struct a2mp_cmd *cmd;
+ int plen;
+
+ plen = sizeof(*cmd) + len;
+ cmd = kzalloc(plen, GFP_KERNEL);
+ if (!cmd)
+ return NULL;
+
+ cmd->code = code;
+ cmd->ident = ident;
+ cmd->len = cpu_to_le16(len);
+
+ memcpy(cmd->data, data, len);
+
+ return cmd;
+}
+
+static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len,
+ void *data)
+{
+ struct l2cap_chan *chan = mgr->a2mp_chan;
+ struct a2mp_cmd *cmd;
+ u16 total_len = len + sizeof(*cmd);
+ struct kvec iv;
+ struct msghdr msg;
+
+ cmd = __a2mp_build(code, ident, len, data);
+ if (!cmd)
+ return;
+
+ iv.iov_base = cmd;
+ iv.iov_len = total_len;
+
+ memset(&msg, 0, sizeof(msg));
+
+ msg.msg_iov = (struct iovec *) &iv;
+ msg.msg_iovlen = 1;
+
+ l2cap_chan_send(chan, &msg, total_len, 0);
+
+ kfree(cmd);
+}
+
+static inline void __a2mp_cl_bredr(struct a2mp_cl *cl)
+{
+ cl->id = 0;
+ cl->type = 0;
+ cl->status = 1;
+}
+
+/* hci_dev_list shall be locked */
+static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl, u8 num_ctrl)
+{
+ int i = 0;
+ struct hci_dev *hdev;
+
+ __a2mp_cl_bredr(cl);
+
+ list_for_each_entry(hdev, &hci_dev_list, list) {
+ /* Iterate through AMP controllers */
+ if (hdev->id == HCI_BREDR_ID)
+ continue;
+
+ /* Starting from second entry */
+ if (++i >= num_ctrl)
+ return;
+
+ cl[i].id = hdev->id;
+ cl[i].type = hdev->amp_type;
+ cl[i].status = hdev->amp_status;
+ }
+}
+
+/* Processing A2MP messages */
+static int a2mp_command_rej(struct amp_mgr *mgr, struct sk_buff *skb,
+ struct a2mp_cmd *hdr)
+{
+ struct a2mp_cmd_rej *rej = (void *) skb->data;
+
+ if (le16_to_cpu(hdr->len) < sizeof(*rej))
+ return -EINVAL;
+
+ BT_DBG("ident %d reason %d", hdr->ident, le16_to_cpu(rej->reason));
+
+ skb_pull(skb, sizeof(*rej));
+
+ return 0;
+}
+
+static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb,
+ struct a2mp_cmd *hdr)
+{
+ struct a2mp_discov_req *req = (void *) skb->data;
+ u16 len = le16_to_cpu(hdr->len);
+ struct a2mp_discov_rsp *rsp;
+ u16 ext_feat;
+ u8 num_ctrl;
+
+ if (len < sizeof(*req))
+ return -EINVAL;
+
+ skb_pull(skb, sizeof(*req));
+
+ ext_feat = le16_to_cpu(req->ext_feat);
+
+ BT_DBG("mtu %d efm 0x%4.4x", le16_to_cpu(req->mtu), ext_feat);
+
+ /* check that packet is not broken for now */
+ while (ext_feat & A2MP_FEAT_EXT) {
+ if (len < sizeof(ext_feat))
+ return -EINVAL;
+
+ ext_feat = get_unaligned_le16(skb->data);
+ BT_DBG("efm 0x%4.4x", ext_feat);
+ len -= sizeof(ext_feat);
+ skb_pull(skb, sizeof(ext_feat));
+ }
+
+ read_lock(&hci_dev_list_lock);
+
+ num_ctrl = __hci_num_ctrl();
+ len = num_ctrl * sizeof(struct a2mp_cl) + sizeof(*rsp);
+ rsp = kmalloc(len, GFP_ATOMIC);
+ if (!rsp) {
+ read_unlock(&hci_dev_list_lock);
+ return -ENOMEM;
+ }
+
+ rsp->mtu = __constant_cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
+ rsp->ext_feat = 0;
+
+ __a2mp_add_cl(mgr, rsp->cl, num_ctrl);
+
+ read_unlock(&hci_dev_list_lock);
+
+ a2mp_send(mgr, A2MP_DISCOVER_RSP, hdr->ident, len, rsp);
+
+ kfree(rsp);
+ return 0;
+}
+
+static int a2mp_change_notify(struct amp_mgr *mgr, struct sk_buff *skb,
+ struct a2mp_cmd *hdr)
+{
+ struct a2mp_cl *cl = (void *) skb->data;
+
+ while (skb->len >= sizeof(*cl)) {
+ BT_DBG("Controller id %d type %d status %d", cl->id, cl->type,
+ cl->status);
+ cl = (struct a2mp_cl *) skb_pull(skb, sizeof(*cl));
+ }
+
+ /* TODO send A2MP_CHANGE_RSP */
+
+ return 0;
+}
+
+static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
+ struct a2mp_cmd *hdr)
+{
+ struct a2mp_info_req *req = (void *) skb->data;
+ struct a2mp_info_rsp rsp;
+ struct hci_dev *hdev;
+
+ if (le16_to_cpu(hdr->len) < sizeof(*req))
+ return -EINVAL;
+
+ BT_DBG("id %d", req->id);
+
+ rsp.id = req->id;
+ rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+ hdev = hci_dev_get(req->id);
+ if (hdev && hdev->amp_type != HCI_BREDR) {
+ rsp.status = 0;
+ rsp.total_bw = cpu_to_le32(hdev->amp_total_bw);
+ rsp.max_bw = cpu_to_le32(hdev->amp_max_bw);
+ rsp.min_latency = cpu_to_le32(hdev->amp_min_latency);
+ rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap);
+ rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size);
+ }
+
+ if (hdev)
+ hci_dev_put(hdev);
+
+ a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp), &rsp);
+
+ skb_pull(skb, sizeof(*req));
+ return 0;
+}
+
+static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb,
+ struct a2mp_cmd *hdr)
+{
+ struct a2mp_amp_assoc_req *req = (void *) skb->data;
+ struct hci_dev *hdev;
+
+ if (le16_to_cpu(hdr->len) < sizeof(*req))
+ return -EINVAL;
+
+ BT_DBG("id %d", req->id);
+
+ hdev = hci_dev_get(req->id);
+ if (!hdev || hdev->amp_type == HCI_BREDR) {
+ struct a2mp_amp_assoc_rsp rsp;
+ rsp.id = req->id;
+ rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+
+ a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, hdr->ident, sizeof(rsp),
+ &rsp);
+ goto clean;
+ }
+
+ /* Placeholder for HCI Read AMP Assoc */
+
+clean:
+ if (hdev)
+ hci_dev_put(hdev);
+
+ skb_pull(skb, sizeof(*req));
+ return 0;
+}
+
+static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
+ struct a2mp_cmd *hdr)
+{
+ struct a2mp_physlink_req *req = (void *) skb->data;
+
+ struct a2mp_physlink_rsp rsp;
+ struct hci_dev *hdev;
+
+ if (le16_to_cpu(hdr->len) < sizeof(*req))
+ return -EINVAL;
+
+ BT_DBG("local_id %d, remote_id %d", req->local_id, req->remote_id);
+
+ rsp.local_id = req->remote_id;
+ rsp.remote_id = req->local_id;
+
+ hdev = hci_dev_get(req->remote_id);
+ if (!hdev || hdev->amp_type != HCI_AMP) {
+ rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+ goto send_rsp;
+ }
+
+ /* TODO process physlink create */
+
+ rsp.status = A2MP_STATUS_SUCCESS;
+
+send_rsp:
+ if (hdev)
+ hci_dev_put(hdev);
+
+ a2mp_send(mgr, A2MP_CREATEPHYSLINK_RSP, hdr->ident, sizeof(rsp),
+ &rsp);
+
+ skb_pull(skb, le16_to_cpu(hdr->len));
+ return 0;
+}
+
+static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
+ struct a2mp_cmd *hdr)
+{
+ struct a2mp_physlink_req *req = (void *) skb->data;
+ struct a2mp_physlink_rsp rsp;
+ struct hci_dev *hdev;
+
+ if (le16_to_cpu(hdr->len) < sizeof(*req))
+ return -EINVAL;
+
+ BT_DBG("local_id %d remote_id %d", req->local_id, req->remote_id);
+
+ rsp.local_id = req->remote_id;
+ rsp.remote_id = req->local_id;
+ rsp.status = A2MP_STATUS_SUCCESS;
+
+ hdev = hci_dev_get(req->local_id);
+ if (!hdev) {
+ rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+ goto send_rsp;
+ }
+
+ /* TODO Disconnect Phys Link here */
+
+ hci_dev_put(hdev);
+
+send_rsp:
+ a2mp_send(mgr, A2MP_DISCONNPHYSLINK_RSP, hdr->ident, sizeof(rsp), &rsp);
+
+ skb_pull(skb, sizeof(*req));
+ return 0;
+}
+
+static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
+ struct a2mp_cmd *hdr)
+{
+ BT_DBG("ident %d code %d", hdr->ident, hdr->code);
+
+ skb_pull(skb, le16_to_cpu(hdr->len));
+ return 0;
+}
+
+/* Handle A2MP signalling */
+static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
+{
+ struct a2mp_cmd *hdr = (void *) skb->data;
+ struct amp_mgr *mgr = chan->data;
+ int err = 0;
+
+ amp_mgr_get(mgr);
+
+ while (skb->len >= sizeof(*hdr)) {
+ struct a2mp_cmd *hdr = (void *) skb->data;
+ u16 len = le16_to_cpu(hdr->len);
+
+ BT_DBG("code 0x%02x id %d len %d", hdr->code, hdr->ident, len);
+
+ skb_pull(skb, sizeof(*hdr));
+
+ if (len > skb->len || !hdr->ident) {
+ err = -EINVAL;
+ break;
+ }
+
+ mgr->ident = hdr->ident;
+
+ switch (hdr->code) {
+ case A2MP_COMMAND_REJ:
+ a2mp_command_rej(mgr, skb, hdr);
+ break;
+
+ case A2MP_DISCOVER_REQ:
+ err = a2mp_discover_req(mgr, skb, hdr);
+ break;
+
+ case A2MP_CHANGE_NOTIFY:
+ err = a2mp_change_notify(mgr, skb, hdr);
+ break;
+
+ case A2MP_GETINFO_REQ:
+ err = a2mp_getinfo_req(mgr, skb, hdr);
+ break;
+
+ case A2MP_GETAMPASSOC_REQ:
+ err = a2mp_getampassoc_req(mgr, skb, hdr);
+ break;
+
+ case A2MP_CREATEPHYSLINK_REQ:
+ err = a2mp_createphyslink_req(mgr, skb, hdr);
+ break;
+
+ case A2MP_DISCONNPHYSLINK_REQ:
+ err = a2mp_discphyslink_req(mgr, skb, hdr);
+ break;
+
+ case A2MP_CHANGE_RSP:
+ case A2MP_DISCOVER_RSP:
+ case A2MP_GETINFO_RSP:
+ case A2MP_GETAMPASSOC_RSP:
+ case A2MP_CREATEPHYSLINK_RSP:
+ case A2MP_DISCONNPHYSLINK_RSP:
+ err = a2mp_cmd_rsp(mgr, skb, hdr);
+ break;
+
+ default:
+ BT_ERR("Unknown A2MP sig cmd 0x%2.2x", hdr->code);
+ err = -EINVAL;
+ break;
+ }
+ }
+
+ if (err) {
+ struct a2mp_cmd_rej rej;
+ rej.reason = __constant_cpu_to_le16(0);
+
+ BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err);
+
+ a2mp_send(mgr, A2MP_COMMAND_REJ, hdr->ident, sizeof(rej),
+ &rej);
+ }
+
+ /* Always free skb and return success error code to prevent
+ from sending L2CAP Disconnect over A2MP channel */
+ kfree_skb(skb);
+
+ amp_mgr_put(mgr);
+
+ return 0;
+}
+
+static void a2mp_chan_close_cb(struct l2cap_chan *chan)
+{
+ l2cap_chan_destroy(chan);
+}
+
+static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state)
+{
+ struct amp_mgr *mgr = chan->data;
+
+ if (!mgr)
+ return;
+
+ BT_DBG("chan %p state %s", chan, state_to_string(state));
+
+ chan->state = state;
+
+ switch (state) {
+ case BT_CLOSED:
+ if (mgr)
+ amp_mgr_put(mgr);
+ break;
+ }
+}
+
+static struct sk_buff *a2mp_chan_alloc_skb_cb(struct l2cap_chan *chan,
+ unsigned long len, int nb)
+{
+ return bt_skb_alloc(len, GFP_KERNEL);
+}
+
+static struct l2cap_ops a2mp_chan_ops = {
+ .name = "L2CAP A2MP channel",
+ .recv = a2mp_chan_recv_cb,
+ .close = a2mp_chan_close_cb,
+ .state_change = a2mp_chan_state_change_cb,
+ .alloc_skb = a2mp_chan_alloc_skb_cb,
+
+ /* Not implemented for A2MP */
+ .new_connection = l2cap_chan_no_new_connection,
+ .teardown = l2cap_chan_no_teardown,
+ .ready = l2cap_chan_no_ready,
+};
+
+static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
+{
+ struct l2cap_chan *chan;
+ int err;
+
+ chan = l2cap_chan_create();
+ if (!chan)
+ return NULL;
+
+ BT_DBG("chan %p", chan);
+
+ chan->chan_type = L2CAP_CHAN_CONN_FIX_A2MP;
+ chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
+
+ chan->ops = &a2mp_chan_ops;
+
+ l2cap_chan_set_defaults(chan);
+ chan->remote_max_tx = chan->max_tx;
+ chan->remote_tx_win = chan->tx_win;
+
+ chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
+ chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
+
+ skb_queue_head_init(&chan->tx_q);
+
+ chan->mode = L2CAP_MODE_ERTM;
+
+ err = l2cap_ertm_init(chan);
+ if (err < 0) {
+ l2cap_chan_del(chan, 0);
+ return NULL;
+ }
+
+ chan->conf_state = 0;
+
+ l2cap_chan_add(conn, chan);
+
+ chan->remote_mps = chan->omtu;
+ chan->mps = chan->omtu;
+
+ chan->state = BT_CONNECTED;
+
+ return chan;
+}
+
+/* AMP Manager functions */
+void amp_mgr_get(struct amp_mgr *mgr)
+{
+ BT_DBG("mgr %p", mgr);
+
+ kref_get(&mgr->kref);
+}
+
+static void amp_mgr_destroy(struct kref *kref)
+{
+ struct amp_mgr *mgr = container_of(kref, struct amp_mgr, kref);
+
+ BT_DBG("mgr %p", mgr);
+
+ kfree(mgr);
+}
+
+int amp_mgr_put(struct amp_mgr *mgr)
+{
+ BT_DBG("mgr %p", mgr);
+
+ return kref_put(&mgr->kref, &amp_mgr_destroy);
+}
+
+static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
+{
+ struct amp_mgr *mgr;
+ struct l2cap_chan *chan;
+
+ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
+ if (!mgr)
+ return NULL;
+
+ BT_DBG("conn %p mgr %p", conn, mgr);
+
+ mgr->l2cap_conn = conn;
+
+ chan = a2mp_chan_open(conn);
+ if (!chan) {
+ kfree(mgr);
+ return NULL;
+ }
+
+ mgr->a2mp_chan = chan;
+ chan->data = mgr;
+
+ conn->hcon->amp_mgr = mgr;
+
+ kref_init(&mgr->kref);
+
+ return mgr;
+}
+
+struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
+ struct sk_buff *skb)
+{
+ struct amp_mgr *mgr;
+
+ mgr = amp_mgr_create(conn);
+ if (!mgr) {
+ BT_ERR("Could not create AMP manager");
+ return NULL;
+ }
+
+ BT_DBG("mgr: %p chan %p", mgr, mgr->a2mp_chan);
+
+ return mgr->a2mp_chan;
+}
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 3e18af4dadc4..f7db5792ec64 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -25,18 +25,7 @@
/* Bluetooth address family and sockets. */
#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <net/sock.h>
#include <asm/ioctls.h>
-#include <linux/kmod.h>
#include <net/bluetooth/bluetooth.h>
@@ -418,7 +407,8 @@ static inline unsigned int bt_accept_poll(struct sock *parent)
return 0;
}
-unsigned int bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait)
+unsigned int bt_sock_poll(struct file *file, struct socket *sock,
+ poll_table *wait)
{
struct sock *sk = sock->sk;
unsigned int mask = 0;
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 031d7d656754..4a6620bc1570 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -26,26 +26,9 @@
*/
#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <linux/freezer.h>
-#include <linux/errno.h>
-#include <linux/net.h>
-#include <linux/slab.h>
#include <linux/kthread.h>
-#include <net/sock.h>
-
-#include <linux/socket.h>
#include <linux/file.h>
-
-#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
@@ -306,7 +289,7 @@ static u8 __bnep_rx_hlen[] = {
ETH_ALEN + 2 /* BNEP_COMPRESSED_DST_ONLY */
};
-static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
+static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
{
struct net_device *dev = s->dev;
struct sk_buff *nskb;
@@ -404,7 +387,7 @@ static u8 __bnep_tx_types[] = {
BNEP_COMPRESSED
};
-static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb)
+static int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb)
{
struct ethhdr *eh = (void *) skb->data;
struct socket *sock = s->sock;
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c
index bc4086480d97..98f86f91d47c 100644
--- a/net/bluetooth/bnep/netdev.c
+++ b/net/bluetooth/bnep/netdev.c
@@ -25,16 +25,8 @@
SOFTWARE IS DISCLAIMED.
*/
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include <linux/socket.h>
-#include <linux/netdevice.h>
+#include <linux/export.h>
#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/wait.h>
-
-#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -128,7 +120,7 @@ static void bnep_net_timeout(struct net_device *dev)
}
#ifdef CONFIG_BT_BNEP_MC_FILTER
-static inline int bnep_net_mc_filter(struct sk_buff *skb, struct bnep_session *s)
+static int bnep_net_mc_filter(struct sk_buff *skb, struct bnep_session *s)
{
struct ethhdr *eh = (void *) skb->data;
@@ -140,7 +132,7 @@ static inline int bnep_net_mc_filter(struct sk_buff *skb, struct bnep_session *s
#ifdef CONFIG_BT_BNEP_PROTO_FILTER
/* Determine ether protocol. Based on eth_type_trans. */
-static inline u16 bnep_net_eth_proto(struct sk_buff *skb)
+static u16 bnep_net_eth_proto(struct sk_buff *skb)
{
struct ethhdr *eh = (void *) skb->data;
u16 proto = ntohs(eh->h_proto);
@@ -154,7 +146,7 @@ static inline u16 bnep_net_eth_proto(struct sk_buff *skb)
return ETH_P_802_2;
}
-static inline int bnep_net_proto_filter(struct sk_buff *skb, struct bnep_session *s)
+static int bnep_net_proto_filter(struct sk_buff *skb, struct bnep_session *s)
{
u16 proto = bnep_net_eth_proto(skb);
struct bnep_proto_filter *f = s->proto_filter;
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index 180bfc45810d..5e5f5b410e0b 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -24,24 +24,8 @@
SOFTWARE IS DISCLAIMED.
*/
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/capability.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/poll.h>
-#include <linux/fcntl.h>
-#include <linux/skbuff.h>
-#include <linux/socket.h>
-#include <linux/ioctl.h>
+#include <linux/export.h>
#include <linux/file.h>
-#include <linux/init.h>
-#include <linux/compat.h>
-#include <linux/gfp.h>
-#include <linux/uaccess.h>
-#include <net/sock.h>
-
#include "bnep.h"
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 3f18a6ed9731..2fcced377e50 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -24,24 +24,11 @@
/* Bluetooth HCI connection handling. */
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/skbuff.h>
-#include <linux/interrupt.h>
-#include <net/sock.h>
-
-#include <linux/uaccess.h>
-#include <asm/unaligned.h>
+#include <linux/export.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/a2mp.h>
static void hci_le_connect(struct hci_conn *conn)
{
@@ -54,15 +41,15 @@ static void hci_le_connect(struct hci_conn *conn)
conn->sec_level = BT_SECURITY_LOW;
memset(&cp, 0, sizeof(cp));
- cp.scan_interval = cpu_to_le16(0x0060);
- cp.scan_window = cpu_to_le16(0x0030);
+ cp.scan_interval = __constant_cpu_to_le16(0x0060);
+ cp.scan_window = __constant_cpu_to_le16(0x0030);
bacpy(&cp.peer_addr, &conn->dst);
cp.peer_addr_type = conn->dst_type;
- cp.conn_interval_min = cpu_to_le16(0x0028);
- cp.conn_interval_max = cpu_to_le16(0x0038);
- cp.supervision_timeout = cpu_to_le16(0x002a);
- cp.min_ce_len = cpu_to_le16(0x0000);
- cp.max_ce_len = cpu_to_le16(0x0000);
+ cp.conn_interval_min = __constant_cpu_to_le16(0x0028);
+ cp.conn_interval_max = __constant_cpu_to_le16(0x0038);
+ cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
+ cp.min_ce_len = __constant_cpu_to_le16(0x0000);
+ cp.max_ce_len = __constant_cpu_to_le16(0x0000);
hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
}
@@ -99,7 +86,7 @@ void hci_acl_connect(struct hci_conn *conn)
cp.pscan_rep_mode = ie->data.pscan_rep_mode;
cp.pscan_mode = ie->data.pscan_mode;
cp.clock_offset = ie->data.clock_offset |
- cpu_to_le16(0x8000);
+ __constant_cpu_to_le16(0x8000);
}
memcpy(conn->dev_class, ie->data.dev_class, 3);
@@ -175,9 +162,9 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
cp.handle = cpu_to_le16(handle);
cp.pkt_type = cpu_to_le16(conn->pkt_type);
- cp.tx_bandwidth = cpu_to_le32(0x00001f40);
- cp.rx_bandwidth = cpu_to_le32(0x00001f40);
- cp.max_latency = cpu_to_le16(0xffff);
+ cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
+ cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
+ cp.max_latency = __constant_cpu_to_le16(0xffff);
cp.voice_setting = cpu_to_le16(hdev->voice_setting);
cp.retrans_effort = 0xff;
@@ -185,7 +172,7 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
}
void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
- u16 latency, u16 to_multiplier)
+ u16 latency, u16 to_multiplier)
{
struct hci_cp_le_conn_update cp;
struct hci_dev *hdev = conn->hdev;
@@ -197,15 +184,14 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
cp.conn_interval_max = cpu_to_le16(max);
cp.conn_latency = cpu_to_le16(latency);
cp.supervision_timeout = cpu_to_le16(to_multiplier);
- cp.min_ce_len = cpu_to_le16(0x0001);
- cp.max_ce_len = cpu_to_le16(0x0001);
+ cp.min_ce_len = __constant_cpu_to_le16(0x0001);
+ cp.max_ce_len = __constant_cpu_to_le16(0x0001);
hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
}
-EXPORT_SYMBOL(hci_le_conn_update);
void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
- __u8 ltk[16])
+ __u8 ltk[16])
{
struct hci_dev *hdev = conn->hdev;
struct hci_cp_le_start_enc cp;
@@ -221,7 +207,6 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
}
-EXPORT_SYMBOL(hci_le_start_enc);
/* Device _must_ be locked */
void hci_sco_setup(struct hci_conn *conn, __u8 status)
@@ -247,7 +232,7 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status)
static void hci_conn_timeout(struct work_struct *work)
{
struct hci_conn *conn = container_of(work, struct hci_conn,
- disc_work.work);
+ disc_work.work);
__u8 reason;
BT_DBG("conn %p state %s", conn, state_to_string(conn->state));
@@ -295,9 +280,9 @@ static void hci_conn_enter_sniff_mode(struct hci_conn *conn)
if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
struct hci_cp_sniff_subrate cp;
cp.handle = cpu_to_le16(conn->handle);
- cp.max_latency = cpu_to_le16(0);
- cp.min_remote_timeout = cpu_to_le16(0);
- cp.min_local_timeout = cpu_to_le16(0);
+ cp.max_latency = __constant_cpu_to_le16(0);
+ cp.min_remote_timeout = __constant_cpu_to_le16(0);
+ cp.min_local_timeout = __constant_cpu_to_le16(0);
hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
}
@@ -306,8 +291,8 @@ static void hci_conn_enter_sniff_mode(struct hci_conn *conn)
cp.handle = cpu_to_le16(conn->handle);
cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
- cp.attempt = cpu_to_le16(4);
- cp.timeout = cpu_to_le16(1);
+ cp.attempt = __constant_cpu_to_le16(4);
+ cp.timeout = __constant_cpu_to_le16(1);
hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
}
}
@@ -327,7 +312,7 @@ static void hci_conn_auto_accept(unsigned long arg)
struct hci_dev *hdev = conn->hdev;
hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst),
- &conn->dst);
+ &conn->dst);
}
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
@@ -376,7 +361,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout);
setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept,
- (unsigned long) conn);
+ (unsigned long) conn);
atomic_set(&conn->refcnt, 0);
@@ -425,9 +410,11 @@ int hci_conn_del(struct hci_conn *conn)
}
}
-
hci_chan_list_flush(conn);
+ if (conn->amp_mgr)
+ amp_mgr_put(conn->amp_mgr);
+
hci_conn_hash_del(hdev, conn);
if (hdev->notify)
hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
@@ -454,7 +441,8 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
read_lock(&hci_dev_list_lock);
list_for_each_entry(d, &hci_dev_list, list) {
- if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags))
+ if (!test_bit(HCI_UP, &d->flags) ||
+ test_bit(HCI_RAW, &d->flags))
continue;
/* Simple routing:
@@ -495,6 +483,11 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
if (type == LE_LINK) {
le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
if (!le) {
+ le = hci_conn_hash_lookup_state(hdev, LE_LINK,
+ BT_CONNECT);
+ if (le)
+ return ERR_PTR(-EBUSY);
+
le = hci_conn_add(hdev, LE_LINK, dst);
if (!le)
return ERR_PTR(-ENOMEM);
@@ -545,7 +538,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
hci_conn_hold(sco);
if (acl->state == BT_CONNECTED &&
- (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
+ (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
set_bit(HCI_CONN_POWER_SAVE, &acl->flags);
hci_conn_enter_active_mode(acl, BT_POWER_FORCE_ACTIVE_ON);
@@ -560,7 +553,6 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
return sco;
}
-EXPORT_SYMBOL(hci_connect);
/* Check link security requirement */
int hci_conn_check_link_mode(struct hci_conn *conn)
@@ -572,7 +564,6 @@ int hci_conn_check_link_mode(struct hci_conn *conn)
return 1;
}
-EXPORT_SYMBOL(hci_conn_check_link_mode);
/* Authenticate remote device */
static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
@@ -600,7 +591,7 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
cp.handle = cpu_to_le16(conn->handle);
hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
- sizeof(cp), &cp);
+ sizeof(cp), &cp);
if (conn->key_type != 0xff)
set_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
}
@@ -618,7 +609,7 @@ static void hci_conn_encrypt(struct hci_conn *conn)
cp.handle = cpu_to_le16(conn->handle);
cp.encrypt = 0x01;
hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
- &cp);
+ &cp);
}
}
@@ -648,8 +639,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
/* An unauthenticated combination key has sufficient security for
security level 1 and 2. */
if (conn->key_type == HCI_LK_UNAUTH_COMBINATION &&
- (sec_level == BT_SECURITY_MEDIUM ||
- sec_level == BT_SECURITY_LOW))
+ (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW))
goto encrypt;
/* A combination key has always sufficient security for the security
@@ -657,8 +647,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
is generated using maximum PIN code length (16).
For pre 2.1 units. */
if (conn->key_type == HCI_LK_COMBINATION &&
- (sec_level != BT_SECURITY_HIGH ||
- conn->pin_length == 16))
+ (sec_level != BT_SECURITY_HIGH || conn->pin_length == 16))
goto encrypt;
auth:
@@ -701,12 +690,11 @@ int hci_conn_change_link_key(struct hci_conn *conn)
struct hci_cp_change_conn_link_key cp;
cp.handle = cpu_to_le16(conn->handle);
hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY,
- sizeof(cp), &cp);
+ sizeof(cp), &cp);
}
return 0;
}
-EXPORT_SYMBOL(hci_conn_change_link_key);
/* Switch role */
int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
@@ -752,7 +740,7 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
timer:
if (hdev->idle_timeout > 0)
mod_timer(&conn->idle_timer,
- jiffies + msecs_to_jiffies(hdev->idle_timeout));
+ jiffies + msecs_to_jiffies(hdev->idle_timeout));
}
/* Drop all connection on the device */
@@ -802,7 +790,7 @@ EXPORT_SYMBOL(hci_conn_put_device);
int hci_get_conn_list(void __user *arg)
{
- register struct hci_conn *c;
+ struct hci_conn *c;
struct hci_conn_list_req req, *cl;
struct hci_conn_info *ci;
struct hci_dev *hdev;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 411ace8e647b..08994ecc3b6a 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -25,28 +25,10 @@
/* Bluetooth HCI core. */
-#include <linux/jiffies.h>
-#include <linux/module.h>
-#include <linux/kmod.h>
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/skbuff.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/rfkill.h>
-#include <linux/timer.h>
-#include <linux/crypto.h>
-#include <net/sock.h>
+#include <linux/export.h>
+#include <linux/idr.h>
-#include <linux/uaccess.h>
-#include <asm/unaligned.h>
+#include <linux/rfkill.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -65,6 +47,9 @@ DEFINE_RWLOCK(hci_dev_list_lock);
LIST_HEAD(hci_cb_list);
DEFINE_RWLOCK(hci_cb_list_lock);
+/* HCI ID Numbering */
+static DEFINE_IDA(hci_index_ida);
+
/* ---- HCI notifications ---- */
static void hci_notify(struct hci_dev *hdev, int event)
@@ -124,8 +109,9 @@ static void hci_req_cancel(struct hci_dev *hdev, int err)
}
/* Execute request and wait for completion. */
-static int __hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, unsigned long opt),
- unsigned long opt, __u32 timeout)
+static int __hci_request(struct hci_dev *hdev,
+ void (*req)(struct hci_dev *hdev, unsigned long opt),
+ unsigned long opt, __u32 timeout)
{
DECLARE_WAITQUEUE(wait, current);
int err = 0;
@@ -166,8 +152,9 @@ static int __hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev,
return err;
}
-static inline int hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, unsigned long opt),
- unsigned long opt, __u32 timeout)
+static int hci_request(struct hci_dev *hdev,
+ void (*req)(struct hci_dev *hdev, unsigned long opt),
+ unsigned long opt, __u32 timeout)
{
int ret;
@@ -202,7 +189,7 @@ static void bredr_init(struct hci_dev *hdev)
/* Mandatory initialization */
/* Reset */
- if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) {
+ if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) {
set_bit(HCI_RESET, &hdev->flags);
hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
}
@@ -235,7 +222,7 @@ static void bredr_init(struct hci_dev *hdev)
hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
/* Connection accept timeout ~20 secs */
- param = cpu_to_le16(0x7d00);
+ param = __constant_cpu_to_le16(0x7d00);
hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
bacpy(&cp.bdaddr, BDADDR_ANY);
@@ -417,7 +404,8 @@ static void inquiry_cache_flush(struct hci_dev *hdev)
INIT_LIST_HEAD(&cache->resolve);
}
-struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
+struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
+ bdaddr_t *bdaddr)
{
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *e;
@@ -478,7 +466,7 @@ void hci_inquiry_cache_update_resolve(struct hci_dev *hdev,
list_for_each_entry(p, &cache->resolve, list) {
if (p->name_state != NAME_PENDING &&
- abs(p->data.rssi) >= abs(ie->data.rssi))
+ abs(p->data.rssi) >= abs(ie->data.rssi))
break;
pos = &p->list;
}
@@ -503,7 +491,7 @@ bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
*ssp = true;
if (ie->name_state == NAME_NEEDED &&
- data->rssi != ie->data.rssi) {
+ data->rssi != ie->data.rssi) {
ie->data.rssi = data->rssi;
hci_inquiry_cache_update_resolve(hdev, ie);
}
@@ -527,7 +515,7 @@ bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
update:
if (name_known && ie->name_state != NAME_KNOWN &&
- ie->name_state != NAME_PENDING) {
+ ie->name_state != NAME_PENDING) {
ie->name_state = NAME_KNOWN;
list_del(&ie->list);
}
@@ -605,8 +593,7 @@ int hci_inquiry(void __user *arg)
hci_dev_lock(hdev);
if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX ||
- inquiry_cache_empty(hdev) ||
- ir.flags & IREQ_CACHE_FLUSH) {
+ inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) {
inquiry_cache_flush(hdev);
do_inquiry = 1;
}
@@ -620,7 +607,9 @@ int hci_inquiry(void __user *arg)
goto done;
}
- /* for unlimited number of responses we will use buffer with 255 entries */
+ /* for unlimited number of responses we will use buffer with
+ * 255 entries
+ */
max_rsp = (ir.num_rsp == 0) ? 255 : ir.num_rsp;
/* cache_dump can't sleep. Therefore we allocate temp buffer and then
@@ -641,7 +630,7 @@ int hci_inquiry(void __user *arg)
if (!copy_to_user(ptr, &ir, sizeof(ir))) {
ptr += sizeof(ir);
if (copy_to_user(ptr, buf, sizeof(struct inquiry_info) *
- ir.num_rsp))
+ ir.num_rsp))
err = -EFAULT;
} else
err = -EFAULT;
@@ -702,11 +691,11 @@ int hci_dev_open(__u16 dev)
hdev->init_last_cmd = 0;
ret = __hci_request(hdev, hci_init_req, 0,
- msecs_to_jiffies(HCI_INIT_TIMEOUT));
+ msecs_to_jiffies(HCI_INIT_TIMEOUT));
if (lmp_host_le_capable(hdev))
ret = __hci_request(hdev, hci_le_init_req, 0,
- msecs_to_jiffies(HCI_INIT_TIMEOUT));
+ msecs_to_jiffies(HCI_INIT_TIMEOUT));
clear_bit(HCI_INIT, &hdev->flags);
}
@@ -791,10 +780,10 @@ static int hci_dev_do_close(struct hci_dev *hdev)
skb_queue_purge(&hdev->cmd_q);
atomic_set(&hdev->cmd_cnt, 1);
if (!test_bit(HCI_RAW, &hdev->flags) &&
- test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) {
+ test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) {
set_bit(HCI_INIT, &hdev->flags);
__hci_request(hdev, hci_reset_req, 0,
- msecs_to_jiffies(250));
+ msecs_to_jiffies(250));
clear_bit(HCI_INIT, &hdev->flags);
}
@@ -884,7 +873,7 @@ int hci_dev_reset(__u16 dev)
if (!test_bit(HCI_RAW, &hdev->flags))
ret = __hci_request(hdev, hci_reset_req, 0,
- msecs_to_jiffies(HCI_INIT_TIMEOUT));
+ msecs_to_jiffies(HCI_INIT_TIMEOUT));
done:
hci_req_unlock(hdev);
@@ -924,7 +913,7 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
switch (cmd) {
case HCISETAUTH:
err = hci_request(hdev, hci_auth_req, dr.dev_opt,
- msecs_to_jiffies(HCI_INIT_TIMEOUT));
+ msecs_to_jiffies(HCI_INIT_TIMEOUT));
break;
case HCISETENCRYPT:
@@ -936,23 +925,23 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
if (!test_bit(HCI_AUTH, &hdev->flags)) {
/* Auth must be enabled first */
err = hci_request(hdev, hci_auth_req, dr.dev_opt,
- msecs_to_jiffies(HCI_INIT_TIMEOUT));
+ msecs_to_jiffies(HCI_INIT_TIMEOUT));
if (err)
break;
}
err = hci_request(hdev, hci_encrypt_req, dr.dev_opt,
- msecs_to_jiffies(HCI_INIT_TIMEOUT));
+ msecs_to_jiffies(HCI_INIT_TIMEOUT));
break;
case HCISETSCAN:
err = hci_request(hdev, hci_scan_req, dr.dev_opt,
- msecs_to_jiffies(HCI_INIT_TIMEOUT));
+ msecs_to_jiffies(HCI_INIT_TIMEOUT));
break;
case HCISETLINKPOL:
err = hci_request(hdev, hci_linkpol_req, dr.dev_opt,
- msecs_to_jiffies(HCI_INIT_TIMEOUT));
+ msecs_to_jiffies(HCI_INIT_TIMEOUT));
break;
case HCISETLINKMODE:
@@ -1103,7 +1092,7 @@ static void hci_power_on(struct work_struct *work)
if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
schedule_delayed_work(&hdev->power_off,
- msecs_to_jiffies(AUTO_OFF_TIMEOUT));
+ msecs_to_jiffies(AUTO_OFF_TIMEOUT));
if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags))
mgmt_index_added(hdev);
@@ -1112,7 +1101,7 @@ static void hci_power_on(struct work_struct *work)
static void hci_power_off(struct work_struct *work)
{
struct hci_dev *hdev = container_of(work, struct hci_dev,
- power_off.work);
+ power_off.work);
BT_DBG("%s", hdev->name);
@@ -1193,7 +1182,7 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
}
static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
- u8 key_type, u8 old_key_type)
+ u8 key_type, u8 old_key_type)
{
/* Legacy key */
if (key_type < 0x03)
@@ -1234,7 +1223,7 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8])
list_for_each_entry(k, &hdev->long_term_keys, list) {
if (k->ediv != ediv ||
- memcmp(rand, k->rand, sizeof(k->rand)))
+ memcmp(rand, k->rand, sizeof(k->rand)))
continue;
return k;
@@ -1242,7 +1231,6 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8])
return NULL;
}
-EXPORT_SYMBOL(hci_find_ltk);
struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type)
@@ -1251,12 +1239,11 @@ struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
list_for_each_entry(k, &hdev->long_term_keys, list)
if (addr_type == k->bdaddr_type &&
- bacmp(bdaddr, &k->bdaddr) == 0)
+ bacmp(bdaddr, &k->bdaddr) == 0)
return k;
return NULL;
}
-EXPORT_SYMBOL(hci_find_ltk_by_addr);
int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
@@ -1283,15 +1270,14 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
* combination key for legacy pairing even when there's no
* previous key */
if (type == HCI_LK_CHANGED_COMBINATION &&
- (!conn || conn->remote_auth == 0xff) &&
- old_key_type == 0xff) {
+ (!conn || conn->remote_auth == 0xff) && old_key_type == 0xff) {
type = HCI_LK_COMBINATION;
if (conn)
conn->key_type = type;
}
bacpy(&key->bdaddr, bdaddr);
- memcpy(key->val, val, 16);
+ memcpy(key->val, val, HCI_LINK_KEY_SIZE);
key->pin_len = pin_len;
if (type == HCI_LK_CHANGED_COMBINATION)
@@ -1540,6 +1526,7 @@ static void le_scan_enable_req(struct hci_dev *hdev, unsigned long opt)
memset(&cp, 0, sizeof(cp));
cp.enable = 1;
+ cp.filter_dup = 1;
hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
}
@@ -1707,41 +1694,39 @@ EXPORT_SYMBOL(hci_free_dev);
/* Register HCI device */
int hci_register_dev(struct hci_dev *hdev)
{
- struct list_head *head, *p;
int id, error;
if (!hdev->open || !hdev->close)
return -EINVAL;
- write_lock(&hci_dev_list_lock);
-
/* Do not allow HCI_AMP devices to register at index 0,
* so the index can be used as the AMP controller ID.
*/
- id = (hdev->dev_type == HCI_BREDR) ? 0 : 1;
- head = &hci_dev_list;
-
- /* Find first available device id */
- list_for_each(p, &hci_dev_list) {
- int nid = list_entry(p, struct hci_dev, list)->id;
- if (nid > id)
- break;
- if (nid == id)
- id++;
- head = p;
+ switch (hdev->dev_type) {
+ case HCI_BREDR:
+ id = ida_simple_get(&hci_index_ida, 0, 0, GFP_KERNEL);
+ break;
+ case HCI_AMP:
+ id = ida_simple_get(&hci_index_ida, 1, 0, GFP_KERNEL);
+ break;
+ default:
+ return -EINVAL;
}
+ if (id < 0)
+ return id;
+
sprintf(hdev->name, "hci%d", id);
hdev->id = id;
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
- list_add(&hdev->list, head);
-
+ write_lock(&hci_dev_list_lock);
+ list_add(&hdev->list, &hci_dev_list);
write_unlock(&hci_dev_list_lock);
hdev->workqueue = alloc_workqueue(hdev->name, WQ_HIGHPRI | WQ_UNBOUND |
- WQ_MEM_RECLAIM, 1);
+ WQ_MEM_RECLAIM, 1);
if (!hdev->workqueue) {
error = -ENOMEM;
goto err;
@@ -1752,7 +1737,8 @@ int hci_register_dev(struct hci_dev *hdev)
goto err_wqueue;
hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
- RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops, hdev);
+ RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops,
+ hdev);
if (hdev->rfkill) {
if (rfkill_register(hdev->rfkill) < 0) {
rfkill_destroy(hdev->rfkill);
@@ -1772,6 +1758,7 @@ int hci_register_dev(struct hci_dev *hdev)
err_wqueue:
destroy_workqueue(hdev->workqueue);
err:
+ ida_simple_remove(&hci_index_ida, hdev->id);
write_lock(&hci_dev_list_lock);
list_del(&hdev->list);
write_unlock(&hci_dev_list_lock);
@@ -1783,12 +1770,14 @@ EXPORT_SYMBOL(hci_register_dev);
/* Unregister HCI device */
void hci_unregister_dev(struct hci_dev *hdev)
{
- int i;
+ int i, id;
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
set_bit(HCI_UNREGISTER, &hdev->dev_flags);
+ id = hdev->id;
+
write_lock(&hci_dev_list_lock);
list_del(&hdev->list);
write_unlock(&hci_dev_list_lock);
@@ -1799,7 +1788,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
kfree_skb(hdev->reassembly[i]);
if (!test_bit(HCI_INIT, &hdev->flags) &&
- !test_bit(HCI_SETUP, &hdev->dev_flags)) {
+ !test_bit(HCI_SETUP, &hdev->dev_flags)) {
hci_dev_lock(hdev);
mgmt_index_removed(hdev);
hci_dev_unlock(hdev);
@@ -1829,6 +1818,8 @@ void hci_unregister_dev(struct hci_dev *hdev)
hci_dev_unlock(hdev);
hci_dev_put(hdev);
+
+ ida_simple_remove(&hci_index_ida, id);
}
EXPORT_SYMBOL(hci_unregister_dev);
@@ -1853,7 +1844,7 @@ int hci_recv_frame(struct sk_buff *skb)
{
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
if (!hdev || (!test_bit(HCI_UP, &hdev->flags)
- && !test_bit(HCI_INIT, &hdev->flags))) {
+ && !test_bit(HCI_INIT, &hdev->flags))) {
kfree_skb(skb);
return -ENXIO;
}
@@ -1872,7 +1863,7 @@ int hci_recv_frame(struct sk_buff *skb)
EXPORT_SYMBOL(hci_recv_frame);
static int hci_reassembly(struct hci_dev *hdev, int type, void *data,
- int count, __u8 index)
+ int count, __u8 index)
{
int len = 0;
int hlen = 0;
@@ -1881,7 +1872,7 @@ static int hci_reassembly(struct hci_dev *hdev, int type, void *data,
struct bt_skb_cb *scb;
if ((type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) ||
- index >= NUM_REASSEMBLY)
+ index >= NUM_REASSEMBLY)
return -EILSEQ;
skb = hdev->reassembly[index];
@@ -2023,7 +2014,7 @@ int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count)
type = bt_cb(skb)->pkt_type;
rem = hci_reassembly(hdev, type, data, count,
- STREAM_REASSEMBLY);
+ STREAM_REASSEMBLY);
if (rem < 0)
return rem;
@@ -2157,7 +2148,7 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
}
static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue,
- struct sk_buff *skb, __u16 flags)
+ struct sk_buff *skb, __u16 flags)
{
struct hci_dev *hdev = conn->hdev;
struct sk_buff *list;
@@ -2216,7 +2207,6 @@ void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags)
queue_work(hdev->workqueue, &hdev->tx_work);
}
-EXPORT_SYMBOL(hci_send_acl);
/* Send SCO data */
void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb)
@@ -2239,12 +2229,12 @@ void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb)
skb_queue_tail(&conn->data_q, skb);
queue_work(hdev->workqueue, &hdev->tx_work);
}
-EXPORT_SYMBOL(hci_send_sco);
/* ---- HCI TX task (outgoing data) ---- */
/* HCI Connection scheduler */
-static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote)
+static struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type,
+ int *quote)
{
struct hci_conn_hash *h = &hdev->conn_hash;
struct hci_conn *conn = NULL, *c;
@@ -2303,7 +2293,7 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
return conn;
}
-static inline void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
+static void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
{
struct hci_conn_hash *h = &hdev->conn_hash;
struct hci_conn *c;
@@ -2316,16 +2306,16 @@ static inline void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
list_for_each_entry_rcu(c, &h->list, list) {
if (c->type == type && c->sent) {
BT_ERR("%s killing stalled connection %s",
- hdev->name, batostr(&c->dst));
- hci_acl_disconn(c, 0x13);
+ hdev->name, batostr(&c->dst));
+ hci_acl_disconn(c, HCI_ERROR_REMOTE_USER_TERM);
}
}
rcu_read_unlock();
}
-static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
- int *quote)
+static struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
+ int *quote)
{
struct hci_conn_hash *h = &hdev->conn_hash;
struct hci_chan *chan = NULL;
@@ -2442,7 +2432,7 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
skb->priority = HCI_PRIO_MAX - 1;
BT_DBG("chan %p skb %p promoted to %d", chan, skb,
- skb->priority);
+ skb->priority);
}
if (hci_conn_num(hdev, type) == num)
@@ -2459,18 +2449,18 @@ static inline int __get_blocks(struct hci_dev *hdev, struct sk_buff *skb)
return DIV_ROUND_UP(skb->len - HCI_ACL_HDR_SIZE, hdev->block_len);
}
-static inline void __check_timeout(struct hci_dev *hdev, unsigned int cnt)
+static void __check_timeout(struct hci_dev *hdev, unsigned int cnt)
{
if (!test_bit(HCI_RAW, &hdev->flags)) {
/* ACL tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
if (!cnt && time_after(jiffies, hdev->acl_last_tx +
- msecs_to_jiffies(HCI_ACL_TX_TIMEOUT)))
+ msecs_to_jiffies(HCI_ACL_TX_TIMEOUT)))
hci_link_tx_to(hdev, ACL_LINK);
}
}
-static inline void hci_sched_acl_pkt(struct hci_dev *hdev)
+static void hci_sched_acl_pkt(struct hci_dev *hdev)
{
unsigned int cnt = hdev->acl_cnt;
struct hci_chan *chan;
@@ -2480,11 +2470,11 @@ static inline void hci_sched_acl_pkt(struct hci_dev *hdev)
__check_timeout(hdev, cnt);
while (hdev->acl_cnt &&
- (chan = hci_chan_sent(hdev, ACL_LINK, &quote))) {
+ (chan = hci_chan_sent(hdev, ACL_LINK, &quote))) {
u32 priority = (skb_peek(&chan->data_q))->priority;
while (quote-- && (skb = skb_peek(&chan->data_q))) {
BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
- skb->len, skb->priority);
+ skb->len, skb->priority);
/* Stop if priority has changed */
if (skb->priority < priority)
@@ -2508,7 +2498,7 @@ static inline void hci_sched_acl_pkt(struct hci_dev *hdev)
hci_prio_recalculate(hdev, ACL_LINK);
}
-static inline void hci_sched_acl_blk(struct hci_dev *hdev)
+static void hci_sched_acl_blk(struct hci_dev *hdev)
{
unsigned int cnt = hdev->block_cnt;
struct hci_chan *chan;
@@ -2518,13 +2508,13 @@ static inline void hci_sched_acl_blk(struct hci_dev *hdev)
__check_timeout(hdev, cnt);
while (hdev->block_cnt > 0 &&
- (chan = hci_chan_sent(hdev, ACL_LINK, &quote))) {
+ (chan = hci_chan_sent(hdev, ACL_LINK, &quote))) {
u32 priority = (skb_peek(&chan->data_q))->priority;
while (quote > 0 && (skb = skb_peek(&chan->data_q))) {
int blocks;
BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
- skb->len, skb->priority);
+ skb->len, skb->priority);
/* Stop if priority has changed */
if (skb->priority < priority)
@@ -2537,7 +2527,7 @@ static inline void hci_sched_acl_blk(struct hci_dev *hdev)
return;
hci_conn_enter_active_mode(chan->conn,
- bt_cb(skb)->force_active);
+ bt_cb(skb)->force_active);
hci_send_frame(skb);
hdev->acl_last_tx = jiffies;
@@ -2554,7 +2544,7 @@ static inline void hci_sched_acl_blk(struct hci_dev *hdev)
hci_prio_recalculate(hdev, ACL_LINK);
}
-static inline void hci_sched_acl(struct hci_dev *hdev)
+static void hci_sched_acl(struct hci_dev *hdev)
{
BT_DBG("%s", hdev->name);
@@ -2573,7 +2563,7 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
}
/* Schedule SCO */
-static inline void hci_sched_sco(struct hci_dev *hdev)
+static void hci_sched_sco(struct hci_dev *hdev)
{
struct hci_conn *conn;
struct sk_buff *skb;
@@ -2596,7 +2586,7 @@ static inline void hci_sched_sco(struct hci_dev *hdev)
}
}
-static inline void hci_sched_esco(struct hci_dev *hdev)
+static void hci_sched_esco(struct hci_dev *hdev)
{
struct hci_conn *conn;
struct sk_buff *skb;
@@ -2607,7 +2597,8 @@ static inline void hci_sched_esco(struct hci_dev *hdev)
if (!hci_conn_num(hdev, ESCO_LINK))
return;
- while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK, &quote))) {
+ while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK,
+ &quote))) {
while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
BT_DBG("skb %p len %d", skb, skb->len);
hci_send_frame(skb);
@@ -2619,7 +2610,7 @@ static inline void hci_sched_esco(struct hci_dev *hdev)
}
}
-static inline void hci_sched_le(struct hci_dev *hdev)
+static void hci_sched_le(struct hci_dev *hdev)
{
struct hci_chan *chan;
struct sk_buff *skb;
@@ -2634,7 +2625,7 @@ static inline void hci_sched_le(struct hci_dev *hdev)
/* LE tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
if (!hdev->le_cnt && hdev->le_pkts &&
- time_after(jiffies, hdev->le_last_tx + HZ * 45))
+ time_after(jiffies, hdev->le_last_tx + HZ * 45))
hci_link_tx_to(hdev, LE_LINK);
}
@@ -2644,7 +2635,7 @@ static inline void hci_sched_le(struct hci_dev *hdev)
u32 priority = (skb_peek(&chan->data_q))->priority;
while (quote-- && (skb = skb_peek(&chan->data_q))) {
BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
- skb->len, skb->priority);
+ skb->len, skb->priority);
/* Stop if priority has changed */
if (skb->priority < priority)
@@ -2676,7 +2667,7 @@ static void hci_tx_work(struct work_struct *work)
struct sk_buff *skb;
BT_DBG("%s acl %d sco %d le %d", hdev->name, hdev->acl_cnt,
- hdev->sco_cnt, hdev->le_cnt);
+ hdev->sco_cnt, hdev->le_cnt);
/* Schedule queues and send stuff to HCI driver */
@@ -2696,7 +2687,7 @@ static void hci_tx_work(struct work_struct *work)
/* ----- HCI RX task (incoming data processing) ----- */
/* ACL data packet */
-static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_acl_hdr *hdr = (void *) skb->data;
struct hci_conn *conn;
@@ -2708,7 +2699,8 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
flags = hci_flags(handle);
handle = hci_handle(handle);
- BT_DBG("%s len %d handle 0x%x flags 0x%x", hdev->name, skb->len, handle, flags);
+ BT_DBG("%s len %d handle 0x%x flags 0x%x", hdev->name, skb->len,
+ handle, flags);
hdev->stat.acl_rx++;
@@ -2732,14 +2724,14 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
return;
} else {
BT_ERR("%s ACL packet for unknown connection handle %d",
- hdev->name, handle);
+ hdev->name, handle);
}
kfree_skb(skb);
}
/* SCO data packet */
-static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_sco_hdr *hdr = (void *) skb->data;
struct hci_conn *conn;
@@ -2763,7 +2755,7 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
return;
} else {
BT_ERR("%s SCO packet for unknown connection handle %d",
- hdev->name, handle);
+ hdev->name, handle);
}
kfree_skb(skb);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 4eefb7f65cf6..1ba929c05d0d 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -24,20 +24,7 @@
/* Bluetooth HCI event handling. */
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/skbuff.h>
-#include <linux/interrupt.h>
-#include <net/sock.h>
-
-#include <linux/uaccess.h>
+#include <linux/export.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
@@ -95,7 +82,8 @@ static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
hci_conn_check_pending(hdev);
}
-static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
BT_DBG("%s", hdev->name);
}
@@ -166,7 +154,8 @@ static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_unlock(hdev);
}
-static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
@@ -178,7 +167,8 @@ static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *sk
hdev->link_policy = __le16_to_cpu(rp->policy);
}
-static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
void *sent;
@@ -329,7 +319,7 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
if (hdev->discov_timeout > 0) {
int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
queue_delayed_work(hdev->workqueue, &hdev->discov_off,
- to);
+ to);
}
} else if (old_iscan)
mgmt_discoverable(hdev, 0);
@@ -358,7 +348,7 @@ static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
memcpy(hdev->dev_class, rp->dev_class, 3);
BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
- hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
+ hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
}
static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
@@ -406,7 +396,8 @@ static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
}
-static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_cc_write_voice_setting(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
__u16 setting;
@@ -473,7 +464,7 @@ static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
return 1;
if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
- hdev->lmp_subver == 0x0757)
+ hdev->lmp_subver == 0x0757)
return 1;
if (hdev->manufacturer == 15) {
@@ -486,7 +477,7 @@ static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
}
if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
- hdev->lmp_subver == 0x1805)
+ hdev->lmp_subver == 0x1805)
return 1;
return 0;
@@ -566,7 +557,7 @@ static void hci_setup(struct hci_dev *hdev)
if (hdev->hci_ver > BLUETOOTH_VER_1_1)
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
- if (hdev->features[6] & LMP_SIMPLE_PAIR) {
+ if (lmp_ssp_capable(hdev)) {
if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
u8 mode = 0x01;
hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
@@ -618,8 +609,7 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
- hdev->manufacturer,
- hdev->hci_ver, hdev->hci_rev);
+ hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
if (test_bit(HCI_INIT, &hdev->flags))
hci_setup(hdev);
@@ -646,7 +636,8 @@ static void hci_setup_link_policy(struct hci_dev *hdev)
hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
}
-static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_cc_read_local_commands(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
struct hci_rp_read_local_commands *rp = (void *) skb->data;
@@ -664,7 +655,8 @@ done:
hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
}
-static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_cc_read_local_features(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
struct hci_rp_read_local_features *rp = (void *) skb->data;
@@ -713,10 +705,10 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb
hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
- hdev->features[0], hdev->features[1],
- hdev->features[2], hdev->features[3],
- hdev->features[4], hdev->features[5],
- hdev->features[6], hdev->features[7]);
+ hdev->features[0], hdev->features[1],
+ hdev->features[2], hdev->features[3],
+ hdev->features[4], hdev->features[5],
+ hdev->features[6], hdev->features[7]);
}
static void hci_set_le_support(struct hci_dev *hdev)
@@ -736,7 +728,7 @@ static void hci_set_le_support(struct hci_dev *hdev)
}
static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
@@ -762,7 +754,7 @@ done:
}
static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
@@ -798,9 +790,8 @@ static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
hdev->acl_cnt = hdev->acl_pkts;
hdev->sco_cnt = hdev->sco_pkts;
- BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name,
- hdev->acl_mtu, hdev->acl_pkts,
- hdev->sco_mtu, hdev->sco_pkts);
+ BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
+ hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
}
static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
@@ -816,7 +807,7 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
}
static void hci_cc_read_data_block_size(struct hci_dev *hdev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct hci_rp_read_data_block_size *rp = (void *) skb->data;
@@ -832,7 +823,7 @@ static void hci_cc_read_data_block_size(struct hci_dev *hdev,
hdev->block_cnt = hdev->num_blocks;
BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
- hdev->block_cnt, hdev->block_len);
+ hdev->block_cnt, hdev->block_len);
hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
}
@@ -847,7 +838,7 @@ static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
}
static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
@@ -871,7 +862,7 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
}
static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
@@ -890,7 +881,7 @@ static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
}
static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
@@ -900,7 +891,7 @@ static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
}
static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
@@ -959,7 +950,7 @@ static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
if (test_bit(HCI_MGMT, &hdev->dev_flags))
mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
- rp->status);
+ rp->status);
hci_dev_unlock(hdev);
}
@@ -1000,7 +991,7 @@ static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
}
static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
@@ -1031,7 +1022,7 @@ static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
}
static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
@@ -1047,7 +1038,7 @@ static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
}
static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
@@ -1076,7 +1067,7 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
}
static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
struct hci_cp_le_set_scan_enable *cp;
__u8 status = *((__u8 *) skb->data);
@@ -1156,8 +1147,8 @@ static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
}
-static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
- struct sk_buff *skb)
+static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
struct hci_cp_write_le_host_supported *sent;
__u8 status = *((__u8 *) skb->data);
@@ -1176,13 +1167,13 @@ static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
}
if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
- !test_bit(HCI_INIT, &hdev->flags))
+ !test_bit(HCI_INIT, &hdev->flags))
mgmt_le_enable_complete(hdev, sent->le, status);
hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
}
-static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
+static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
{
BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1203,7 +1194,7 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
hci_dev_unlock(hdev);
}
-static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
+static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_create_conn *cp;
struct hci_conn *conn;
@@ -1333,7 +1324,7 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
}
static int hci_outgoing_auth_needed(struct hci_dev *hdev,
- struct hci_conn *conn)
+ struct hci_conn *conn)
{
if (conn->state != BT_CONFIG || !conn->out)
return 0;
@@ -1343,15 +1334,14 @@ static int hci_outgoing_auth_needed(struct hci_dev *hdev,
/* Only request authentication for SSP connections or non-SSP
* devices with sec_level HIGH or if MITM protection is requested */
- if (!hci_conn_ssp_enabled(conn) &&
- conn->pending_sec_level != BT_SECURITY_HIGH &&
- !(conn->auth_type & 0x01))
+ if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
+ conn->pending_sec_level != BT_SECURITY_HIGH)
return 0;
return 1;
}
-static inline int hci_resolve_name(struct hci_dev *hdev,
+static int hci_resolve_name(struct hci_dev *hdev,
struct inquiry_entry *e)
{
struct hci_cp_remote_name_req cp;
@@ -1638,7 +1628,7 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
- conn);
+ conn);
if (status) {
if (conn && conn->state == BT_CONNECT) {
@@ -1668,7 +1658,7 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
BT_DBG("%s status 0x%x", hdev->name, status);
}
-static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
struct discovery_state *discov = &hdev->discovery;
@@ -1708,7 +1698,7 @@ unlock:
hci_dev_unlock(hdev);
}
-static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct inquiry_data data;
struct inquiry_info *info = (void *) (skb->data + 1);
@@ -1745,7 +1735,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
hci_dev_unlock(hdev);
}
-static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_conn_complete *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -1823,18 +1813,18 @@ unlock:
hci_conn_check_pending(hdev);
}
-static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_conn_request *ev = (void *) skb->data;
int mask = hdev->link_mode;
- BT_DBG("%s bdaddr %s type 0x%x", hdev->name,
- batostr(&ev->bdaddr), ev->link_type);
+ BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr),
+ ev->link_type);
mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
if ((mask & HCI_LM_ACCEPT) &&
- !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
+ !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
/* Connection accepted */
struct inquiry_entry *ie;
struct hci_conn *conn;
@@ -1845,7 +1835,8 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
if (ie)
memcpy(ie->data.dev_class, ev->dev_class, 3);
- conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
+ conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
+ &ev->bdaddr);
if (!conn) {
conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
if (!conn) {
@@ -1878,9 +1869,9 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
bacpy(&cp.bdaddr, &ev->bdaddr);
cp.pkt_type = cpu_to_le16(conn->pkt_type);
- cp.tx_bandwidth = cpu_to_le32(0x00001f40);
- cp.rx_bandwidth = cpu_to_le32(0x00001f40);
- cp.max_latency = cpu_to_le16(0xffff);
+ cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
+ cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
+ cp.max_latency = __constant_cpu_to_le16(0xffff);
cp.content_format = cpu_to_le16(hdev->voice_setting);
cp.retrans_effort = 0xff;
@@ -1897,7 +1888,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
}
}
-static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_disconn_complete *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -1914,10 +1905,10 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
conn->state = BT_CLOSED;
if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
- (conn->type == ACL_LINK || conn->type == LE_LINK)) {
+ (conn->type == ACL_LINK || conn->type == LE_LINK)) {
if (ev->status != 0)
mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
- conn->dst_type, ev->status);
+ conn->dst_type, ev->status);
else
mgmt_device_disconnected(hdev, &conn->dst, conn->type,
conn->dst_type);
@@ -1934,7 +1925,7 @@ unlock:
hci_dev_unlock(hdev);
}
-static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_auth_complete *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -1949,7 +1940,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if (!ev->status) {
if (!hci_conn_ssp_enabled(conn) &&
- test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
+ test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
BT_INFO("re-auth of legacy device is not possible.");
} else {
conn->link_mode |= HCI_LM_AUTH;
@@ -1969,7 +1960,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
cp.handle = ev->handle;
cp.encrypt = 0x01;
hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
- &cp);
+ &cp);
} else {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
@@ -1989,7 +1980,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
cp.handle = ev->handle;
cp.encrypt = 0x01;
hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
- &cp);
+ &cp);
} else {
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
hci_encrypt_cfm(conn, ev->status, 0x00);
@@ -2000,7 +1991,7 @@ unlock:
hci_dev_unlock(hdev);
}
-static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_remote_name *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -2039,7 +2030,7 @@ unlock:
hci_dev_unlock(hdev);
}
-static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_encrypt_change *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -2082,7 +2073,8 @@ unlock:
hci_dev_unlock(hdev);
}
-static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -2104,7 +2096,8 @@ static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct
hci_dev_unlock(hdev);
}
-static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_remote_features_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
struct hci_ev_remote_features *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -2128,7 +2121,7 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
cp.handle = ev->handle;
cp.page = 0x01;
hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
- sizeof(cp), &cp);
+ sizeof(cp), &cp);
goto unlock;
}
@@ -2153,17 +2146,18 @@ unlock:
hci_dev_unlock(hdev);
}
-static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
BT_DBG("%s", hdev->name);
}
-static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
BT_DBG("%s", hdev->name);
}
-static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_cmd_complete *ev = (void *) skb->data;
__u16 opcode;
@@ -2384,7 +2378,7 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
}
}
-static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_cmd_status *ev = (void *) skb->data;
__u16 opcode;
@@ -2465,7 +2459,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
}
}
-static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_role_change *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -2491,7 +2485,7 @@ static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb
hci_dev_unlock(hdev);
}
-static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
int i;
@@ -2502,7 +2496,7 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
}
if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
- ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
+ ev->num_hndl * sizeof(struct hci_comp_pkts_info)) {
BT_DBG("%s bad parameters", hdev->name);
return;
}
@@ -2557,8 +2551,7 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
queue_work(hdev->workqueue, &hdev->tx_work);
}
-static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
- struct sk_buff *skb)
+static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
int i;
@@ -2569,13 +2562,13 @@ static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
}
if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
- ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
+ ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
BT_DBG("%s bad parameters", hdev->name);
return;
}
BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
- ev->num_hndl);
+ ev->num_hndl);
for (i = 0; i < ev->num_hndl; i++) {
struct hci_comp_blocks_info *info = &ev->handles[i];
@@ -2607,7 +2600,7 @@ static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
queue_work(hdev->workqueue, &hdev->tx_work);
}
-static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_mode_change *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -2621,7 +2614,8 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb
conn->mode = ev->mode;
conn->interval = __le16_to_cpu(ev->interval);
- if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
+ if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
+ &conn->flags)) {
if (conn->mode == HCI_CM_ACTIVE)
set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
else
@@ -2635,7 +2629,7 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb
hci_dev_unlock(hdev);
}
-static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_pin_code_req *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -2656,7 +2650,7 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
- sizeof(ev->bdaddr), &ev->bdaddr);
+ sizeof(ev->bdaddr), &ev->bdaddr);
else if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
u8 secure;
@@ -2672,7 +2666,7 @@ unlock:
hci_dev_unlock(hdev);
}
-static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_link_key_req *ev = (void *) skb->data;
struct hci_cp_link_key_reply cp;
@@ -2689,15 +2683,15 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff
key = hci_find_link_key(hdev, &ev->bdaddr);
if (!key) {
BT_DBG("%s link key not found for %s", hdev->name,
- batostr(&ev->bdaddr));
+ batostr(&ev->bdaddr));
goto not_found;
}
BT_DBG("%s found key type %u for %s", hdev->name, key->type,
- batostr(&ev->bdaddr));
+ batostr(&ev->bdaddr));
if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
- key->type == HCI_LK_DEBUG_COMBINATION) {
+ key->type == HCI_LK_DEBUG_COMBINATION) {
BT_DBG("%s ignoring debug key", hdev->name);
goto not_found;
}
@@ -2705,16 +2699,15 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (conn) {
if (key->type == HCI_LK_UNAUTH_COMBINATION &&
- conn->auth_type != 0xff &&
- (conn->auth_type & 0x01)) {
+ conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
BT_DBG("%s ignoring unauthenticated key", hdev->name);
goto not_found;
}
if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
- conn->pending_sec_level == BT_SECURITY_HIGH) {
- BT_DBG("%s ignoring key unauthenticated for high \
- security", hdev->name);
+ conn->pending_sec_level == BT_SECURITY_HIGH) {
+ BT_DBG("%s ignoring key unauthenticated for high security",
+ hdev->name);
goto not_found;
}
@@ -2723,7 +2716,7 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff
}
bacpy(&cp.bdaddr, &ev->bdaddr);
- memcpy(cp.link_key, key->val, 16);
+ memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
@@ -2736,7 +2729,7 @@ not_found:
hci_dev_unlock(hdev);
}
-static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_link_key_notify *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -2760,12 +2753,12 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff
if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
- ev->key_type, pin_len);
+ ev->key_type, pin_len);
hci_dev_unlock(hdev);
}
-static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_clock_offset *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -2788,7 +2781,7 @@ static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_dev_unlock(hdev);
}
-static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_pkt_type_change *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -2804,7 +2797,7 @@ static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff
hci_dev_unlock(hdev);
}
-static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
struct inquiry_entry *ie;
@@ -2822,7 +2815,8 @@ static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *
hci_dev_unlock(hdev);
}
-static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
struct inquiry_data data;
int num_rsp = *((__u8 *) skb->data);
@@ -2881,7 +2875,8 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
hci_dev_unlock(hdev);
}
-static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_remote_ext_features_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
struct hci_ev_remote_ext_features *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -2929,7 +2924,8 @@ unlock:
hci_dev_unlock(hdev);
}
-static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -2984,19 +2980,20 @@ unlock:
hci_dev_unlock(hdev);
}
-static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
BT_DBG("%s", hdev->name);
}
-static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_sniff_subrate *ev = (void *) skb->data;
BT_DBG("%s status %d", hdev->name, ev->status);
}
-static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
struct inquiry_data data;
struct extended_inquiry_info *info = (void *) (skb->data + 1);
@@ -3043,7 +3040,51 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
hci_dev_unlock(hdev);
}
-static inline u8 hci_get_auth_req(struct hci_conn *conn)
+static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
+ struct hci_conn *conn;
+
+ BT_DBG("%s status %u handle %u", hdev->name, ev->status,
+ __le16_to_cpu(ev->handle));
+
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
+ if (!conn)
+ goto unlock;
+
+ if (!ev->status)
+ conn->sec_level = conn->pending_sec_level;
+
+ clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
+
+ if (ev->status && conn->state == BT_CONNECTED) {
+ hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
+ hci_conn_put(conn);
+ goto unlock;
+ }
+
+ if (conn->state == BT_CONFIG) {
+ if (!ev->status)
+ conn->state = BT_CONNECTED;
+
+ hci_proto_connect_cfm(conn, ev->status);
+ hci_conn_put(conn);
+ } else {
+ hci_auth_cfm(conn, ev->status);
+
+ hci_conn_hold(conn);
+ conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+ hci_conn_put(conn);
+ }
+
+unlock:
+ hci_dev_unlock(hdev);
+}
+
+static u8 hci_get_auth_req(struct hci_conn *conn)
{
/* If remote requests dedicated bonding follow that lead */
if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
@@ -3062,7 +3103,7 @@ static inline u8 hci_get_auth_req(struct hci_conn *conn)
return conn->auth_type;
}
-static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_io_capa_request *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -3081,7 +3122,7 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
goto unlock;
if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) ||
- (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
+ (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
struct hci_cp_io_capability_reply cp;
bacpy(&cp.bdaddr, &ev->bdaddr);
@@ -3092,14 +3133,14 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
conn->auth_type = hci_get_auth_req(conn);
cp.authentication = conn->auth_type;
- if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
- hci_find_remote_oob_data(hdev, &conn->dst))
+ if (hci_find_remote_oob_data(hdev, &conn->dst) &&
+ (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
cp.oob_data = 0x01;
else
cp.oob_data = 0x00;
hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
- sizeof(cp), &cp);
+ sizeof(cp), &cp);
} else {
struct hci_cp_io_capability_neg_reply cp;
@@ -3107,14 +3148,14 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
- sizeof(cp), &cp);
+ sizeof(cp), &cp);
}
unlock:
hci_dev_unlock(hdev);
}
-static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_io_capa_reply *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -3136,8 +3177,8 @@ unlock:
hci_dev_unlock(hdev);
}
-static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
- struct sk_buff *skb)
+static void hci_user_confirm_request_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
struct hci_ev_user_confirm_req *ev = (void *) skb->data;
int loc_mitm, rem_mitm, confirm_hint = 0;
@@ -3165,13 +3206,13 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
BT_DBG("Rejecting request: remote device can't provide MITM");
hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
- sizeof(ev->bdaddr), &ev->bdaddr);
+ sizeof(ev->bdaddr), &ev->bdaddr);
goto unlock;
}
/* If no side requires MITM protection; auto-accept */
if ((!loc_mitm || conn->remote_cap == 0x03) &&
- (!rem_mitm || conn->io_capability == 0x03)) {
+ (!rem_mitm || conn->io_capability == 0x03)) {
/* If we're not the initiators request authorization to
* proceed from user space (mgmt_user_confirm with
@@ -3183,7 +3224,7 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
}
BT_DBG("Auto-accept of user confirmation with %ums delay",
- hdev->auto_accept_delay);
+ hdev->auto_accept_delay);
if (hdev->auto_accept_delay > 0) {
int delay = msecs_to_jiffies(hdev->auto_accept_delay);
@@ -3192,7 +3233,7 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
}
hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
- sizeof(ev->bdaddr), &ev->bdaddr);
+ sizeof(ev->bdaddr), &ev->bdaddr);
goto unlock;
}
@@ -3204,8 +3245,8 @@ unlock:
hci_dev_unlock(hdev);
}
-static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
- struct sk_buff *skb)
+static void hci_user_passkey_request_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
struct hci_ev_user_passkey_req *ev = (void *) skb->data;
@@ -3219,7 +3260,8 @@ static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
hci_dev_unlock(hdev);
}
-static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -3247,7 +3289,8 @@ unlock:
hci_dev_unlock(hdev);
}
-static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_remote_host_features_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
struct hci_ev_remote_host_features *ev = (void *) skb->data;
struct inquiry_entry *ie;
@@ -3263,8 +3306,8 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_
hci_dev_unlock(hdev);
}
-static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
- struct sk_buff *skb)
+static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
{
struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
struct oob_data *data;
@@ -3285,20 +3328,20 @@ static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
- &cp);
+ &cp);
} else {
struct hci_cp_remote_oob_data_neg_reply cp;
bacpy(&cp.bdaddr, &ev->bdaddr);
hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
- &cp);
+ &cp);
}
unlock:
hci_dev_unlock(hdev);
}
-static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_le_conn_complete *ev = (void *) skb->data;
struct hci_conn *conn;
@@ -3307,6 +3350,19 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
hci_dev_lock(hdev);
+ if (ev->status) {
+ conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
+ if (!conn)
+ goto unlock;
+
+ mgmt_connect_failed(hdev, &conn->dst, conn->type,
+ conn->dst_type, ev->status);
+ hci_proto_connect_cfm(conn, ev->status);
+ conn->state = BT_CLOSED;
+ hci_conn_del(conn);
+ goto unlock;
+ }
+
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
if (!conn) {
conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
@@ -3319,15 +3375,6 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
conn->dst_type = ev->bdaddr_type;
}
- if (ev->status) {
- mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
- conn->dst_type, ev->status);
- hci_proto_connect_cfm(conn, ev->status);
- conn->state = BT_CLOSED;
- hci_conn_del(conn);
- goto unlock;
- }
-
if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
conn->dst_type, 0, NULL, 0, NULL);
@@ -3345,8 +3392,7 @@ unlock:
hci_dev_unlock(hdev);
}
-static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
- struct sk_buff *skb)
+static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
u8 num_reports = skb->data[0];
void *ptr = &skb->data[1];
@@ -3367,8 +3413,7 @@ static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
hci_dev_unlock(hdev);
}
-static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
- struct sk_buff *skb)
+static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_le_ltk_req *ev = (void *) skb->data;
struct hci_cp_le_ltk_reply cp;
@@ -3411,7 +3456,7 @@ not_found:
hci_dev_unlock(hdev);
}
-static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_le_meta *le_ev = (void *) skb->data;
@@ -3559,6 +3604,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_extended_inquiry_result_evt(hdev, skb);
break;
+ case HCI_EV_KEY_REFRESH_COMPLETE:
+ hci_key_refresh_complete_evt(hdev, skb);
+ break;
+
case HCI_EV_IO_CAPA_REQUEST:
hci_io_capa_request_evt(hdev, skb);
break;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 5914623f426a..a7f04de03d79 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -24,25 +24,7 @@
/* Bluetooth HCI sockets. */
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/capability.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/skbuff.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/compat.h>
-#include <linux/socket.h>
-#include <linux/ioctl.h>
-#include <net/sock.h>
-
-#include <linux/uaccess.h>
+#include <linux/export.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
@@ -113,11 +95,12 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
flt = &hci_pi(sk)->filter;
if (!test_bit((bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) ?
- 0 : (bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS), &flt->type_mask))
+ 0 : (bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS),
+ &flt->type_mask))
continue;
if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) {
- register int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
+ int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
if (!hci_test_bit(evt, &flt->event_mask))
continue;
@@ -240,7 +223,8 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb)
struct hci_mon_hdr *hdr;
/* Create a private copy with headroom */
- skb_copy = __pskb_copy(skb, HCI_MON_HDR_SIZE, GFP_ATOMIC);
+ skb_copy = __pskb_copy(skb, HCI_MON_HDR_SIZE,
+ GFP_ATOMIC);
if (!skb_copy)
continue;
@@ -495,7 +479,8 @@ static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
}
/* Ioctls that require bound socket */
-static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
+static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
+ unsigned long arg)
{
struct hci_dev *hdev = hci_pi(sk)->hdev;
@@ -540,7 +525,8 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
}
}
-static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
+ unsigned long arg)
{
struct sock *sk = sock->sk;
void __user *argp = (void __user *) arg;
@@ -601,7 +587,8 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long a
}
}
-static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
+static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
+ int addr_len)
{
struct sockaddr_hci haddr;
struct sock *sk = sock->sk;
@@ -690,7 +677,8 @@ done:
return err;
}
-static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer)
+static int hci_sock_getname(struct socket *sock, struct sockaddr *addr,
+ int *addr_len, int peer)
{
struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
struct sock *sk = sock->sk;
@@ -711,13 +699,15 @@ static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *add
return 0;
}
-static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
+static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg,
+ struct sk_buff *skb)
{
__u32 mask = hci_pi(sk)->cmsg_mask;
if (mask & HCI_CMSG_DIR) {
int incoming = bt_cb(skb)->incoming;
- put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), &incoming);
+ put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming),
+ &incoming);
}
if (mask & HCI_CMSG_TSTAMP) {
@@ -747,7 +737,7 @@ static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_
}
static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
- struct msghdr *msg, size_t len, int flags)
+ struct msghdr *msg, size_t len, int flags)
{
int noblock = flags & MSG_DONTWAIT;
struct sock *sk = sock->sk;
@@ -857,8 +847,9 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
u16 ocf = hci_opcode_ocf(opcode);
if (((ogf > HCI_SFLT_MAX_OGF) ||
- !hci_test_bit(ocf & HCI_FLT_OCF_BITS, &hci_sec_filter.ocf_mask[ogf])) &&
- !capable(CAP_NET_RAW)) {
+ !hci_test_bit(ocf & HCI_FLT_OCF_BITS,
+ &hci_sec_filter.ocf_mask[ogf])) &&
+ !capable(CAP_NET_RAW)) {
err = -EPERM;
goto drop;
}
@@ -891,7 +882,8 @@ drop:
goto done;
}
-static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int len)
+static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, unsigned int len)
{
struct hci_ufilter uf = { .opcode = 0 };
struct sock *sk = sock->sk;
@@ -973,7 +965,8 @@ done:
return err;
}
-static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
+static int hci_sock_getsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, int __user *optlen)
{
struct hci_ufilter uf;
struct sock *sk = sock->sk;
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 937f3187eafa..a20e61c3653d 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -1,10 +1,6 @@
/* Bluetooth HCI driver model support. */
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/init.h>
#include <linux/debugfs.h>
-#include <linux/seq_file.h>
#include <linux/module.h>
#include <net/bluetooth/bluetooth.h>
@@ -31,27 +27,30 @@ static inline char *link_typetostr(int type)
}
}
-static ssize_t show_link_type(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_link_type(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct hci_conn *conn = to_hci_conn(dev);
return sprintf(buf, "%s\n", link_typetostr(conn->type));
}
-static ssize_t show_link_address(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_link_address(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct hci_conn *conn = to_hci_conn(dev);
return sprintf(buf, "%s\n", batostr(&conn->dst));
}
-static ssize_t show_link_features(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_link_features(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct hci_conn *conn = to_hci_conn(dev);
return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
- conn->features[0], conn->features[1],
- conn->features[2], conn->features[3],
- conn->features[4], conn->features[5],
- conn->features[6], conn->features[7]);
+ conn->features[0], conn->features[1],
+ conn->features[2], conn->features[3],
+ conn->features[4], conn->features[5],
+ conn->features[6], conn->features[7]);
}
#define LINK_ATTR(_name, _mode, _show, _store) \
@@ -185,19 +184,22 @@ static inline char *host_typetostr(int type)
}
}
-static ssize_t show_bus(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_bus(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%s\n", host_bustostr(hdev->bus));
}
-static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_type(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%s\n", host_typetostr(hdev->dev_type));
}
-static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
char name[HCI_MAX_NAME_LENGTH + 1];
@@ -210,55 +212,64 @@ static ssize_t show_name(struct device *dev, struct device_attribute *attr, char
return sprintf(buf, "%s\n", name);
}
-static ssize_t show_class(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_class(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
- return sprintf(buf, "0x%.2x%.2x%.2x\n",
- hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
+ return sprintf(buf, "0x%.2x%.2x%.2x\n", hdev->dev_class[2],
+ hdev->dev_class[1], hdev->dev_class[0]);
}
-static ssize_t show_address(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_address(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%s\n", batostr(&hdev->bdaddr));
}
-static ssize_t show_features(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_features(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
- hdev->features[0], hdev->features[1],
- hdev->features[2], hdev->features[3],
- hdev->features[4], hdev->features[5],
- hdev->features[6], hdev->features[7]);
+ hdev->features[0], hdev->features[1],
+ hdev->features[2], hdev->features[3],
+ hdev->features[4], hdev->features[5],
+ hdev->features[6], hdev->features[7]);
}
-static ssize_t show_manufacturer(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_manufacturer(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%d\n", hdev->manufacturer);
}
-static ssize_t show_hci_version(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_hci_version(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%d\n", hdev->hci_ver);
}
-static ssize_t show_hci_revision(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_hci_revision(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%d\n", hdev->hci_rev);
}
-static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_idle_timeout(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%d\n", hdev->idle_timeout);
}
-static ssize_t store_idle_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t store_idle_timeout(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct hci_dev *hdev = to_hci_dev(dev);
unsigned int val;
@@ -276,13 +287,16 @@ static ssize_t store_idle_timeout(struct device *dev, struct device_attribute *a
return count;
}
-static ssize_t show_sniff_max_interval(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_sniff_max_interval(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%d\n", hdev->sniff_max_interval);
}
-static ssize_t store_sniff_max_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t store_sniff_max_interval(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct hci_dev *hdev = to_hci_dev(dev);
u16 val;
@@ -300,13 +314,16 @@ static ssize_t store_sniff_max_interval(struct device *dev, struct device_attrib
return count;
}
-static ssize_t show_sniff_min_interval(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_sniff_min_interval(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%d\n", hdev->sniff_min_interval);
}
-static ssize_t store_sniff_min_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t store_sniff_min_interval(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct hci_dev *hdev = to_hci_dev(dev);
u16 val;
@@ -335,11 +352,11 @@ static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL);
static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL);
static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR,
- show_idle_timeout, store_idle_timeout);
+ show_idle_timeout, store_idle_timeout);
static DEVICE_ATTR(sniff_max_interval, S_IRUGO | S_IWUSR,
- show_sniff_max_interval, store_sniff_max_interval);
+ show_sniff_max_interval, store_sniff_max_interval);
static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR,
- show_sniff_min_interval, store_sniff_min_interval);
+ show_sniff_min_interval, store_sniff_min_interval);
static struct attribute *bt_host_attrs[] = {
&dev_attr_bus.attr,
@@ -455,8 +472,8 @@ static void print_bt_uuid(struct seq_file *f, u8 *uuid)
memcpy(&data5, &uuid[14], 2);
seq_printf(f, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x\n",
- ntohl(data0), ntohs(data1), ntohs(data2),
- ntohs(data3), ntohl(data4), ntohs(data5));
+ ntohl(data0), ntohs(data1), ntohs(data2), ntohs(data3),
+ ntohl(data4), ntohs(data5));
}
static int uuids_show(struct seq_file *f, void *p)
@@ -513,7 +530,7 @@ static int auto_accept_delay_get(void *data, u64 *val)
}
DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get,
- auto_accept_delay_set, "%llu\n");
+ auto_accept_delay_set, "%llu\n");
void hci_init_sysfs(struct hci_dev *hdev)
{
@@ -547,15 +564,15 @@ int hci_add_sysfs(struct hci_dev *hdev)
return 0;
debugfs_create_file("inquiry_cache", 0444, hdev->debugfs,
- hdev, &inquiry_cache_fops);
+ hdev, &inquiry_cache_fops);
debugfs_create_file("blacklist", 0444, hdev->debugfs,
- hdev, &blacklist_fops);
+ hdev, &blacklist_fops);
debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
debugfs_create_file("auto_accept_delay", 0444, hdev->debugfs, hdev,
- &auto_accept_delay_fops);
+ &auto_accept_delay_fops);
return 0;
}
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 2c20d765b394..ccd985da6518 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -21,27 +21,8 @@
*/
#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/freezer.h>
-#include <linux/fcntl.h>
-#include <linux/skbuff.h>
-#include <linux/socket.h>
-#include <linux/ioctl.h>
#include <linux/file.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <linux/mutex.h>
#include <linux/kthread.h>
-#include <net/sock.h>
-
-#include <linux/input.h>
-#include <linux/hid.h>
#include <linux/hidraw.h>
#include <net/bluetooth/bluetooth.h>
@@ -244,7 +225,8 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
}
static int __hidp_send_ctrl_message(struct hidp_session *session,
- unsigned char hdr, unsigned char *data, int size)
+ unsigned char hdr, unsigned char *data,
+ int size)
{
struct sk_buff *skb;
@@ -268,7 +250,7 @@ static int __hidp_send_ctrl_message(struct hidp_session *session,
return 0;
}
-static inline int hidp_send_ctrl_message(struct hidp_session *session,
+static int hidp_send_ctrl_message(struct hidp_session *session,
unsigned char hdr, unsigned char *data, int size)
{
int err;
@@ -471,7 +453,7 @@ static void hidp_set_timer(struct hidp_session *session)
mod_timer(&session->timer, jiffies + HZ * session->idle_to);
}
-static inline void hidp_del_timer(struct hidp_session *session)
+static void hidp_del_timer(struct hidp_session *session)
{
if (session->idle_to > 0)
del_timer(&session->timer);
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index 73a32d705c1f..18b3f6892a36 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -20,22 +20,8 @@
SOFTWARE IS DISCLAIMED.
*/
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/capability.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/poll.h>
-#include <linux/fcntl.h>
-#include <linux/skbuff.h>
-#include <linux/socket.h>
-#include <linux/ioctl.h>
+#include <linux/export.h>
#include <linux/file.h>
-#include <linux/init.h>
-#include <linux/compat.h>
-#include <linux/gfp.h>
-#include <net/sock.h>
#include "hidp.h"
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 24f144b72a96..d42dfdc83ebb 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -30,32 +30,14 @@
#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/capability.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/socket.h>
-#include <linux/skbuff.h>
-#include <linux/list.h>
-#include <linux/device.h>
#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
#include <linux/crc16.h>
-#include <net/sock.h>
-
-#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/smp.h>
+#include <net/bluetooth/a2mp.h>
bool disable_ertm;
@@ -73,6 +55,9 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
static void l2cap_send_disconn_req(struct l2cap_conn *conn,
struct l2cap_chan *chan, int err);
+static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
+ struct sk_buff_head *skbs, u8 event);
+
/* ---- L2CAP channels ---- */
static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
@@ -196,7 +181,7 @@ static void __l2cap_state_change(struct l2cap_chan *chan, int state)
state_to_string(state));
chan->state = state;
- chan->ops->state_change(chan->data, state);
+ chan->ops->state_change(chan, state);
}
static void l2cap_state_change(struct l2cap_chan *chan, int state)
@@ -224,6 +209,37 @@ static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
release_sock(sk);
}
+static void __set_retrans_timer(struct l2cap_chan *chan)
+{
+ if (!delayed_work_pending(&chan->monitor_timer) &&
+ chan->retrans_timeout) {
+ l2cap_set_timer(chan, &chan->retrans_timer,
+ msecs_to_jiffies(chan->retrans_timeout));
+ }
+}
+
+static void __set_monitor_timer(struct l2cap_chan *chan)
+{
+ __clear_retrans_timer(chan);
+ if (chan->monitor_timeout) {
+ l2cap_set_timer(chan, &chan->monitor_timer,
+ msecs_to_jiffies(chan->monitor_timeout));
+ }
+}
+
+static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
+ u16 seq)
+{
+ struct sk_buff *skb;
+
+ skb_queue_walk(head, skb) {
+ if (bt_cb(skb)->control.txseq == seq)
+ return skb;
+ }
+
+ return NULL;
+}
+
/* ---- L2CAP sequence number lists ---- */
/* For ERTM, ordered lists of sequence numbers must be tracked for
@@ -366,7 +382,7 @@ static void l2cap_chan_timeout(struct work_struct *work)
l2cap_chan_unlock(chan);
- chan->ops->close(chan->data);
+ chan->ops->close(chan);
mutex_unlock(&conn->chan_lock);
l2cap_chan_put(chan);
@@ -392,6 +408,9 @@ struct l2cap_chan *l2cap_chan_create(void)
atomic_set(&chan->refcnt, 1);
+ /* This flag is cleared in l2cap_chan_ready() */
+ set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
+
BT_DBG("chan %p", chan);
return chan;
@@ -430,7 +449,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
case L2CAP_CHAN_CONN_ORIENTED:
if (conn->hcon->type == LE_LINK) {
/* LE connection */
- chan->omtu = L2CAP_LE_DEFAULT_MTU;
+ chan->omtu = L2CAP_DEFAULT_MTU;
chan->scid = L2CAP_CID_LE_DATA;
chan->dcid = L2CAP_CID_LE_DATA;
} else {
@@ -447,6 +466,13 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
chan->omtu = L2CAP_DEFAULT_MTU;
break;
+ case L2CAP_CHAN_CONN_FIX_A2MP:
+ chan->scid = L2CAP_CID_A2MP;
+ chan->dcid = L2CAP_CID_A2MP;
+ chan->omtu = L2CAP_A2MP_DEFAULT_MTU;
+ chan->imtu = L2CAP_A2MP_DEFAULT_MTU;
+ break;
+
default:
/* Raw socket can send/recv signalling messages only */
chan->scid = L2CAP_CID_SIGNALING;
@@ -466,18 +492,16 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
list_add(&chan->list, &conn->chan_l);
}
-static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
+void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
{
mutex_lock(&conn->chan_lock);
__l2cap_chan_add(conn, chan);
mutex_unlock(&conn->chan_lock);
}
-static void l2cap_chan_del(struct l2cap_chan *chan, int err)
+void l2cap_chan_del(struct l2cap_chan *chan, int err)
{
- struct sock *sk = chan->sk;
struct l2cap_conn *conn = chan->conn;
- struct sock *parent = bt_sk(sk)->parent;
__clear_chan_timer(chan);
@@ -490,34 +514,22 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err)
l2cap_chan_put(chan);
chan->conn = NULL;
- hci_conn_put(conn->hcon);
- }
-
- lock_sock(sk);
-
- __l2cap_state_change(chan, BT_CLOSED);
- sock_set_flag(sk, SOCK_ZAPPED);
-
- if (err)
- __l2cap_chan_set_err(chan, err);
- if (parent) {
- bt_accept_unlink(sk);
- parent->sk_data_ready(parent, 0);
- } else
- sk->sk_state_change(sk);
+ if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP)
+ hci_conn_put(conn->hcon);
+ }
- release_sock(sk);
+ if (chan->ops->teardown)
+ chan->ops->teardown(chan, err);
- if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
- test_bit(CONF_INPUT_DONE, &chan->conf_state)))
+ if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
return;
- skb_queue_purge(&chan->tx_q);
-
- if (chan->mode == L2CAP_MODE_ERTM) {
- struct srej_list *l, *tmp;
+ switch(chan->mode) {
+ case L2CAP_MODE_BASIC:
+ break;
+ case L2CAP_MODE_ERTM:
__clear_retrans_timer(chan);
__clear_monitor_timer(chan);
__clear_ack_timer(chan);
@@ -526,30 +538,15 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err)
l2cap_seq_list_free(&chan->srej_list);
l2cap_seq_list_free(&chan->retrans_list);
- list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
- list_del(&l->list);
- kfree(l);
- }
- }
-}
-
-static void l2cap_chan_cleanup_listen(struct sock *parent)
-{
- struct sock *sk;
-
- BT_DBG("parent %p", parent);
-
- /* Close not yet accepted channels */
- while ((sk = bt_accept_dequeue(parent, NULL))) {
- struct l2cap_chan *chan = l2cap_pi(sk)->chan;
- l2cap_chan_lock(chan);
- __clear_chan_timer(chan);
- l2cap_chan_close(chan, ECONNRESET);
- l2cap_chan_unlock(chan);
+ /* fall through */
- chan->ops->close(chan->data);
+ case L2CAP_MODE_STREAMING:
+ skb_queue_purge(&chan->tx_q);
+ break;
}
+
+ return;
}
void l2cap_chan_close(struct l2cap_chan *chan, int reason)
@@ -562,12 +559,8 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
switch (chan->state) {
case BT_LISTEN:
- lock_sock(sk);
- l2cap_chan_cleanup_listen(sk);
-
- __l2cap_state_change(chan, BT_CLOSED);
- sock_set_flag(sk, SOCK_ZAPPED);
- release_sock(sk);
+ if (chan->ops->teardown)
+ chan->ops->teardown(chan, 0);
break;
case BT_CONNECTED:
@@ -595,7 +588,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
rsp.scid = cpu_to_le16(chan->dcid);
rsp.dcid = cpu_to_le16(chan->scid);
rsp.result = cpu_to_le16(result);
- rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+ rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
sizeof(rsp), &rsp);
}
@@ -609,9 +602,8 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
break;
default:
- lock_sock(sk);
- sock_set_flag(sk, SOCK_ZAPPED);
- release_sock(sk);
+ if (chan->ops->teardown)
+ chan->ops->teardown(chan, 0);
break;
}
}
@@ -627,7 +619,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
default:
return HCI_AT_NO_BONDING;
}
- } else if (chan->psm == cpu_to_le16(0x0001)) {
+ } else if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) {
if (chan->sec_level == BT_SECURITY_LOW)
chan->sec_level = BT_SECURITY_SDP;
@@ -773,9 +765,11 @@ static inline void __unpack_control(struct l2cap_chan *chan,
if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
__unpack_extended_control(get_unaligned_le32(skb->data),
&bt_cb(skb)->control);
+ skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
} else {
__unpack_enhanced_control(get_unaligned_le16(skb->data),
&bt_cb(skb)->control);
+ skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
}
}
@@ -830,66 +824,102 @@ static inline void __pack_control(struct l2cap_chan *chan,
}
}
-static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
+static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan)
{
- struct sk_buff *skb;
- struct l2cap_hdr *lh;
- struct l2cap_conn *conn = chan->conn;
- int count, hlen;
-
- if (chan->state != BT_CONNECTED)
- return;
-
if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- hlen = L2CAP_EXT_HDR_SIZE;
+ return L2CAP_EXT_HDR_SIZE;
else
- hlen = L2CAP_ENH_HDR_SIZE;
+ return L2CAP_ENH_HDR_SIZE;
+}
+
+static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
+ u32 control)
+{
+ struct sk_buff *skb;
+ struct l2cap_hdr *lh;
+ int hlen = __ertm_hdr_size(chan);
if (chan->fcs == L2CAP_FCS_CRC16)
hlen += L2CAP_FCS_SIZE;
- BT_DBG("chan %p, control 0x%8.8x", chan, control);
+ skb = bt_skb_alloc(hlen, GFP_KERNEL);
- count = min_t(unsigned int, conn->mtu, hlen);
-
- control |= __set_sframe(chan);
-
- if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
- control |= __set_ctrl_final(chan);
-
- if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
- control |= __set_ctrl_poll(chan);
-
- skb = bt_skb_alloc(count, GFP_ATOMIC);
if (!skb)
- return;
+ return ERR_PTR(-ENOMEM);
lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
lh->cid = cpu_to_le16(chan->dcid);
- __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
+ else
+ put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
if (chan->fcs == L2CAP_FCS_CRC16) {
- u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
+ u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
}
skb->priority = HCI_PRIO_MAX;
- l2cap_do_send(chan, skb);
+ return skb;
}
-static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
+static void l2cap_send_sframe(struct l2cap_chan *chan,
+ struct l2cap_ctrl *control)
{
- if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
- control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
+ struct sk_buff *skb;
+ u32 control_field;
+
+ BT_DBG("chan %p, control %p", chan, control);
+
+ if (!control->sframe)
+ return;
+
+ if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
+ !control->poll)
+ control->final = 1;
+
+ if (control->super == L2CAP_SUPER_RR)
+ clear_bit(CONN_RNR_SENT, &chan->conn_state);
+ else if (control->super == L2CAP_SUPER_RNR)
set_bit(CONN_RNR_SENT, &chan->conn_state);
- } else
- control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
- control |= __set_reqseq(chan, chan->buffer_seq);
+ if (control->super != L2CAP_SUPER_SREJ) {
+ chan->last_acked_seq = control->reqseq;
+ __clear_ack_timer(chan);
+ }
+
+ BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
+ control->final, control->poll, control->super);
+
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ control_field = __pack_extended_control(control);
+ else
+ control_field = __pack_enhanced_control(control);
- l2cap_send_sframe(chan, control);
+ skb = l2cap_create_sframe_pdu(chan, control_field);
+ if (!IS_ERR(skb))
+ l2cap_do_send(chan, skb);
+}
+
+static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
+{
+ struct l2cap_ctrl control;
+
+ BT_DBG("chan %p, poll %d", chan, poll);
+
+ memset(&control, 0, sizeof(control));
+ control.sframe = 1;
+ control.poll = poll;
+
+ if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
+ control.super = L2CAP_SUPER_RNR;
+ else
+ control.super = L2CAP_SUPER_RR;
+
+ control.reqseq = chan->buffer_seq;
+ l2cap_send_sframe(chan, &control);
}
static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
@@ -914,25 +944,13 @@ static void l2cap_send_conn_req(struct l2cap_chan *chan)
static void l2cap_chan_ready(struct l2cap_chan *chan)
{
- struct sock *sk = chan->sk;
- struct sock *parent;
-
- lock_sock(sk);
-
- parent = bt_sk(sk)->parent;
-
- BT_DBG("sk %p, parent %p", sk, parent);
-
+ /* This clears all conf flags, including CONF_NOT_COMPLETE */
chan->conf_state = 0;
__clear_chan_timer(chan);
- __l2cap_state_change(chan, BT_CONNECTED);
- sk->sk_state_change(sk);
+ chan->state = BT_CONNECTED;
- if (parent)
- parent->sk_data_ready(parent, 0);
-
- release_sock(sk);
+ chan->ops->ready(chan);
}
static void l2cap_do_start(struct l2cap_chan *chan)
@@ -953,7 +971,7 @@ static void l2cap_do_start(struct l2cap_chan *chan)
l2cap_send_conn_req(chan);
} else {
struct l2cap_info_req req;
- req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
+ req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
conn->info_ident = l2cap_get_ident(conn);
@@ -995,6 +1013,11 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c
__clear_ack_timer(chan);
}
+ if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
+ __l2cap_state_change(chan, BT_DISCONN);
+ return;
+ }
+
req.dcid = cpu_to_le16(chan->dcid);
req.scid = cpu_to_le16(chan->scid);
l2cap_send_cmd(conn, l2cap_get_ident(conn),
@@ -1053,20 +1076,20 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
if (test_bit(BT_SK_DEFER_SETUP,
&bt_sk(sk)->flags)) {
struct sock *parent = bt_sk(sk)->parent;
- rsp.result = cpu_to_le16(L2CAP_CR_PEND);
- rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
+ rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
+ rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
if (parent)
parent->sk_data_ready(parent, 0);
} else {
__l2cap_state_change(chan, BT_CONFIG);
- rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
- rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+ rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
+ rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
}
release_sock(sk);
} else {
- rsp.result = cpu_to_le16(L2CAP_CR_PEND);
- rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
+ rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
+ rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
}
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
@@ -1150,13 +1173,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
lock_sock(parent);
- /* Check for backlog size */
- if (sk_acceptq_is_full(parent)) {
- BT_DBG("backlog full %d", parent->sk_ack_backlog);
- goto clean;
- }
-
- chan = pchan->ops->new_connection(pchan->data);
+ chan = pchan->ops->new_connection(pchan);
if (!chan)
goto clean;
@@ -1171,10 +1188,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
l2cap_chan_add(conn, chan);
- __set_chan_timer(chan, sk->sk_sndtimeo);
-
- __l2cap_state_change(chan, BT_CONNECTED);
- parent->sk_data_ready(parent, 0);
+ l2cap_chan_ready(chan);
clean:
release_sock(parent);
@@ -1198,6 +1212,11 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
l2cap_chan_lock(chan);
+ if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
+ l2cap_chan_unlock(chan);
+ continue;
+ }
+
if (conn->hcon->type == LE_LINK) {
if (smp_conn_security(conn, chan->sec_level))
l2cap_chan_ready(chan);
@@ -1270,7 +1289,7 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
l2cap_chan_unlock(chan);
- chan->ops->close(chan->data);
+ chan->ops->close(chan);
l2cap_chan_put(chan);
}
@@ -1295,7 +1314,12 @@ static void security_timeout(struct work_struct *work)
struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
security_timer.work);
- l2cap_conn_del(conn->hcon, ETIMEDOUT);
+ BT_DBG("conn %p", conn);
+
+ if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
+ smp_chan_destroy(conn);
+ l2cap_conn_del(conn->hcon, ETIMEDOUT);
+ }
}
static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
@@ -1439,21 +1463,17 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
goto done;
}
- lock_sock(sk);
-
- switch (sk->sk_state) {
+ switch (chan->state) {
case BT_CONNECT:
case BT_CONNECT2:
case BT_CONFIG:
/* Already connecting */
err = 0;
- release_sock(sk);
goto done;
case BT_CONNECTED:
/* Already connected */
err = -EISCONN;
- release_sock(sk);
goto done;
case BT_OPEN:
@@ -1463,13 +1483,12 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
default:
err = -EBADFD;
- release_sock(sk);
goto done;
}
/* Set destination address and psm */
+ lock_sock(sk);
bacpy(&bt_sk(sk)->dst, dst);
-
release_sock(sk);
chan->psm = psm;
@@ -1571,23 +1590,20 @@ int __l2cap_wait_ack(struct sock *sk)
static void l2cap_monitor_timeout(struct work_struct *work)
{
struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
- monitor_timer.work);
+ monitor_timer.work);
BT_DBG("chan %p", chan);
l2cap_chan_lock(chan);
- if (chan->retry_count >= chan->remote_max_tx) {
- l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
+ if (!chan->conn) {
l2cap_chan_unlock(chan);
l2cap_chan_put(chan);
return;
}
- chan->retry_count++;
- __set_monitor_timer(chan);
+ l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO);
- l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
l2cap_chan_unlock(chan);
l2cap_chan_put(chan);
}
@@ -1595,234 +1611,293 @@ static void l2cap_monitor_timeout(struct work_struct *work)
static void l2cap_retrans_timeout(struct work_struct *work)
{
struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
- retrans_timer.work);
+ retrans_timer.work);
BT_DBG("chan %p", chan);
l2cap_chan_lock(chan);
- chan->retry_count = 1;
- __set_monitor_timer(chan);
-
- set_bit(CONN_WAIT_F, &chan->conn_state);
-
- l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
+ if (!chan->conn) {
+ l2cap_chan_unlock(chan);
+ l2cap_chan_put(chan);
+ return;
+ }
+ l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO);
l2cap_chan_unlock(chan);
l2cap_chan_put(chan);
}
-static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
+static void l2cap_streaming_send(struct l2cap_chan *chan,
+ struct sk_buff_head *skbs)
{
struct sk_buff *skb;
+ struct l2cap_ctrl *control;
- while ((skb = skb_peek(&chan->tx_q)) &&
- chan->unacked_frames) {
- if (bt_cb(skb)->control.txseq == chan->expected_ack_seq)
- break;
+ BT_DBG("chan %p, skbs %p", chan, skbs);
- skb = skb_dequeue(&chan->tx_q);
- kfree_skb(skb);
+ skb_queue_splice_tail_init(skbs, &chan->tx_q);
- chan->unacked_frames--;
- }
+ while (!skb_queue_empty(&chan->tx_q)) {
- if (!chan->unacked_frames)
- __clear_retrans_timer(chan);
-}
+ skb = skb_dequeue(&chan->tx_q);
-static void l2cap_streaming_send(struct l2cap_chan *chan)
-{
- struct sk_buff *skb;
- u32 control;
- u16 fcs;
+ bt_cb(skb)->control.retries = 1;
+ control = &bt_cb(skb)->control;
+
+ control->reqseq = 0;
+ control->txseq = chan->next_tx_seq;
- while ((skb = skb_dequeue(&chan->tx_q))) {
- control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
- control |= __set_txseq(chan, chan->next_tx_seq);
- control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
- __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
+ __pack_control(chan, control, skb);
if (chan->fcs == L2CAP_FCS_CRC16) {
- fcs = crc16(0, (u8 *)skb->data,
- skb->len - L2CAP_FCS_SIZE);
- put_unaligned_le16(fcs,
- skb->data + skb->len - L2CAP_FCS_SIZE);
+ u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
+ put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
}
l2cap_do_send(chan, skb);
+ BT_DBG("Sent txseq %d", (int)control->txseq);
+
chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
+ chan->frames_sent++;
}
}
-static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
+static int l2cap_ertm_send(struct l2cap_chan *chan)
{
struct sk_buff *skb, *tx_skb;
- u16 fcs;
- u32 control;
+ struct l2cap_ctrl *control;
+ int sent = 0;
- skb = skb_peek(&chan->tx_q);
- if (!skb)
- return;
+ BT_DBG("chan %p", chan);
- while (bt_cb(skb)->control.txseq != tx_seq) {
- if (skb_queue_is_last(&chan->tx_q, skb))
- return;
+ if (chan->state != BT_CONNECTED)
+ return -ENOTCONN;
- skb = skb_queue_next(&chan->tx_q, skb);
- }
+ if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
+ return 0;
- if (bt_cb(skb)->control.retries == chan->remote_max_tx &&
- chan->remote_max_tx) {
- l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
- return;
- }
+ while (chan->tx_send_head &&
+ chan->unacked_frames < chan->remote_tx_win &&
+ chan->tx_state == L2CAP_TX_STATE_XMIT) {
- tx_skb = skb_clone(skb, GFP_ATOMIC);
- bt_cb(skb)->control.retries++;
+ skb = chan->tx_send_head;
- control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
- control &= __get_sar_mask(chan);
+ bt_cb(skb)->control.retries = 1;
+ control = &bt_cb(skb)->control;
- if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
- control |= __set_ctrl_final(chan);
+ if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
+ control->final = 1;
- control |= __set_reqseq(chan, chan->buffer_seq);
- control |= __set_txseq(chan, tx_seq);
+ control->reqseq = chan->buffer_seq;
+ chan->last_acked_seq = chan->buffer_seq;
+ control->txseq = chan->next_tx_seq;
- __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
+ __pack_control(chan, control, skb);
- if (chan->fcs == L2CAP_FCS_CRC16) {
- fcs = crc16(0, (u8 *)tx_skb->data,
- tx_skb->len - L2CAP_FCS_SIZE);
- put_unaligned_le16(fcs,
- tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
+ if (chan->fcs == L2CAP_FCS_CRC16) {
+ u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
+ put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
+ }
+
+ /* Clone after data has been modified. Data is assumed to be
+ read-only (for locking purposes) on cloned sk_buffs.
+ */
+ tx_skb = skb_clone(skb, GFP_KERNEL);
+
+ if (!tx_skb)
+ break;
+
+ __set_retrans_timer(chan);
+
+ chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
+ chan->unacked_frames++;
+ chan->frames_sent++;
+ sent++;
+
+ if (skb_queue_is_last(&chan->tx_q, skb))
+ chan->tx_send_head = NULL;
+ else
+ chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
+
+ l2cap_do_send(chan, tx_skb);
+ BT_DBG("Sent txseq %d", (int)control->txseq);
}
- l2cap_do_send(chan, tx_skb);
+ BT_DBG("Sent %d, %d unacked, %d in ERTM queue", sent,
+ (int) chan->unacked_frames, skb_queue_len(&chan->tx_q));
+
+ return sent;
}
-static int l2cap_ertm_send(struct l2cap_chan *chan)
+static void l2cap_ertm_resend(struct l2cap_chan *chan)
{
- struct sk_buff *skb, *tx_skb;
- u16 fcs;
- u32 control;
- int nsent = 0;
+ struct l2cap_ctrl control;
+ struct sk_buff *skb;
+ struct sk_buff *tx_skb;
+ u16 seq;
- if (chan->state != BT_CONNECTED)
- return -ENOTCONN;
+ BT_DBG("chan %p", chan);
if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
- return 0;
+ return;
- while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
+ while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
+ seq = l2cap_seq_list_pop(&chan->retrans_list);
- if (bt_cb(skb)->control.retries == chan->remote_max_tx &&
- chan->remote_max_tx) {
- l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
- break;
+ skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
+ if (!skb) {
+ BT_DBG("Error: Can't retransmit seq %d, frame missing",
+ seq);
+ continue;
}
- tx_skb = skb_clone(skb, GFP_ATOMIC);
-
bt_cb(skb)->control.retries++;
+ control = bt_cb(skb)->control;
- control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
- control &= __get_sar_mask(chan);
+ if (chan->max_tx != 0 &&
+ bt_cb(skb)->control.retries > chan->max_tx) {
+ BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
+ l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ l2cap_seq_list_clear(&chan->retrans_list);
+ break;
+ }
+ control.reqseq = chan->buffer_seq;
if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
- control |= __set_ctrl_final(chan);
+ control.final = 1;
+ else
+ control.final = 0;
+
+ if (skb_cloned(skb)) {
+ /* Cloned sk_buffs are read-only, so we need a
+ * writeable copy
+ */
+ tx_skb = skb_copy(skb, GFP_ATOMIC);
+ } else {
+ tx_skb = skb_clone(skb, GFP_ATOMIC);
+ }
- control |= __set_reqseq(chan, chan->buffer_seq);
- control |= __set_txseq(chan, chan->next_tx_seq);
- control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
+ if (!tx_skb) {
+ l2cap_seq_list_clear(&chan->retrans_list);
+ break;
+ }
- __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
+ /* Update skb contents */
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
+ put_unaligned_le32(__pack_extended_control(&control),
+ tx_skb->data + L2CAP_HDR_SIZE);
+ } else {
+ put_unaligned_le16(__pack_enhanced_control(&control),
+ tx_skb->data + L2CAP_HDR_SIZE);
+ }
if (chan->fcs == L2CAP_FCS_CRC16) {
- fcs = crc16(0, (u8 *)skb->data,
- tx_skb->len - L2CAP_FCS_SIZE);
- put_unaligned_le16(fcs, skb->data +
- tx_skb->len - L2CAP_FCS_SIZE);
+ u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len);
+ put_unaligned_le16(fcs, skb_put(tx_skb,
+ L2CAP_FCS_SIZE));
}
l2cap_do_send(chan, tx_skb);
- __set_retrans_timer(chan);
-
- bt_cb(skb)->control.txseq = chan->next_tx_seq;
+ BT_DBG("Resent txseq %d", control.txseq);
- chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
-
- if (bt_cb(skb)->control.retries == 1) {
- chan->unacked_frames++;
-
- if (!nsent++)
- __clear_ack_timer(chan);
- }
-
- chan->frames_sent++;
-
- if (skb_queue_is_last(&chan->tx_q, skb))
- chan->tx_send_head = NULL;
- else
- chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
+ chan->last_acked_seq = chan->buffer_seq;
}
-
- return nsent;
}
-static int l2cap_retransmit_frames(struct l2cap_chan *chan)
+static void l2cap_retransmit(struct l2cap_chan *chan,
+ struct l2cap_ctrl *control)
{
- int ret;
+ BT_DBG("chan %p, control %p", chan, control);
- if (!skb_queue_empty(&chan->tx_q))
- chan->tx_send_head = chan->tx_q.next;
-
- chan->next_tx_seq = chan->expected_ack_seq;
- ret = l2cap_ertm_send(chan);
- return ret;
+ l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
+ l2cap_ertm_resend(chan);
}
-static void __l2cap_send_ack(struct l2cap_chan *chan)
+static void l2cap_retransmit_all(struct l2cap_chan *chan,
+ struct l2cap_ctrl *control)
{
- u32 control = 0;
+ struct sk_buff *skb;
- control |= __set_reqseq(chan, chan->buffer_seq);
+ BT_DBG("chan %p, control %p", chan, control);
- if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
- control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
- set_bit(CONN_RNR_SENT, &chan->conn_state);
- l2cap_send_sframe(chan, control);
- return;
- }
+ if (control->poll)
+ set_bit(CONN_SEND_FBIT, &chan->conn_state);
+
+ l2cap_seq_list_clear(&chan->retrans_list);
- if (l2cap_ertm_send(chan) > 0)
+ if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
return;
- control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
- l2cap_send_sframe(chan, control);
+ if (chan->unacked_frames) {
+ skb_queue_walk(&chan->tx_q, skb) {
+ if (bt_cb(skb)->control.txseq == control->reqseq ||
+ skb == chan->tx_send_head)
+ break;
+ }
+
+ skb_queue_walk_from(&chan->tx_q, skb) {
+ if (skb == chan->tx_send_head)
+ break;
+
+ l2cap_seq_list_append(&chan->retrans_list,
+ bt_cb(skb)->control.txseq);
+ }
+
+ l2cap_ertm_resend(chan);
+ }
}
static void l2cap_send_ack(struct l2cap_chan *chan)
{
- __clear_ack_timer(chan);
- __l2cap_send_ack(chan);
-}
+ struct l2cap_ctrl control;
+ u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
+ chan->last_acked_seq);
+ int threshold;
-static void l2cap_send_srejtail(struct l2cap_chan *chan)
-{
- struct srej_list *tail;
- u32 control;
+ BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
+ chan, chan->last_acked_seq, chan->buffer_seq);
- control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
- control |= __set_ctrl_final(chan);
+ memset(&control, 0, sizeof(control));
+ control.sframe = 1;
- tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
- control |= __set_reqseq(chan, tail->tx_seq);
+ if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
+ chan->rx_state == L2CAP_RX_STATE_RECV) {
+ __clear_ack_timer(chan);
+ control.super = L2CAP_SUPER_RNR;
+ control.reqseq = chan->buffer_seq;
+ l2cap_send_sframe(chan, &control);
+ } else {
+ if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
+ l2cap_ertm_send(chan);
+ /* If any i-frames were sent, they included an ack */
+ if (chan->buffer_seq == chan->last_acked_seq)
+ frames_to_ack = 0;
+ }
- l2cap_send_sframe(chan, control);
+ /* Ack now if the tx window is 3/4ths full.
+ * Calculate without mul or div
+ */
+ threshold = chan->tx_win;
+ threshold += threshold << 1;
+ threshold >>= 2;
+
+ BT_DBG("frames_to_ack %d, threshold %d", (int)frames_to_ack,
+ threshold);
+
+ if (frames_to_ack >= threshold) {
+ __clear_ack_timer(chan);
+ control.super = L2CAP_SUPER_RR;
+ control.reqseq = chan->buffer_seq;
+ l2cap_send_sframe(chan, &control);
+ frames_to_ack = 0;
+ }
+
+ if (frames_to_ack)
+ __set_ack_timer(chan);
+ }
}
static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
@@ -1951,10 +2026,7 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
if (!conn)
return ERR_PTR(-ENOTCONN);
- if (test_bit(FLAG_EXT_CTRL, &chan->flags))
- hlen = L2CAP_EXT_HDR_SIZE;
- else
- hlen = L2CAP_ENH_HDR_SIZE;
+ hlen = __ertm_hdr_size(chan);
if (sdulen)
hlen += L2CAP_SDULEN_SIZE;
@@ -1974,7 +2046,11 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
lh->cid = cpu_to_le16(chan->dcid);
lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
- __put_control(chan, 0, skb_put(skb, __ctrl_size(chan)));
+ /* Control header is populated later */
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
+ else
+ put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
if (sdulen)
put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
@@ -1985,9 +2061,7 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
return ERR_PTR(err);
}
- if (chan->fcs == L2CAP_FCS_CRC16)
- put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
-
+ bt_cb(skb)->control.fcs = chan->fcs;
bt_cb(skb)->control.retries = 0;
return skb;
}
@@ -1999,7 +2073,6 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan,
struct sk_buff *skb;
u16 sdu_len;
size_t pdu_len;
- int err = 0;
u8 sar;
BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len);
@@ -2015,7 +2088,10 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan,
pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
/* Adjust for largest possible L2CAP overhead. */
- pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE;
+ if (chan->fcs)
+ pdu_len -= L2CAP_FCS_SIZE;
+
+ pdu_len -= __ertm_hdr_size(chan);
/* Remote device may have requested smaller PDUs */
pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
@@ -2055,7 +2131,7 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan,
}
}
- return err;
+ return 0;
}
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
@@ -2117,17 +2193,12 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
if (err)
break;
- if (chan->mode == L2CAP_MODE_ERTM && chan->tx_send_head == NULL)
- chan->tx_send_head = seg_queue.next;
- skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
-
if (chan->mode == L2CAP_MODE_ERTM)
- err = l2cap_ertm_send(chan);
+ l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
else
- l2cap_streaming_send(chan);
+ l2cap_streaming_send(chan, &seg_queue);
- if (err >= 0)
- err = len;
+ err = len;
/* If the skbs were not queued for sending, they'll still be in
* seg_queue and need to be purged.
@@ -2143,6 +2214,296 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
return err;
}
+static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
+{
+ struct l2cap_ctrl control;
+ u16 seq;
+
+ BT_DBG("chan %p, txseq %d", chan, txseq);
+
+ memset(&control, 0, sizeof(control));
+ control.sframe = 1;
+ control.super = L2CAP_SUPER_SREJ;
+
+ for (seq = chan->expected_tx_seq; seq != txseq;
+ seq = __next_seq(chan, seq)) {
+ if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
+ control.reqseq = seq;
+ l2cap_send_sframe(chan, &control);
+ l2cap_seq_list_append(&chan->srej_list, seq);
+ }
+ }
+
+ chan->expected_tx_seq = __next_seq(chan, txseq);
+}
+
+static void l2cap_send_srej_tail(struct l2cap_chan *chan)
+{
+ struct l2cap_ctrl control;
+
+ BT_DBG("chan %p", chan);
+
+ if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
+ return;
+
+ memset(&control, 0, sizeof(control));
+ control.sframe = 1;
+ control.super = L2CAP_SUPER_SREJ;
+ control.reqseq = chan->srej_list.tail;
+ l2cap_send_sframe(chan, &control);
+}
+
+static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
+{
+ struct l2cap_ctrl control;
+ u16 initial_head;
+ u16 seq;
+
+ BT_DBG("chan %p, txseq %d", chan, txseq);
+
+ memset(&control, 0, sizeof(control));
+ control.sframe = 1;
+ control.super = L2CAP_SUPER_SREJ;
+
+ /* Capture initial list head to allow only one pass through the list. */
+ initial_head = chan->srej_list.head;
+
+ do {
+ seq = l2cap_seq_list_pop(&chan->srej_list);
+ if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
+ break;
+
+ control.reqseq = seq;
+ l2cap_send_sframe(chan, &control);
+ l2cap_seq_list_append(&chan->srej_list, seq);
+ } while (chan->srej_list.head != initial_head);
+}
+
+static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
+{
+ struct sk_buff *acked_skb;
+ u16 ackseq;
+
+ BT_DBG("chan %p, reqseq %d", chan, reqseq);
+
+ if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
+ return;
+
+ BT_DBG("expected_ack_seq %d, unacked_frames %d",
+ chan->expected_ack_seq, chan->unacked_frames);
+
+ for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
+ ackseq = __next_seq(chan, ackseq)) {
+
+ acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
+ if (acked_skb) {
+ skb_unlink(acked_skb, &chan->tx_q);
+ kfree_skb(acked_skb);
+ chan->unacked_frames--;
+ }
+ }
+
+ chan->expected_ack_seq = reqseq;
+
+ if (chan->unacked_frames == 0)
+ __clear_retrans_timer(chan);
+
+ BT_DBG("unacked_frames %d", (int) chan->unacked_frames);
+}
+
+static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
+{
+ BT_DBG("chan %p", chan);
+
+ chan->expected_tx_seq = chan->buffer_seq;
+ l2cap_seq_list_clear(&chan->srej_list);
+ skb_queue_purge(&chan->srej_q);
+ chan->rx_state = L2CAP_RX_STATE_RECV;
+}
+
+static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
+ struct l2cap_ctrl *control,
+ struct sk_buff_head *skbs, u8 event)
+{
+ BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
+ event);
+
+ switch (event) {
+ case L2CAP_EV_DATA_REQUEST:
+ if (chan->tx_send_head == NULL)
+ chan->tx_send_head = skb_peek(skbs);
+
+ skb_queue_splice_tail_init(skbs, &chan->tx_q);
+ l2cap_ertm_send(chan);
+ break;
+ case L2CAP_EV_LOCAL_BUSY_DETECTED:
+ BT_DBG("Enter LOCAL_BUSY");
+ set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
+
+ if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
+ /* The SREJ_SENT state must be aborted if we are to
+ * enter the LOCAL_BUSY state.
+ */
+ l2cap_abort_rx_srej_sent(chan);
+ }
+
+ l2cap_send_ack(chan);
+
+ break;
+ case L2CAP_EV_LOCAL_BUSY_CLEAR:
+ BT_DBG("Exit LOCAL_BUSY");
+ clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
+
+ if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
+ struct l2cap_ctrl local_control;
+
+ memset(&local_control, 0, sizeof(local_control));
+ local_control.sframe = 1;
+ local_control.super = L2CAP_SUPER_RR;
+ local_control.poll = 1;
+ local_control.reqseq = chan->buffer_seq;
+ l2cap_send_sframe(chan, &local_control);
+
+ chan->retry_count = 1;
+ __set_monitor_timer(chan);
+ chan->tx_state = L2CAP_TX_STATE_WAIT_F;
+ }
+ break;
+ case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
+ l2cap_process_reqseq(chan, control->reqseq);
+ break;
+ case L2CAP_EV_EXPLICIT_POLL:
+ l2cap_send_rr_or_rnr(chan, 1);
+ chan->retry_count = 1;
+ __set_monitor_timer(chan);
+ __clear_ack_timer(chan);
+ chan->tx_state = L2CAP_TX_STATE_WAIT_F;
+ break;
+ case L2CAP_EV_RETRANS_TO:
+ l2cap_send_rr_or_rnr(chan, 1);
+ chan->retry_count = 1;
+ __set_monitor_timer(chan);
+ chan->tx_state = L2CAP_TX_STATE_WAIT_F;
+ break;
+ case L2CAP_EV_RECV_FBIT:
+ /* Nothing to process */
+ break;
+ default:
+ break;
+ }
+}
+
+static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
+ struct l2cap_ctrl *control,
+ struct sk_buff_head *skbs, u8 event)
+{
+ BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
+ event);
+
+ switch (event) {
+ case L2CAP_EV_DATA_REQUEST:
+ if (chan->tx_send_head == NULL)
+ chan->tx_send_head = skb_peek(skbs);
+ /* Queue data, but don't send. */
+ skb_queue_splice_tail_init(skbs, &chan->tx_q);
+ break;
+ case L2CAP_EV_LOCAL_BUSY_DETECTED:
+ BT_DBG("Enter LOCAL_BUSY");
+ set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
+
+ if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
+ /* The SREJ_SENT state must be aborted if we are to
+ * enter the LOCAL_BUSY state.
+ */
+ l2cap_abort_rx_srej_sent(chan);
+ }
+
+ l2cap_send_ack(chan);
+
+ break;
+ case L2CAP_EV_LOCAL_BUSY_CLEAR:
+ BT_DBG("Exit LOCAL_BUSY");
+ clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
+
+ if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
+ struct l2cap_ctrl local_control;
+ memset(&local_control, 0, sizeof(local_control));
+ local_control.sframe = 1;
+ local_control.super = L2CAP_SUPER_RR;
+ local_control.poll = 1;
+ local_control.reqseq = chan->buffer_seq;
+ l2cap_send_sframe(chan, &local_control);
+
+ chan->retry_count = 1;
+ __set_monitor_timer(chan);
+ chan->tx_state = L2CAP_TX_STATE_WAIT_F;
+ }
+ break;
+ case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
+ l2cap_process_reqseq(chan, control->reqseq);
+
+ /* Fall through */
+
+ case L2CAP_EV_RECV_FBIT:
+ if (control && control->final) {
+ __clear_monitor_timer(chan);
+ if (chan->unacked_frames > 0)
+ __set_retrans_timer(chan);
+ chan->retry_count = 0;
+ chan->tx_state = L2CAP_TX_STATE_XMIT;
+ BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
+ }
+ break;
+ case L2CAP_EV_EXPLICIT_POLL:
+ /* Ignore */
+ break;
+ case L2CAP_EV_MONITOR_TO:
+ if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
+ l2cap_send_rr_or_rnr(chan, 1);
+ __set_monitor_timer(chan);
+ chan->retry_count++;
+ } else {
+ l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
+ struct sk_buff_head *skbs, u8 event)
+{
+ BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
+ chan, control, skbs, event, chan->tx_state);
+
+ switch (chan->tx_state) {
+ case L2CAP_TX_STATE_XMIT:
+ l2cap_tx_state_xmit(chan, control, skbs, event);
+ break;
+ case L2CAP_TX_STATE_WAIT_F:
+ l2cap_tx_state_wait_f(chan, control, skbs, event);
+ break;
+ default:
+ /* Ignore event */
+ break;
+ }
+}
+
+static void l2cap_pass_to_tx(struct l2cap_chan *chan,
+ struct l2cap_ctrl *control)
+{
+ BT_DBG("chan %p, control %p", chan, control);
+ l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
+}
+
+static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
+ struct l2cap_ctrl *control)
+{
+ BT_DBG("chan %p, control %p", chan, control);
+ l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT);
+}
+
/* Copy frame to all raw sockets on that connection */
static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
{
@@ -2165,7 +2526,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
if (!nskb)
continue;
- if (chan->ops->recv(chan->data, nskb))
+ if (chan->ops->recv(chan, nskb))
kfree_skb(nskb);
}
@@ -2195,9 +2556,9 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
if (conn->hcon->type == LE_LINK)
- lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
+ lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING);
else
- lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
+ lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING);
cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
cmd->code = code;
@@ -2309,8 +2670,8 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
efs.stype = chan->local_stype;
efs.msdu = cpu_to_le16(chan->local_msdu);
efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
- efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
- efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
+ efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
+ efs.flush_to = __constant_cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
break;
case L2CAP_MODE_STREAMING:
@@ -2333,20 +2694,24 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
static void l2cap_ack_timeout(struct work_struct *work)
{
struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
- ack_timer.work);
+ ack_timer.work);
+ u16 frames_to_ack;
BT_DBG("chan %p", chan);
l2cap_chan_lock(chan);
- __l2cap_send_ack(chan);
+ frames_to_ack = __seq_offset(chan, chan->buffer_seq,
+ chan->last_acked_seq);
- l2cap_chan_unlock(chan);
+ if (frames_to_ack)
+ l2cap_send_rr_or_rnr(chan, 0);
+ l2cap_chan_unlock(chan);
l2cap_chan_put(chan);
}
-static inline int l2cap_ertm_init(struct l2cap_chan *chan)
+int l2cap_ertm_init(struct l2cap_chan *chan)
{
int err;
@@ -2355,7 +2720,6 @@ static inline int l2cap_ertm_init(struct l2cap_chan *chan)
chan->expected_ack_seq = 0;
chan->unacked_frames = 0;
chan->buffer_seq = 0;
- chan->num_acked = 0;
chan->frames_sent = 0;
chan->last_acked_seq = 0;
chan->sdu = NULL;
@@ -2376,12 +2740,15 @@ static inline int l2cap_ertm_init(struct l2cap_chan *chan)
skb_queue_head_init(&chan->srej_q);
- INIT_LIST_HEAD(&chan->srej_l);
err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
if (err < 0)
return err;
- return l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
+ err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
+ if (err < 0)
+ l2cap_seq_list_free(&chan->srej_list);
+
+ return err;
}
static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
@@ -2507,6 +2874,7 @@ done:
break;
case L2CAP_MODE_STREAMING:
+ l2cap_txwin_setup(chan);
rfc.mode = L2CAP_MODE_STREAMING;
rfc.txwin_size = 0;
rfc.max_transmit = 0;
@@ -2537,7 +2905,7 @@ done:
}
req->dcid = cpu_to_le16(chan->dcid);
- req->flags = cpu_to_le16(0);
+ req->flags = __constant_cpu_to_le16(0);
return ptr - data;
}
@@ -2757,7 +3125,7 @@ done:
}
rsp->scid = cpu_to_le16(chan->dcid);
rsp->result = cpu_to_le16(result);
- rsp->flags = cpu_to_le16(0x0000);
+ rsp->flags = __constant_cpu_to_le16(0);
return ptr - data;
}
@@ -2856,7 +3224,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
}
req->dcid = cpu_to_le16(chan->dcid);
- req->flags = cpu_to_le16(0x0000);
+ req->flags = __constant_cpu_to_le16(0);
return ptr - data;
}
@@ -2883,8 +3251,8 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
rsp.scid = cpu_to_le16(chan->dcid);
rsp.dcid = cpu_to_le16(chan->scid);
- rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
- rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+ rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
+ rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
l2cap_send_cmd(conn, chan->ident,
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
@@ -2910,20 +3278,22 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
while (len >= L2CAP_CONF_OPT_SIZE) {
len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
- switch (type) {
- case L2CAP_CONF_RFC:
- if (olen == sizeof(rfc))
- memcpy(&rfc, (void *)val, olen);
- goto done;
- }
+ if (type != L2CAP_CONF_RFC)
+ continue;
+
+ if (olen != sizeof(rfc))
+ break;
+
+ memcpy(&rfc, (void *)val, olen);
+ goto done;
}
/* Use sane default values in case a misbehaving remote device
* did not send an RFC option.
*/
rfc.mode = chan->mode;
- rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
- rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+ rfc.retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
+ rfc.monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
rfc.max_pdu_size = cpu_to_le16(chan->imtu);
BT_ERR("Expected RFC option was not found, using defaults");
@@ -2986,7 +3356,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
lock_sock(parent);
/* Check if the ACL is secure enough (if not SDP) */
- if (psm != cpu_to_le16(0x0001) &&
+ if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
!hci_conn_check_link_mode(conn->hcon)) {
conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
result = L2CAP_CR_SEC_BLOCK;
@@ -2995,25 +3365,16 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
result = L2CAP_CR_NO_MEM;
- /* Check for backlog size */
- if (sk_acceptq_is_full(parent)) {
- BT_DBG("backlog full %d", parent->sk_ack_backlog);
+ /* Check if we already have channel with that dcid */
+ if (__l2cap_get_chan_by_dcid(conn, scid))
goto response;
- }
- chan = pchan->ops->new_connection(pchan->data);
+ chan = pchan->ops->new_connection(pchan);
if (!chan)
goto response;
sk = chan->sk;
- /* Check if we already have channel with that dcid */
- if (__l2cap_get_chan_by_dcid(conn, scid)) {
- sock_set_flag(sk, SOCK_ZAPPED);
- chan->ops->close(chan->data);
- goto response;
- }
-
hci_conn_hold(conn->hcon);
bacpy(&bt_sk(sk)->src, conn->src);
@@ -3067,7 +3428,7 @@ sendresp:
if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
struct l2cap_info_req info;
- info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
+ info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
conn->info_ident = l2cap_get_ident(conn);
@@ -3189,7 +3550,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
struct l2cap_cmd_rej_cid rej;
- rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
+ rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
rej.scid = cpu_to_le16(chan->scid);
rej.dcid = cpu_to_le16(chan->dcid);
@@ -3211,11 +3572,11 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
memcpy(chan->conf_req + chan->conf_len, req->data, len);
chan->conf_len += len;
- if (flags & 0x0001) {
+ if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
/* Incomplete config. Send empty response. */
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
l2cap_build_conf_rsp(chan, rsp,
- L2CAP_CONF_SUCCESS, 0x0001), rsp);
+ L2CAP_CONF_SUCCESS, flags), rsp);
goto unlock;
}
@@ -3238,8 +3599,6 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
set_default_fcs(chan);
- l2cap_state_change(chan, BT_CONNECTED);
-
if (chan->mode == L2CAP_MODE_ERTM ||
chan->mode == L2CAP_MODE_STREAMING)
err = l2cap_ertm_init(chan);
@@ -3271,7 +3630,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
l2cap_build_conf_rsp(chan, rsp,
- L2CAP_CONF_SUCCESS, 0x0000), rsp);
+ L2CAP_CONF_SUCCESS, flags), rsp);
}
unlock:
@@ -3362,7 +3721,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
goto done;
}
- if (flags & 0x01)
+ if (flags & L2CAP_CONF_FLAG_CONTINUATION)
goto done;
set_bit(CONF_INPUT_DONE, &chan->conf_state);
@@ -3370,7 +3729,6 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
set_default_fcs(chan);
- l2cap_state_change(chan, BT_CONNECTED);
if (chan->mode == L2CAP_MODE_ERTM ||
chan->mode == L2CAP_MODE_STREAMING)
err = l2cap_ertm_init(chan);
@@ -3424,7 +3782,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
l2cap_chan_unlock(chan);
- chan->ops->close(chan->data);
+ chan->ops->close(chan);
l2cap_chan_put(chan);
mutex_unlock(&conn->chan_lock);
@@ -3458,7 +3816,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
l2cap_chan_unlock(chan);
- chan->ops->close(chan->data);
+ chan->ops->close(chan);
l2cap_chan_put(chan);
mutex_unlock(&conn->chan_lock);
@@ -3479,8 +3837,8 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm
u8 buf[8];
u32 feat_mask = l2cap_feat_mask;
struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
- rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
- rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
+ rsp->type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
+ rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
if (!disable_ertm)
feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
| L2CAP_FEAT_FCS;
@@ -3500,15 +3858,15 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm
else
l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
- rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
- rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
+ rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
+ rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
l2cap_send_cmd(conn, cmd->ident,
L2CAP_INFO_RSP, sizeof(buf), buf);
} else {
struct l2cap_info_rsp rsp;
rsp.type = cpu_to_le16(type);
- rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
+ rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP);
l2cap_send_cmd(conn, cmd->ident,
L2CAP_INFO_RSP, sizeof(rsp), &rsp);
}
@@ -3548,7 +3906,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
struct l2cap_info_req req;
- req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
+ req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
conn->info_ident = l2cap_get_ident(conn);
@@ -3783,9 +4141,9 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
err = l2cap_check_conn_param(min, max, latency, to_multiplier);
if (err)
- rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
+ rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
else
- rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
+ rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
sizeof(rsp), &rsp);
@@ -3933,7 +4291,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
BT_ERR("Wrong link type (%d)", err);
/* FIXME: Map err to a valid reason */
- rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
+ rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
}
@@ -3965,65 +4323,38 @@ static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
return 0;
}
-static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
+static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
{
- u32 control = 0;
+ struct l2cap_ctrl control;
- chan->frames_sent = 0;
+ BT_DBG("chan %p", chan);
- control |= __set_reqseq(chan, chan->buffer_seq);
+ memset(&control, 0, sizeof(control));
+ control.sframe = 1;
+ control.final = 1;
+ control.reqseq = chan->buffer_seq;
+ set_bit(CONN_SEND_FBIT, &chan->conn_state);
if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
- control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
- l2cap_send_sframe(chan, control);
- set_bit(CONN_RNR_SENT, &chan->conn_state);
+ control.super = L2CAP_SUPER_RNR;
+ l2cap_send_sframe(chan, &control);
}
- if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
- l2cap_retransmit_frames(chan);
+ if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
+ chan->unacked_frames > 0)
+ __set_retrans_timer(chan);
+ /* Send pending iframes */
l2cap_ertm_send(chan);
if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
- chan->frames_sent == 0) {
- control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
- l2cap_send_sframe(chan, control);
- }
-}
-
-static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar)
-{
- struct sk_buff *next_skb;
- int tx_seq_offset, next_tx_seq_offset;
-
- bt_cb(skb)->control.txseq = tx_seq;
- bt_cb(skb)->control.sar = sar;
-
- next_skb = skb_peek(&chan->srej_q);
-
- tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
-
- while (next_skb) {
- if (bt_cb(next_skb)->control.txseq == tx_seq)
- return -EINVAL;
-
- next_tx_seq_offset = __seq_offset(chan,
- bt_cb(next_skb)->control.txseq, chan->buffer_seq);
-
- if (next_tx_seq_offset > tx_seq_offset) {
- __skb_queue_before(&chan->srej_q, next_skb, skb);
- return 0;
- }
-
- if (skb_queue_is_last(&chan->srej_q, next_skb))
- next_skb = NULL;
- else
- next_skb = skb_queue_next(&chan->srej_q, next_skb);
+ test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
+ /* F-bit wasn't sent in an s-frame or i-frame yet, so
+ * send it now.
+ */
+ control.super = L2CAP_SUPER_RR;
+ l2cap_send_sframe(chan, &control);
}
-
- __skb_queue_tail(&chan->srej_q, skb);
-
- return 0;
}
static void append_skb_frag(struct sk_buff *skb,
@@ -4045,16 +4376,17 @@ static void append_skb_frag(struct sk_buff *skb,
skb->truesize += new_frag->truesize;
}
-static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
+static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
+ struct l2cap_ctrl *control)
{
int err = -EINVAL;
- switch (__get_ctrl_sar(chan, control)) {
+ switch (control->sar) {
case L2CAP_SAR_UNSEGMENTED:
if (chan->sdu)
break;
- err = chan->ops->recv(chan->data, skb);
+ err = chan->ops->recv(chan, skb);
break;
case L2CAP_SAR_START:
@@ -4104,7 +4436,7 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u3
if (chan->sdu->len != chan->sdu_len)
break;
- err = chan->ops->recv(chan->data, chan->sdu);
+ err = chan->ops->recv(chan, chan->sdu);
if (!err) {
/* Reassembly complete */
@@ -4126,448 +4458,609 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u3
return err;
}
-static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
+void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
{
- BT_DBG("chan %p, Enter local busy", chan);
+ u8 event;
- set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
- l2cap_seq_list_clear(&chan->srej_list);
+ if (chan->mode != L2CAP_MODE_ERTM)
+ return;
- __set_ack_timer(chan);
+ event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
+ l2cap_tx(chan, NULL, NULL, event);
}
-static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
+static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
{
- u32 control;
-
- if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
- goto done;
+ int err = 0;
+ /* Pass sequential frames to l2cap_reassemble_sdu()
+ * until a gap is encountered.
+ */
- control = __set_reqseq(chan, chan->buffer_seq);
- control |= __set_ctrl_poll(chan);
- control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
- l2cap_send_sframe(chan, control);
- chan->retry_count = 1;
+ BT_DBG("chan %p", chan);
- __clear_retrans_timer(chan);
- __set_monitor_timer(chan);
+ while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
+ struct sk_buff *skb;
+ BT_DBG("Searching for skb with txseq %d (queue len %d)",
+ chan->buffer_seq, skb_queue_len(&chan->srej_q));
- set_bit(CONN_WAIT_F, &chan->conn_state);
+ skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
-done:
- clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
- clear_bit(CONN_RNR_SENT, &chan->conn_state);
+ if (!skb)
+ break;
- BT_DBG("chan %p, Exit local busy", chan);
-}
+ skb_unlink(skb, &chan->srej_q);
+ chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
+ err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control);
+ if (err)
+ break;
+ }
-void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
-{
- if (chan->mode == L2CAP_MODE_ERTM) {
- if (busy)
- l2cap_ertm_enter_local_busy(chan);
- else
- l2cap_ertm_exit_local_busy(chan);
+ if (skb_queue_empty(&chan->srej_q)) {
+ chan->rx_state = L2CAP_RX_STATE_RECV;
+ l2cap_send_ack(chan);
}
+
+ return err;
}
-static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
+static void l2cap_handle_srej(struct l2cap_chan *chan,
+ struct l2cap_ctrl *control)
{
struct sk_buff *skb;
- u32 control;
- while ((skb = skb_peek(&chan->srej_q)) &&
- !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
- int err;
+ BT_DBG("chan %p, control %p", chan, control);
- if (bt_cb(skb)->control.txseq != tx_seq)
- break;
+ if (control->reqseq == chan->next_tx_seq) {
+ BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
+ l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ return;
+ }
- skb = skb_dequeue(&chan->srej_q);
- control = __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
- err = l2cap_reassemble_sdu(chan, skb, control);
+ skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
- if (err < 0) {
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
- break;
- }
+ if (skb == NULL) {
+ BT_DBG("Seq %d not available for retransmission",
+ control->reqseq);
+ return;
+ }
- chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
- tx_seq = __next_seq(chan, tx_seq);
+ if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) {
+ BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
+ l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ return;
}
-}
-static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
-{
- struct srej_list *l, *tmp;
- u32 control;
+ clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
- list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
- if (l->tx_seq == tx_seq) {
- list_del(&l->list);
- kfree(l);
- return;
+ if (control->poll) {
+ l2cap_pass_to_tx(chan, control);
+
+ set_bit(CONN_SEND_FBIT, &chan->conn_state);
+ l2cap_retransmit(chan, control);
+ l2cap_ertm_send(chan);
+
+ if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
+ set_bit(CONN_SREJ_ACT, &chan->conn_state);
+ chan->srej_save_reqseq = control->reqseq;
+ }
+ } else {
+ l2cap_pass_to_tx_fbit(chan, control);
+
+ if (control->final) {
+ if (chan->srej_save_reqseq != control->reqseq ||
+ !test_and_clear_bit(CONN_SREJ_ACT,
+ &chan->conn_state))
+ l2cap_retransmit(chan, control);
+ } else {
+ l2cap_retransmit(chan, control);
+ if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
+ set_bit(CONN_SREJ_ACT, &chan->conn_state);
+ chan->srej_save_reqseq = control->reqseq;
+ }
}
- control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
- control |= __set_reqseq(chan, l->tx_seq);
- l2cap_send_sframe(chan, control);
- list_del(&l->list);
- list_add_tail(&l->list, &chan->srej_l);
}
}
-static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
+static void l2cap_handle_rej(struct l2cap_chan *chan,
+ struct l2cap_ctrl *control)
{
- struct srej_list *new;
- u32 control;
-
- while (tx_seq != chan->expected_tx_seq) {
- control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
- control |= __set_reqseq(chan, chan->expected_tx_seq);
- l2cap_seq_list_append(&chan->srej_list, chan->expected_tx_seq);
- l2cap_send_sframe(chan, control);
+ struct sk_buff *skb;
- new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
- if (!new)
- return -ENOMEM;
+ BT_DBG("chan %p, control %p", chan, control);
- new->tx_seq = chan->expected_tx_seq;
+ if (control->reqseq == chan->next_tx_seq) {
+ BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
+ l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ return;
+ }
- chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
+ skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
- list_add_tail(&new->list, &chan->srej_l);
+ if (chan->max_tx && skb &&
+ bt_cb(skb)->control.retries >= chan->max_tx) {
+ BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
+ l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ return;
}
- chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
+ clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
- return 0;
+ l2cap_pass_to_tx(chan, control);
+
+ if (control->final) {
+ if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
+ l2cap_retransmit_all(chan, control);
+ } else {
+ l2cap_retransmit_all(chan, control);
+ l2cap_ertm_send(chan);
+ if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
+ set_bit(CONN_REJ_ACT, &chan->conn_state);
+ }
}
-static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
+static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
{
- u16 tx_seq = __get_txseq(chan, rx_control);
- u16 req_seq = __get_reqseq(chan, rx_control);
- u8 sar = __get_ctrl_sar(chan, rx_control);
- int tx_seq_offset, expected_tx_seq_offset;
- int num_to_ack = (chan->tx_win/6) + 1;
- int err = 0;
+ BT_DBG("chan %p, txseq %d", chan, txseq);
- BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len,
- tx_seq, rx_control);
+ BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
+ chan->expected_tx_seq);
- if (__is_ctrl_final(chan, rx_control) &&
- test_bit(CONN_WAIT_F, &chan->conn_state)) {
- __clear_monitor_timer(chan);
- if (chan->unacked_frames > 0)
- __set_retrans_timer(chan);
- clear_bit(CONN_WAIT_F, &chan->conn_state);
- }
+ if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
+ if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
+ chan->tx_win) {
+ /* See notes below regarding "double poll" and
+ * invalid packets.
+ */
+ if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
+ BT_DBG("Invalid/Ignore - after SREJ");
+ return L2CAP_TXSEQ_INVALID_IGNORE;
+ } else {
+ BT_DBG("Invalid - in window after SREJ sent");
+ return L2CAP_TXSEQ_INVALID;
+ }
+ }
- chan->expected_ack_seq = req_seq;
- l2cap_drop_acked_frames(chan);
+ if (chan->srej_list.head == txseq) {
+ BT_DBG("Expected SREJ");
+ return L2CAP_TXSEQ_EXPECTED_SREJ;
+ }
- tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
+ if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
+ BT_DBG("Duplicate SREJ - txseq already stored");
+ return L2CAP_TXSEQ_DUPLICATE_SREJ;
+ }
- /* invalid tx_seq */
- if (tx_seq_offset >= chan->tx_win) {
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
- goto drop;
+ if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
+ BT_DBG("Unexpected SREJ - not requested");
+ return L2CAP_TXSEQ_UNEXPECTED_SREJ;
+ }
}
- if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
- if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
- l2cap_send_ack(chan);
- goto drop;
+ if (chan->expected_tx_seq == txseq) {
+ if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
+ chan->tx_win) {
+ BT_DBG("Invalid - txseq outside tx window");
+ return L2CAP_TXSEQ_INVALID;
+ } else {
+ BT_DBG("Expected");
+ return L2CAP_TXSEQ_EXPECTED;
+ }
}
- if (tx_seq == chan->expected_tx_seq)
- goto expected;
+ if (__seq_offset(chan, txseq, chan->last_acked_seq) <
+ __seq_offset(chan, chan->expected_tx_seq,
+ chan->last_acked_seq)){
+ BT_DBG("Duplicate - expected_tx_seq later than txseq");
+ return L2CAP_TXSEQ_DUPLICATE;
+ }
+
+ if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
+ /* A source of invalid packets is a "double poll" condition,
+ * where delays cause us to send multiple poll packets. If
+ * the remote stack receives and processes both polls,
+ * sequence numbers can wrap around in such a way that a
+ * resent frame has a sequence number that looks like new data
+ * with a sequence gap. This would trigger an erroneous SREJ
+ * request.
+ *
+ * Fortunately, this is impossible with a tx window that's
+ * less than half of the maximum sequence number, which allows
+ * invalid frames to be safely ignored.
+ *
+ * With tx window sizes greater than half of the tx window
+ * maximum, the frame is invalid and cannot be ignored. This
+ * causes a disconnect.
+ */
+
+ if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
+ BT_DBG("Invalid/Ignore - txseq outside tx window");
+ return L2CAP_TXSEQ_INVALID_IGNORE;
+ } else {
+ BT_DBG("Invalid - txseq outside tx window");
+ return L2CAP_TXSEQ_INVALID;
+ }
+ } else {
+ BT_DBG("Unexpected - txseq indicates missing frames");
+ return L2CAP_TXSEQ_UNEXPECTED;
+ }
+}
- if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
- struct srej_list *first;
+static int l2cap_rx_state_recv(struct l2cap_chan *chan,
+ struct l2cap_ctrl *control,
+ struct sk_buff *skb, u8 event)
+{
+ int err = 0;
+ bool skb_in_use = 0;
- first = list_first_entry(&chan->srej_l,
- struct srej_list, list);
- if (tx_seq == first->tx_seq) {
- l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
- l2cap_check_srej_gap(chan, tx_seq);
+ BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
+ event);
- list_del(&first->list);
- kfree(first);
+ switch (event) {
+ case L2CAP_EV_RECV_IFRAME:
+ switch (l2cap_classify_txseq(chan, control->txseq)) {
+ case L2CAP_TXSEQ_EXPECTED:
+ l2cap_pass_to_tx(chan, control);
- if (list_empty(&chan->srej_l)) {
- chan->buffer_seq = chan->buffer_seq_srej;
- clear_bit(CONN_SREJ_SENT, &chan->conn_state);
- l2cap_send_ack(chan);
- BT_DBG("chan %p, Exit SREJ_SENT", chan);
+ if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
+ BT_DBG("Busy, discarding expected seq %d",
+ control->txseq);
+ break;
}
- } else {
- struct srej_list *l;
- /* duplicated tx_seq */
- if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
- goto drop;
+ chan->expected_tx_seq = __next_seq(chan,
+ control->txseq);
+
+ chan->buffer_seq = chan->expected_tx_seq;
+ skb_in_use = 1;
+
+ err = l2cap_reassemble_sdu(chan, skb, control);
+ if (err)
+ break;
- list_for_each_entry(l, &chan->srej_l, list) {
- if (l->tx_seq == tx_seq) {
- l2cap_resend_srejframe(chan, tx_seq);
- return 0;
+ if (control->final) {
+ if (!test_and_clear_bit(CONN_REJ_ACT,
+ &chan->conn_state)) {
+ control->final = 0;
+ l2cap_retransmit_all(chan, control);
+ l2cap_ertm_send(chan);
}
}
- err = l2cap_send_srejframe(chan, tx_seq);
- if (err < 0) {
- l2cap_send_disconn_req(chan->conn, chan, -err);
- return err;
+ if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
+ l2cap_send_ack(chan);
+ break;
+ case L2CAP_TXSEQ_UNEXPECTED:
+ l2cap_pass_to_tx(chan, control);
+
+ /* Can't issue SREJ frames in the local busy state.
+ * Drop this frame, it will be seen as missing
+ * when local busy is exited.
+ */
+ if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
+ BT_DBG("Busy, discarding unexpected seq %d",
+ control->txseq);
+ break;
}
- }
- } else {
- expected_tx_seq_offset = __seq_offset(chan,
- chan->expected_tx_seq, chan->buffer_seq);
-
- /* duplicated tx_seq */
- if (tx_seq_offset < expected_tx_seq_offset)
- goto drop;
- set_bit(CONN_SREJ_SENT, &chan->conn_state);
+ /* There was a gap in the sequence, so an SREJ
+ * must be sent for each missing frame. The
+ * current frame is stored for later use.
+ */
+ skb_queue_tail(&chan->srej_q, skb);
+ skb_in_use = 1;
+ BT_DBG("Queued %p (queue len %d)", skb,
+ skb_queue_len(&chan->srej_q));
- BT_DBG("chan %p, Enter SREJ", chan);
+ clear_bit(CONN_SREJ_ACT, &chan->conn_state);
+ l2cap_seq_list_clear(&chan->srej_list);
+ l2cap_send_srej(chan, control->txseq);
- INIT_LIST_HEAD(&chan->srej_l);
- chan->buffer_seq_srej = chan->buffer_seq;
+ chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
+ break;
+ case L2CAP_TXSEQ_DUPLICATE:
+ l2cap_pass_to_tx(chan, control);
+ break;
+ case L2CAP_TXSEQ_INVALID_IGNORE:
+ break;
+ case L2CAP_TXSEQ_INVALID:
+ default:
+ l2cap_send_disconn_req(chan->conn, chan,
+ ECONNRESET);
+ break;
+ }
+ break;
+ case L2CAP_EV_RECV_RR:
+ l2cap_pass_to_tx(chan, control);
+ if (control->final) {
+ clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
- __skb_queue_head_init(&chan->srej_q);
- l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
+ if (!test_and_clear_bit(CONN_REJ_ACT,
+ &chan->conn_state)) {
+ control->final = 0;
+ l2cap_retransmit_all(chan, control);
+ }
- /* Set P-bit only if there are some I-frames to ack. */
- if (__clear_ack_timer(chan))
- set_bit(CONN_SEND_PBIT, &chan->conn_state);
+ l2cap_ertm_send(chan);
+ } else if (control->poll) {
+ l2cap_send_i_or_rr_or_rnr(chan);
+ } else {
+ if (test_and_clear_bit(CONN_REMOTE_BUSY,
+ &chan->conn_state) &&
+ chan->unacked_frames)
+ __set_retrans_timer(chan);
- err = l2cap_send_srejframe(chan, tx_seq);
- if (err < 0) {
- l2cap_send_disconn_req(chan->conn, chan, -err);
- return err;
+ l2cap_ertm_send(chan);
}
+ break;
+ case L2CAP_EV_RECV_RNR:
+ set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
+ l2cap_pass_to_tx(chan, control);
+ if (control && control->poll) {
+ set_bit(CONN_SEND_FBIT, &chan->conn_state);
+ l2cap_send_rr_or_rnr(chan, 0);
+ }
+ __clear_retrans_timer(chan);
+ l2cap_seq_list_clear(&chan->retrans_list);
+ break;
+ case L2CAP_EV_RECV_REJ:
+ l2cap_handle_rej(chan, control);
+ break;
+ case L2CAP_EV_RECV_SREJ:
+ l2cap_handle_srej(chan, control);
+ break;
+ default:
+ break;
}
- return 0;
-
-expected:
- chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
-
- if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
- bt_cb(skb)->control.txseq = tx_seq;
- bt_cb(skb)->control.sar = sar;
- __skb_queue_tail(&chan->srej_q, skb);
- return 0;
- }
-
- err = l2cap_reassemble_sdu(chan, skb, rx_control);
- chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
- if (err < 0) {
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
- return err;
+ if (skb && !skb_in_use) {
+ BT_DBG("Freeing %p", skb);
+ kfree_skb(skb);
}
- if (__is_ctrl_final(chan, rx_control)) {
- if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
- l2cap_retransmit_frames(chan);
- }
+ return err;
+}
+static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
+ struct l2cap_ctrl *control,
+ struct sk_buff *skb, u8 event)
+{
+ int err = 0;
+ u16 txseq = control->txseq;
+ bool skb_in_use = 0;
+
+ BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
+ event);
+
+ switch (event) {
+ case L2CAP_EV_RECV_IFRAME:
+ switch (l2cap_classify_txseq(chan, txseq)) {
+ case L2CAP_TXSEQ_EXPECTED:
+ /* Keep frame for reassembly later */
+ l2cap_pass_to_tx(chan, control);
+ skb_queue_tail(&chan->srej_q, skb);
+ skb_in_use = 1;
+ BT_DBG("Queued %p (queue len %d)", skb,
+ skb_queue_len(&chan->srej_q));
+
+ chan->expected_tx_seq = __next_seq(chan, txseq);
+ break;
+ case L2CAP_TXSEQ_EXPECTED_SREJ:
+ l2cap_seq_list_pop(&chan->srej_list);
- chan->num_acked = (chan->num_acked + 1) % num_to_ack;
- if (chan->num_acked == num_to_ack - 1)
- l2cap_send_ack(chan);
- else
- __set_ack_timer(chan);
+ l2cap_pass_to_tx(chan, control);
+ skb_queue_tail(&chan->srej_q, skb);
+ skb_in_use = 1;
+ BT_DBG("Queued %p (queue len %d)", skb,
+ skb_queue_len(&chan->srej_q));
- return 0;
+ err = l2cap_rx_queued_iframes(chan);
+ if (err)
+ break;
-drop:
- kfree_skb(skb);
- return 0;
-}
+ break;
+ case L2CAP_TXSEQ_UNEXPECTED:
+ /* Got a frame that can't be reassembled yet.
+ * Save it for later, and send SREJs to cover
+ * the missing frames.
+ */
+ skb_queue_tail(&chan->srej_q, skb);
+ skb_in_use = 1;
+ BT_DBG("Queued %p (queue len %d)", skb,
+ skb_queue_len(&chan->srej_q));
+
+ l2cap_pass_to_tx(chan, control);
+ l2cap_send_srej(chan, control->txseq);
+ break;
+ case L2CAP_TXSEQ_UNEXPECTED_SREJ:
+ /* This frame was requested with an SREJ, but
+ * some expected retransmitted frames are
+ * missing. Request retransmission of missing
+ * SREJ'd frames.
+ */
+ skb_queue_tail(&chan->srej_q, skb);
+ skb_in_use = 1;
+ BT_DBG("Queued %p (queue len %d)", skb,
+ skb_queue_len(&chan->srej_q));
+
+ l2cap_pass_to_tx(chan, control);
+ l2cap_send_srej_list(chan, control->txseq);
+ break;
+ case L2CAP_TXSEQ_DUPLICATE_SREJ:
+ /* We've already queued this frame. Drop this copy. */
+ l2cap_pass_to_tx(chan, control);
+ break;
+ case L2CAP_TXSEQ_DUPLICATE:
+ /* Expecting a later sequence number, so this frame
+ * was already received. Ignore it completely.
+ */
+ break;
+ case L2CAP_TXSEQ_INVALID_IGNORE:
+ break;
+ case L2CAP_TXSEQ_INVALID:
+ default:
+ l2cap_send_disconn_req(chan->conn, chan,
+ ECONNRESET);
+ break;
+ }
+ break;
+ case L2CAP_EV_RECV_RR:
+ l2cap_pass_to_tx(chan, control);
+ if (control->final) {
+ clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
-static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
-{
- BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
- __get_reqseq(chan, rx_control), rx_control);
+ if (!test_and_clear_bit(CONN_REJ_ACT,
+ &chan->conn_state)) {
+ control->final = 0;
+ l2cap_retransmit_all(chan, control);
+ }
- chan->expected_ack_seq = __get_reqseq(chan, rx_control);
- l2cap_drop_acked_frames(chan);
+ l2cap_ertm_send(chan);
+ } else if (control->poll) {
+ if (test_and_clear_bit(CONN_REMOTE_BUSY,
+ &chan->conn_state) &&
+ chan->unacked_frames) {
+ __set_retrans_timer(chan);
+ }
- if (__is_ctrl_poll(chan, rx_control)) {
- set_bit(CONN_SEND_FBIT, &chan->conn_state);
- if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
- if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
- (chan->unacked_frames > 0))
+ set_bit(CONN_SEND_FBIT, &chan->conn_state);
+ l2cap_send_srej_tail(chan);
+ } else {
+ if (test_and_clear_bit(CONN_REMOTE_BUSY,
+ &chan->conn_state) &&
+ chan->unacked_frames)
__set_retrans_timer(chan);
- clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
- l2cap_send_srejtail(chan);
+ l2cap_send_ack(chan);
+ }
+ break;
+ case L2CAP_EV_RECV_RNR:
+ set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
+ l2cap_pass_to_tx(chan, control);
+ if (control->poll) {
+ l2cap_send_srej_tail(chan);
} else {
- l2cap_send_i_or_rr_or_rnr(chan);
+ struct l2cap_ctrl rr_control;
+ memset(&rr_control, 0, sizeof(rr_control));
+ rr_control.sframe = 1;
+ rr_control.super = L2CAP_SUPER_RR;
+ rr_control.reqseq = chan->buffer_seq;
+ l2cap_send_sframe(chan, &rr_control);
}
- } else if (__is_ctrl_final(chan, rx_control)) {
- clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
-
- if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
- l2cap_retransmit_frames(chan);
-
- } else {
- if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
- (chan->unacked_frames > 0))
- __set_retrans_timer(chan);
+ break;
+ case L2CAP_EV_RECV_REJ:
+ l2cap_handle_rej(chan, control);
+ break;
+ case L2CAP_EV_RECV_SREJ:
+ l2cap_handle_srej(chan, control);
+ break;
+ }
- clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
- if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
- l2cap_send_ack(chan);
- else
- l2cap_ertm_send(chan);
+ if (skb && !skb_in_use) {
+ BT_DBG("Freeing %p", skb);
+ kfree_skb(skb);
}
+
+ return err;
}
-static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
+static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
{
- u16 tx_seq = __get_reqseq(chan, rx_control);
+ /* Make sure reqseq is for a packet that has been sent but not acked */
+ u16 unacked;
- BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
-
- clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
-
- chan->expected_ack_seq = tx_seq;
- l2cap_drop_acked_frames(chan);
-
- if (__is_ctrl_final(chan, rx_control)) {
- if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
- l2cap_retransmit_frames(chan);
- } else {
- l2cap_retransmit_frames(chan);
-
- if (test_bit(CONN_WAIT_F, &chan->conn_state))
- set_bit(CONN_REJ_ACT, &chan->conn_state);
- }
+ unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
+ return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
}
-static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
-{
- u16 tx_seq = __get_reqseq(chan, rx_control);
-
- BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
- clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
-
- if (__is_ctrl_poll(chan, rx_control)) {
- chan->expected_ack_seq = tx_seq;
- l2cap_drop_acked_frames(chan);
-
- set_bit(CONN_SEND_FBIT, &chan->conn_state);
- l2cap_retransmit_one_frame(chan, tx_seq);
+static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
+ struct sk_buff *skb, u8 event)
+{
+ int err = 0;
- l2cap_ertm_send(chan);
+ BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
+ control, skb, event, chan->rx_state);
- if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
- chan->srej_save_reqseq = tx_seq;
- set_bit(CONN_SREJ_ACT, &chan->conn_state);
+ if (__valid_reqseq(chan, control->reqseq)) {
+ switch (chan->rx_state) {
+ case L2CAP_RX_STATE_RECV:
+ err = l2cap_rx_state_recv(chan, control, skb, event);
+ break;
+ case L2CAP_RX_STATE_SREJ_SENT:
+ err = l2cap_rx_state_srej_sent(chan, control, skb,
+ event);
+ break;
+ default:
+ /* shut it down */
+ break;
}
- } else if (__is_ctrl_final(chan, rx_control)) {
- if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
- chan->srej_save_reqseq == tx_seq)
- clear_bit(CONN_SREJ_ACT, &chan->conn_state);
- else
- l2cap_retransmit_one_frame(chan, tx_seq);
} else {
- l2cap_retransmit_one_frame(chan, tx_seq);
- if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
- chan->srej_save_reqseq = tx_seq;
- set_bit(CONN_SREJ_ACT, &chan->conn_state);
- }
+ BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
+ control->reqseq, chan->next_tx_seq,
+ chan->expected_ack_seq);
+ l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
}
+
+ return err;
}
-static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
+static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
+ struct sk_buff *skb)
{
- u16 tx_seq = __get_reqseq(chan, rx_control);
+ int err = 0;
- BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
+ BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
+ chan->rx_state);
- set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
- chan->expected_ack_seq = tx_seq;
- l2cap_drop_acked_frames(chan);
+ if (l2cap_classify_txseq(chan, control->txseq) ==
+ L2CAP_TXSEQ_EXPECTED) {
+ l2cap_pass_to_tx(chan, control);
- if (__is_ctrl_poll(chan, rx_control))
- set_bit(CONN_SEND_FBIT, &chan->conn_state);
+ BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
+ __next_seq(chan, chan->buffer_seq));
- if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
- __clear_retrans_timer(chan);
- if (__is_ctrl_poll(chan, rx_control))
- l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
- return;
- }
+ chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
- if (__is_ctrl_poll(chan, rx_control)) {
- l2cap_send_srejtail(chan);
+ l2cap_reassemble_sdu(chan, skb, control);
} else {
- rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
- l2cap_send_sframe(chan, rx_control);
- }
-}
-
-static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
-{
- BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
+ if (chan->sdu) {
+ kfree_skb(chan->sdu);
+ chan->sdu = NULL;
+ }
+ chan->sdu_last_frag = NULL;
+ chan->sdu_len = 0;
- if (__is_ctrl_final(chan, rx_control) &&
- test_bit(CONN_WAIT_F, &chan->conn_state)) {
- __clear_monitor_timer(chan);
- if (chan->unacked_frames > 0)
- __set_retrans_timer(chan);
- clear_bit(CONN_WAIT_F, &chan->conn_state);
+ if (skb) {
+ BT_DBG("Freeing %p", skb);
+ kfree_skb(skb);
+ }
}
- switch (__get_ctrl_super(chan, rx_control)) {
- case L2CAP_SUPER_RR:
- l2cap_data_channel_rrframe(chan, rx_control);
- break;
-
- case L2CAP_SUPER_REJ:
- l2cap_data_channel_rejframe(chan, rx_control);
- break;
-
- case L2CAP_SUPER_SREJ:
- l2cap_data_channel_srejframe(chan, rx_control);
- break;
-
- case L2CAP_SUPER_RNR:
- l2cap_data_channel_rnrframe(chan, rx_control);
- break;
- }
+ chan->last_acked_seq = control->txseq;
+ chan->expected_tx_seq = __next_seq(chan, control->txseq);
- kfree_skb(skb);
- return 0;
+ return err;
}
-static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
+static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
{
- u32 control;
- u16 req_seq;
- int len, next_tx_seq_offset, req_seq_offset;
+ struct l2cap_ctrl *control = &bt_cb(skb)->control;
+ u16 len;
+ u8 event;
__unpack_control(chan, skb);
- control = __get_control(chan, skb->data);
- skb_pull(skb, __ctrl_size(chan));
len = skb->len;
/*
* We can just drop the corrupted I-frame here.
* Receiver will miss it and start proper recovery
- * procedures and ask retransmission.
+ * procedures and ask for retransmission.
*/
if (l2cap_check_fcs(chan, skb))
goto drop;
- if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
+ if (!control->sframe && control->sar == L2CAP_SAR_START)
len -= L2CAP_SDULEN_SIZE;
if (chan->fcs == L2CAP_FCS_CRC16)
@@ -4578,34 +5071,57 @@ static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
goto drop;
}
- req_seq = __get_reqseq(chan, control);
-
- req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
+ if (!control->sframe) {
+ int err;
- next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
- chan->expected_ack_seq);
+ BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
+ control->sar, control->reqseq, control->final,
+ control->txseq);
- /* check for invalid req-seq */
- if (req_seq_offset > next_tx_seq_offset) {
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
- goto drop;
- }
-
- if (!__is_sframe(chan, control)) {
- if (len < 0) {
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+ /* Validate F-bit - F=0 always valid, F=1 only
+ * valid in TX WAIT_F
+ */
+ if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
goto drop;
+
+ if (chan->mode != L2CAP_MODE_STREAMING) {
+ event = L2CAP_EV_RECV_IFRAME;
+ err = l2cap_rx(chan, control, skb, event);
+ } else {
+ err = l2cap_stream_rx(chan, control, skb);
}
- l2cap_data_channel_iframe(chan, control, skb);
+ if (err)
+ l2cap_send_disconn_req(chan->conn, chan,
+ ECONNRESET);
} else {
+ const u8 rx_func_to_event[4] = {
+ L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
+ L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
+ };
+
+ /* Only I-frames are expected in streaming mode */
+ if (chan->mode == L2CAP_MODE_STREAMING)
+ goto drop;
+
+ BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
+ control->reqseq, control->final, control->poll,
+ control->super);
+
if (len != 0) {
BT_ERR("%d", len);
l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
goto drop;
}
- l2cap_data_channel_sframe(chan, control, skb);
+ /* Validate F and P bits */
+ if (control->final && (control->poll ||
+ chan->tx_state != L2CAP_TX_STATE_WAIT_F))
+ goto drop;
+
+ event = rx_func_to_event[control->super];
+ if (l2cap_rx(chan, control, skb, event))
+ l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
}
return 0;
@@ -4615,19 +5131,27 @@ drop:
return 0;
}
-static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
+static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
+ struct sk_buff *skb)
{
struct l2cap_chan *chan;
- u32 control;
- u16 tx_seq;
- int len;
chan = l2cap_get_chan_by_scid(conn, cid);
if (!chan) {
- BT_DBG("unknown cid 0x%4.4x", cid);
- /* Drop packet and return */
- kfree_skb(skb);
- return 0;
+ if (cid == L2CAP_CID_A2MP) {
+ chan = a2mp_channel_create(conn, skb);
+ if (!chan) {
+ kfree_skb(skb);
+ return;
+ }
+
+ l2cap_chan_lock(chan);
+ } else {
+ BT_DBG("unknown cid 0x%4.4x", cid);
+ /* Drop packet and return */
+ kfree_skb(skb);
+ return;
+ }
}
BT_DBG("chan %p, len %d", chan, skb->len);
@@ -4645,49 +5169,13 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
if (chan->imtu < skb->len)
goto drop;
- if (!chan->ops->recv(chan->data, skb))
+ if (!chan->ops->recv(chan, skb))
goto done;
break;
case L2CAP_MODE_ERTM:
- l2cap_ertm_data_rcv(chan, skb);
-
- goto done;
-
case L2CAP_MODE_STREAMING:
- control = __get_control(chan, skb->data);
- skb_pull(skb, __ctrl_size(chan));
- len = skb->len;
-
- if (l2cap_check_fcs(chan, skb))
- goto drop;
-
- if (__is_sar_start(chan, control))
- len -= L2CAP_SDULEN_SIZE;
-
- if (chan->fcs == L2CAP_FCS_CRC16)
- len -= L2CAP_FCS_SIZE;
-
- if (len > chan->mps || len < 0 || __is_sframe(chan, control))
- goto drop;
-
- tx_seq = __get_txseq(chan, control);
-
- if (chan->expected_tx_seq != tx_seq) {
- /* Frame(s) missing - must discard partial SDU */
- kfree_skb(chan->sdu);
- chan->sdu = NULL;
- chan->sdu_last_frag = NULL;
- chan->sdu_len = 0;
-
- /* TODO: Notify userland of missing data */
- }
-
- chan->expected_tx_seq = __next_seq(chan, tx_seq);
-
- if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
- l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
-
+ l2cap_data_rcv(chan, skb);
goto done;
default:
@@ -4700,11 +5188,10 @@ drop:
done:
l2cap_chan_unlock(chan);
-
- return 0;
}
-static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
+static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
+ struct sk_buff *skb)
{
struct l2cap_chan *chan;
@@ -4720,17 +5207,15 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str
if (chan->imtu < skb->len)
goto drop;
- if (!chan->ops->recv(chan->data, skb))
- return 0;
+ if (!chan->ops->recv(chan, skb))
+ return;
drop:
kfree_skb(skb);
-
- return 0;
}
-static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
- struct sk_buff *skb)
+static void l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
+ struct sk_buff *skb)
{
struct l2cap_chan *chan;
@@ -4746,13 +5231,11 @@ static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
if (chan->imtu < skb->len)
goto drop;
- if (!chan->ops->recv(chan->data, skb))
- return 0;
+ if (!chan->ops->recv(chan, skb))
+ return;
drop:
kfree_skb(skb);
-
- return 0;
}
static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
@@ -4780,7 +5263,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
case L2CAP_CID_CONN_LESS:
psm = get_unaligned((__le16 *) skb->data);
- skb_pull(skb, 2);
+ skb_pull(skb, L2CAP_PSMLEN_SIZE);
l2cap_conless_channel(conn, psm, skb);
break;
@@ -4974,6 +5457,17 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
rsp.status = cpu_to_le16(stat);
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
sizeof(rsp), &rsp);
+
+ if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
+ res == L2CAP_CR_SUCCESS) {
+ char buf[128];
+ set_bit(CONF_REQ_SENT, &chan->conf_state);
+ l2cap_send_cmd(conn, l2cap_get_ident(conn),
+ L2CAP_CONF_REQ,
+ l2cap_build_conf_req(chan, buf),
+ buf);
+ chan->num_conf_req++;
+ }
}
l2cap_chan_unlock(chan);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 3bb1611b9d48..a4bb27e8427e 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -27,7 +27,6 @@
/* Bluetooth L2CAP sockets. */
-#include <linux/security.h>
#include <linux/export.h>
#include <net/bluetooth/bluetooth.h>
@@ -89,8 +88,8 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
if (err < 0)
goto done;
- if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
- __le16_to_cpu(la.l2_psm) == 0x0003)
+ if (__le16_to_cpu(la.l2_psm) == L2CAP_PSM_SDP ||
+ __le16_to_cpu(la.l2_psm) == L2CAP_PSM_RFCOMM)
chan->sec_level = BT_SECURITY_SDP;
bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
@@ -446,6 +445,22 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
return err;
}
+static bool l2cap_valid_mtu(struct l2cap_chan *chan, u16 mtu)
+{
+ switch (chan->scid) {
+ case L2CAP_CID_LE_DATA:
+ if (mtu < L2CAP_LE_MIN_MTU)
+ return false;
+ break;
+
+ default:
+ if (mtu < L2CAP_DEFAULT_MIN_MTU)
+ return false;
+ }
+
+ return true;
+}
+
static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
@@ -484,6 +499,11 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
break;
}
+ if (!l2cap_valid_mtu(chan, opts.imtu)) {
+ err = -EINVAL;
+ break;
+ }
+
chan->mode = opts.mode;
switch (chan->mode) {
case L2CAP_MODE_BASIC:
@@ -873,9 +893,34 @@ static int l2cap_sock_release(struct socket *sock)
return err;
}
-static struct l2cap_chan *l2cap_sock_new_connection_cb(void *data)
+static void l2cap_sock_cleanup_listen(struct sock *parent)
{
- struct sock *sk, *parent = data;
+ struct sock *sk;
+
+ BT_DBG("parent %p", parent);
+
+ /* Close not yet accepted channels */
+ while ((sk = bt_accept_dequeue(parent, NULL))) {
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+
+ l2cap_chan_lock(chan);
+ __clear_chan_timer(chan);
+ l2cap_chan_close(chan, ECONNRESET);
+ l2cap_chan_unlock(chan);
+
+ l2cap_sock_kill(sk);
+ }
+}
+
+static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
+{
+ struct sock *sk, *parent = chan->data;
+
+ /* Check for backlog size */
+ if (sk_acceptq_is_full(parent)) {
+ BT_DBG("backlog full %d", parent->sk_ack_backlog);
+ return NULL;
+ }
sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
GFP_ATOMIC);
@@ -889,10 +934,10 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(void *data)
return l2cap_pi(sk)->chan;
}
-static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb)
+static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
{
int err;
- struct sock *sk = data;
+ struct sock *sk = chan->data;
struct l2cap_pinfo *pi = l2cap_pi(sk);
lock_sock(sk);
@@ -925,16 +970,57 @@ done:
return err;
}
-static void l2cap_sock_close_cb(void *data)
+static void l2cap_sock_close_cb(struct l2cap_chan *chan)
{
- struct sock *sk = data;
+ struct sock *sk = chan->data;
l2cap_sock_kill(sk);
}
-static void l2cap_sock_state_change_cb(void *data, int state)
+static void l2cap_sock_teardown_cb(struct l2cap_chan *chan, int err)
{
- struct sock *sk = data;
+ struct sock *sk = chan->data;
+ struct sock *parent;
+
+ lock_sock(sk);
+
+ parent = bt_sk(sk)->parent;
+
+ sock_set_flag(sk, SOCK_ZAPPED);
+
+ switch (chan->state) {
+ case BT_OPEN:
+ case BT_BOUND:
+ case BT_CLOSED:
+ break;
+ case BT_LISTEN:
+ l2cap_sock_cleanup_listen(sk);
+ sk->sk_state = BT_CLOSED;
+ chan->state = BT_CLOSED;
+
+ break;
+ default:
+ sk->sk_state = BT_CLOSED;
+ chan->state = BT_CLOSED;
+
+ sk->sk_err = err;
+
+ if (parent) {
+ bt_accept_unlink(sk);
+ parent->sk_data_ready(parent, 0);
+ } else {
+ sk->sk_state_change(sk);
+ }
+
+ break;
+ }
+
+ release_sock(sk);
+}
+
+static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state)
+{
+ struct sock *sk = chan->data;
sk->sk_state = state;
}
@@ -955,12 +1041,34 @@ static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan,
return skb;
}
+static void l2cap_sock_ready_cb(struct l2cap_chan *chan)
+{
+ struct sock *sk = chan->data;
+ struct sock *parent;
+
+ lock_sock(sk);
+
+ parent = bt_sk(sk)->parent;
+
+ BT_DBG("sk %p, parent %p", sk, parent);
+
+ sk->sk_state = BT_CONNECTED;
+ sk->sk_state_change(sk);
+
+ if (parent)
+ parent->sk_data_ready(parent, 0);
+
+ release_sock(sk);
+}
+
static struct l2cap_ops l2cap_chan_ops = {
.name = "L2CAP Socket Interface",
.new_connection = l2cap_sock_new_connection_cb,
.recv = l2cap_sock_recv_cb,
.close = l2cap_sock_close_cb,
+ .teardown = l2cap_sock_teardown_cb,
.state_change = l2cap_sock_state_change_cb,
+ .ready = l2cap_sock_ready_cb,
.alloc_skb = l2cap_sock_alloc_skb_cb,
};
diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c
index 506628876f36..e1c97527e16c 100644
--- a/net/bluetooth/lib.c
+++ b/net/bluetooth/lib.c
@@ -26,12 +26,7 @@
#define pr_fmt(fmt) "Bluetooth: " fmt
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/stddef.h>
-#include <linux/string.h>
-#include <asm/errno.h>
+#include <linux/export.h>
#include <net/bluetooth/bluetooth.h>
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 25d220776079..a6e0f3d8da6c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -24,8 +24,6 @@
/* Bluetooth HCI Management interface */
-#include <linux/kernel.h>
-#include <linux/uaccess.h>
#include <linux/module.h>
#include <asm/unaligned.h>
@@ -714,7 +712,8 @@ static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
}
static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
- void (*cb)(struct pending_cmd *cmd, void *data),
+ void (*cb)(struct pending_cmd *cmd,
+ void *data),
void *data)
{
struct list_head *p, *n;
@@ -871,7 +870,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
}
if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
- mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
+ mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_BUSY);
goto failed;
@@ -978,7 +977,7 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
}
if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
- mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
+ mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
MGMT_STATUS_BUSY);
goto failed;
@@ -1001,7 +1000,7 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
scan = 0;
if (test_bit(HCI_ISCAN, &hdev->flags) &&
- hdev->discov_timeout > 0)
+ hdev->discov_timeout > 0)
cancel_delayed_work(&hdev->discov_off);
}
@@ -1056,7 +1055,7 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
bool changed = false;
if (!!cp->val != test_bit(HCI_LINK_SECURITY,
- &hdev->dev_flags)) {
+ &hdev->dev_flags)) {
change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
changed = true;
}
@@ -1317,7 +1316,7 @@ static bool enable_service_cache(struct hci_dev *hdev)
}
static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
- u16 len)
+ u16 len)
{
struct mgmt_cp_remove_uuid *cp = data;
struct pending_cmd *cmd;
@@ -1442,7 +1441,7 @@ unlock:
}
static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
- u16 len)
+ u16 len)
{
struct mgmt_cp_load_link_keys *cp = data;
u16 key_count, expected_len;
@@ -1454,13 +1453,13 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
sizeof(struct mgmt_link_key_info);
if (expected_len != len) {
BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
- len, expected_len);
+ len, expected_len);
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
MGMT_STATUS_INVALID_PARAMS);
}
BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
- key_count);
+ key_count);
hci_dev_lock(hdev);
@@ -1535,10 +1534,10 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
if (cp->disconnect) {
if (cp->addr.type == BDADDR_BREDR)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
- &cp->addr.bdaddr);
+ &cp->addr.bdaddr);
else
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
- &cp->addr.bdaddr);
+ &cp->addr.bdaddr);
} else {
conn = NULL;
}
@@ -1594,11 +1593,12 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
}
if (cp->addr.type == BDADDR_BREDR)
- conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
+ &cp->addr.bdaddr);
else
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
- if (!conn) {
+ if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
err = cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT,
MGMT_STATUS_NOT_CONNECTED);
goto failed;
@@ -1813,7 +1813,7 @@ static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
hdev->io_capability = cp->io_capability;
BT_DBG("%s IO capability set to 0x%02x", hdev->name,
- hdev->io_capability);
+ hdev->io_capability);
hci_dev_unlock(hdev);
@@ -1821,7 +1821,7 @@ static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
0);
}
-static inline struct pending_cmd *find_pairing(struct hci_conn *conn)
+static struct pending_cmd *find_pairing(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
struct pending_cmd *cmd;
@@ -1873,6 +1873,22 @@ static void pairing_complete_cb(struct hci_conn *conn, u8 status)
pairing_complete(cmd, mgmt_status(status));
}
+static void le_connect_complete_cb(struct hci_conn *conn, u8 status)
+{
+ struct pending_cmd *cmd;
+
+ BT_DBG("status %u", status);
+
+ if (!status)
+ return;
+
+ cmd = find_pairing(conn);
+ if (!cmd)
+ BT_DBG("Unable to find a pending command");
+ else
+ pairing_complete(cmd, mgmt_status(status));
+}
+
static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
@@ -1911,8 +1927,15 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
rp.addr.type = cp->addr.type;
if (IS_ERR(conn)) {
+ int status;
+
+ if (PTR_ERR(conn) == -EBUSY)
+ status = MGMT_STATUS_BUSY;
+ else
+ status = MGMT_STATUS_CONNECT_FAILED;
+
err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
- MGMT_STATUS_CONNECT_FAILED, &rp,
+ status, &rp,
sizeof(rp));
goto unlock;
}
@@ -1934,6 +1957,8 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
/* For LE, just connecting isn't a proof that the pairing finished */
if (cp->addr.type == BDADDR_BREDR)
conn->connect_cfm_cb = pairing_complete_cb;
+ else
+ conn->connect_cfm_cb = le_connect_complete_cb;
conn->security_cfm_cb = pairing_complete_cb;
conn->disconn_cfm_cb = pairing_complete_cb;
@@ -1941,7 +1966,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
cmd->user_data = conn;
if (conn->state == BT_CONNECTED &&
- hci_conn_security(conn, sec_level, auth_type))
+ hci_conn_security(conn, sec_level, auth_type))
pairing_complete(cmd, 0);
err = 0;
@@ -2238,7 +2263,7 @@ unlock:
}
static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
- void *data, u16 len)
+ void *data, u16 len)
{
struct mgmt_cp_remove_remote_oob_data *cp = data;
u8 status;
@@ -2407,7 +2432,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
case DISCOVERY_RESOLVING:
e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
- NAME_PENDING);
+ NAME_PENDING);
if (!e) {
mgmt_pending_remove(cmd);
err = cmd_complete(sk, hdev->id,
@@ -2629,7 +2654,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
sizeof(struct mgmt_ltk_info);
if (expected_len != len) {
BT_ERR("load_keys: expected %u bytes, got %u bytes",
- len, expected_len);
+ len, expected_len);
return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
EINVAL);
}
@@ -2754,7 +2779,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
}
if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
- mgmt_handlers[opcode].func == NULL) {
+ mgmt_handlers[opcode].func == NULL) {
BT_DBG("Unknown op %u", opcode);
err = cmd_status(sk, index, opcode,
MGMT_STATUS_UNKNOWN_COMMAND);
@@ -2762,7 +2787,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
}
if ((hdev && opcode < MGMT_OP_READ_INFO) ||
- (!hdev && opcode >= MGMT_OP_READ_INFO)) {
+ (!hdev && opcode >= MGMT_OP_READ_INFO)) {
err = cmd_status(sk, index, opcode,
MGMT_STATUS_INVALID_INDEX);
goto done;
@@ -2771,7 +2796,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
handler = &mgmt_handlers[opcode];
if ((handler->var_len && len < handler->data_len) ||
- (!handler->var_len && len != handler->data_len)) {
+ (!handler->var_len && len != handler->data_len)) {
err = cmd_status(sk, index, opcode,
MGMT_STATUS_INVALID_PARAMS);
goto done;
@@ -2955,7 +2980,7 @@ int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
ev.key.addr.type = BDADDR_BREDR;
ev.key.type = key->type;
- memcpy(ev.key.val, key->val, 16);
+ memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
ev.key.pin_len = key->pin_len;
return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
@@ -3090,7 +3115,7 @@ int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
mgmt_pending_remove(cmd);
mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
- hdev);
+ hdev);
return err;
}
@@ -3180,7 +3205,7 @@ int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
}
int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 link_type, u8 addr_type)
+ u8 link_type, u8 addr_type)
{
struct mgmt_ev_user_passkey_request ev;
@@ -3194,8 +3219,8 @@ int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
}
static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 link_type, u8 addr_type, u8 status,
- u8 opcode)
+ u8 link_type, u8 addr_type, u8 status,
+ u8 opcode)
{
struct pending_cmd *cmd;
struct mgmt_rp_user_confirm_reply rp;
@@ -3226,7 +3251,8 @@ int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u8 status)
{
return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
- status, MGMT_OP_USER_CONFIRM_NEG_REPLY);
+ status,
+ MGMT_OP_USER_CONFIRM_NEG_REPLY);
}
int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
@@ -3240,7 +3266,8 @@ int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u8 status)
{
return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
- status, MGMT_OP_USER_PASSKEY_NEG_REPLY);
+ status,
+ MGMT_OP_USER_PASSKEY_NEG_REPLY);
}
int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 8a602388f1e7..c75107ef8920 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -26,22 +26,8 @@
*/
#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <linux/device.h>
#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/net.h>
-#include <linux/mutex.h>
#include <linux/kthread.h>
-#include <linux/slab.h>
-
-#include <net/sock.h>
-#include <linux/uaccess.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
@@ -115,14 +101,14 @@ static void rfcomm_session_del(struct rfcomm_session *s);
#define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1)
#define __get_rpn_parity(line) (((line) >> 3) & 0x7)
-static inline void rfcomm_schedule(void)
+static void rfcomm_schedule(void)
{
if (!rfcomm_thread)
return;
wake_up_process(rfcomm_thread);
}
-static inline void rfcomm_session_put(struct rfcomm_session *s)
+static void rfcomm_session_put(struct rfcomm_session *s)
{
if (atomic_dec_and_test(&s->refcnt))
rfcomm_session_del(s);
@@ -227,7 +213,7 @@ static int rfcomm_l2sock_create(struct socket **sock)
return err;
}
-static inline int rfcomm_check_security(struct rfcomm_dlc *d)
+static int rfcomm_check_security(struct rfcomm_dlc *d)
{
struct sock *sk = d->session->sock->sk;
struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
@@ -1750,7 +1736,7 @@ static void rfcomm_process_connect(struct rfcomm_session *s)
/* Send data queued for the DLC.
* Return number of frames left in the queue.
*/
-static inline int rfcomm_process_tx(struct rfcomm_dlc *d)
+static int rfcomm_process_tx(struct rfcomm_dlc *d)
{
struct sk_buff *skb;
int err;
@@ -1798,7 +1784,7 @@ static inline int rfcomm_process_tx(struct rfcomm_dlc *d)
return skb_queue_len(&d->tx_queue);
}
-static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
+static void rfcomm_process_dlcs(struct rfcomm_session *s)
{
struct rfcomm_dlc *d;
struct list_head *p, *n;
@@ -1858,7 +1844,7 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
}
}
-static inline void rfcomm_process_rx(struct rfcomm_session *s)
+static void rfcomm_process_rx(struct rfcomm_session *s)
{
struct socket *sock = s->sock;
struct sock *sk = sock->sk;
@@ -1883,7 +1869,7 @@ static inline void rfcomm_process_rx(struct rfcomm_session *s)
}
}
-static inline void rfcomm_accept_connection(struct rfcomm_session *s)
+static void rfcomm_accept_connection(struct rfcomm_session *s)
{
struct socket *sock = s->sock, *nsock;
int err;
@@ -1917,7 +1903,7 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s)
sock_release(nsock);
}
-static inline void rfcomm_check_connection(struct rfcomm_session *s)
+static void rfcomm_check_connection(struct rfcomm_session *s)
{
struct sock *sk = s->sock->sk;
@@ -1941,7 +1927,7 @@ static inline void rfcomm_check_connection(struct rfcomm_session *s)
}
}
-static inline void rfcomm_process_sessions(void)
+static void rfcomm_process_sessions(void)
{
struct list_head *p, *n;
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index e8707debb864..7e1e59645c05 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -25,27 +25,8 @@
* RFCOMM sockets.
*/
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/socket.h>
-#include <linux/skbuff.h>
-#include <linux/list.h>
-#include <linux/device.h>
+#include <linux/export.h>
#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/security.h>
-#include <net/sock.h>
-
-#include <linux/uaccess.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index d1820ff14aee..cb960773c002 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -31,11 +31,6 @@
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
-#include <linux/capability.h>
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/workqueue.h>
-
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/rfcomm.h>
@@ -132,7 +127,7 @@ static struct rfcomm_dev *__rfcomm_dev_get(int id)
return NULL;
}
-static inline struct rfcomm_dev *rfcomm_dev_get(int id)
+static struct rfcomm_dev *rfcomm_dev_get(int id)
{
struct rfcomm_dev *dev;
@@ -345,7 +340,7 @@ static void rfcomm_wfree(struct sk_buff *skb)
tty_port_put(&dev->port);
}
-static inline void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev)
+static void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev)
{
tty_port_get(&dev->port);
atomic_add(skb->truesize, &dev->wmem_alloc);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index cbdd313659a7..40bbe25dcff7 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -25,26 +25,8 @@
/* Bluetooth SCO sockets. */
#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/socket.h>
-#include <linux/skbuff.h>
-#include <linux/device.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
-#include <linux/list.h>
-#include <linux/security.h>
-#include <net/sock.h>
-
-#include <linux/uaccess.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -123,7 +105,7 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
return conn;
}
-static inline struct sock *sco_chan_get(struct sco_conn *conn)
+static struct sock *sco_chan_get(struct sco_conn *conn)
{
struct sock *sk = NULL;
sco_conn_lock(conn);
@@ -157,7 +139,8 @@ static int sco_conn_del(struct hci_conn *hcon, int err)
return 0;
}
-static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
+static int sco_chan_add(struct sco_conn *conn, struct sock *sk,
+ struct sock *parent)
{
int err = 0;
@@ -228,7 +211,7 @@ done:
return err;
}
-static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
+static int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
{
struct sco_conn *conn = sco_pi(sk)->conn;
struct sk_buff *skb;
@@ -254,7 +237,7 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
return len;
}
-static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
+static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
{
struct sock *sk = sco_chan_get(conn);
@@ -523,7 +506,7 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
goto done;
err = bt_sock_wait_state(sk, BT_CONNECTED,
- sock_sndtimeo(sk, flags & O_NONBLOCK));
+ sock_sndtimeo(sk, flags & O_NONBLOCK));
done:
release_sock(sk);
@@ -788,7 +771,7 @@ static int sco_sock_shutdown(struct socket *sock, int how)
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
err = bt_sock_wait_state(sk, BT_CLOSED,
- sk->sk_lingertime);
+ sk->sk_lingertime);
}
release_sock(sk);
return err;
@@ -878,7 +861,7 @@ static void sco_conn_ready(struct sco_conn *conn)
bh_lock_sock(parent);
sk = sco_sock_alloc(sock_net(parent), NULL,
- BTPROTO_SCO, GFP_ATOMIC);
+ BTPROTO_SCO, GFP_ATOMIC);
if (!sk) {
bh_unlock_sock(parent);
goto done;
@@ -907,7 +890,7 @@ done:
/* ----- SCO interface with lower layer (HCI) ----- */
int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
- register struct sock *sk;
+ struct sock *sk;
struct hlist_node *node;
int lm = 0;
@@ -920,7 +903,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
continue;
if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) ||
- !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
+ !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
lm |= HCI_LM_ACCEPT;
break;
}
@@ -981,7 +964,7 @@ static int sco_debugfs_show(struct seq_file *f, void *p)
sk_for_each(sk, node, &sco_sk_list.head) {
seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src),
- batostr(&bt_sk(sk)->dst), sk->sk_state);
+ batostr(&bt_sk(sk)->dst), sk->sk_state);
}
read_unlock(&sco_sk_list.lock);
@@ -1044,8 +1027,8 @@ int __init sco_init(void)
}
if (bt_debugfs) {
- sco_debugfs = debugfs_create_file("sco", 0444,
- bt_debugfs, NULL, &sco_debugfs_fops);
+ sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs,
+ NULL, &sco_debugfs_fops);
if (!sco_debugfs)
BT_ERR("Failed to create SCO debug file");
}
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 6fc7c4708f3e..16ef0dc85a0a 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -20,14 +20,15 @@
SOFTWARE IS DISCLAIMED.
*/
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#include <crypto/b128ops.h>
+
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/mgmt.h>
#include <net/bluetooth/smp.h>
-#include <linux/crypto.h>
-#include <linux/scatterlist.h>
-#include <crypto/b128ops.h>
#define SMP_TIMEOUT msecs_to_jiffies(30000)
@@ -648,7 +649,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
- ret = tk_request(conn, 0, auth, rsp->io_capability, req->io_capability);
+ ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
if (ret)
return SMP_UNSPECIFIED;
@@ -703,7 +704,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
return 0;
}
-static u8 smp_ltk_encrypt(struct l2cap_conn *conn)
+static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
{
struct smp_ltk *key;
struct hci_conn *hcon = conn->hcon;
@@ -712,6 +713,9 @@ static u8 smp_ltk_encrypt(struct l2cap_conn *conn)
if (!key)
return 0;
+ if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated)
+ return 0;
+
if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
return 1;
@@ -732,7 +736,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
- if (smp_ltk_encrypt(conn))
+ if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
return 0;
if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
@@ -771,7 +775,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
return 1;
if (hcon->link_mode & HCI_LM_MASTER)
- if (smp_ltk_encrypt(conn))
+ if (smp_ltk_encrypt(conn, sec_level))
goto done;
if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 8d249d705980..63af25458fda 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -107,6 +107,19 @@ config MAC80211_DEBUGFS
Say N unless you know you need this.
+config MAC80211_MESSAGE_TRACING
+ bool "Trace all mac80211 debug messages"
+ depends on MAC80211
+ ---help---
+ Select this option to have mac80211 register the
+ mac80211_msg trace subsystem with tracepoints to
+ collect all debugging messages, independent of
+ printing them into the kernel log.
+
+ The overhead in this option is that all the messages
+ need to be present in the binary and formatted at
+ runtime for tracing.
+
menuconfig MAC80211_DEBUG_MENU
bool "Select mac80211 debugging features"
depends on MAC80211
@@ -140,26 +153,35 @@ config MAC80211_VERBOSE_DEBUG
Do not select this option.
-config MAC80211_HT_DEBUG
- bool "Verbose HT debugging"
+config MAC80211_MLME_DEBUG
+ bool "Verbose managed MLME output"
depends on MAC80211_DEBUG_MENU
---help---
- This option enables 802.11n High Throughput features
- debug tracing output.
-
- It should not be selected on production systems as some
+ Selecting this option causes mac80211 to print out
+ debugging messages for the managed-mode MLME. It
+ should not be selected on production systems as some
of the messages are remotely triggerable.
Do not select this option.
-config MAC80211_TKIP_DEBUG
- bool "Verbose TKIP debugging"
+config MAC80211_STA_DEBUG
+ bool "Verbose station debugging"
depends on MAC80211_DEBUG_MENU
---help---
Selecting this option causes mac80211 to print out
- very verbose TKIP debugging messages. It should not
- be selected on production systems as those messages
- are remotely triggerable.
+ debugging messages for station addition/removal.
+
+ Do not select this option.
+
+config MAC80211_HT_DEBUG
+ bool "Verbose HT debugging"
+ depends on MAC80211_DEBUG_MENU
+ ---help---
+ This option enables 802.11n High Throughput features
+ debug tracing output.
+
+ It should not be selected on production systems as some
+ of the messages are remotely triggerable.
Do not select this option.
@@ -174,7 +196,7 @@ config MAC80211_IBSS_DEBUG
Do not select this option.
-config MAC80211_VERBOSE_PS_DEBUG
+config MAC80211_PS_DEBUG
bool "Verbose powersave mode debugging"
depends on MAC80211_DEBUG_MENU
---help---
@@ -186,7 +208,7 @@ config MAC80211_VERBOSE_PS_DEBUG
Do not select this option.
-config MAC80211_VERBOSE_MPL_DEBUG
+config MAC80211_MPL_DEBUG
bool "Verbose mesh peer link debugging"
depends on MAC80211_DEBUG_MENU
depends on MAC80211_MESH
@@ -199,7 +221,7 @@ config MAC80211_VERBOSE_MPL_DEBUG
Do not select this option.
-config MAC80211_VERBOSE_MPATH_DEBUG
+config MAC80211_MPATH_DEBUG
bool "Verbose mesh path debugging"
depends on MAC80211_DEBUG_MENU
depends on MAC80211_MESH
@@ -212,7 +234,7 @@ config MAC80211_VERBOSE_MPATH_DEBUG
Do not select this option.
-config MAC80211_VERBOSE_MHWMP_DEBUG
+config MAC80211_MHWMP_DEBUG
bool "Verbose mesh HWMP routing debugging"
depends on MAC80211_DEBUG_MENU
depends on MAC80211_MESH
@@ -225,7 +247,7 @@ config MAC80211_VERBOSE_MHWMP_DEBUG
Do not select this option.
-config MAC80211_VERBOSE_MESH_SYNC_DEBUG
+config MAC80211_MESH_SYNC_DEBUG
bool "Verbose mesh mesh synchronization debugging"
depends on MAC80211_DEBUG_MENU
depends on MAC80211_MESH
@@ -236,7 +258,7 @@ config MAC80211_VERBOSE_MESH_SYNC_DEBUG
Do not select this option.
-config MAC80211_VERBOSE_TDLS_DEBUG
+config MAC80211_TDLS_DEBUG
bool "Verbose TDLS debugging"
depends on MAC80211_DEBUG_MENU
---help---
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 2b1470bac178..a7dd110faafa 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -24,7 +24,7 @@ mac80211-y := \
wme.o \
event.o \
chan.o \
- driver-trace.o mlme.o
+ trace.o mlme.o
mac80211-$(CONFIG_MAC80211_LEDS) += led.o
mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
@@ -42,7 +42,7 @@ mac80211-$(CONFIG_MAC80211_MESH) += \
mac80211-$(CONFIG_PM) += pm.o
-CFLAGS_driver-trace.o := -I$(src)
+CFLAGS_trace.o := -I$(src)
# objects for PID algorithm
rc80211_pid-y := rc80211_pid_algo.o
@@ -58,4 +58,4 @@ mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc80211_pid-y)
mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
mac80211-$(CONFIG_MAC80211_RC_MINSTREL_HT) += $(rc80211_minstrel_ht-y)
-ccflags-y += -D__CHECK_ENDIAN__
+ccflags-y += -D__CHECK_ENDIAN__ -DDEBUG
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 32ef11d69798..186d9919b043 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -74,15 +74,17 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL);
- ht_vdbg("Rx BA session stop requested for %pM tid %u %s reason: %d\n",
- sta->sta.addr, tid,
- initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator",
- (int)reason);
+ ht_dbg(sta->sdata,
+ "Rx BA session stop requested for %pM tid %u %s reason: %d\n",
+ sta->sta.addr, tid,
+ initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator",
+ (int)reason);
if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP,
&sta->sta, tid, NULL, 0))
- pr_debug("HW problem - can not stop rx aggregation for tid %d\n",
- tid);
+ sdata_info(sta->sdata,
+ "HW problem - can not stop rx aggregation for tid %d\n",
+ tid);
/* check if this is a self generated aggregation halt */
if (initiator == WLAN_BACK_RECIPIENT && tx)
@@ -157,7 +159,7 @@ static void sta_rx_agg_session_timer_expired(unsigned long data)
}
rcu_read_unlock();
- ht_vdbg("rx session timer expired on tid %d\n", (u16)*ptid);
+ ht_dbg(sta->sdata, "rx session timer expired on tid %d\n", (u16)*ptid);
set_bit(*ptid, sta->ampdu_mlme.tid_rx_timer_expired);
ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
@@ -245,7 +247,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
status = WLAN_STATUS_REQUEST_DECLINED;
if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
- ht_vdbg("Suspend in progress - Denying ADDBA request\n");
+ ht_dbg(sta->sdata, "Suspend in progress - Denying ADDBA request\n");
goto end_no_lock;
}
@@ -257,10 +259,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
(!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA))) ||
(buf_size > IEEE80211_MAX_AMPDU_BUF)) {
status = WLAN_STATUS_INVALID_QOS_PARAM;
-#ifdef CONFIG_MAC80211_HT_DEBUG
- net_dbg_ratelimited("AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n",
- mgmt->sa, tid, ba_policy, buf_size);
-#endif /* CONFIG_MAC80211_HT_DEBUG */
+ ht_dbg_ratelimited(sta->sdata,
+ "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n",
+ mgmt->sa, tid, ba_policy, buf_size);
goto end_no_lock;
}
/* determine default buffer size */
@@ -275,10 +276,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
mutex_lock(&sta->ampdu_mlme.mtx);
if (sta->ampdu_mlme.tid_rx[tid]) {
-#ifdef CONFIG_MAC80211_HT_DEBUG
- net_dbg_ratelimited("unexpected AddBA Req from %pM on tid %u\n",
- mgmt->sa, tid);
-#endif /* CONFIG_MAC80211_HT_DEBUG */
+ ht_dbg_ratelimited(sta->sdata,
+ "unexpected AddBA Req from %pM on tid %u\n",
+ mgmt->sa, tid);
/* delete existing Rx BA session on the same tid */
___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
@@ -317,7 +317,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START,
&sta->sta, tid, &start_seq_num, 0);
- ht_vdbg("Rx A-MPDU request on tid %d result %d\n", tid, ret);
+ ht_dbg(sta->sdata, "Rx A-MPDU request on tid %d result %d\n", tid, ret);
if (ret) {
kfree(tid_agg_rx->reorder_buf);
kfree(tid_agg_rx->reorder_time);
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index da07f01cfe4d..d0deb3edae21 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -135,7 +135,8 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
bar->control = cpu_to_le16(bar_control);
bar->start_seq_num = cpu_to_le16(ssn);
- IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
+ IEEE80211_TX_CTL_REQ_TX_STATUS;
ieee80211_tx_skb_tid(sdata, skb, tid);
}
EXPORT_SYMBOL(ieee80211_send_bar);
@@ -184,8 +185,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
spin_unlock_bh(&sta->lock);
- ht_vdbg("Tx BA session stop requested for %pM tid %u\n",
- sta->sta.addr, tid);
+ ht_dbg(sta->sdata, "Tx BA session stop requested for %pM tid %u\n",
+ sta->sta.addr, tid);
del_timer_sync(&tid_tx->addba_resp_timer);
del_timer_sync(&tid_tx->session_timer);
@@ -251,12 +252,13 @@ static void sta_addba_resp_timer_expired(unsigned long data)
if (!tid_tx ||
test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) {
rcu_read_unlock();
- ht_vdbg("timer expired on tid %d but we are not (or no longer) expecting addBA response there\n",
- tid);
+ ht_dbg(sta->sdata,
+ "timer expired on tid %d but we are not (or no longer) expecting addBA response there\n",
+ tid);
return;
}
- ht_vdbg("addBA response timer expired on tid %d\n", tid);
+ ht_dbg(sta->sdata, "addBA response timer expired on tid %d\n", tid);
ieee80211_stop_tx_ba_session(&sta->sta, tid);
rcu_read_unlock();
@@ -316,8 +318,9 @@ ieee80211_agg_splice_packets(struct ieee80211_sub_if_data *sdata,
ieee80211_stop_queue_agg(sdata, tid);
- if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates"
- " from the pending queue\n", tid))
+ if (WARN(!tid_tx,
+ "TID %d gone but expected when splicing aggregates from the pending queue\n",
+ tid))
return;
if (!skb_queue_empty(&tid_tx->pending)) {
@@ -365,7 +368,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START,
&sta->sta, tid, &start_seq_num, 0);
if (ret) {
- ht_vdbg("BA request denied - HW unavailable for tid %d\n", tid);
+ ht_dbg(sdata,
+ "BA request denied - HW unavailable for tid %d\n", tid);
spin_lock_bh(&sta->lock);
ieee80211_agg_splice_packets(sdata, tid_tx, tid);
ieee80211_assign_tid_tx(sta, tid, NULL);
@@ -378,7 +382,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
/* activate the timer for the recipient's addBA response */
mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL);
- ht_vdbg("activated addBA response timer on tid %d\n", tid);
+ ht_dbg(sdata, "activated addBA response timer on tid %d\n", tid);
spin_lock_bh(&sta->lock);
sta->ampdu_mlme.last_addba_req_time[tid] = jiffies;
@@ -425,7 +429,7 @@ static void sta_tx_agg_session_timer_expired(unsigned long data)
rcu_read_unlock();
- ht_vdbg("tx session timer expired on tid %d\n", (u16)*ptid);
+ ht_dbg(sta->sdata, "tx session timer expired on tid %d\n", (u16)*ptid);
ieee80211_stop_tx_ba_session(&sta->sta, *ptid);
}
@@ -449,8 +453,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
(local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW))
return -EINVAL;
- ht_vdbg("Open BA session requested for %pM tid %u\n",
- pubsta->addr, tid);
+ ht_dbg(sdata, "Open BA session requested for %pM tid %u\n",
+ pubsta->addr, tid);
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
@@ -460,7 +464,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
return -EINVAL;
if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
- ht_vdbg("BA sessions blocked - Denying BA session request\n");
+ ht_dbg(sdata,
+ "BA sessions blocked - Denying BA session request\n");
return -EINVAL;
}
@@ -478,8 +483,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
*/
if (sta->sdata->vif.type == NL80211_IFTYPE_ADHOC &&
!sta->sta.ht_cap.ht_supported) {
- ht_vdbg("BA request denied - IBSS STA %pM does not advertise HT support\n",
- pubsta->addr);
+ ht_dbg(sdata,
+ "BA request denied - IBSS STA %pM does not advertise HT support\n",
+ pubsta->addr);
return -EINVAL;
}
@@ -499,8 +505,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_BURST_RETRIES &&
time_before(jiffies, sta->ampdu_mlme.last_addba_req_time[tid] +
HT_AGG_RETRIES_PERIOD)) {
- ht_vdbg("BA request denied - waiting a grace period after %d failed requests on tid %u\n",
- sta->ampdu_mlme.addba_req_num[tid], tid);
+ ht_dbg(sdata,
+ "BA request denied - waiting a grace period after %d failed requests on tid %u\n",
+ sta->ampdu_mlme.addba_req_num[tid], tid);
ret = -EBUSY;
goto err_unlock_sta;
}
@@ -508,8 +515,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
/* check if the TID is not in aggregation flow already */
if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) {
- ht_vdbg("BA request denied - session is not idle on tid %u\n",
- tid);
+ ht_dbg(sdata,
+ "BA request denied - session is not idle on tid %u\n",
+ tid);
ret = -EAGAIN;
goto err_unlock_sta;
}
@@ -564,7 +572,7 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
- ht_vdbg("Aggregation is on for tid %d\n", tid);
+ ht_dbg(sta->sdata, "Aggregation is on for tid %d\n", tid);
drv_ampdu_action(local, sta->sdata,
IEEE80211_AMPDU_TX_OPERATIONAL,
@@ -598,7 +606,8 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
trace_api_start_tx_ba_cb(sdata, ra, tid);
if (tid >= STA_TID_NUM) {
- ht_vdbg("Bad TID value: tid = %d (>= %d)\n", tid, STA_TID_NUM);
+ ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n",
+ tid, STA_TID_NUM);
return;
}
@@ -606,7 +615,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
sta = sta_info_get_bss(sdata, ra);
if (!sta) {
mutex_unlock(&local->sta_mtx);
- ht_vdbg("Could not find station: %pM\n", ra);
+ ht_dbg(sdata, "Could not find station: %pM\n", ra);
return;
}
@@ -614,7 +623,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
if (WARN_ON(!tid_tx)) {
- ht_vdbg("addBA was not requested!\n");
+ ht_dbg(sdata, "addBA was not requested!\n");
goto unlock;
}
@@ -714,17 +723,18 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
trace_api_stop_tx_ba_cb(sdata, ra, tid);
if (tid >= STA_TID_NUM) {
- ht_vdbg("Bad TID value: tid = %d (>= %d)\n", tid, STA_TID_NUM);
+ ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n",
+ tid, STA_TID_NUM);
return;
}
- ht_vdbg("Stopping Tx BA session for %pM tid %d\n", ra, tid);
+ ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n", ra, tid);
mutex_lock(&local->sta_mtx);
sta = sta_info_get_bss(sdata, ra);
if (!sta) {
- ht_vdbg("Could not find station: %pM\n", ra);
+ ht_dbg(sdata, "Could not find station: %pM\n", ra);
goto unlock;
}
@@ -733,7 +743,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
- ht_vdbg("unexpected callback to A-MPDU stop\n");
+ ht_dbg(sdata, "unexpected callback to A-MPDU stop\n");
goto unlock_sta;
}
@@ -809,13 +819,13 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
goto out;
if (mgmt->u.action.u.addba_resp.dialog_token != tid_tx->dialog_token) {
- ht_vdbg("wrong addBA response token, tid %d\n", tid);
+ ht_dbg(sta->sdata, "wrong addBA response token, tid %d\n", tid);
goto out;
}
del_timer_sync(&tid_tx->addba_resp_timer);
- ht_vdbg("switched off addBA timer for tid %d\n", tid);
+ ht_dbg(sta->sdata, "switched off addBA timer for tid %d\n", tid);
/*
* addba_resp_timer may have fired before we got here, and
@@ -824,8 +834,9 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
*/
if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) ||
test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
- ht_vdbg("got addBA resp for tid %d but we already gave up\n",
- tid);
+ ht_dbg(sta->sdata,
+ "got addBA resp for tid %d but we already gave up\n",
+ tid);
goto out;
}
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 498c94e34427..cfdc03f59e27 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -20,31 +20,31 @@
#include "rate.h"
#include "mesh.h"
-static struct net_device *ieee80211_add_iface(struct wiphy *wiphy, char *name,
- enum nl80211_iftype type,
- u32 *flags,
- struct vif_params *params)
+static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, char *name,
+ enum nl80211_iftype type,
+ u32 *flags,
+ struct vif_params *params)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
- struct net_device *dev;
+ struct wireless_dev *wdev;
struct ieee80211_sub_if_data *sdata;
int err;
- err = ieee80211_if_add(local, name, &dev, type, params);
+ err = ieee80211_if_add(local, name, &wdev, type, params);
if (err)
return ERR_PTR(err);
if (type == NL80211_IFTYPE_MONITOR && flags) {
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
sdata->u.mntr_flags = *flags;
}
- return dev;
+ return wdev;
}
-static int ieee80211_del_iface(struct wiphy *wiphy, struct net_device *dev)
+static int ieee80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
{
- ieee80211_if_remove(IEEE80211_DEV_TO_SUB_IF(dev));
+ ieee80211_if_remove(IEEE80211_WDEV_TO_SUB_IF(wdev));
return 0;
}
@@ -353,6 +353,7 @@ void sta_set_rate_info_tx(struct sta_info *sta,
static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
+ struct ieee80211_local *local = sdata->local;
struct timespec uptime;
sinfo->generation = sdata->local->sta_generation;
@@ -388,7 +389,9 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) ||
(sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) {
sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG;
- sinfo->signal = (s8)sta->last_signal;
+ if (!local->ops->get_rssi ||
+ drv_get_rssi(local, sdata, &sta->sta, &sinfo->signal))
+ sinfo->signal = (s8)sta->last_signal;
sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
}
@@ -517,7 +520,7 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
* network device.
*/
- rcu_read_lock();
+ mutex_lock(&local->sta_mtx);
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid);
@@ -546,7 +549,7 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
data[i] = (u8)sinfo.signal_avg;
i++;
} else {
- list_for_each_entry_rcu(sta, &local->sta_list, list) {
+ list_for_each_entry(sta, &local->sta_list, list) {
/* Make sure this station belongs to the proper dev */
if (sta->sdata->dev != dev)
continue;
@@ -603,7 +606,7 @@ do_survey:
else
data[i++] = -1LL;
- rcu_read_unlock();
+ mutex_unlock(&local->sta_mtx);
if (WARN_ON(i != STA_STATS_LEN))
return;
@@ -629,10 +632,11 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
int idx, u8 *mac, struct station_info *sinfo)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
int ret = -ENOENT;
- rcu_read_lock();
+ mutex_lock(&local->sta_mtx);
sta = sta_info_get_by_idx(sdata, idx);
if (sta) {
@@ -641,7 +645,7 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
sta_set_sinfo(sta, sinfo);
}
- rcu_read_unlock();
+ mutex_unlock(&local->sta_mtx);
return ret;
}
@@ -658,10 +662,11 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
u8 *mac, struct station_info *sinfo)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
int ret = -ENOENT;
- rcu_read_lock();
+ mutex_lock(&local->sta_mtx);
sta = sta_info_get_bss(sdata, mac);
if (sta) {
@@ -669,7 +674,7 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
sta_set_sinfo(sta, sinfo);
}
- rcu_read_unlock();
+ mutex_unlock(&local->sta_mtx);
return ret;
}
@@ -689,7 +694,8 @@ static int ieee80211_set_channel(struct wiphy *wiphy,
case CHAN_MODE_HOPPING:
return -EBUSY;
case CHAN_MODE_FIXED:
- if (local->oper_channel != chan)
+ if (local->oper_channel != chan ||
+ (!sdata && local->_oper_channel_type != channel_type))
return -EBUSY;
if (!sdata && local->_oper_channel_type == channel_type)
return 0;
@@ -1529,7 +1535,7 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask))
conf->dot11MeshTTL = nconf->dot11MeshTTL;
if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask))
- conf->dot11MeshTTL = nconf->element_ttl;
+ conf->element_ttl = nconf->element_ttl;
if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask))
conf->auto_open_plinks = nconf->auto_open_plinks;
if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask))
@@ -1564,17 +1570,16 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
* announcements, so require this ifmsh to also be a root node
* */
if (nconf->dot11MeshGateAnnouncementProtocol &&
- !conf->dot11MeshHWMPRootMode) {
- conf->dot11MeshHWMPRootMode = 1;
+ !(conf->dot11MeshHWMPRootMode > IEEE80211_ROOTMODE_ROOT)) {
+ conf->dot11MeshHWMPRootMode = IEEE80211_PROACTIVE_RANN;
ieee80211_mesh_root_setup(ifmsh);
}
conf->dot11MeshGateAnnouncementProtocol =
nconf->dot11MeshGateAnnouncementProtocol;
}
- if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) {
+ if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask))
conf->dot11MeshHWMPRannInterval =
nconf->dot11MeshHWMPRannInterval;
- }
if (_chg_mesh_attr(NL80211_MESHCONF_FORWARDING, mask))
conf->dot11MeshForwarding = nconf->dot11MeshForwarding;
if (_chg_mesh_attr(NL80211_MESHCONF_RSSI_THRESHOLD, mask)) {
@@ -1590,6 +1595,15 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
sdata->vif.bss_conf.ht_operation_mode = nconf->ht_opmode;
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT);
}
+ if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, mask))
+ conf->dot11MeshHWMPactivePathToRootTimeout =
+ nconf->dot11MeshHWMPactivePathToRootTimeout;
+ if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ROOT_INTERVAL, mask))
+ conf->dot11MeshHWMProotInterval =
+ nconf->dot11MeshHWMProotInterval;
+ if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, mask))
+ conf->dot11MeshHWMPconfirmationInterval =
+ nconf->dot11MeshHWMPconfirmationInterval;
return 0;
}
@@ -1727,6 +1741,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
return -EINVAL;
}
+ ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
+
return 0;
}
@@ -1747,10 +1763,11 @@ static int ieee80211_resume(struct wiphy *wiphy)
#endif
static int ieee80211_scan(struct wiphy *wiphy,
- struct net_device *dev,
struct cfg80211_scan_request *req)
{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_sub_if_data *sdata;
+
+ sdata = IEEE80211_WDEV_TO_SUB_IF(req->wdev);
switch (ieee80211_vif_type_p2p(&sdata->vif)) {
case NL80211_IFTYPE_STATION:
@@ -2097,6 +2114,9 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
int i, ret;
+ if (!ieee80211_sdata_running(sdata))
+ return -ENETDOWN;
+
if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) {
ret = drv_set_bitrate_mask(local, sdata, mask);
if (ret)
@@ -2280,13 +2300,13 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
}
static int ieee80211_remain_on_channel(struct wiphy *wiphy,
- struct net_device *dev,
+ struct wireless_dev *wdev,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration,
u64 *cookie)
{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
struct ieee80211_local *local = sdata->local;
int ret;
@@ -2306,6 +2326,21 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
mutex_lock(&local->mtx);
list_for_each_entry_safe(roc, tmp, &local->roc_list, list) {
+ struct ieee80211_roc_work *dep, *tmp2;
+
+ list_for_each_entry_safe(dep, tmp2, &roc->dependents, list) {
+ if (!mgmt_tx && (unsigned long)dep != cookie)
+ continue;
+ else if (mgmt_tx && dep->mgmt_tx_cookie != cookie)
+ continue;
+ /* found dependent item -- just remove it */
+ list_del(&dep->list);
+ mutex_unlock(&local->mtx);
+
+ ieee80211_roc_notify_destroy(dep);
+ return 0;
+ }
+
if (!mgmt_tx && (unsigned long)roc != cookie)
continue;
else if (mgmt_tx && roc->mgmt_tx_cookie != cookie)
@@ -2320,6 +2355,13 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
return -ENOENT;
}
+ /*
+ * We found the item to cancel, so do that. Note that it
+ * may have dependents, which we also cancel (and send
+ * the expired signal for.) Not doing so would be quite
+ * tricky here, but we may need to fix it later.
+ */
+
if (local->ops->remain_on_channel) {
if (found->started) {
ret = drv_cancel_remain_on_channel(local);
@@ -2331,8 +2373,8 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
list_del(&found->list);
- ieee80211_run_deferred_scan(local);
- ieee80211_start_next_roc(local);
+ if (found->started)
+ ieee80211_start_next_roc(local);
mutex_unlock(&local->mtx);
ieee80211_roc_notify_destroy(found);
@@ -2351,23 +2393,23 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
}
static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
- struct net_device *dev,
+ struct wireless_dev *wdev,
u64 cookie)
{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
struct ieee80211_local *local = sdata->local;
return ieee80211_cancel_roc(local, cookie, false);
}
-static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
+static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type,
bool channel_type_valid, unsigned int wait,
const u8 *buf, size_t len, bool no_cck,
bool dont_wait_for_ack, u64 *cookie)
{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct sta_info *sta;
@@ -2472,30 +2514,43 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
}
static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
- struct net_device *dev,
+ struct wireless_dev *wdev,
u64 cookie)
{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_local *local = sdata->local;
+ struct ieee80211_local *local = wiphy_priv(wiphy);
return ieee80211_cancel_roc(local, cookie, true);
}
static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
- struct net_device *dev,
+ struct wireless_dev *wdev,
u16 frame_type, bool reg)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
- if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
- return;
+ switch (frame_type) {
+ case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH:
+ if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+ struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- if (reg)
- local->probe_req_reg++;
- else
- local->probe_req_reg--;
+ if (reg)
+ ifibss->auth_frame_registrations++;
+ else
+ ifibss->auth_frame_registrations--;
+ }
+ break;
+ case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ:
+ if (reg)
+ local->probe_req_reg++;
+ else
+ local->probe_req_reg--;
- ieee80211_queue_work(&local->hw, &local->reconfig_filter);
+ ieee80211_queue_work(&local->hw, &local->reconfig_filter);
+ break;
+ default:
+ break;
+ }
}
static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
@@ -2615,8 +2670,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
tf->u.setup_req.capability =
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
- ieee80211_add_srates_ie(&sdata->vif, skb, false);
- ieee80211_add_ext_srates_ie(&sdata->vif, skb, false);
+ ieee80211_add_srates_ie(sdata, skb, false);
+ ieee80211_add_ext_srates_ie(sdata, skb, false);
ieee80211_tdls_add_ext_capab(skb);
break;
case WLAN_TDLS_SETUP_RESPONSE:
@@ -2629,8 +2684,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
tf->u.setup_resp.capability =
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
- ieee80211_add_srates_ie(&sdata->vif, skb, false);
- ieee80211_add_ext_srates_ie(&sdata->vif, skb, false);
+ ieee80211_add_srates_ie(sdata, skb, false);
+ ieee80211_add_ext_srates_ie(sdata, skb, false);
ieee80211_tdls_add_ext_capab(skb);
break;
case WLAN_TDLS_SETUP_CONFIRM:
@@ -2690,8 +2745,8 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
mgmt->u.action.u.tdls_discover_resp.capability =
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
- ieee80211_add_srates_ie(&sdata->vif, skb, false);
- ieee80211_add_ext_srates_ie(&sdata->vif, skb, false);
+ ieee80211_add_srates_ie(sdata, skb, false);
+ ieee80211_add_ext_srates_ie(sdata, skb, false);
ieee80211_tdls_add_ext_capab(skb);
break;
default:
@@ -2721,9 +2776,8 @@ static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
!sdata->u.mgd.associated)
return -EINVAL;
-#ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG
- pr_debug("TDLS mgmt action %d peer %pM\n", action_code, peer);
-#endif
+ tdls_dbg(sdata, "TDLS mgmt action %d peer %pM\n",
+ action_code, peer);
skb = dev_alloc_skb(local->hw.extra_tx_headroom +
max(sizeof(struct ieee80211_mgmt),
@@ -2832,9 +2886,7 @@ static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
if (sdata->vif.type != NL80211_IFTYPE_STATION)
return -EINVAL;
-#ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG
- pr_debug("TDLS oper %d peer %pM\n", oper, peer);
-#endif
+ tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer);
switch (oper) {
case NL80211_TDLS_ENABLE_LINK:
@@ -2930,14 +2982,14 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
return 0;
}
-static struct ieee80211_channel *
-ieee80211_wiphy_get_channel(struct wiphy *wiphy,
- enum nl80211_channel_type *type)
+static void ieee80211_set_monitor_enabled(struct wiphy *wiphy, bool enabled)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
- *type = local->_oper_channel_type;
- return local->oper_channel;
+ if (enabled)
+ WARN_ON(ieee80211_add_virtual_monitor(local));
+ else
+ ieee80211_del_virtual_monitor(local);
}
#ifdef CONFIG_PM
@@ -3013,8 +3065,8 @@ struct cfg80211_ops mac80211_config_ops = {
.tdls_oper = ieee80211_tdls_oper,
.tdls_mgmt = ieee80211_tdls_mgmt,
.probe_client = ieee80211_probe_client,
- .get_channel = ieee80211_wiphy_get_channel,
.set_noack_map = ieee80211_set_noack_map,
+ .set_monitor_enabled = ieee80211_set_monitor_enabled,
#ifdef CONFIG_PM
.set_wakeup = ieee80211_set_wakeup,
#endif
diff --git a/net/mac80211/debug.h b/net/mac80211/debug.h
new file mode 100644
index 000000000000..8f383a576016
--- /dev/null
+++ b/net/mac80211/debug.h
@@ -0,0 +1,170 @@
+#ifndef __MAC80211_DEBUG_H
+#define __MAC80211_DEBUG_H
+#include <net/cfg80211.h>
+
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+#define MAC80211_IBSS_DEBUG 1
+#else
+#define MAC80211_IBSS_DEBUG 0
+#endif
+
+#ifdef CONFIG_MAC80211_PS_DEBUG
+#define MAC80211_PS_DEBUG 1
+#else
+#define MAC80211_PS_DEBUG 0
+#endif
+
+#ifdef CONFIG_MAC80211_HT_DEBUG
+#define MAC80211_HT_DEBUG 1
+#else
+#define MAC80211_HT_DEBUG 0
+#endif
+
+#ifdef CONFIG_MAC80211_MPL_DEBUG
+#define MAC80211_MPL_DEBUG 1
+#else
+#define MAC80211_MPL_DEBUG 0
+#endif
+
+#ifdef CONFIG_MAC80211_MPATH_DEBUG
+#define MAC80211_MPATH_DEBUG 1
+#else
+#define MAC80211_MPATH_DEBUG 0
+#endif
+
+#ifdef CONFIG_MAC80211_MHWMP_DEBUG
+#define MAC80211_MHWMP_DEBUG 1
+#else
+#define MAC80211_MHWMP_DEBUG 0
+#endif
+
+#ifdef CONFIG_MAC80211_MESH_SYNC_DEBUG
+#define MAC80211_MESH_SYNC_DEBUG 1
+#else
+#define MAC80211_MESH_SYNC_DEBUG 0
+#endif
+
+#ifdef CONFIG_MAC80211_TDLS_DEBUG
+#define MAC80211_TDLS_DEBUG 1
+#else
+#define MAC80211_TDLS_DEBUG 0
+#endif
+
+#ifdef CONFIG_MAC80211_STA_DEBUG
+#define MAC80211_STA_DEBUG 1
+#else
+#define MAC80211_STA_DEBUG 0
+#endif
+
+#ifdef CONFIG_MAC80211_MLME_DEBUG
+#define MAC80211_MLME_DEBUG 1
+#else
+#define MAC80211_MLME_DEBUG 0
+#endif
+
+#ifdef CONFIG_MAC80211_MESSAGE_TRACING
+void __sdata_info(const char *fmt, ...) __printf(1, 2);
+void __sdata_dbg(bool print, const char *fmt, ...) __printf(2, 3);
+void __sdata_err(const char *fmt, ...) __printf(1, 2);
+void __wiphy_dbg(struct wiphy *wiphy, bool print, const char *fmt, ...)
+ __printf(3, 4);
+
+#define _sdata_info(sdata, fmt, ...) \
+ __sdata_info("%s: " fmt, (sdata)->name, ##__VA_ARGS__)
+#define _sdata_dbg(print, sdata, fmt, ...) \
+ __sdata_dbg(print, "%s: " fmt, (sdata)->name, ##__VA_ARGS__)
+#define _sdata_err(sdata, fmt, ...) \
+ __sdata_err("%s: " fmt, (sdata)->name, ##__VA_ARGS__)
+#define _wiphy_dbg(print, wiphy, fmt, ...) \
+ __wiphy_dbg(wiphy, print, fmt, ##__VA_ARGS__)
+#else
+#define _sdata_info(sdata, fmt, ...) \
+do { \
+ pr_info("%s: " fmt, \
+ (sdata)->name, ##__VA_ARGS__); \
+} while (0)
+
+#define _sdata_dbg(print, sdata, fmt, ...) \
+do { \
+ if (print) \
+ pr_debug("%s: " fmt, \
+ (sdata)->name, ##__VA_ARGS__); \
+} while (0)
+
+#define _sdata_err(sdata, fmt, ...) \
+do { \
+ pr_err("%s: " fmt, \
+ (sdata)->name, ##__VA_ARGS__); \
+} while (0)
+
+#define _wiphy_dbg(print, wiphy, fmt, ...) \
+do { \
+ if (print) \
+ wiphy_dbg((wiphy), fmt, ##__VA_ARGS__); \
+} while (0)
+#endif
+
+#define sdata_info(sdata, fmt, ...) \
+ _sdata_info(sdata, fmt, ##__VA_ARGS__)
+#define sdata_err(sdata, fmt, ...) \
+ _sdata_err(sdata, fmt, ##__VA_ARGS__)
+#define sdata_dbg(sdata, fmt, ...) \
+ _sdata_dbg(1, sdata, fmt, ##__VA_ARGS__)
+
+#define ht_dbg(sdata, fmt, ...) \
+ _sdata_dbg(MAC80211_HT_DEBUG, \
+ sdata, fmt, ##__VA_ARGS__)
+
+#define ht_dbg_ratelimited(sdata, fmt, ...) \
+ _sdata_dbg(MAC80211_HT_DEBUG && net_ratelimit(), \
+ sdata, fmt, ##__VA_ARGS__)
+
+#define ibss_dbg(sdata, fmt, ...) \
+ _sdata_dbg(MAC80211_IBSS_DEBUG, \
+ sdata, fmt, ##__VA_ARGS__)
+
+#define ps_dbg(sdata, fmt, ...) \
+ _sdata_dbg(MAC80211_PS_DEBUG, \
+ sdata, fmt, ##__VA_ARGS__)
+
+#define ps_dbg_hw(hw, fmt, ...) \
+ _wiphy_dbg(MAC80211_PS_DEBUG, \
+ (hw)->wiphy, fmt, ##__VA_ARGS__)
+
+#define ps_dbg_ratelimited(sdata, fmt, ...) \
+ _sdata_dbg(MAC80211_PS_DEBUG && net_ratelimit(), \
+ sdata, fmt, ##__VA_ARGS__)
+
+#define mpl_dbg(sdata, fmt, ...) \
+ _sdata_dbg(MAC80211_MPL_DEBUG, \
+ sdata, fmt, ##__VA_ARGS__)
+
+#define mpath_dbg(sdata, fmt, ...) \
+ _sdata_dbg(MAC80211_MPATH_DEBUG, \
+ sdata, fmt, ##__VA_ARGS__)
+
+#define mhwmp_dbg(sdata, fmt, ...) \
+ _sdata_dbg(MAC80211_MHWMP_DEBUG, \
+ sdata, fmt, ##__VA_ARGS__)
+
+#define msync_dbg(sdata, fmt, ...) \
+ _sdata_dbg(MAC80211_MESH_SYNC_DEBUG, \
+ sdata, fmt, ##__VA_ARGS__)
+
+#define tdls_dbg(sdata, fmt, ...) \
+ _sdata_dbg(MAC80211_TDLS_DEBUG, \
+ sdata, fmt, ##__VA_ARGS__)
+
+#define sta_dbg(sdata, fmt, ...) \
+ _sdata_dbg(MAC80211_STA_DEBUG, \
+ sdata, fmt, ##__VA_ARGS__)
+
+#define mlme_dbg(sdata, fmt, ...) \
+ _sdata_dbg(MAC80211_MLME_DEBUG, \
+ sdata, fmt, ##__VA_ARGS__)
+
+#define mlme_dbg_ratelimited(sdata, fmt, ...) \
+ _sdata_dbg(MAC80211_MLME_DEBUG && net_ratelimit(), \
+ sdata, fmt, ##__VA_ARGS__)
+
+#endif /* __MAC80211_DEBUG_H */
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 778e5916d7c3..b8dfb440c8ef 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -325,8 +325,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
local->rx_handlers_drop_defrag);
DEBUGFS_STATS_ADD(rx_handlers_drop_short,
local->rx_handlers_drop_short);
- DEBUGFS_STATS_ADD(rx_handlers_drop_passive_scan,
- local->rx_handlers_drop_passive_scan);
DEBUGFS_STATS_ADD(tx_expand_skb_head,
local->tx_expand_skb_head);
DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned,
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 7932767bb482..090d08ff22c4 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -283,6 +283,11 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
lockdep_assert_held(&sdata->local->key_mtx);
+ if (sdata->debugfs.default_unicast_key) {
+ debugfs_remove(sdata->debugfs.default_unicast_key);
+ sdata->debugfs.default_unicast_key = NULL;
+ }
+
if (sdata->default_unicast_key) {
key = key_mtx_dereference(sdata->local,
sdata->default_unicast_key);
@@ -290,9 +295,11 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
sdata->debugfs.default_unicast_key =
debugfs_create_symlink("default_unicast_key",
sdata->debugfs.dir, buf);
- } else {
- debugfs_remove(sdata->debugfs.default_unicast_key);
- sdata->debugfs.default_unicast_key = NULL;
+ }
+
+ if (sdata->debugfs.default_multicast_key) {
+ debugfs_remove(sdata->debugfs.default_multicast_key);
+ sdata->debugfs.default_multicast_key = NULL;
}
if (sdata->default_multicast_key) {
@@ -302,9 +309,6 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
sdata->debugfs.default_multicast_key =
debugfs_create_symlink("default_multicast_key",
sdata->debugfs.dir, buf);
- } else {
- debugfs_remove(sdata->debugfs.default_multicast_key);
- sdata->debugfs.default_multicast_key = NULL;
}
}
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index d4272ff43f71..6d5aec9418ee 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -468,48 +468,54 @@ IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC);
IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC);
IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC);
IEEE80211_IF_FILE(dropped_frames_congestion,
- u.mesh.mshstats.dropped_frames_congestion, DEC);
+ u.mesh.mshstats.dropped_frames_congestion, DEC);
IEEE80211_IF_FILE(dropped_frames_no_route,
- u.mesh.mshstats.dropped_frames_no_route, DEC);
+ u.mesh.mshstats.dropped_frames_no_route, DEC);
IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC);
/* Mesh parameters */
IEEE80211_IF_FILE(dot11MeshMaxRetries,
- u.mesh.mshcfg.dot11MeshMaxRetries, DEC);
+ u.mesh.mshcfg.dot11MeshMaxRetries, DEC);
IEEE80211_IF_FILE(dot11MeshRetryTimeout,
- u.mesh.mshcfg.dot11MeshRetryTimeout, DEC);
+ u.mesh.mshcfg.dot11MeshRetryTimeout, DEC);
IEEE80211_IF_FILE(dot11MeshConfirmTimeout,
- u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC);
+ u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC);
IEEE80211_IF_FILE(dot11MeshHoldingTimeout,
- u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC);
+ u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC);
IEEE80211_IF_FILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC);
IEEE80211_IF_FILE(element_ttl, u.mesh.mshcfg.element_ttl, DEC);
IEEE80211_IF_FILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC);
IEEE80211_IF_FILE(dot11MeshMaxPeerLinks,
- u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC);
+ u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPactivePathTimeout,
- u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC);
+ u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPpreqMinInterval,
- u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC);
+ u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPperrMinInterval,
- u.mesh.mshcfg.dot11MeshHWMPperrMinInterval, DEC);
+ u.mesh.mshcfg.dot11MeshHWMPperrMinInterval, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPnetDiameterTraversalTime,
- u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC);
+ u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPmaxPREQretries,
- u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC);
+ u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC);
IEEE80211_IF_FILE(path_refresh_time,
- u.mesh.mshcfg.path_refresh_time, DEC);
+ u.mesh.mshcfg.path_refresh_time, DEC);
IEEE80211_IF_FILE(min_discovery_timeout,
- u.mesh.mshcfg.min_discovery_timeout, DEC);
+ u.mesh.mshcfg.min_discovery_timeout, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPRootMode,
- u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC);
+ u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC);
IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol,
- u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC);
+ u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
- u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
+ u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC);
IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC);
IEEE80211_IF_FILE(ht_opmode, u.mesh.mshcfg.ht_opmode, DEC);
+IEEE80211_IF_FILE(dot11MeshHWMPactivePathToRootTimeout,
+ u.mesh.mshcfg.dot11MeshHWMPactivePathToRootTimeout, DEC);
+IEEE80211_IF_FILE(dot11MeshHWMProotInterval,
+ u.mesh.mshcfg.dot11MeshHWMProotInterval, DEC);
+IEEE80211_IF_FILE(dot11MeshHWMPconfirmationInterval,
+ u.mesh.mshcfg.dot11MeshHWMPconfirmationInterval, DEC);
#endif
#define DEBUGFS_ADD_MODE(name, mode) \
@@ -611,6 +617,9 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol);
MESHPARAMS_ADD(rssi_threshold);
MESHPARAMS_ADD(ht_opmode);
+ MESHPARAMS_ADD(dot11MeshHWMPactivePathToRootTimeout);
+ MESHPARAMS_ADD(dot11MeshHWMProotInterval);
+ MESHPARAMS_ADD(dot11MeshHWMPconfirmationInterval);
#undef MESHPARAMS_ADD
}
#endif
@@ -686,6 +695,7 @@ void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
sprintf(buf, "netdev:%s", sdata->name);
if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf))
- pr_err("mac80211: debugfs: failed to rename debugfs "
- "dir to %s\n", buf);
+ sdata_err(sdata,
+ "debugfs: failed to rename debugfs dir to %s\n",
+ buf);
}
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 6d33a0c743ab..df9203199102 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -3,7 +3,7 @@
#include <net/mac80211.h>
#include "ieee80211_i.h"
-#include "driver-trace.h"
+#include "trace.h"
static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata)
{
@@ -27,14 +27,6 @@ static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb)
local->ops->tx(&local->hw, skb);
}
-static inline void drv_tx_frags(struct ieee80211_local *local,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct sk_buff_head *skbs)
-{
- local->ops->tx_frags(&local->hw, vif, sta, skbs);
-}
-
static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata,
u32 sset, u8 *data)
{
@@ -845,4 +837,33 @@ drv_allow_buffered_frames(struct ieee80211_local *local,
more_data);
trace_drv_return_void(local);
}
+
+static inline int drv_get_rssi(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta *sta,
+ s8 *rssi_dbm)
+{
+ int ret;
+
+ might_sleep();
+
+ ret = local->ops->get_rssi(&local->hw, &sdata->vif, sta, rssi_dbm);
+ trace_drv_get_rssi(local, sta, *rssi_dbm, ret);
+
+ return ret;
+}
+
+static inline void drv_mgd_prepare_tx(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata)
+{
+ might_sleep();
+
+ check_sdata_in_driver(sdata);
+ WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION);
+
+ trace_drv_mgd_prepare_tx(local, sdata);
+ if (local->ops->mgd_prepare_tx)
+ local->ops->mgd_prepare_tx(&local->hw, &sdata->vif);
+ trace_drv_return_void(local);
+}
#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/driver-trace.c b/net/mac80211/driver-trace.c
deleted file mode 100644
index 8ed8711b1a6d..000000000000
--- a/net/mac80211/driver-trace.c
+++ /dev/null
@@ -1,9 +0,0 @@
-/* bug in tracepoint.h, it should include this */
-#include <linux/module.h>
-
-/* sparse isn't too happy with all macros... */
-#ifndef __CHECKER__
-#include "driver-ops.h"
-#define CREATE_TRACE_POINTS
-#include "driver-trace.h"
-#endif
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 6f8615c54b22..4b4538d63925 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -305,12 +305,10 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11;
-#ifdef CONFIG_MAC80211_HT_DEBUG
- net_dbg_ratelimited("delba from %pM (%s) tid %d reason code %d\n",
- mgmt->sa, initiator ? "initiator" : "recipient",
- tid,
- le16_to_cpu(mgmt->u.action.u.delba.reason_code));
-#endif /* CONFIG_MAC80211_HT_DEBUG */
+ ht_dbg_ratelimited(sdata, "delba from %pM (%s) tid %d reason code %d\n",
+ mgmt->sa, initiator ? "initiator" : "recipient",
+ tid,
+ le16_to_cpu(mgmt->u.action.u.delba.reason_code));
if (initiator == WLAN_BACK_INITIATOR)
__ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0,
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 725cb4be229d..5746d62faba1 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -261,11 +261,7 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta,
memcpy(addr, sta->sta.addr, ETH_ALEN);
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- wiphy_debug(sdata->local->hw.wiphy,
- "Adding new IBSS station %pM (dev=%s)\n",
- addr, sdata->name);
-#endif
+ ibss_dbg(sdata, "Adding new IBSS station %pM\n", addr);
sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
@@ -279,9 +275,10 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta,
/* If it fails, maybe we raced another insertion? */
if (sta_info_insert_rcu(sta))
return sta_info_get(sdata, addr);
- if (auth) {
- ibss_vdbg("TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n",
- sdata->vif.addr, sdata->u.ibss.bssid, addr);
+ if (auth && !sdata->u.ibss.auth_frame_registrations) {
+ ibss_dbg(sdata,
+ "TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n",
+ sdata->vif.addr, sdata->u.ibss.bssid, addr);
ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, NULL, 0,
addr, sdata->u.ibss.bssid, NULL, 0, 0);
}
@@ -304,7 +301,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
* allow new one to be added.
*/
if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
- net_dbg_ratelimited("%s: No room for a new IBSS STA entry %pM\n",
+ net_info_ratelimited("%s: No room for a new IBSS STA entry %pM\n",
sdata->name, addr);
rcu_read_lock();
return NULL;
@@ -351,9 +348,9 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1)
return;
- ibss_vdbg("%s: RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n",
- sdata->name, mgmt->sa, mgmt->da, mgmt->bssid,
- auth_transaction);
+ ibss_dbg(sdata,
+ "RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n",
+ mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction);
sta_info_destroy_addr(sdata, mgmt->sa);
ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false);
rcu_read_unlock();
@@ -416,10 +413,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
ieee80211_mandatory_rates(local, band);
if (sta->sta.supp_rates[band] != prev_rates) {
- ibss_vdbg("%s: updated supp_rates set for %pM based on beacon/probe_resp (0x%x -> 0x%x)\n",
- sdata->name, sta->sta.addr,
- prev_rates,
- sta->sta.supp_rates[band]);
+ ibss_dbg(sdata,
+ "updated supp_rates set for %pM based on beacon/probe_resp (0x%x -> 0x%x)\n",
+ sta->sta.addr, prev_rates,
+ sta->sta.supp_rates[band]);
rates_updated = true;
}
} else {
@@ -534,16 +531,18 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
rx_timestamp = drv_get_tsf(local, sdata);
}
- ibss_vdbg("RX beacon SA=%pM BSSID=%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n",
- mgmt->sa, mgmt->bssid,
- (unsigned long long)rx_timestamp,
- (unsigned long long)beacon_timestamp,
- (unsigned long long)(rx_timestamp - beacon_timestamp),
- jiffies);
+ ibss_dbg(sdata,
+ "RX beacon SA=%pM BSSID=%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n",
+ mgmt->sa, mgmt->bssid,
+ (unsigned long long)rx_timestamp,
+ (unsigned long long)beacon_timestamp,
+ (unsigned long long)(rx_timestamp - beacon_timestamp),
+ jiffies);
if (beacon_timestamp > rx_timestamp) {
- ibss_vdbg("%s: beacon TSF higher than local TSF - IBSS merge with BSSID %pM\n",
- sdata->name, mgmt->bssid);
+ ibss_dbg(sdata,
+ "beacon TSF higher than local TSF - IBSS merge with BSSID %pM\n",
+ mgmt->bssid);
ieee80211_sta_join_ibss(sdata, bss);
supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL);
ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
@@ -569,7 +568,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
* allow new one to be added.
*/
if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
- net_dbg_ratelimited("%s: No room for a new IBSS STA entry %pM\n",
+ net_info_ratelimited("%s: No room for a new IBSS STA entry %pM\n",
sdata->name, addr);
return;
}
@@ -645,8 +644,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
if (ifibss->fixed_channel)
return;
- pr_debug("%s: No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n",
- sdata->name);
+ sdata_info(sdata,
+ "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n");
ieee80211_request_internal_scan(sdata,
ifibss->ssid, ifibss->ssid_len, NULL);
@@ -674,8 +673,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
bssid[0] |= 0x02;
}
- pr_debug("%s: Creating new IBSS network, BSSID %pM\n",
- sdata->name, bssid);
+ sdata_info(sdata, "Creating new IBSS network, BSSID %pM\n", bssid);
capability = WLAN_CAPABILITY_IBSS;
@@ -706,8 +704,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
lockdep_assert_held(&ifibss->mtx);
active_ibss = ieee80211_sta_active_ibss(sdata);
- ibss_vdbg("%s: sta_find_ibss (active_ibss=%d)\n",
- sdata->name, active_ibss);
+ ibss_dbg(sdata, "sta_find_ibss (active_ibss=%d)\n", active_ibss);
if (active_ibss)
return;
@@ -730,23 +727,24 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
struct ieee80211_bss *bss;
bss = (void *)cbss->priv;
- ibss_vdbg(" sta_find_ibss: selected %pM current %pM\n",
- cbss->bssid, ifibss->bssid);
- pr_debug("%s: Selected IBSS BSSID %pM based on configured SSID\n",
- sdata->name, cbss->bssid);
+ ibss_dbg(sdata,
+ "sta_find_ibss: selected %pM current %pM\n",
+ cbss->bssid, ifibss->bssid);
+ sdata_info(sdata,
+ "Selected IBSS BSSID %pM based on configured SSID\n",
+ cbss->bssid);
ieee80211_sta_join_ibss(sdata, bss);
ieee80211_rx_bss_put(local, bss);
return;
}
- ibss_vdbg(" did not try to join ibss\n");
+ ibss_dbg(sdata, "sta_find_ibss: did not try to join ibss\n");
/* Selected IBSS not found in current scan results - try to scan */
if (time_after(jiffies, ifibss->last_scan_completed +
IEEE80211_SCAN_INTERVAL)) {
- pr_debug("%s: Trigger new scan to find an IBSS to join\n",
- sdata->name);
+ sdata_info(sdata, "Trigger new scan to find an IBSS to join\n");
ieee80211_request_internal_scan(sdata,
ifibss->ssid, ifibss->ssid_len,
@@ -760,9 +758,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
ieee80211_sta_create_ibss(sdata);
return;
}
- pr_debug("%s: IBSS not allowed on %d MHz\n",
- sdata->name,
- local->hw.conf.channel->center_freq);
+ sdata_info(sdata, "IBSS not allowed on %d MHz\n",
+ local->hw.conf.channel->center_freq);
/* No IBSS found - decrease scan interval and continue
* scanning. */
@@ -797,9 +794,9 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
tx_last_beacon = drv_tx_last_beacon(local);
- ibss_vdbg("%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM (tx_last_beacon=%d)\n",
- sdata->name, mgmt->sa, mgmt->da,
- mgmt->bssid, tx_last_beacon);
+ ibss_dbg(sdata,
+ "RX ProbeReq SA=%pM DA=%pM BSSID=%pM (tx_last_beacon=%d)\n",
+ mgmt->sa, mgmt->da, mgmt->bssid, tx_last_beacon);
if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da))
return;
@@ -812,8 +809,8 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
pos = mgmt->u.probe_req.variable;
if (pos[0] != WLAN_EID_SSID ||
pos + 2 + pos[1] > end) {
- ibss_vdbg("%s: Invalid SSID IE in ProbeReq from %pM\n",
- sdata->name, mgmt->sa);
+ ibss_dbg(sdata, "Invalid SSID IE in ProbeReq from %pM\n",
+ mgmt->sa);
return;
}
if (pos[1] != 0 &&
@@ -830,7 +827,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
resp = (struct ieee80211_mgmt *) skb->data;
memcpy(resp->da, mgmt->sa, ETH_ALEN);
- ibss_vdbg("%s: Sending ProbeResp to %pM\n", sdata->name, resp->da);
+ ibss_dbg(sdata, "Sending ProbeResp to %pM\n", resp->da);
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
ieee80211_tx_skb(sdata, skb);
}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e6cbf5b68c89..7998513ec831 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -30,6 +30,7 @@
#include <net/mac80211.h>
#include "key.h"
#include "sta_info.h"
+#include "debug.h"
struct ieee80211_local;
@@ -55,11 +56,14 @@ struct ieee80211_local;
#define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024))
#define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x))
+/*
+ * Some APs experience problems when working with U-APSD. Decrease the
+ * probability of that happening by using legacy mode for all ACs but VO.
+ * The AP that caused us trouble was a Cisco 4410N. It ignores our
+ * setting, and always treats non-VO ACs as legacy.
+ */
#define IEEE80211_DEFAULT_UAPSD_QUEUES \
- (IEEE80211_WMM_IE_STA_QOSINFO_AC_BK | \
- IEEE80211_WMM_IE_STA_QOSINFO_AC_BE | \
- IEEE80211_WMM_IE_STA_QOSINFO_AC_VI | \
- IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
+ IEEE80211_WMM_IE_STA_QOSINFO_AC_VO
#define IEEE80211_DEFAULT_MAX_SP_LEN \
IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL
@@ -81,6 +85,8 @@ struct ieee80211_bss {
size_t ssid_len;
u8 ssid[IEEE80211_MAX_SSID_LEN];
+ u32 device_ts;
+
u8 dtim_period;
bool wmm_used;
@@ -203,7 +209,6 @@ typedef unsigned __bitwise__ ieee80211_rx_result;
* enum ieee80211_packet_rx_flags - packet RX flags
* @IEEE80211_RX_RA_MATCH: frame is destined to interface currently processed
* (incl. multicast frames)
- * @IEEE80211_RX_IN_SCAN: received while scanning
* @IEEE80211_RX_FRAGMENTED: fragmented frame
* @IEEE80211_RX_AMSDU: a-MSDU packet
* @IEEE80211_RX_MALFORMED_ACTION_FRM: action frame is malformed
@@ -213,7 +218,6 @@ typedef unsigned __bitwise__ ieee80211_rx_result;
* @rx_flags field of &struct ieee80211_rx_status.
*/
enum ieee80211_packet_rx_flags {
- IEEE80211_RX_IN_SCAN = BIT(0),
IEEE80211_RX_RA_MATCH = BIT(1),
IEEE80211_RX_FRAGMENTED = BIT(2),
IEEE80211_RX_AMSDU = BIT(3),
@@ -508,6 +512,7 @@ struct ieee80211_if_ibss {
bool privacy;
bool control_port;
+ unsigned int auth_frame_registrations;
u8 bssid[ETH_ALEN] __aligned(2);
u8 ssid[IEEE80211_MAX_SSID_LEN];
@@ -677,6 +682,9 @@ struct ieee80211_sub_if_data {
/* TID bitmap for NoAck policy */
u16 noack_map;
+ /* bit field of ACM bits (BIT(802.1D tag)) */
+ u8 wmm_acm;
+
struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
struct ieee80211_key __rcu *default_unicast_key;
struct ieee80211_key __rcu *default_multicast_key;
@@ -881,6 +889,9 @@ struct ieee80211_local {
/* device is started */
bool started;
+ /* device is during a HW reconfig */
+ bool in_reconfig;
+
/* wowlan is enabled -- don't reconfig on resume */
bool wowlan;
@@ -954,14 +965,14 @@ struct ieee80211_local {
int scan_channel_idx;
int scan_ies_len;
- bool sched_scanning;
struct ieee80211_sched_scan_ies sched_scan_ies;
struct work_struct sched_scan_stopped_work;
+ struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
unsigned long leave_oper_channel_time;
enum mac80211_scan_state next_scan_state;
struct delayed_work scan_work;
- struct ieee80211_sub_if_data *scan_sdata;
+ struct ieee80211_sub_if_data __rcu *scan_sdata;
enum nl80211_channel_type _oper_channel_type;
struct ieee80211_channel *oper_channel, *csa_channel;
@@ -1003,7 +1014,6 @@ struct ieee80211_local {
unsigned int rx_handlers_drop_nullfunc;
unsigned int rx_handlers_drop_defrag;
unsigned int rx_handlers_drop_short;
- unsigned int rx_handlers_drop_passive_scan;
unsigned int tx_expand_skb_head;
unsigned int tx_expand_skb_head_cloned;
unsigned int rx_expand_skb_head;
@@ -1019,7 +1029,6 @@ struct ieee80211_local {
int total_ps_buffered; /* total number of all buffered unicast and
* multicast packets for power saving stations
*/
- unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
bool pspolling;
bool offchannel_ps_enabled;
@@ -1081,6 +1090,12 @@ IEEE80211_DEV_TO_SUB_IF(struct net_device *dev)
return netdev_priv(dev);
}
+static inline struct ieee80211_sub_if_data *
+IEEE80211_WDEV_TO_SUB_IF(struct wireless_dev *wdev)
+{
+ return container_of(wdev, struct ieee80211_sub_if_data, wdev);
+}
+
/* this struct represents 802.11n's RA/TID combination */
struct ieee80211_ra_tid {
u8 ra[ETH_ALEN];
@@ -1231,8 +1246,7 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
struct cfg80211_scan_request *req);
void ieee80211_scan_cancel(struct ieee80211_local *local);
void ieee80211_run_deferred_scan(struct ieee80211_local *local);
-ieee80211_rx_result
-ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
+void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb);
void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local);
struct ieee80211_bss *
@@ -1268,13 +1282,12 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
int ieee80211_iface_init(void);
void ieee80211_iface_exit(void);
int ieee80211_if_add(struct ieee80211_local *local, const char *name,
- struct net_device **new_dev, enum nl80211_iftype type,
+ struct wireless_dev **new_wdev, enum nl80211_iftype type,
struct vif_params *params);
int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
enum nl80211_iftype type);
void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata);
void ieee80211_remove_interfaces(struct ieee80211_local *local);
-u32 __ieee80211_recalc_idle(struct ieee80211_local *local);
void ieee80211_recalc_idle(struct ieee80211_local *local);
void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
const int offset);
@@ -1471,6 +1484,16 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
struct ieee80211_channel *channel,
enum nl80211_channel_type channel_type,
u16 prot_mode);
+u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
+ u32 cap);
+int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, bool need_basic);
+int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, bool need_basic);
+
+/* virtual monitor */
+int ieee80211_add_virtual_monitor(struct ieee80211_local *local);
+void ieee80211_del_virtual_monitor(struct ieee80211_local *local);
/* channel management */
enum ieee80211_chan_mode {
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 87aeb4f21ffd..334ee0fb18ca 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -43,6 +43,128 @@
*/
+static u32 ieee80211_idle_off(struct ieee80211_local *local,
+ const char *reason)
+{
+ if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
+ return 0;
+
+ local->hw.conf.flags &= ~IEEE80211_CONF_IDLE;
+ return IEEE80211_CONF_CHANGE_IDLE;
+}
+
+static u32 ieee80211_idle_on(struct ieee80211_local *local)
+{
+ if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
+ return 0;
+
+ drv_flush(local, false);
+
+ local->hw.conf.flags |= IEEE80211_CONF_IDLE;
+ return IEEE80211_CONF_CHANGE_IDLE;
+}
+
+static u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
+{
+ struct ieee80211_sub_if_data *sdata;
+ int count = 0;
+ bool working = false, scanning = false;
+ unsigned int led_trig_start = 0, led_trig_stop = 0;
+ struct ieee80211_roc_work *roc;
+
+#ifdef CONFIG_PROVE_LOCKING
+ WARN_ON(debug_locks && !lockdep_rtnl_is_held() &&
+ !lockdep_is_held(&local->iflist_mtx));
+#endif
+ lockdep_assert_held(&local->mtx);
+
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!ieee80211_sdata_running(sdata)) {
+ sdata->vif.bss_conf.idle = true;
+ continue;
+ }
+
+ sdata->old_idle = sdata->vif.bss_conf.idle;
+
+ /* do not count disabled managed interfaces */
+ if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+ !sdata->u.mgd.associated &&
+ !sdata->u.mgd.auth_data &&
+ !sdata->u.mgd.assoc_data) {
+ sdata->vif.bss_conf.idle = true;
+ continue;
+ }
+ /* do not count unused IBSS interfaces */
+ if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
+ !sdata->u.ibss.ssid_len) {
+ sdata->vif.bss_conf.idle = true;
+ continue;
+ }
+ /* count everything else */
+ sdata->vif.bss_conf.idle = false;
+ count++;
+ }
+
+ if (!local->ops->remain_on_channel) {
+ list_for_each_entry(roc, &local->roc_list, list) {
+ working = true;
+ roc->sdata->vif.bss_conf.idle = false;
+ }
+ }
+
+ sdata = rcu_dereference_protected(local->scan_sdata,
+ lockdep_is_held(&local->mtx));
+ if (sdata && !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) {
+ scanning = true;
+ sdata->vif.bss_conf.idle = false;
+ }
+
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ continue;
+ if (sdata->old_idle == sdata->vif.bss_conf.idle)
+ continue;
+ if (!ieee80211_sdata_running(sdata))
+ continue;
+ ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
+ }
+
+ if (working || scanning)
+ led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK;
+ else
+ led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK;
+
+ if (count)
+ led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
+ else
+ led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
+
+ ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop);
+
+ if (working)
+ return ieee80211_idle_off(local, "working");
+ if (scanning)
+ return ieee80211_idle_off(local, "scanning");
+ if (!count)
+ return ieee80211_idle_on(local);
+ else
+ return ieee80211_idle_off(local, "in use");
+
+ return 0;
+}
+
+void ieee80211_recalc_idle(struct ieee80211_local *local)
+{
+ u32 chg;
+
+ mutex_lock(&local->iflist_mtx);
+ chg = __ieee80211_recalc_idle(local);
+ mutex_unlock(&local->iflist_mtx);
+ if (chg)
+ ieee80211_hw_config(local, chg);
+}
+
static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
{
int meshhdrlen;
@@ -57,9 +179,6 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
return -EINVAL;
}
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- pr_debug("%s: setting MTU %d\n", dev->name, new_mtu);
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
dev->mtu = new_mtu;
return 0;
}
@@ -100,15 +219,12 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_sub_if_data *nsdata;
- struct net_device *dev = sdata->dev;
ASSERT_RTNL();
/* we hold the RTNL here so can safely walk the list */
list_for_each_entry(nsdata, &local->interfaces, list) {
- struct net_device *ndev = nsdata->dev;
-
- if (ndev != dev && ieee80211_sdata_running(nsdata)) {
+ if (nsdata != sdata && ieee80211_sdata_running(nsdata)) {
/*
* Allow only a single IBSS interface to be up at any
* time. This is restricted because beacon distribution
@@ -127,7 +243,8 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
* The remaining checks are only performed for interfaces
* with the same MAC address.
*/
- if (!ether_addr_equal(dev->dev_addr, ndev->dev_addr))
+ if (!ether_addr_equal(sdata->vif.addr,
+ nsdata->vif.addr))
continue;
/*
@@ -214,20 +331,24 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
}
-static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
+int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata;
- int ret;
+ int ret = 0;
if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
return 0;
+ mutex_lock(&local->iflist_mtx);
+
if (local->monitor_sdata)
- return 0;
+ goto out_unlock;
sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
- if (!sdata)
- return -ENOMEM;
+ if (!sdata) {
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
/* set up data */
sdata->local = local;
@@ -241,31 +362,34 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
if (WARN_ON(ret)) {
/* ok .. stupid driver, it asked for this! */
kfree(sdata);
- return ret;
+ goto out_unlock;
}
ret = ieee80211_check_queues(sdata);
if (ret) {
kfree(sdata);
- return ret;
+ goto out_unlock;
}
rcu_assign_pointer(local->monitor_sdata, sdata);
-
- return 0;
+ out_unlock:
+ mutex_unlock(&local->iflist_mtx);
+ return ret;
}
-static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
+void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata;
if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
return;
- sdata = rtnl_dereference(local->monitor_sdata);
+ mutex_lock(&local->iflist_mtx);
+ sdata = rcu_dereference_protected(local->monitor_sdata,
+ lockdep_is_held(&local->iflist_mtx));
if (!sdata)
- return;
+ goto out_unlock;
rcu_assign_pointer(local->monitor_sdata, NULL);
synchronize_net();
@@ -273,6 +397,8 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
drv_remove_interface(local, sdata);
kfree(sdata);
+ out_unlock:
+ mutex_unlock(&local->iflist_mtx);
}
/*
@@ -371,12 +497,6 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
break;
}
- if (local->monitors == 0 && local->open_count == 0) {
- res = ieee80211_add_virtual_monitor(local);
- if (res)
- goto err_stop;
- }
-
/* must be before the call to ieee80211_configure_filter */
local->monitors++;
if (local->monitors == 1) {
@@ -391,8 +511,6 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
break;
default:
if (coming_up) {
- ieee80211_del_virtual_monitor(local);
-
res = drv_add_interface(local, sdata);
if (res)
goto err_stop;
@@ -520,7 +638,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
clear_bit(SDATA_STATE_RUNNING, &sdata->state);
- if (local->scan_sdata == sdata)
+ if (rcu_access_pointer(local->scan_sdata) == sdata)
ieee80211_scan_cancel(local);
/*
@@ -627,7 +745,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
if (local->monitors == 0) {
local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR;
hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
- ieee80211_del_virtual_monitor(local);
}
ieee80211_adjust_monitor_flags(sdata, -1);
@@ -701,9 +818,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
}
}
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
-
- if (local->monitors == local->open_count && local->monitors > 0)
- ieee80211_add_virtual_monitor(local);
}
static int ieee80211_stop(struct net_device *dev)
@@ -808,7 +922,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev,
hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
- return ieee80211_select_queue_80211(local, skb, hdr);
+ return ieee80211_select_queue_80211(sdata, skb, hdr);
}
static const struct net_device_ops ieee80211_monitorif_ops = {
@@ -1223,7 +1337,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
if (__ffs64(mask) + hweight64(mask) != fls64(mask)) {
/* not a contiguous mask ... not handled now! */
- pr_debug("not contiguous\n");
+ pr_info("not contiguous\n");
break;
}
@@ -1269,7 +1383,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
}
int ieee80211_if_add(struct ieee80211_local *local, const char *name,
- struct net_device **new_dev, enum nl80211_iftype type,
+ struct wireless_dev **new_wdev, enum nl80211_iftype type,
struct vif_params *params)
{
struct net_device *ndev;
@@ -1359,8 +1473,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
list_add_tail_rcu(&sdata->list, &local->interfaces);
mutex_unlock(&local->iflist_mtx);
- if (new_dev)
- *new_dev = ndev;
+ if (new_wdev)
+ *new_wdev = &sdata->wdev;
return 0;
@@ -1408,135 +1522,6 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
list_del(&unreg_list);
}
-static u32 ieee80211_idle_off(struct ieee80211_local *local,
- const char *reason)
-{
- if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
- return 0;
-
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- wiphy_debug(local->hw.wiphy, "device no longer idle - %s\n", reason);
-#endif
-
- local->hw.conf.flags &= ~IEEE80211_CONF_IDLE;
- return IEEE80211_CONF_CHANGE_IDLE;
-}
-
-static u32 ieee80211_idle_on(struct ieee80211_local *local)
-{
- if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
- return 0;
-
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- wiphy_debug(local->hw.wiphy, "device now idle\n");
-#endif
-
- drv_flush(local, false);
-
- local->hw.conf.flags |= IEEE80211_CONF_IDLE;
- return IEEE80211_CONF_CHANGE_IDLE;
-}
-
-u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
-{
- struct ieee80211_sub_if_data *sdata;
- int count = 0;
- bool working = false, scanning = false;
- unsigned int led_trig_start = 0, led_trig_stop = 0;
- struct ieee80211_roc_work *roc;
-
-#ifdef CONFIG_PROVE_LOCKING
- WARN_ON(debug_locks && !lockdep_rtnl_is_held() &&
- !lockdep_is_held(&local->iflist_mtx));
-#endif
- lockdep_assert_held(&local->mtx);
-
- list_for_each_entry(sdata, &local->interfaces, list) {
- if (!ieee80211_sdata_running(sdata)) {
- sdata->vif.bss_conf.idle = true;
- continue;
- }
-
- sdata->old_idle = sdata->vif.bss_conf.idle;
-
- /* do not count disabled managed interfaces */
- if (sdata->vif.type == NL80211_IFTYPE_STATION &&
- !sdata->u.mgd.associated &&
- !sdata->u.mgd.auth_data &&
- !sdata->u.mgd.assoc_data) {
- sdata->vif.bss_conf.idle = true;
- continue;
- }
- /* do not count unused IBSS interfaces */
- if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
- !sdata->u.ibss.ssid_len) {
- sdata->vif.bss_conf.idle = true;
- continue;
- }
- /* count everything else */
- sdata->vif.bss_conf.idle = false;
- count++;
- }
-
- if (!local->ops->remain_on_channel) {
- list_for_each_entry(roc, &local->roc_list, list) {
- working = true;
- roc->sdata->vif.bss_conf.idle = false;
- }
- }
-
- if (local->scan_sdata &&
- !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) {
- scanning = true;
- local->scan_sdata->vif.bss_conf.idle = false;
- }
-
- list_for_each_entry(sdata, &local->interfaces, list) {
- if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
- sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- continue;
- if (sdata->old_idle == sdata->vif.bss_conf.idle)
- continue;
- if (!ieee80211_sdata_running(sdata))
- continue;
- ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
- }
-
- if (working || scanning)
- led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK;
- else
- led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK;
-
- if (count)
- led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
- else
- led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
-
- ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop);
-
- if (working)
- return ieee80211_idle_off(local, "working");
- if (scanning)
- return ieee80211_idle_off(local, "scanning");
- if (!count)
- return ieee80211_idle_on(local);
- else
- return ieee80211_idle_off(local, "in use");
-
- return 0;
-}
-
-void ieee80211_recalc_idle(struct ieee80211_local *local)
-{
- u32 chg;
-
- mutex_lock(&local->iflist_mtx);
- chg = __ieee80211_recalc_idle(local);
- mutex_unlock(&local->iflist_mtx);
- if (chg)
- ieee80211_hw_config(local, chg);
-}
-
static int netdev_notify(struct notifier_block *nb,
unsigned long state,
void *ndev)
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 5bb600d93d77..7ae678ba5d67 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -139,7 +139,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
}
if (ret != -ENOSPC && ret != -EOPNOTSUPP)
- wiphy_err(key->local->hw.wiphy,
+ sdata_err(sdata,
"failed to set key (%d, %pM) to hardware (%d)\n",
key->conf.keyidx,
sta ? sta->sta.addr : bcast_addr, ret);
@@ -186,7 +186,7 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
sta ? &sta->sta : NULL, &key->conf);
if (ret)
- wiphy_err(key->local->hw.wiphy,
+ sdata_err(sdata,
"failed to remove key (%d, %pM) from hardware (%d)\n",
key->conf.keyidx,
sta ? sta->sta.addr : bcast_addr, ret);
@@ -194,26 +194,6 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
}
-void ieee80211_key_removed(struct ieee80211_key_conf *key_conf)
-{
- struct ieee80211_key *key;
-
- key = container_of(key_conf, struct ieee80211_key, conf);
-
- might_sleep();
- assert_key_lock(key->local);
-
- key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
-
- /*
- * Flush TX path to avoid attempts to use this key
- * after this function returns. Until then, drivers
- * must be prepared to handle the key.
- */
- synchronize_rcu();
-}
-EXPORT_SYMBOL_GPL(ieee80211_key_removed);
-
static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
int idx, bool uni, bool multi)
{
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index d81c178c7712..c26e231c733a 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -322,7 +322,8 @@ static void ieee80211_restart_work(struct work_struct *work)
mutex_lock(&local->mtx);
WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
- local->sched_scanning,
+ rcu_dereference_protected(local->sched_scan_sdata,
+ lockdep_is_held(&local->mtx)),
"%s called with hardware scan in progress\n", __func__);
mutex_unlock(&local->mtx);
@@ -345,6 +346,13 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
ieee80211_stop_queues_by_reason(hw,
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
+ /*
+ * Stop all Rx during the reconfig. We don't want state changes
+ * or driver callbacks while this is in progress.
+ */
+ local->in_reconfig = true;
+ barrier();
+
schedule_work(&local->restart_work);
}
EXPORT_SYMBOL(ieee80211_restart_hw);
@@ -455,7 +463,9 @@ static const struct ieee80211_txrx_stypes
ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
[NL80211_IFTYPE_ADHOC] = {
.tx = 0xffff,
- .rx = BIT(IEEE80211_STYPE_ACTION >> 4),
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4) |
+ BIT(IEEE80211_STYPE_DEAUTH >> 4),
},
[NL80211_IFTYPE_STATION] = {
.tx = 0xffff,
@@ -578,7 +588,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN);
- BUG_ON(!ops->tx && !ops->tx_frags);
+ BUG_ON(!ops->tx);
BUG_ON(!ops->start);
BUG_ON(!ops->stop);
BUG_ON(!ops->config);
@@ -679,7 +689,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
int result, i;
enum ieee80211_band band;
int channels, max_bitrates;
- bool supp_ht;
+ bool supp_ht, supp_vht;
netdev_features_t feature_whitelist;
static const u32 cipher_suites[] = {
/* keep WEP first, it may be removed below */
@@ -697,12 +707,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
local->hw.offchannel_tx_hw_queue >= local->hw.queues))
return -EINVAL;
- if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns)
#ifdef CONFIG_PM
- && (!local->ops->suspend || !local->ops->resume)
-#endif
- )
+ if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) &&
+ (!local->ops->suspend || !local->ops->resume))
return -EINVAL;
+#endif
if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan)
return -EINVAL;
@@ -724,6 +733,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
channels = 0;
max_bitrates = 0;
supp_ht = false;
+ supp_vht = false;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
struct ieee80211_supported_band *sband;
@@ -741,6 +751,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (max_bitrates < sband->n_bitrates)
max_bitrates = sband->n_bitrates;
supp_ht = supp_ht || sband->ht_cap.ht_supported;
+ supp_vht = supp_vht || sband->vht_cap.vht_supported;
}
local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
@@ -816,6 +827,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (supp_ht)
local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap);
+ if (supp_vht)
+ local->scan_ies_len +=
+ 2 + sizeof(struct ieee80211_vht_capabilities);
+
if (!local->ops->hw_scan) {
/* For hw_scan, driver needs to set these up. */
local->hw.wiphy->max_scan_ssids = 4;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 7cf19509fb68..764593d65fc3 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -443,7 +443,7 @@ static void ieee80211_mesh_path_root_timer(unsigned long data)
void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
{
- if (ifmsh->mshcfg.dot11MeshHWMPRootMode)
+ if (ifmsh->mshcfg.dot11MeshHWMPRootMode > IEEE80211_ROOTMODE_ROOT)
set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
else {
clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
@@ -523,10 +523,6 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
{
bool free_plinks;
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- pr_debug("%s: running mesh housekeeping\n", sdata->name);
-#endif
-
ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT);
mesh_path_expire(sdata);
@@ -541,11 +537,17 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ u32 interval;
mesh_path_tx_root_frame(sdata);
+
+ if (ifmsh->mshcfg.dot11MeshHWMPRootMode == IEEE80211_PROACTIVE_RANN)
+ interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
+ else
+ interval = ifmsh->mshcfg.dot11MeshHWMProotInterval;
+
mod_timer(&ifmsh->mesh_path_root_timer,
- round_jiffies(TU_TO_EXP_TIME(
- ifmsh->mshcfg.dot11MeshHWMPRannInterval)));
+ round_jiffies(TU_TO_EXP_TIME(interval)));
}
#ifdef CONFIG_PM
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index e3642756f8f4..faaa39bcfd10 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -104,6 +104,7 @@ enum mesh_deferred_task_flags {
* an mpath to a hash bucket on a path table.
* @rann_snd_addr: the RANN sender address
* @rann_metric: the aggregated path metric towards the root node
+ * @last_preq_to_root: Timestamp of last PREQ sent to root
* @is_root: the destination station of this path is a root node
* @is_gate: the destination station of this path is a mesh gate
*
@@ -131,6 +132,7 @@ struct mesh_path {
spinlock_t state_lock;
u8 rann_snd_addr[ETH_ALEN];
u32 rann_metric;
+ unsigned long last_preq_to_root;
bool is_root;
bool is_gate;
};
@@ -245,7 +247,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
void ieee80211s_init(void);
void ieee80211s_update_metric(struct ieee80211_local *local,
- struct sta_info *stainfo, struct sk_buff *skb);
+ struct sta_info *sta, struct sk_buff *skb);
void ieee80211s_stop(void);
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index fa7c58035246..fb7b6a11d0ba 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -13,13 +13,6 @@
#include "wme.h"
#include "mesh.h"
-#ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG
-#define mhwmp_dbg(fmt, args...) \
- pr_debug("Mesh HWMP (%s): " fmt "\n", sdata->name, ##args)
-#else
-#define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0)
-#endif
-
#define TEST_FRAME_LEN 8192
#define MAX_METRIC 0xffffffff
#define ARITH_SHIFT 8
@@ -98,6 +91,8 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae)
#define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries)
#define disc_timeout_jiff(s) \
msecs_to_jiffies(sdata->u.mesh.mshcfg.min_discovery_timeout)
+#define root_path_confirmation_jiffies(s) \
+ msecs_to_jiffies(sdata->u.mesh.mshcfg.dot11MeshHWMPconfirmationInterval)
enum mpath_frame_type {
MPATH_PREQ = 0,
@@ -142,19 +137,19 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
switch (action) {
case MPATH_PREQ:
- mhwmp_dbg("sending PREQ to %pM", target);
+ mhwmp_dbg(sdata, "sending PREQ to %pM\n", target);
ie_len = 37;
pos = skb_put(skb, 2 + ie_len);
*pos++ = WLAN_EID_PREQ;
break;
case MPATH_PREP:
- mhwmp_dbg("sending PREP to %pM", target);
+ mhwmp_dbg(sdata, "sending PREP to %pM\n", target);
ie_len = 31;
pos = skb_put(skb, 2 + ie_len);
*pos++ = WLAN_EID_PREP;
break;
case MPATH_RANN:
- mhwmp_dbg("sending RANN from %pM", orig_addr);
+ mhwmp_dbg(sdata, "sending RANN from %pM\n", orig_addr);
ie_len = sizeof(struct ieee80211_rann_ie);
pos = skb_put(skb, 2 + ie_len);
*pos++ = WLAN_EID_RANN;
@@ -303,7 +298,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
}
void ieee80211s_update_metric(struct ieee80211_local *local,
- struct sta_info *stainfo, struct sk_buff *skb)
+ struct sta_info *sta, struct sk_buff *skb)
{
struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -315,15 +310,14 @@ void ieee80211s_update_metric(struct ieee80211_local *local,
failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);
/* moving average, scaled to 100 */
- stainfo->fail_avg = ((80 * stainfo->fail_avg + 5) / 100 + 20 * failed);
- if (stainfo->fail_avg > 95)
- mesh_plink_broken(stainfo);
+ sta->fail_avg = ((80 * sta->fail_avg + 5) / 100 + 20 * failed);
+ if (sta->fail_avg > 95)
+ mesh_plink_broken(sta);
}
static u32 airtime_link_metric_get(struct ieee80211_local *local,
struct sta_info *sta)
{
- struct ieee80211_supported_band *sband;
struct rate_info rinfo;
/* This should be adjusted for each device */
int device_constant = 1 << ARITH_SHIFT;
@@ -333,8 +327,6 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
u32 tx_time, estimated_retx;
u64 result;
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
if (sta->fail_avg >= 100)
return MAX_METRIC;
@@ -519,10 +511,11 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
struct mesh_path *mpath = NULL;
u8 *target_addr, *orig_addr;
const u8 *da;
- u8 target_flags, ttl;
- u32 orig_sn, target_sn, lifetime;
+ u8 target_flags, ttl, flags;
+ u32 orig_sn, target_sn, lifetime, orig_metric;
bool reply = false;
bool forward = true;
+ bool root_is_gate;
/* Update target SN, if present */
target_addr = PREQ_IE_TARGET_ADDR(preq_elem);
@@ -530,11 +523,15 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
target_sn = PREQ_IE_TARGET_SN(preq_elem);
orig_sn = PREQ_IE_ORIG_SN(preq_elem);
target_flags = PREQ_IE_TARGET_F(preq_elem);
+ orig_metric = metric;
+ /* Proactive PREQ gate announcements */
+ flags = PREQ_IE_FLAGS(preq_elem);
+ root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
- mhwmp_dbg("received PREQ from %pM", orig_addr);
+ mhwmp_dbg(sdata, "received PREQ from %pM\n", orig_addr);
if (ether_addr_equal(target_addr, sdata->vif.addr)) {
- mhwmp_dbg("PREQ is for us");
+ mhwmp_dbg(sdata, "PREQ is for us\n");
forward = false;
reply = true;
metric = 0;
@@ -544,6 +541,22 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
target_sn = ++ifmsh->sn;
ifmsh->last_sn_update = jiffies;
}
+ } else if (is_broadcast_ether_addr(target_addr) &&
+ (target_flags & IEEE80211_PREQ_TO_FLAG)) {
+ rcu_read_lock();
+ mpath = mesh_path_lookup(orig_addr, sdata);
+ if (mpath) {
+ if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) {
+ reply = true;
+ target_addr = sdata->vif.addr;
+ target_sn = ++ifmsh->sn;
+ metric = 0;
+ ifmsh->last_sn_update = jiffies;
+ }
+ if (root_is_gate)
+ mesh_path_add_gate(mpath);
+ }
+ rcu_read_unlock();
} else {
rcu_read_lock();
mpath = mesh_path_lookup(target_addr, sdata);
@@ -570,19 +583,20 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
lifetime = PREQ_IE_LIFETIME(preq_elem);
ttl = ifmsh->mshcfg.element_ttl;
if (ttl != 0) {
- mhwmp_dbg("replying to the PREQ");
+ mhwmp_dbg(sdata, "replying to the PREQ\n");
mesh_path_sel_frame_tx(MPATH_PREP, 0, orig_addr,
cpu_to_le32(orig_sn), 0, target_addr,
cpu_to_le32(target_sn), mgmt->sa, 0, ttl,
cpu_to_le32(lifetime), cpu_to_le32(metric),
0, sdata);
- } else
+ } else {
ifmsh->mshstats.dropped_frames_ttl++;
+ }
}
if (forward && ifmsh->mshcfg.dot11MeshForwarding) {
u32 preq_id;
- u8 hopcount, flags;
+ u8 hopcount;
ttl = PREQ_IE_TTL(preq_elem);
lifetime = PREQ_IE_LIFETIME(preq_elem);
@@ -590,13 +604,19 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
ifmsh->mshstats.dropped_frames_ttl++;
return;
}
- mhwmp_dbg("forwarding the PREQ from %pM", orig_addr);
+ mhwmp_dbg(sdata, "forwarding the PREQ from %pM\n", orig_addr);
--ttl;
- flags = PREQ_IE_FLAGS(preq_elem);
preq_id = PREQ_IE_PREQ_ID(preq_elem);
hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1;
da = (mpath && mpath->is_root) ?
mpath->rann_snd_addr : broadcast_addr;
+
+ if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) {
+ target_addr = PREQ_IE_TARGET_ADDR(preq_elem);
+ target_sn = PREQ_IE_TARGET_SN(preq_elem);
+ metric = orig_metric;
+ }
+
mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
cpu_to_le32(orig_sn), target_flags, target_addr,
cpu_to_le32(target_sn), da,
@@ -631,7 +651,8 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
u8 next_hop[ETH_ALEN];
u32 target_sn, orig_sn, lifetime;
- mhwmp_dbg("received PREP from %pM", PREP_IE_ORIG_ADDR(prep_elem));
+ mhwmp_dbg(sdata, "received PREP from %pM\n",
+ PREP_IE_ORIG_ADDR(prep_elem));
orig_addr = PREP_IE_ORIG_ADDR(prep_elem);
if (ether_addr_equal(orig_addr, sdata->vif.addr))
@@ -744,11 +765,6 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
bool root_is_gate;
ttl = rann->rann_ttl;
- if (ttl <= 1) {
- ifmsh->mshstats.dropped_frames_ttl++;
- return;
- }
- ttl--;
flags = rann->rann_flags;
root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
orig_addr = rann->rann_addr;
@@ -762,8 +778,9 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
if (ether_addr_equal(orig_addr, sdata->vif.addr))
return;
- mhwmp_dbg("received RANN from %pM via neighbour %pM (is_gate=%d)",
- orig_addr, mgmt->sa, root_is_gate);
+ mhwmp_dbg(sdata,
+ "received RANN from %pM via neighbour %pM (is_gate=%d)\n",
+ orig_addr, mgmt->sa, root_is_gate);
rcu_read_lock();
sta = sta_info_get(sdata, mgmt->sa);
@@ -785,34 +802,50 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
}
}
+ if (!(SN_LT(mpath->sn, orig_sn)) &&
+ !(mpath->sn == orig_sn && metric < mpath->rann_metric)) {
+ rcu_read_unlock();
+ return;
+ }
+
if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) ||
- time_after(jiffies, mpath->exp_time - 1*HZ)) &&
- !(mpath->flags & MESH_PATH_FIXED)) {
- mhwmp_dbg("%s time to refresh root mpath %pM", sdata->name,
- orig_addr);
+ (time_after(jiffies, mpath->last_preq_to_root +
+ root_path_confirmation_jiffies(sdata)) ||
+ time_before(jiffies, mpath->last_preq_to_root))) &&
+ !(mpath->flags & MESH_PATH_FIXED) && (ttl != 0)) {
+ mhwmp_dbg(sdata,
+ "time to refresh root mpath %pM\n",
+ orig_addr);
mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
+ mpath->last_preq_to_root = jiffies;
+ }
+
+ mpath->sn = orig_sn;
+ mpath->rann_metric = metric + metric_txsta;
+ mpath->is_root = true;
+ /* Recording RANNs sender address to send individually
+ * addressed PREQs destined for root mesh STA */
+ memcpy(mpath->rann_snd_addr, mgmt->sa, ETH_ALEN);
+
+ if (root_is_gate)
+ mesh_path_add_gate(mpath);
+
+ if (ttl <= 1) {
+ ifmsh->mshstats.dropped_frames_ttl++;
+ rcu_read_unlock();
+ return;
}
+ ttl--;
- if ((SN_LT(mpath->sn, orig_sn) || (mpath->sn == orig_sn &&
- metric < mpath->rann_metric)) && ifmsh->mshcfg.dot11MeshForwarding) {
+ if (ifmsh->mshcfg.dot11MeshForwarding) {
mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
cpu_to_le32(orig_sn),
0, NULL, 0, broadcast_addr,
hopcount, ttl, cpu_to_le32(interval),
cpu_to_le32(metric + metric_txsta),
0, sdata);
- mpath->sn = orig_sn;
- mpath->rann_metric = metric + metric_txsta;
- /* Recording RANNs sender address to send individually
- * addressed PREQs destined for root mesh STA */
- memcpy(mpath->rann_snd_addr, mgmt->sa, ETH_ALEN);
}
- mpath->is_root = true;
-
- if (root_is_gate)
- mesh_path_add_gate(mpath);
-
rcu_read_unlock();
}
@@ -889,7 +922,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC);
if (!preq_node) {
- mhwmp_dbg("could not allocate PREQ node");
+ mhwmp_dbg(sdata, "could not allocate PREQ node\n");
return;
}
@@ -898,7 +931,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
kfree(preq_node);
if (printk_ratelimit())
- mhwmp_dbg("PREQ node queue full");
+ mhwmp_dbg(sdata, "PREQ node queue full\n");
return;
}
@@ -1146,7 +1179,7 @@ void mesh_path_timer(unsigned long data)
if (!mpath->is_gate && mesh_gate_num(sdata) > 0) {
ret = mesh_path_send_to_gates(mpath);
if (ret)
- mhwmp_dbg("no gate was reachable");
+ mhwmp_dbg(sdata, "no gate was reachable\n");
} else
mesh_path_flush_pending(mpath);
}
@@ -1157,13 +1190,34 @@ mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
- u8 flags;
+ u8 flags, target_flags = 0;
flags = (ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol)
? RANN_FLAG_IS_GATE : 0;
- mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,
+
+ switch (ifmsh->mshcfg.dot11MeshHWMPRootMode) {
+ case IEEE80211_PROACTIVE_RANN:
+ mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,
cpu_to_le32(++ifmsh->sn),
0, NULL, 0, broadcast_addr,
- 0, sdata->u.mesh.mshcfg.element_ttl,
+ 0, ifmsh->mshcfg.element_ttl,
cpu_to_le32(interval), 0, 0, sdata);
+ break;
+ case IEEE80211_PROACTIVE_PREQ_WITH_PREP:
+ flags |= IEEE80211_PREQ_PROACTIVE_PREP_FLAG;
+ case IEEE80211_PROACTIVE_PREQ_NO_PREP:
+ interval = ifmsh->mshcfg.dot11MeshHWMPactivePathToRootTimeout;
+ target_flags |= IEEE80211_PREQ_TO_FLAG |
+ IEEE80211_PREQ_USN_FLAG;
+ mesh_path_sel_frame_tx(MPATH_PREQ, flags, sdata->vif.addr,
+ cpu_to_le32(++ifmsh->sn), target_flags,
+ (u8 *) broadcast_addr, 0, broadcast_addr,
+ 0, ifmsh->mshcfg.element_ttl,
+ cpu_to_le32(interval),
+ 0, cpu_to_le32(ifmsh->preq_id++), sdata);
+ break;
+ default:
+ mhwmp_dbg(sdata, "Proactive mechanism not supported\n");
+ return;
+ }
}
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 572f706fd65b..c9ae931dd693 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -18,12 +18,6 @@
#include "ieee80211_i.h"
#include "mesh.h"
-#ifdef CONFIG_MAC80211_VERBOSE_MPATH_DEBUG
-#define mpath_dbg(fmt, args...) pr_debug(fmt, ##args)
-#else
-#define mpath_dbg(fmt, args...) do { (void)(0); } while (0)
-#endif
-
/* There will be initially 2^INIT_PATHS_SIZE_ORDER buckets */
#define INIT_PATHS_SIZE_ORDER 2
@@ -322,9 +316,8 @@ static void mesh_path_move_to_queue(struct mesh_path *gate_mpath,
spin_lock_irqsave(&gate_mpath->frame_queue.lock, flags);
skb_queue_splice(&gateq, &gate_mpath->frame_queue);
- mpath_dbg("Mpath queue for gate %pM has %d frames\n",
- gate_mpath->dst,
- skb_queue_len(&gate_mpath->frame_queue));
+ mpath_dbg(gate_mpath->sdata, "Mpath queue for gate %pM has %d frames\n",
+ gate_mpath->dst, skb_queue_len(&gate_mpath->frame_queue));
spin_unlock_irqrestore(&gate_mpath->frame_queue.lock, flags);
if (!copy)
@@ -446,9 +439,9 @@ int mesh_path_add_gate(struct mesh_path *mpath)
hlist_add_head_rcu(&new_gate->list, tbl->known_gates);
spin_unlock_bh(&tbl->gates_lock);
rcu_read_unlock();
- mpath_dbg("Mesh path (%s): Recorded new gate: %pM. %d known gates\n",
- mpath->sdata->name, mpath->dst,
- mpath->sdata->u.mesh.num_gates);
+ mpath_dbg(mpath->sdata,
+ "Mesh path: Recorded new gate: %pM. %d known gates\n",
+ mpath->dst, mpath->sdata->u.mesh.num_gates);
return 0;
err_rcu:
rcu_read_unlock();
@@ -477,8 +470,8 @@ static int mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath)
spin_unlock_bh(&tbl->gates_lock);
mpath->sdata->u.mesh.num_gates--;
mpath->is_gate = false;
- mpath_dbg("Mesh path (%s): Deleted gate: %pM. "
- "%d known gates\n", mpath->sdata->name,
+ mpath_dbg(mpath->sdata,
+ "Mesh path: Deleted gate: %pM. %d known gates\n",
mpath->dst, mpath->sdata->u.mesh.num_gates);
break;
}
@@ -946,19 +939,20 @@ int mesh_path_send_to_gates(struct mesh_path *mpath)
continue;
if (gate->mpath->flags & MESH_PATH_ACTIVE) {
- mpath_dbg("Forwarding to %pM\n", gate->mpath->dst);
+ mpath_dbg(sdata, "Forwarding to %pM\n", gate->mpath->dst);
mesh_path_move_to_queue(gate->mpath, from_mpath, copy);
from_mpath = gate->mpath;
copy = true;
} else {
- mpath_dbg("Not forwarding %p\n", gate->mpath);
- mpath_dbg("flags %x\n", gate->mpath->flags);
+ mpath_dbg(sdata,
+ "Not forwarding %p (flags %#x)\n",
+ gate->mpath, gate->mpath->flags);
}
}
hlist_for_each_entry_rcu(gate, n, known_gates, list)
if (gate->mpath->sdata == sdata) {
- mpath_dbg("Sending to %pM\n", gate->mpath->dst);
+ mpath_dbg(sdata, "Sending to %pM\n", gate->mpath->dst);
mesh_path_tx_pending(gate->mpath);
}
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index be4fad128c34..425685914d7d 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -13,12 +13,6 @@
#include "rate.h"
#include "mesh.h"
-#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
-#define mpl_dbg(fmt, args...) pr_debug(fmt, ##args)
-#else
-#define mpl_dbg(fmt, args...) do { (void)(0); } while (0)
-#endif
-
#define PLINK_GET_LLID(p) (p + 2)
#define PLINK_GET_PLID(p) (p + 4)
@@ -134,12 +128,14 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
switch (sta->ch_type) {
case NL80211_CHAN_NO_HT:
- mpl_dbg("mesh_plink %pM: nonHT sta (%pM) is present",
+ mpl_dbg(sdata,
+ "mesh_plink %pM: nonHT sta (%pM) is present\n",
sdata->vif.addr, sta->sta.addr);
non_ht_sta = true;
goto out;
case NL80211_CHAN_HT20:
- mpl_dbg("mesh_plink %pM: HT20 sta (%pM) is present",
+ mpl_dbg(sdata,
+ "mesh_plink %pM: HT20 sta (%pM) is present\n",
sdata->vif.addr, sta->sta.addr);
ht20_sta = true;
default:
@@ -160,7 +156,8 @@ out:
sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
sdata->u.mesh.mshcfg.ht_opmode = ht_opmode;
changed = BSS_CHANGED_HT;
- mpl_dbg("mesh_plink %pM: protection mode changed to %d",
+ mpl_dbg(sdata,
+ "mesh_plink %pM: protection mode changed to %d\n",
sdata->vif.addr, ht_opmode);
}
@@ -261,8 +258,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
pos = skb_put(skb, 2);
memcpy(pos + 2, &plid, 2);
}
- if (ieee80211_add_srates_ie(&sdata->vif, skb, true) ||
- ieee80211_add_ext_srates_ie(&sdata->vif, skb, true) ||
+ if (ieee80211_add_srates_ie(sdata, skb, true) ||
+ ieee80211_add_ext_srates_ie(sdata, skb, true) ||
mesh_add_rsn_ie(skb, sdata) ||
mesh_add_meshid_ie(skb, sdata) ||
mesh_add_meshconf_ie(skb, sdata))
@@ -437,7 +434,8 @@ static void mesh_plink_timer(unsigned long data)
spin_unlock_bh(&sta->lock);
return;
}
- mpl_dbg("Mesh plink timer for %pM fired on state %d\n",
+ mpl_dbg(sta->sdata,
+ "Mesh plink timer for %pM fired on state %d\n",
sta->sta.addr, sta->plink_state);
reason = 0;
llid = sta->llid;
@@ -450,7 +448,8 @@ static void mesh_plink_timer(unsigned long data)
/* retry timer */
if (sta->plink_retries < dot11MeshMaxRetries(sdata)) {
u32 rand;
- mpl_dbg("Mesh plink for %pM (retry, timeout): %d %d\n",
+ mpl_dbg(sta->sdata,
+ "Mesh plink for %pM (retry, timeout): %d %d\n",
sta->sta.addr, sta->plink_retries,
sta->plink_timeout);
get_random_bytes(&rand, sizeof(u32));
@@ -530,7 +529,8 @@ int mesh_plink_open(struct sta_info *sta)
sta->plink_state = NL80211_PLINK_OPN_SNT;
mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
spin_unlock_bh(&sta->lock);
- mpl_dbg("Mesh plink: starting establishment with %pM\n",
+ mpl_dbg(sdata,
+ "Mesh plink: starting establishment with %pM\n",
sta->sta.addr);
return mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
@@ -565,7 +565,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
u8 *baseaddr;
u32 changed = 0;
__le16 plid, llid, reason;
-#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
static const char *mplstates[] = {
[NL80211_PLINK_LISTEN] = "LISTEN",
[NL80211_PLINK_OPN_SNT] = "OPN-SNT",
@@ -575,14 +574,14 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
[NL80211_PLINK_HOLDING] = "HOLDING",
[NL80211_PLINK_BLOCKED] = "BLOCKED"
};
-#endif
/* need action_code, aux */
if (len < IEEE80211_MIN_ACTION_SIZE + 3)
return;
if (is_multicast_ether_addr(mgmt->da)) {
- mpl_dbg("Mesh plink: ignore frame from multicast address");
+ mpl_dbg(sdata,
+ "Mesh plink: ignore frame from multicast address\n");
return;
}
@@ -595,12 +594,14 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
}
ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
if (!elems.peering) {
- mpl_dbg("Mesh plink: missing necessary peer link ie\n");
+ mpl_dbg(sdata,
+ "Mesh plink: missing necessary peer link ie\n");
return;
}
if (elems.rsn_len &&
sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
- mpl_dbg("Mesh plink: can't establish link with secure peer\n");
+ mpl_dbg(sdata,
+ "Mesh plink: can't establish link with secure peer\n");
return;
}
@@ -610,14 +611,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
(ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) ||
(ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6
&& ie_len != 8)) {
- mpl_dbg("Mesh plink: incorrect plink ie length %d %d\n",
- ftype, ie_len);
+ mpl_dbg(sdata,
+ "Mesh plink: incorrect plink ie length %d %d\n",
+ ftype, ie_len);
return;
}
if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
(!elems.mesh_id || !elems.mesh_config)) {
- mpl_dbg("Mesh plink: missing necessary ie\n");
+ mpl_dbg(sdata, "Mesh plink: missing necessary ie\n");
return;
}
/* Note the lines below are correct, the llid in the frame is the plid
@@ -632,21 +634,21 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
sta = sta_info_get(sdata, mgmt->sa);
if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) {
- mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");
+ mpl_dbg(sdata, "Mesh plink: cls or cnf from unknown peer\n");
rcu_read_unlock();
return;
}
if (ftype == WLAN_SP_MESH_PEERING_OPEN &&
!rssi_threshold_check(sta, sdata)) {
- mpl_dbg("Mesh plink: %pM does not meet rssi threshold\n",
+ mpl_dbg(sdata, "Mesh plink: %pM does not meet rssi threshold\n",
mgmt->sa);
rcu_read_unlock();
return;
}
if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) {
- mpl_dbg("Mesh plink: Action frame from non-authed peer\n");
+ mpl_dbg(sdata, "Mesh plink: Action frame from non-authed peer\n");
rcu_read_unlock();
return;
}
@@ -683,7 +685,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
} else if (!sta) {
/* ftype == WLAN_SP_MESH_PEERING_OPEN */
if (!mesh_plink_free_count(sdata)) {
- mpl_dbg("Mesh plink error: no more free plinks\n");
+ mpl_dbg(sdata, "Mesh plink error: no more free plinks\n");
rcu_read_unlock();
return;
}
@@ -724,7 +726,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
event = CLS_ACPT;
break;
default:
- mpl_dbg("Mesh plink: unknown frame subtype\n");
+ mpl_dbg(sdata, "Mesh plink: unknown frame subtype\n");
rcu_read_unlock();
return;
}
@@ -734,13 +736,14 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
/* allocate sta entry if necessary and update info */
sta = mesh_peer_init(sdata, mgmt->sa, &elems);
if (!sta) {
- mpl_dbg("Mesh plink: failed to init peer!\n");
+ mpl_dbg(sdata, "Mesh plink: failed to init peer!\n");
rcu_read_unlock();
return;
}
}
- mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n",
+ mpl_dbg(sdata,
+ "Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n",
mgmt->sa, mplstates[sta->plink_state],
le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
event);
@@ -851,7 +854,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
mesh_plink_inc_estab_count(sdata);
changed |= mesh_set_ht_prot_mode(sdata);
changed |= BSS_CHANGED_BEACON;
- mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
+ mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
sta->sta.addr);
break;
default:
@@ -887,7 +890,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
mesh_plink_inc_estab_count(sdata);
changed |= mesh_set_ht_prot_mode(sdata);
changed |= BSS_CHANGED_BEACON;
- mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
+ mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
sta->sta.addr);
mesh_plink_frame_tx(sdata,
WLAN_SP_MESH_PEERING_CONFIRM,
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c
index 0ccdad49f987..accfa00ffcdf 100644
--- a/net/mac80211/mesh_sync.c
+++ b/net/mac80211/mesh_sync.c
@@ -12,13 +12,6 @@
#include "mesh.h"
#include "driver-ops.h"
-#ifdef CONFIG_MAC80211_VERBOSE_MESH_SYNC_DEBUG
-#define msync_dbg(fmt, args...) \
- pr_debug("Mesh sync (%s): " fmt "\n", sdata->name, ##args)
-#else
-#define msync_dbg(fmt, args...) do { (void)(0); } while (0)
-#endif
-
/* This is not in the standard. It represents a tolerable tbtt drift below
* which we do no TSF adjustment.
*/
@@ -65,14 +58,14 @@ void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
spin_lock_bh(&ifmsh->sync_offset_lock);
if (ifmsh->sync_offset_clockdrift_max < beacon_int_fraction) {
- msync_dbg("TBTT : max clockdrift=%lld; adjusting",
- (long long) ifmsh->sync_offset_clockdrift_max);
+ msync_dbg(sdata, "TBTT : max clockdrift=%lld; adjusting\n",
+ (long long) ifmsh->sync_offset_clockdrift_max);
tsfdelta = -ifmsh->sync_offset_clockdrift_max;
ifmsh->sync_offset_clockdrift_max = 0;
} else {
- msync_dbg("TBTT : max clockdrift=%lld; adjusting by %llu",
- (long long) ifmsh->sync_offset_clockdrift_max,
- (unsigned long long) beacon_int_fraction);
+ msync_dbg(sdata, "TBTT : max clockdrift=%lld; adjusting by %llu\n",
+ (long long) ifmsh->sync_offset_clockdrift_max,
+ (unsigned long long) beacon_int_fraction);
tsfdelta = -beacon_int_fraction;
ifmsh->sync_offset_clockdrift_max -= beacon_int_fraction;
}
@@ -120,7 +113,7 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
if (elems->mesh_config && mesh_peer_tbtt_adjusting(elems)) {
clear_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN);
- msync_dbg("STA %pM : is adjusting TBTT", sta->sta.addr);
+ msync_dbg(sdata, "STA %pM : is adjusting TBTT\n", sta->sta.addr);
goto no_sync;
}
@@ -169,7 +162,8 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) {
s64 t_clockdrift = sta->t_offset_setpoint
- sta->t_offset;
- msync_dbg("STA %pM : sta->t_offset=%lld, sta->t_offset_setpoint=%lld, t_clockdrift=%lld",
+ msync_dbg(sdata,
+ "STA %pM : sta->t_offset=%lld, sta->t_offset_setpoint=%lld, t_clockdrift=%lld\n",
sta->sta.addr,
(long long) sta->t_offset,
(long long)
@@ -178,7 +172,8 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
if (t_clockdrift > TOFFSET_MAXIMUM_ADJUSTMENT ||
t_clockdrift < -TOFFSET_MAXIMUM_ADJUSTMENT) {
- msync_dbg("STA %pM : t_clockdrift=%lld too large, setpoint reset",
+ msync_dbg(sdata,
+ "STA %pM : t_clockdrift=%lld too large, setpoint reset\n",
sta->sta.addr,
(long long) t_clockdrift);
clear_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN);
@@ -197,8 +192,8 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
} else {
sta->t_offset_setpoint = sta->t_offset - TOFFSET_SET_MARGIN;
set_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN);
- msync_dbg("STA %pM : offset was invalid, "
- " sta->t_offset=%lld",
+ msync_dbg(sdata,
+ "STA %pM : offset was invalid, sta->t_offset=%lld\n",
sta->sta.addr,
(long long) sta->t_offset);
rcu_read_unlock();
@@ -226,17 +221,15 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
* to the driver tsf setter, we punt
* the tsf adjustment to the mesh tasklet
*/
- msync_dbg("TBTT : kicking off TBTT "
- "adjustment with "
- "clockdrift_max=%lld",
- ifmsh->sync_offset_clockdrift_max);
+ msync_dbg(sdata,
+ "TBTT : kicking off TBTT adjustment with clockdrift_max=%lld\n",
+ ifmsh->sync_offset_clockdrift_max);
set_bit(MESH_WORK_DRIFT_ADJUST,
&ifmsh->wrkq_flags);
} else {
- msync_dbg("TBTT : max clockdrift=%lld; "
- "too small to adjust",
- (long long)
- ifmsh->sync_offset_clockdrift_max);
+ msync_dbg(sdata,
+ "TBTT : max clockdrift=%lld; too small to adjust\n",
+ (long long)ifmsh->sync_offset_clockdrift_max);
ifmsh->sync_offset_clockdrift_max = 0;
}
spin_unlock_bh(&ifmsh->sync_offset_lock);
@@ -268,7 +261,7 @@ static void mesh_sync_vendor_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
const u8 *oui;
WARN_ON(sdata->u.mesh.mesh_sp_id != IEEE80211_SYNC_METHOD_VENDOR);
- msync_dbg("called mesh_sync_vendor_rx_bcn_presp");
+ msync_dbg(sdata, "called mesh_sync_vendor_rx_bcn_presp\n");
oui = mesh_get_vendor_oui(sdata);
/* here you would implement the vendor offset tracking for this oui */
}
@@ -278,7 +271,7 @@ static void mesh_sync_vendor_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
const u8 *oui;
WARN_ON(sdata->u.mesh.mesh_sp_id != IEEE80211_SYNC_METHOD_VENDOR);
- msync_dbg("called mesh_sync_vendor_adjust_tbtt");
+ msync_dbg(sdata, "called mesh_sync_vendor_adjust_tbtt\n");
oui = mesh_get_vendor_oui(sdata);
/* here you would implement the vendor tsf adjustment for this oui */
}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d7134c170336..de4350fce11e 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -541,6 +541,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
memcpy(pos, assoc_data->ie + offset, noffset - offset);
}
+ drv_mgd_prepare_tx(local, sdata);
+
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
ieee80211_tx_skb(sdata, skb);
}
@@ -580,6 +582,9 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
IEEE80211_SKB_CB(skb)->flags |=
IEEE80211_TX_INTFL_DONT_ENCRYPT;
+
+ drv_mgd_prepare_tx(local, sdata);
+
ieee80211_tx_skb(sdata, skb);
}
}
@@ -902,9 +907,6 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
if (!mgd->associated)
return false;
- if (!mgd->associated->beacon_ies)
- return false;
-
if (mgd->flags & (IEEE80211_STA_BEACON_POLL |
IEEE80211_STA_CONNECTION_POLL))
return false;
@@ -1106,7 +1108,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
}
/* MLME */
-static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
+static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
u8 *wmm_param, size_t wmm_param_len)
{
@@ -1117,23 +1119,23 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
u8 *pos, uapsd_queues = 0;
if (!local->ops->conf_tx)
- return;
+ return false;
if (local->hw.queues < IEEE80211_NUM_ACS)
- return;
+ return false;
if (!wmm_param)
- return;
+ return false;
if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
- return;
+ return false;
if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
uapsd_queues = ifmgd->uapsd_queues;
count = wmm_param[6] & 0x0f;
if (count == ifmgd->wmm_last_param_set)
- return;
+ return false;
ifmgd->wmm_last_param_set = count;
pos = wmm_param + 8;
@@ -1141,7 +1143,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
memset(&params, 0, sizeof(params));
- local->wmm_acm = 0;
+ sdata->wmm_acm = 0;
for (; left >= 4; left -= 4, pos += 4) {
int aci = (pos[0] >> 5) & 0x03;
int acm = (pos[0] >> 4) & 0x01;
@@ -1152,21 +1154,21 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
case 1: /* AC_BK */
queue = 3;
if (acm)
- local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
+ sdata->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
uapsd = true;
break;
case 2: /* AC_VI */
queue = 1;
if (acm)
- local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
+ sdata->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
uapsd = true;
break;
case 3: /* AC_VO */
queue = 0;
if (acm)
- local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
+ sdata->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
uapsd = true;
break;
@@ -1174,7 +1176,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
default:
queue = 2;
if (acm)
- local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
+ sdata->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
uapsd = true;
break;
@@ -1186,23 +1188,21 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
params.txop = get_unaligned_le16(pos + 2);
params.uapsd = uapsd;
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- wiphy_debug(local->hw.wiphy,
- "WMM queue=%d aci=%d acm=%d aifs=%d "
- "cWmin=%d cWmax=%d txop=%d uapsd=%d\n",
- queue, aci, acm,
- params.aifs, params.cw_min, params.cw_max,
- params.txop, params.uapsd);
-#endif
+ mlme_dbg(sdata,
+ "WMM queue=%d aci=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d\n",
+ queue, aci, acm,
+ params.aifs, params.cw_min, params.cw_max,
+ params.txop, params.uapsd);
sdata->tx_conf[queue] = params;
if (drv_conf_tx(local, sdata, queue, &params))
- wiphy_debug(local->hw.wiphy,
- "failed to set TX queue parameters for queue %d\n",
- queue);
+ sdata_err(sdata,
+ "failed to set TX queue parameters for queue %d\n",
+ queue);
}
/* enable WMM or activate new settings */
sdata->vif.bss_conf.qos = true;
+ return true;
}
static void __ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata)
@@ -1269,13 +1269,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
bss_info_changed |= BSS_CHANGED_ASSOC;
- /* set timing information */
- bss_conf->beacon_int = cbss->beacon_interval;
- bss_conf->last_tsf = cbss->tsf;
-
- bss_info_changed |= BSS_CHANGED_BEACON_INT;
bss_info_changed |= ieee80211_handle_bss_capability(sdata,
- cbss->capability, bss->has_erp_value, bss->erp_value);
+ bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value);
sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec(
IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int));
@@ -1327,7 +1322,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
u32 changed = 0;
- u8 bssid[ETH_ALEN];
ASSERT_MGD_MTX(ifmgd);
@@ -1337,10 +1331,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
if (WARN_ON(!ifmgd->associated))
return;
- memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
+ ieee80211_stop_poll(sdata);
ifmgd->associated = NULL;
- memset(ifmgd->bssid, 0, ETH_ALEN);
/*
* we need to commit the associated = NULL change because the
@@ -1360,22 +1353,29 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
netif_carrier_off(sdata->dev);
mutex_lock(&local->sta_mtx);
- sta = sta_info_get(sdata, bssid);
+ sta = sta_info_get(sdata, ifmgd->bssid);
if (sta) {
set_sta_flag(sta, WLAN_STA_BLOCK_BA);
ieee80211_sta_tear_down_BA_sessions(sta, tx);
}
mutex_unlock(&local->sta_mtx);
+ /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */
+ if (tx)
+ drv_flush(local, false);
+
/* deauthenticate/disassociate now */
if (tx || frame_buf)
- ieee80211_send_deauth_disassoc(sdata, bssid, stype, reason,
- tx, frame_buf);
+ ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype,
+ reason, tx, frame_buf);
/* flush out frame */
if (tx)
drv_flush(local, false);
+ /* clear bssid only after building the needed mgmt frames */
+ memset(ifmgd->bssid, 0, ETH_ALEN);
+
/* remove AP and TDLS peers */
sta_info_flush(local, sdata);
@@ -1565,11 +1565,10 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
goto out;
}
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
if (beacon)
- net_dbg_ratelimited("%s: detected beacon loss from AP - sending probe request\n",
- sdata->name);
-#endif
+ mlme_dbg_ratelimited(sdata,
+ "detected beacon loss from AP - sending probe request\n");
+
ieee80211_cqm_rssi_notify(&sdata->vif,
NL80211_CQM_RSSI_BEACON_LOSS_EVENT, GFP_KERNEL);
@@ -1613,6 +1612,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ struct cfg80211_bss *cbss;
struct sk_buff *skb;
const u8 *ssid;
int ssid_len;
@@ -1622,16 +1622,22 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
ASSERT_MGD_MTX(ifmgd);
- if (!ifmgd->associated)
+ if (ifmgd->associated)
+ cbss = ifmgd->associated;
+ else if (ifmgd->auth_data)
+ cbss = ifmgd->auth_data->bss;
+ else if (ifmgd->assoc_data)
+ cbss = ifmgd->assoc_data->bss;
+ else
return NULL;
- ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
+ ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID);
if (WARN_ON_ONCE(ssid == NULL))
ssid_len = 0;
else
ssid_len = ssid[1];
- skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid,
+ skb = ieee80211_build_probe_req(sdata, cbss->bssid,
(u32) -1, ssid + 2, ssid_len,
NULL, 0, true);
@@ -1654,7 +1660,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
- pr_debug("%s: Connection to AP %pM lost\n", sdata->name, bssid);
+ sdata_info(sdata, "Connection to AP %pM lost\n", bssid);
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
@@ -1750,6 +1756,7 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
if (!elems.challenge)
return;
auth_data->expected_transaction = 4;
+ drv_mgd_prepare_tx(sdata->local, sdata);
ieee80211_send_auth(sdata, 3, auth_data->algorithm,
elems.challenge - 2, elems.challenge_len + 2,
auth_data->bss->bssid, auth_data->bss->bssid,
@@ -1788,8 +1795,8 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
return RX_MGMT_NONE;
if (status_code != WLAN_STATUS_SUCCESS) {
- pr_debug("%s: %pM denied authentication (status %d)\n",
- sdata->name, mgmt->sa, status_code);
+ sdata_info(sdata, "%pM denied authentication (status %d)\n",
+ mgmt->sa, status_code);
ieee80211_destroy_auth_data(sdata, false);
return RX_MGMT_CFG80211_RX_AUTH;
}
@@ -1812,7 +1819,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
return RX_MGMT_NONE;
}
- pr_debug("%s: authenticated\n", sdata->name);
+ sdata_info(sdata, "authenticated\n");
ifmgd->auth_data->done = true;
ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
run_again(ifmgd, ifmgd->auth_data->timeout);
@@ -1825,7 +1832,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
goto out_err;
}
if (sta_info_move_state(sta, IEEE80211_STA_AUTH)) {
- pr_debug("%s: failed moving %pM to auth\n", sdata->name, bssid);
+ sdata_info(sdata, "failed moving %pM to auth\n", bssid);
goto out_err;
}
mutex_unlock(&sdata->local->sta_mtx);
@@ -1859,8 +1866,8 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
- pr_debug("%s: deauthenticated from %pM (Reason: %u)\n",
- sdata->name, bssid, reason_code);
+ sdata_info(sdata, "deauthenticated from %pM (Reason: %u)\n",
+ bssid, reason_code);
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
@@ -1890,8 +1897,8 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
- pr_debug("%s: disassociated from %pM (Reason: %u)\n",
- sdata->name, mgmt->sa, reason_code);
+ sdata_info(sdata, "disassociated from %pM (Reason: %u)\n",
+ mgmt->sa, reason_code);
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
@@ -1983,15 +1990,15 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
- pr_debug("%s: invalid AID value 0x%x; bits 15:14 not set\n",
- sdata->name, aid);
+ sdata_info(sdata, "invalid AID value 0x%x; bits 15:14 not set\n",
+ aid);
aid &= ~(BIT(15) | BIT(14));
ifmgd->broken_ap = false;
if (aid == 0 || aid > IEEE80211_MAX_AID) {
- pr_debug("%s: invalid AID value %d (out of range), turn off PS\n",
- sdata->name, aid);
+ sdata_info(sdata, "invalid AID value %d (out of range), turn off PS\n",
+ aid);
aid = 0;
ifmgd->broken_ap = true;
}
@@ -2000,8 +2007,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
if (!elems.supp_rates) {
- pr_debug("%s: no SuppRates element in AssocResp\n",
- sdata->name);
+ sdata_info(sdata, "no SuppRates element in AssocResp\n");
return false;
}
@@ -2041,8 +2047,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
if (err) {
- pr_debug("%s: failed to move station %pM to desired state\n",
- sdata->name, sta->sta.addr);
+ sdata_info(sdata,
+ "failed to move station %pM to desired state\n",
+ sta->sta.addr);
WARN_ON(__sta_info_destroy(sta));
mutex_unlock(&sdata->local->sta_mtx);
return false;
@@ -2125,9 +2132,10 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
- pr_debug("%s: RX %sssocResp from %pM (capab=0x%x status=%d aid=%d)\n",
- sdata->name, reassoc ? "Rea" : "A", mgmt->sa,
- capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
+ sdata_info(sdata,
+ "RX %sssocResp from %pM (capab=0x%x status=%d aid=%d)\n",
+ reassoc ? "Rea" : "A", mgmt->sa,
+ capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
pos = mgmt->u.assoc_resp.variable;
ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
@@ -2138,8 +2146,9 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
u32 tu, ms;
tu = get_unaligned_le32(elems.timeout_int + 1);
ms = tu * 1024 / 1000;
- pr_debug("%s: %pM rejected association temporarily; comeback duration %u TU (%u ms)\n",
- sdata->name, mgmt->sa, tu, ms);
+ sdata_info(sdata,
+ "%pM rejected association temporarily; comeback duration %u TU (%u ms)\n",
+ mgmt->sa, tu, ms);
assoc_data->timeout = jiffies + msecs_to_jiffies(ms);
if (ms > IEEE80211_ASSOC_TIMEOUT)
run_again(ifmgd, assoc_data->timeout);
@@ -2149,19 +2158,17 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
*bss = assoc_data->bss;
if (status_code != WLAN_STATUS_SUCCESS) {
- pr_debug("%s: %pM denied association (code=%d)\n",
- sdata->name, mgmt->sa, status_code);
+ sdata_info(sdata, "%pM denied association (code=%d)\n",
+ mgmt->sa, status_code);
ieee80211_destroy_assoc_data(sdata, false);
} else {
- pr_debug("%s: associated\n", sdata->name);
-
if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) {
/* oops -- internal error -- send timeout for now */
- ieee80211_destroy_assoc_data(sdata, true);
- sta_info_destroy_addr(sdata, mgmt->bssid);
+ ieee80211_destroy_assoc_data(sdata, false);
cfg80211_put_bss(*bss);
return RX_MGMT_CFG80211_ASSOC_TIMEOUT;
}
+ sdata_info(sdata, "associated\n");
/*
* destroy assoc_data afterwards, as otherwise an idle
@@ -2261,7 +2268,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies &&
ether_addr_equal(mgmt->bssid, ifmgd->auth_data->bss->bssid)) {
/* got probe response, continue with auth */
- pr_debug("%s: direct probe responded\n", sdata->name);
+ sdata_info(sdata, "direct probe responded\n");
ifmgd->auth_data->tries = 0;
ifmgd->auth_data->timeout = jiffies;
run_again(ifmgd, ifmgd->auth_data->timeout);
@@ -2397,10 +2404,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
}
if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- net_dbg_ratelimited("%s: cancelling probereq poll due to a received beacon\n",
- sdata->name);
-#endif
+ mlme_dbg_ratelimited(sdata,
+ "cancelling probereq poll due to a received beacon\n");
mutex_lock(&local->mtx);
ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL;
ieee80211_run_deferred_scan(local);
@@ -2426,14 +2431,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len,
ifmgd->aid);
- if (ncrc != ifmgd->beacon_crc || !ifmgd->beacon_crc_valid) {
- ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems,
- true);
-
- ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
- elems.wmm_param_len);
- }
-
if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) {
if (directed_tim) {
if (local->hw.conf.dynamic_ps_timeout > 0) {
@@ -2464,6 +2461,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
ifmgd->beacon_crc = ncrc;
ifmgd->beacon_crc_valid = true;
+ ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems,
+ true);
+
+ if (ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
+ elems.wmm_param_len))
+ changed |= BSS_CHANGED_QOS;
+
if (elems.erp_info && elems.erp_info_len >= 1) {
erp_valid = true;
erp_value = elems.erp_info[0];
@@ -2592,8 +2596,6 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u8 frame_buf[DEAUTH_DISASSOC_LEN];
- ieee80211_stop_poll(sdata);
-
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,
false, frame_buf);
mutex_unlock(&ifmgd->mtx);
@@ -2625,8 +2627,8 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
auth_data->tries++;
if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) {
- pr_debug("%s: authentication with %pM timed out\n",
- sdata->name, auth_data->bss->bssid);
+ sdata_info(sdata, "authentication with %pM timed out\n",
+ auth_data->bss->bssid);
/*
* Most likely AP is not in the range so remove the
@@ -2637,10 +2639,12 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
return -ETIMEDOUT;
}
+ drv_mgd_prepare_tx(local, sdata);
+
if (auth_data->bss->proberesp_ies) {
- pr_debug("%s: send auth to %pM (try %d/%d)\n",
- sdata->name, auth_data->bss->bssid, auth_data->tries,
- IEEE80211_AUTH_MAX_TRIES);
+ sdata_info(sdata, "send auth to %pM (try %d/%d)\n",
+ auth_data->bss->bssid, auth_data->tries,
+ IEEE80211_AUTH_MAX_TRIES);
auth_data->expected_transaction = 2;
ieee80211_send_auth(sdata, 1, auth_data->algorithm,
@@ -2650,9 +2654,9 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
} else {
const u8 *ssidie;
- pr_debug("%s: direct probe to %pM (try %d/%i)\n",
- sdata->name, auth_data->bss->bssid, auth_data->tries,
- IEEE80211_AUTH_MAX_TRIES);
+ sdata_info(sdata, "direct probe to %pM (try %d/%i)\n",
+ auth_data->bss->bssid, auth_data->tries,
+ IEEE80211_AUTH_MAX_TRIES);
ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID);
if (!ssidie)
@@ -2680,8 +2684,8 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
assoc_data->tries++;
if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) {
- pr_debug("%s: association with %pM timed out\n",
- sdata->name, assoc_data->bss->bssid);
+ sdata_info(sdata, "association with %pM timed out\n",
+ assoc_data->bss->bssid);
/*
* Most likely AP is not in the range so remove the
@@ -2692,9 +2696,9 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
return -ETIMEDOUT;
}
- pr_debug("%s: associate with %pM (try %d/%d)\n",
- sdata->name, assoc_data->bss->bssid, assoc_data->tries,
- IEEE80211_ASSOC_MAX_TRIES);
+ sdata_info(sdata, "associate with %pM (try %d/%d)\n",
+ assoc_data->bss->bssid, assoc_data->tries,
+ IEEE80211_ASSOC_MAX_TRIES);
ieee80211_send_assoc(sdata);
assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
@@ -2767,45 +2771,31 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
ieee80211_reset_ap_probe(sdata);
else if (ifmgd->nullfunc_failed) {
if (ifmgd->probe_send_count < max_tries) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- wiphy_debug(local->hw.wiphy,
- "%s: No ack for nullfunc frame to"
- " AP %pM, try %d/%i\n",
- sdata->name, bssid,
- ifmgd->probe_send_count, max_tries);
-#endif
+ mlme_dbg(sdata,
+ "No ack for nullfunc frame to AP %pM, try %d/%i\n",
+ bssid, ifmgd->probe_send_count,
+ max_tries);
ieee80211_mgd_probe_ap_send(sdata);
} else {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- wiphy_debug(local->hw.wiphy,
- "%s: No ack for nullfunc frame to"
- " AP %pM, disconnecting.\n",
- sdata->name, bssid);
-#endif
+ mlme_dbg(sdata,
+ "No ack for nullfunc frame to AP %pM, disconnecting.\n",
+ bssid);
ieee80211_sta_connection_lost(sdata, bssid,
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
}
} else if (time_is_after_jiffies(ifmgd->probe_timeout))
run_again(ifmgd, ifmgd->probe_timeout);
else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- wiphy_debug(local->hw.wiphy,
- "%s: Failed to send nullfunc to AP %pM"
- " after %dms, disconnecting.\n",
- sdata->name,
- bssid, probe_wait_ms);
-#endif
+ mlme_dbg(sdata,
+ "Failed to send nullfunc to AP %pM after %dms, disconnecting\n",
+ bssid, probe_wait_ms);
ieee80211_sta_connection_lost(sdata, bssid,
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
} else if (ifmgd->probe_send_count < max_tries) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- wiphy_debug(local->hw.wiphy,
- "%s: No probe response from AP %pM"
- " after %dms, try %d/%i\n",
- sdata->name,
- bssid, probe_wait_ms,
- ifmgd->probe_send_count, max_tries);
-#endif
+ mlme_dbg(sdata,
+ "No probe response from AP %pM after %dms, try %d/%i\n",
+ bssid, probe_wait_ms,
+ ifmgd->probe_send_count, max_tries);
ieee80211_mgd_probe_ap_send(sdata);
} else {
/*
@@ -2920,11 +2910,8 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME;
mutex_lock(&ifmgd->mtx);
if (ifmgd->associated) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- wiphy_debug(sdata->local->hw.wiphy,
- "%s: driver requested disconnect after resume.\n",
- sdata->name);
-#endif
+ mlme_dbg(sdata,
+ "driver requested disconnect after resume\n");
ieee80211_sta_connection_lost(sdata,
ifmgd->associated->bssid,
WLAN_REASON_UNSPECIFIED);
@@ -2982,7 +2969,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
/* scan finished notification */
void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
{
- struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+ struct ieee80211_sub_if_data *sdata;
/* Restart STA timers */
rcu_read_lock();
@@ -3012,7 +2999,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_bss *bss = (void *)cbss->priv;
- struct sta_info *sta;
+ struct sta_info *sta = NULL;
bool have_sta = false;
int err;
int ht_cfreq;
@@ -3065,10 +3052,11 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
* since we look at probe response/beacon data here
* it should be OK.
*/
- pr_debug("%s: Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
- sdata->name, cbss->channel->center_freq,
- ht_cfreq, ht_oper->primary_chan,
- cbss->channel->band);
+ sdata_info(sdata,
+ "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
+ cbss->channel->center_freq,
+ ht_cfreq, ht_oper->primary_chan,
+ cbss->channel->band);
ht_oper = NULL;
}
}
@@ -3092,8 +3080,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
if (!ieee80211_set_channel_type(local, sdata, channel_type)) {
/* can only fail due to HT40+/- mismatch */
channel_type = NL80211_CHAN_HT20;
- pr_debug("%s: disabling 40 MHz due to multi-vif mismatch\n",
- sdata->name);
+ sdata_info(sdata,
+ "disabling 40 MHz due to multi-vif mismatch\n");
ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
WARN_ON(!ieee80211_set_channel_type(local, sdata,
channel_type));
@@ -3102,7 +3090,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
local->oper_channel = cbss->channel;
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
- if (!have_sta) {
+ if (sta) {
u32 rates = 0, basic_rates = 0;
bool have_higher_than_11mbit;
int min_rate = INT_MAX, min_rate_index = -1;
@@ -3122,8 +3110,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
* we can connect -- with a warning.
*/
if (!basic_rates && min_rate_index >= 0) {
- pr_debug("%s: No basic rates, using min rate instead\n",
- sdata->name);
+ sdata_info(sdata,
+ "No basic rates, using min rate instead\n");
basic_rates = BIT(min_rate_index);
}
@@ -3139,9 +3127,15 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
memcpy(ifmgd->bssid, cbss->bssid, ETH_ALEN);
- /* tell driver about BSSID and basic rates */
+ /* set timing information */
+ sdata->vif.bss_conf.beacon_int = cbss->beacon_interval;
+ sdata->vif.bss_conf.sync_tsf = cbss->tsf;
+ sdata->vif.bss_conf.sync_device_ts = bss->device_ts;
+
+ /* tell driver about BSSID, basic rates and timing */
ieee80211_bss_info_change_notify(sdata,
- BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES);
+ BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES |
+ BSS_CHANGED_BEACON_INT);
if (assoc)
sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
@@ -3149,8 +3143,9 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
err = sta_info_insert(sta);
sta = NULL;
if (err) {
- pr_debug("%s: failed to insert STA entry for the AP (error %d)\n",
- sdata->name, err);
+ sdata_info(sdata,
+ "failed to insert STA entry for the AP (error %d)\n",
+ err);
return err;
}
} else
@@ -3228,7 +3223,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
if (ifmgd->associated)
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
- pr_debug("%s: authenticate with %pM\n", sdata->name, req->bss->bssid);
+ sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
err = ieee80211_prep_connection(sdata, req->bss, false);
if (err)
@@ -3410,8 +3405,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
* Wait up to one beacon interval ...
* should this be more if we miss one?
*/
- pr_debug("%s: waiting for beacon from %pM\n",
- sdata->name, ifmgd->bssid);
+ sdata_info(sdata, "waiting for beacon from %pM\n",
+ ifmgd->bssid);
assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval);
} else {
assoc_data->have_beacon = true;
@@ -3430,8 +3425,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
corrupt_type = "beacon";
} else if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP)
corrupt_type = "probe response";
- pr_debug("%s: associating with AP with corrupt %s\n",
- sdata->name, corrupt_type);
+ sdata_info(sdata, "associating with AP with corrupt %s\n",
+ corrupt_type);
}
err = 0;
@@ -3460,8 +3455,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
return 0;
}
- pr_debug("%s: deauthenticating from %pM by local choice (reason=%d)\n",
- sdata->name, req->bssid, req->reason_code);
+ sdata_info(sdata,
+ "deauthenticating from %pM by local choice (reason=%d)\n",
+ req->bssid, req->reason_code);
if (ifmgd->associated &&
ether_addr_equal(ifmgd->associated->bssid, req->bssid))
@@ -3503,8 +3499,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
return -ENOLINK;
}
- pr_debug("%s: disassociating from %pM by local choice (reason=%d)\n",
- sdata->name, req->bss->bssid, req->reason_code);
+ sdata_info(sdata,
+ "disassociating from %pM by local choice (reason=%d)\n",
+ req->bss->bssid, req->reason_code);
memcpy(bssid, req->bss->bssid, ETH_ALEN);
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC,
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index abb226dc4753..8c047fc8b325 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -15,7 +15,6 @@
#include <linux/export.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
-#include "driver-trace.h"
#include "driver-ops.h"
/*
@@ -25,8 +24,7 @@
* because we *may* be doing work on-operating channel, and want our
* hardware unconditionally awake, but still let the AP send us normal frames.
*/
-static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata,
- bool tell_ap)
+static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -47,8 +45,8 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata,
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
}
- if (tell_ap && (!local->offchannel_ps_enabled ||
- !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)))
+ if (!local->offchannel_ps_enabled ||
+ !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
/*
* If power save was enabled, no need to send a nullfunc
* frame because AP knows that we are sleeping. But if the
@@ -133,7 +131,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
if (offchannel_ps_enable &&
(sdata->vif.type == NL80211_IFTYPE_STATION) &&
sdata->u.mgd.associated)
- ieee80211_offchannel_ps_enable(sdata, true);
+ ieee80211_offchannel_ps_enable(sdata);
}
}
mutex_unlock(&local->iflist_mtx);
@@ -193,7 +191,7 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc)
roc->frame = NULL;
}
} else {
- cfg80211_ready_on_channel(roc->sdata->dev, (unsigned long)roc,
+ cfg80211_ready_on_channel(&roc->sdata->wdev, (unsigned long)roc,
roc->chan, roc->chan_type,
roc->req_duration, GFP_KERNEL);
}
@@ -263,6 +261,9 @@ void ieee80211_start_next_roc(struct ieee80211_local *local)
roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work,
list);
+ if (WARN_ON_ONCE(roc->started))
+ return;
+
if (local->ops->remain_on_channel) {
int ret, duration = roc->duration;
@@ -298,7 +299,7 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
/* was never transmitted */
if (roc->frame) {
- cfg80211_mgmt_tx_status(roc->sdata->dev,
+ cfg80211_mgmt_tx_status(&roc->sdata->wdev,
(unsigned long)roc->frame,
roc->frame->data, roc->frame->len,
false, GFP_KERNEL);
@@ -306,7 +307,7 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
}
if (!roc->mgmt_tx_cookie)
- cfg80211_remain_on_channel_expired(roc->sdata->dev,
+ cfg80211_remain_on_channel_expired(&roc->sdata->wdev,
(unsigned long)roc,
roc->chan, roc->chan_type,
GFP_KERNEL);
@@ -378,8 +379,8 @@ void ieee80211_sw_roc_work(struct work_struct *work)
ieee80211_recalc_idle(local);
- ieee80211_start_next_roc(local);
- ieee80211_run_deferred_scan(local);
+ if (roc->started)
+ ieee80211_start_next_roc(local);
}
out_unlock:
@@ -410,9 +411,6 @@ static void ieee80211_hw_roc_done(struct work_struct *work)
/* if there's another roc, start it now */
ieee80211_start_next_roc(local);
- /* or scan maybe */
- ieee80211_run_deferred_scan(local);
-
out_unlock:
mutex_unlock(&local->mtx);
}
@@ -455,7 +453,6 @@ void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata)
}
ieee80211_start_next_roc(local);
- ieee80211_run_deferred_scan(local);
mutex_unlock(&local->mtx);
list_for_each_entry_safe(roc, tmp, &tmp_list, list) {
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 98c128be3827..5c572e7a1a71 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -78,6 +78,16 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
if (err < 0) {
local->quiescing = false;
local->wowlan = false;
+ if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
+ mutex_lock(&local->sta_mtx);
+ list_for_each_entry(sta,
+ &local->sta_list, list) {
+ clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
+ }
+ mutex_unlock(&local->sta_mtx);
+ }
+ ieee80211_wake_queues_by_reason(hw,
+ IEEE80211_QUEUE_STOP_REASON_SUSPEND);
return err;
} else if (err > 0) {
WARN_ON(err != 1);
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 2d1acc6c5445..fb1d4aa65e8c 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -626,8 +626,12 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
#ifdef CONFIG_MAC80211_DEBUGFS
/* use fixed index if set */
- if (mp->fixed_rate_idx != -1)
- sample_idx = mp->fixed_rate_idx;
+ if (mp->fixed_rate_idx != -1) {
+ mi->max_tp_rate = mp->fixed_rate_idx;
+ mi->max_tp_rate2 = mp->fixed_rate_idx;
+ mi->max_prob_rate = mp->fixed_rate_idx;
+ sample_idx = -1;
+ }
#endif
if (sample_idx >= 0) {
@@ -809,7 +813,7 @@ minstrel_ht_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
max_rates = sband->n_bitrates;
}
- msp = kzalloc(sizeof(struct minstrel_ht_sta), gfp);
+ msp = kzalloc(sizeof(*msp), gfp);
if (!msp)
return NULL;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 6fd2cb0838c4..090d417919af 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -413,29 +413,6 @@ static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx)
/* rx handlers */
-static ieee80211_rx_result debug_noinline
-ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
-{
- struct ieee80211_local *local = rx->local;
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
- struct sk_buff *skb = rx->skb;
-
- if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&
- !local->sched_scanning))
- return RX_CONTINUE;
-
- if (test_bit(SCAN_HW_SCANNING, &local->scanning) ||
- test_bit(SCAN_SW_SCANNING, &local->scanning) ||
- test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
- local->sched_scanning)
- return ieee80211_scan_rx(rx->sdata, skb);
-
- /* scanning finished during invoking of handlers */
- I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
- return RX_DROP_UNUSABLE;
-}
-
-
static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -554,11 +531,11 @@ static inline u16 seq_sub(u16 sq1, u16 sq2)
}
-static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw,
+static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,
struct tid_ampdu_rx *tid_agg_rx,
int index)
{
- struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_local *local = sdata->local;
struct sk_buff *skb = tid_agg_rx->reorder_buf[index];
struct ieee80211_rx_status *status;
@@ -578,7 +555,7 @@ no_frame:
tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
}
-static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
+static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata,
struct tid_ampdu_rx *tid_agg_rx,
u16 head_seq_num)
{
@@ -589,7 +566,7 @@ static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) {
index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
tid_agg_rx->buf_size;
- ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
+ ieee80211_release_reorder_frame(sdata, tid_agg_rx, index);
}
}
@@ -604,7 +581,7 @@ static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
*/
#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10)
-static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
+static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
struct tid_ampdu_rx *tid_agg_rx)
{
int index, j;
@@ -632,12 +609,9 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
HT_RX_REORDER_BUF_TIMEOUT))
goto set_release_timer;
-#ifdef CONFIG_MAC80211_HT_DEBUG
- if (net_ratelimit())
- wiphy_debug(hw->wiphy,
- "release an RX reorder frame due to timeout on earlier frames\n");
-#endif
- ieee80211_release_reorder_frame(hw, tid_agg_rx, j);
+ ht_dbg_ratelimited(sdata,
+ "release an RX reorder frame due to timeout on earlier frames\n");
+ ieee80211_release_reorder_frame(sdata, tid_agg_rx, j);
/*
* Increment the head seq# also for the skipped slots.
@@ -647,7 +621,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
skipped = 0;
}
} else while (tid_agg_rx->reorder_buf[index]) {
- ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
+ ieee80211_release_reorder_frame(sdata, tid_agg_rx, index);
index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
tid_agg_rx->buf_size;
}
@@ -677,7 +651,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
* rcu_read_lock protection. It returns false if the frame
* can be processed immediately, true if it was consumed.
*/
-static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
+static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata,
struct tid_ampdu_rx *tid_agg_rx,
struct sk_buff *skb)
{
@@ -706,7 +680,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) {
head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size));
/* release stored frames up to new head to stack */
- ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num);
+ ieee80211_release_reorder_frames(sdata, tid_agg_rx,
+ head_seq_num);
}
/* Now the new frame is always in the range of the reordering buffer */
@@ -736,7 +711,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
tid_agg_rx->reorder_buf[index] = skb;
tid_agg_rx->reorder_time[index] = jiffies;
tid_agg_rx->stored_mpdu_num++;
- ieee80211_sta_reorder_release(hw, tid_agg_rx);
+ ieee80211_sta_reorder_release(sdata, tid_agg_rx);
out:
spin_unlock(&tid_agg_rx->reorder_lock);
@@ -751,7 +726,6 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx)
{
struct sk_buff *skb = rx->skb;
struct ieee80211_local *local = rx->local;
- struct ieee80211_hw *hw = &local->hw;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct sta_info *sta = rx->sta;
@@ -813,7 +787,7 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx)
* sure that we cannot get to it any more before doing
* anything with it.
*/
- if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb))
+ if (ieee80211_sta_manage_reorder_buf(rx->sdata, tid_agg_rx, skb))
return;
dont_reorder:
@@ -1136,24 +1110,18 @@ static void ap_sta_ps_start(struct sta_info *sta)
set_sta_flag(sta, WLAN_STA_PS_STA);
if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- pr_debug("%s: STA %pM aid %d enters power save mode\n",
- sdata->name, sta->sta.addr, sta->sta.aid);
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+ ps_dbg(sdata, "STA %pM aid %d enters power save mode\n",
+ sta->sta.addr, sta->sta.aid);
}
static void ap_sta_ps_end(struct sta_info *sta)
{
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- pr_debug("%s: STA %pM aid %d exits power save mode\n",
- sta->sdata->name, sta->sta.addr, sta->sta.aid);
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+ ps_dbg(sta->sdata, "STA %pM aid %d exits power save mode\n",
+ sta->sta.addr, sta->sta.aid);
if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- pr_debug("%s: STA %pM aid %d driver-ps-blocked\n",
- sta->sdata->name, sta->sta.addr, sta->sta.aid);
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+ ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n",
+ sta->sta.addr, sta->sta.aid);
return;
}
@@ -1383,17 +1351,8 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX)
sdata->fragment_next = 0;
- if (!skb_queue_empty(&entry->skb_list)) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- struct ieee80211_hdr *hdr =
- (struct ieee80211_hdr *) entry->skb_list.next->data;
- pr_debug("%s: RX reassembly removed oldest fragment entry (idx=%d age=%lu seq=%d last_frag=%d addr1=%pM addr2=%pM\n",
- sdata->name, idx,
- jiffies - entry->first_frag_time, entry->seq,
- entry->last_frag, hdr->addr1, hdr->addr2);
-#endif
+ if (!skb_queue_empty(&entry->skb_list))
__skb_queue_purge(&entry->skb_list);
- }
__skb_queue_tail(&entry->skb_list, *skb); /* no need for locking */
*skb = NULL;
@@ -1751,7 +1710,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
*/
xmit_skb = skb_copy(skb, GFP_ATOMIC);
if (!xmit_skb)
- net_dbg_ratelimited("%s: failed to clone multicast frame\n",
+ net_info_ratelimited("%s: failed to clone multicast frame\n",
dev->name);
} else {
dsta = sta_info_get(sdata, skb->data);
@@ -1935,7 +1894,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
ether_addr_equal(sdata->vif.addr, hdr->addr3))
return RX_CONTINUE;
- q = ieee80211_select_queue_80211(local, skb, hdr);
+ q = ieee80211_select_queue_80211(sdata, skb, hdr);
if (ieee80211_queue_stopped(&local->hw, q)) {
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion);
return RX_DROP_MONITOR;
@@ -1955,7 +1914,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
fwd_skb = skb_copy(skb, GFP_ATOMIC);
if (!fwd_skb) {
- net_dbg_ratelimited("%s: failed to clone mesh frame\n",
+ net_info_ratelimited("%s: failed to clone mesh frame\n",
sdata->name);
goto out;
}
@@ -2058,8 +2017,6 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
{
- struct ieee80211_local *local = rx->local;
- struct ieee80211_hw *hw = &local->hw;
struct sk_buff *skb = rx->skb;
struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data;
struct tid_ampdu_rx *tid_agg_rx;
@@ -2096,7 +2053,8 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
spin_lock(&tid_agg_rx->reorder_lock);
/* release stored frames up to start of BAR */
- ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num);
+ ieee80211_release_reorder_frames(rx->sdata, tid_agg_rx,
+ start_seq_num);
spin_unlock(&tid_agg_rx->reorder_lock);
kfree_skb(skb);
@@ -2423,7 +2381,7 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
sig = status->signal;
- if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq, sig,
+ if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig,
rx->skb->data, rx->skb->len,
GFP_ATOMIC)) {
if (rx->sta)
@@ -2453,7 +2411,7 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
* frames that we didn't handle, including returning unknown
* ones. For all other modes we will return them to the sender,
* setting the 0x80 bit in the action category, as required by
- * 802.11-2007 7.3.1.11.
+ * 802.11-2012 9.24.4.
* Newer versions of hostapd shall also use the management frame
* registration mechanisms, but older ones still use cooked
* monitor interfaces so push all frames there.
@@ -2463,6 +2421,9 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
return RX_DROP_MONITOR;
+ if (is_multicast_ether_addr(mgmt->da))
+ return RX_DROP_MONITOR;
+
/* do not return rejected action frames */
if (mgmt->u.action.category & 0x80)
return RX_DROP_UNUSABLE;
@@ -2711,7 +2672,6 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
goto rxh_next; \
} while (0);
- CALL_RXH(ieee80211_rx_h_passive_scan)
CALL_RXH(ieee80211_rx_h_check)
ieee80211_rx_reorder_ampdu(rx);
@@ -2747,7 +2707,7 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
return;
spin_lock(&tid_agg_rx->reorder_lock);
- ieee80211_sta_reorder_release(&sta->local->hw, tid_agg_rx);
+ ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx);
spin_unlock(&tid_agg_rx->reorder_lock);
ieee80211_rx_handlers(&rx);
@@ -2781,11 +2741,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
return 0;
if (ieee80211_is_beacon(hdr->frame_control)) {
return 1;
- }
- else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {
- if (!(status->rx_flags & IEEE80211_RX_IN_SCAN))
- return 0;
- status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
+ } else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {
+ return 0;
} else if (!multicast &&
!ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
if (!(sdata->dev->flags & IFF_PROMISC))
@@ -2823,11 +2780,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
* and location updates. Note that mac80211
* itself never looks at these frames.
*/
- if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&
- ieee80211_is_public_action(hdr, skb->len))
+ if (ieee80211_is_public_action(hdr, skb->len))
return 1;
- if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&
- !ieee80211_is_beacon(hdr->frame_control))
+ if (!ieee80211_is_beacon(hdr->frame_control))
return 0;
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
}
@@ -2893,7 +2848,6 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
struct sk_buff *skb)
{
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
struct ieee80211_hdr *hdr;
@@ -2911,11 +2865,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
local->dot11ReceivedFragmentCount++;
- if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
- test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
- test_bit(SCAN_SW_SCANNING, &local->scanning)))
- status->rx_flags |= IEEE80211_RX_IN_SCAN;
-
if (ieee80211_is_mgmt(fc))
err = skb_linearize(skb);
else
@@ -2930,6 +2879,10 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
ieee80211_parse_qos(&rx);
ieee80211_verify_alignment(&rx);
+ if (unlikely(ieee80211_is_probe_resp(hdr->frame_control) ||
+ ieee80211_is_beacon(hdr->frame_control)))
+ ieee80211_scan_rx(local, skb);
+
if (ieee80211_is_data(fc)) {
prev_sta = NULL;
@@ -3027,6 +2980,10 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
if (unlikely(local->quiescing || local->suspended))
goto drop;
+ /* We might be during a HW reconfig, prevent Rx for the same reason */
+ if (unlikely(local->in_reconfig))
+ goto drop;
+
/*
* The same happens when we're not even started,
* but that's worth a warning.
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 379f178eab5f..e80a8b644aa0 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -83,13 +83,14 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel,
mgmt, len, signal, GFP_ATOMIC);
-
if (!cbss)
return NULL;
cbss->free_priv = ieee80211_rx_bss_free;
bss = (void *)cbss->priv;
+ bss->device_ts = rx_status->device_timestamp;
+
if (elems->parse_error) {
if (beacon)
bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON;
@@ -165,52 +166,47 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
return bss;
}
-ieee80211_rx_result
-ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
+void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
{
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
- struct ieee80211_mgmt *mgmt;
+ struct ieee80211_sub_if_data *sdata1, *sdata2;
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
struct ieee80211_bss *bss;
u8 *elements;
struct ieee80211_channel *channel;
size_t baselen;
int freq;
- __le16 fc;
- bool presp, beacon = false;
+ bool beacon;
struct ieee802_11_elems elems;
- if (skb->len < 2)
- return RX_DROP_UNUSABLE;
-
- mgmt = (struct ieee80211_mgmt *) skb->data;
- fc = mgmt->frame_control;
+ if (skb->len < 24 ||
+ (!ieee80211_is_probe_resp(mgmt->frame_control) &&
+ !ieee80211_is_beacon(mgmt->frame_control)))
+ return;
- if (ieee80211_is_ctl(fc))
- return RX_CONTINUE;
+ sdata1 = rcu_dereference(local->scan_sdata);
+ sdata2 = rcu_dereference(local->sched_scan_sdata);
- if (skb->len < 24)
- return RX_CONTINUE;
+ if (likely(!sdata1 && !sdata2))
+ return;
- presp = ieee80211_is_probe_resp(fc);
- if (presp) {
+ if (ieee80211_is_probe_resp(mgmt->frame_control)) {
/* ignore ProbeResp to foreign address */
- if (!ether_addr_equal(mgmt->da, sdata->vif.addr))
- return RX_DROP_MONITOR;
+ if ((!sdata1 || !ether_addr_equal(mgmt->da, sdata1->vif.addr)) &&
+ (!sdata2 || !ether_addr_equal(mgmt->da, sdata2->vif.addr)))
+ return;
- presp = true;
elements = mgmt->u.probe_resp.variable;
baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+ beacon = false;
} else {
- beacon = ieee80211_is_beacon(fc);
baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
elements = mgmt->u.beacon.variable;
+ beacon = true;
}
- if (!presp && !beacon)
- return RX_CONTINUE;
-
if (baselen > skb->len)
- return RX_DROP_MONITOR;
+ return;
ieee802_11_parse_elems(elements, skb->len - baselen, &elems);
@@ -220,22 +216,16 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
else
freq = rx_status->freq;
- channel = ieee80211_get_channel(sdata->local->hw.wiphy, freq);
+ channel = ieee80211_get_channel(local->hw.wiphy, freq);
if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
- return RX_DROP_MONITOR;
+ return;
- bss = ieee80211_bss_info_update(sdata->local, rx_status,
+ bss = ieee80211_bss_info_update(local, rx_status,
mgmt, skb->len, &elems,
channel, beacon);
if (bss)
- ieee80211_rx_bss_put(sdata->local, bss);
-
- if (channel == sdata->local->oper_channel)
- return RX_CONTINUE;
-
- dev_kfree_skb(skb);
- return RX_QUEUED;
+ ieee80211_rx_bss_put(local, bss);
}
/* return false if no more work */
@@ -293,7 +283,13 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
return;
if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
- int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req);
+ int rc;
+
+ rc = drv_hw_scan(local,
+ rcu_dereference_protected(local->scan_sdata,
+ lockdep_is_held(&local->mtx)),
+ local->hw_scan_req);
+
if (rc == 0)
return;
}
@@ -394,7 +390,10 @@ void ieee80211_run_deferred_scan(struct ieee80211_local *local)
if (!local->scan_req || local->scanning)
return;
- if (!ieee80211_can_scan(local, local->scan_sdata))
+ if (!ieee80211_can_scan(local,
+ rcu_dereference_protected(
+ local->scan_sdata,
+ lockdep_is_held(&local->mtx))))
return;
ieee80211_queue_delayed_work(&local->hw, &local->scan_work,
@@ -405,9 +404,12 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
unsigned long *next_delay)
{
int i;
- struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+ struct ieee80211_sub_if_data *sdata;
enum ieee80211_band band = local->hw.conf.channel->band;
+ sdata = rcu_dereference_protected(local->scan_sdata,
+ lockdep_is_held(&local->mtx));;
+
for (i = 0; i < local->scan_req->n_ssids; i++)
ieee80211_send_probe_req(
sdata, NULL,
@@ -439,7 +441,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
if (!ieee80211_can_scan(local, sdata)) {
/* wait for the work to finish/time out */
local->scan_req = req;
- local->scan_sdata = sdata;
+ rcu_assign_pointer(local->scan_sdata, sdata);
return 0;
}
@@ -473,7 +475,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
}
local->scan_req = req;
- local->scan_sdata = sdata;
+ rcu_assign_pointer(local->scan_sdata, sdata);
if (local->ops->hw_scan) {
__set_bit(SCAN_HW_SCANNING, &local->scanning);
@@ -533,7 +535,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
ieee80211_recalc_idle(local);
local->scan_req = NULL;
- local->scan_sdata = NULL;
+ rcu_assign_pointer(local->scan_sdata, NULL);
}
return rc;
@@ -720,7 +722,8 @@ void ieee80211_scan_work(struct work_struct *work)
mutex_lock(&local->mtx);
- sdata = local->scan_sdata;
+ sdata = rcu_dereference_protected(local->scan_sdata,
+ lockdep_is_held(&local->mtx));
/* When scanning on-channel, the first-callback means completed. */
if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) {
@@ -741,7 +744,7 @@ void ieee80211_scan_work(struct work_struct *work)
int rc;
local->scan_req = NULL;
- local->scan_sdata = NULL;
+ rcu_assign_pointer(local->scan_sdata, NULL);
rc = __ieee80211_start_scan(sdata, req);
if (rc) {
@@ -893,7 +896,9 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
if (test_bit(SCAN_HW_SCANNING, &local->scanning)) {
if (local->ops->cancel_hw_scan)
- drv_cancel_hw_scan(local, local->scan_sdata);
+ drv_cancel_hw_scan(local,
+ rcu_dereference_protected(local->scan_sdata,
+ lockdep_is_held(&local->mtx)));
goto out;
}
@@ -915,9 +920,9 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
int ret, i;
- mutex_lock(&sdata->local->mtx);
+ mutex_lock(&local->mtx);
- if (local->sched_scanning) {
+ if (rcu_access_pointer(local->sched_scan_sdata)) {
ret = -EBUSY;
goto out;
}
@@ -928,6 +933,9 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
}
for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
+ if (!local->hw.wiphy->bands[i])
+ continue;
+
local->sched_scan_ies.ie[i] = kzalloc(2 +
IEEE80211_MAX_SSID_LEN +
local->scan_ies_len +
@@ -948,7 +956,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
ret = drv_sched_scan_start(local, sdata, req,
&local->sched_scan_ies);
if (ret == 0) {
- local->sched_scanning = true;
+ rcu_assign_pointer(local->sched_scan_sdata, sdata);
goto out;
}
@@ -956,7 +964,7 @@ out_free:
while (i > 0)
kfree(local->sched_scan_ies.ie[--i]);
out:
- mutex_unlock(&sdata->local->mtx);
+ mutex_unlock(&local->mtx);
return ret;
}
@@ -965,22 +973,22 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
struct ieee80211_local *local = sdata->local;
int ret = 0, i;
- mutex_lock(&sdata->local->mtx);
+ mutex_lock(&local->mtx);
if (!local->ops->sched_scan_stop) {
ret = -ENOTSUPP;
goto out;
}
- if (local->sched_scanning) {
+ if (rcu_access_pointer(local->sched_scan_sdata)) {
for (i = 0; i < IEEE80211_NUM_BANDS; i++)
kfree(local->sched_scan_ies.ie[i]);
drv_sched_scan_stop(local, sdata);
- local->sched_scanning = false;
+ rcu_assign_pointer(local->sched_scan_sdata, NULL);
}
out:
- mutex_unlock(&sdata->local->mtx);
+ mutex_unlock(&local->mtx);
return ret;
}
@@ -1004,7 +1012,7 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work)
mutex_lock(&local->mtx);
- if (!local->sched_scanning) {
+ if (!rcu_access_pointer(local->sched_scan_sdata)) {
mutex_unlock(&local->mtx);
return;
}
@@ -1012,7 +1020,7 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work)
for (i = 0; i < IEEE80211_NUM_BANDS; i++)
kfree(local->sched_scan_ies.ie[i]);
- local->sched_scanning = false;
+ rcu_assign_pointer(local->sched_scan_sdata, NULL);
mutex_unlock(&local->mtx);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 77dcf2f89d42..06fa75ceb025 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -169,9 +169,7 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
if (sta->rate_ctrl)
rate_control_free_sta(sta);
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- wiphy_debug(local->hw.wiphy, "Destroyed STA %pM\n", sta->sta.addr);
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+ sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
kfree(sta);
}
@@ -278,9 +276,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX);
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- wiphy_debug(local->hw.wiphy, "Allocated STA %pM\n", sta->sta.addr);
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+ sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
#ifdef CONFIG_MAC80211_MESH
sta->plink_state = NL80211_PLINK_LISTEN;
@@ -333,8 +329,9 @@ static int sta_info_insert_drv_state(struct ieee80211_local *local,
}
if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
- pr_debug("%s: failed to move IBSS STA %pM to state %d (%d) - keeping it anyway\n",
- sdata->name, sta->sta.addr, state + 1, err);
+ sdata_info(sdata,
+ "failed to move IBSS STA %pM to state %d (%d) - keeping it anyway\n",
+ sta->sta.addr, state + 1, err);
err = 0;
}
@@ -389,9 +386,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
sinfo.generation = local->sta_generation;
cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr);
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+ sta_dbg(sdata, "Inserted STA %pM\n", sta->sta.addr);
/* move reference to rcu-protected */
rcu_read_lock();
@@ -617,9 +612,8 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local,
break;
local->total_ps_buffered--;
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- pr_debug("Buffered frame expired (STA %pM)\n", sta->sta.addr);
-#endif
+ ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n",
+ sta->sta.addr);
dev_kfree_skb(skb);
}
@@ -745,9 +739,8 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
mesh_accept_plinks_update(sdata);
#endif
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- wiphy_debug(local->hw.wiphy, "Removed STA %pM\n", sta->sta.addr);
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+ sta_dbg(sdata, "Removed STA %pM\n", sta->sta.addr);
+
cancel_work_sync(&sta->drv_unblock_wk);
cfg80211_del_sta(sdata->dev, sta->sta.addr, GFP_KERNEL);
@@ -887,8 +880,8 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
continue;
if (time_after(jiffies, sta->last_rx + exp_time)) {
- ibss_vdbg("%s: expiring inactive STA %pM\n",
- sdata->name, sta->sta.addr);
+ ibss_dbg(sdata, "expiring inactive STA %pM\n",
+ sta->sta.addr);
WARN_ON(__sta_info_destroy(sta));
}
}
@@ -986,10 +979,9 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
sta_info_recalc_tim(sta);
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- pr_debug("%s: STA %pM aid %d sending %d filtered/%d PS frames since STA not sleeping anymore\n",
- sdata->name, sta->sta.addr, sta->sta.aid, filtered, buffered);
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+ ps_dbg(sdata,
+ "STA %pM aid %d sending %d filtered/%d PS frames since STA not sleeping anymore\n",
+ sta->sta.addr, sta->sta.aid, filtered, buffered);
}
static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
@@ -1379,10 +1371,8 @@ int sta_info_move_state(struct sta_info *sta,
return -EINVAL;
}
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- pr_debug("%s: moving STA %pM to state %d\n",
- sta->sdata->name, sta->sta.addr, new_state);
-#endif
+ sta_dbg(sta->sdata, "moving STA %pM to state %d\n",
+ sta->sta.addr, new_state);
/*
* notify the driver before the actual changes so it can
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 3bb24a121c95..a470e1123a55 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -271,6 +271,9 @@ struct sta_ampdu_mlme {
* @plink_timer: peer link watch timer
* @plink_timer_was_running: used by suspend/resume to restore timers
* @t_offset: timing offset relative to this host
+ * @t_offset_setpoint: reference timing offset of this sta to be used when
+ * calculating clockdrift
+ * @ch_type: peer's channel type
* @debugfs: debug filesystem info
* @dead: set to true when sta is unlinked
* @uploaded: set to true when sta is uploaded to the driver
@@ -278,6 +281,8 @@ struct sta_ampdu_mlme {
* @sta: station information we share with the driver
* @sta_state: duplicates information about station state (for debug)
* @beacon_loss_count: number of times beacon loss has triggered
+ * @supports_40mhz: tracks whether the station advertised 40 MHz support
+ * as we overwrite its HT parameters with the currently used value
*/
struct sta_info {
/* General information, mostly static */
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 6b4f42527887..8cd72914cdaf 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -155,13 +155,10 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
return;
}
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- if (net_ratelimit())
- wiphy_debug(local->hw.wiphy,
- "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n",
- skb_queue_len(&sta->tx_filtered[ac]),
- !!test_sta_flag(sta, WLAN_STA_PS_STA), jiffies);
-#endif
+ ps_dbg_ratelimited(sta->sdata,
+ "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n",
+ skb_queue_len(&sta->tx_filtered[ac]),
+ !!test_sta_flag(sta, WLAN_STA_PS_STA), jiffies);
dev_kfree_skb(skb);
}
@@ -522,14 +519,19 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
u64 cookie = (unsigned long)skb;
acked = info->flags & IEEE80211_TX_STAT_ACK;
+ /*
+ * TODO: When we have non-netdev frame TX,
+ * we cannot use skb->dev->ieee80211_ptr
+ */
+
if (ieee80211_is_nullfunc(hdr->frame_control) ||
ieee80211_is_qos_nullfunc(hdr->frame_control))
cfg80211_probe_status(skb->dev, hdr->addr1,
cookie, acked, GFP_ATOMIC);
else
cfg80211_mgmt_tx_status(
- skb->dev, cookie, skb->data, skb->len,
- acked, GFP_ATOMIC);
+ skb->dev->ieee80211_ptr, cookie, skb->data,
+ skb->len, acked, GFP_ATOMIC);
}
if (unlikely(info->ack_frame_id)) {
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c
index 68be47ca208f..57e14d59e12f 100644
--- a/net/mac80211/tkip.c
+++ b/net/mac80211/tkip.c
@@ -260,16 +260,6 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
keyid = pos[3];
iv32 = get_unaligned_le32(pos + 4);
pos += 8;
-#ifdef CONFIG_MAC80211_TKIP_DEBUG
- {
- int i;
- pr_debug("TKIP decrypt: data(len=%zd)", payload_len);
- for (i = 0; i < payload_len; i++)
- printk(" %02x", payload[i]);
- printk("\n");
- pr_debug("TKIP decrypt: iv16=%04x iv32=%08x\n", iv16, iv32);
- }
-#endif
if (!(keyid & (1 << 5)))
return TKIP_DECRYPT_NO_EXT_IV;
@@ -280,15 +270,8 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
if (key->u.tkip.rx[queue].state != TKIP_STATE_NOT_INIT &&
(iv32 < key->u.tkip.rx[queue].iv32 ||
(iv32 == key->u.tkip.rx[queue].iv32 &&
- iv16 <= key->u.tkip.rx[queue].iv16))) {
-#ifdef CONFIG_MAC80211_TKIP_DEBUG
- pr_debug("TKIP replay detected for RX frame from %pM (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n",
- ta, iv32, iv16,
- key->u.tkip.rx[queue].iv32,
- key->u.tkip.rx[queue].iv16);
-#endif
+ iv16 <= key->u.tkip.rx[queue].iv16)))
return TKIP_DECRYPT_REPLAY;
- }
if (only_iv) {
res = TKIP_DECRYPT_OK;
@@ -300,21 +283,6 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
key->u.tkip.rx[queue].iv32 != iv32) {
/* IV16 wrapped around - perform TKIP phase 1 */
tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32);
-#ifdef CONFIG_MAC80211_TKIP_DEBUG
- {
- int i;
- u8 key_offset = NL80211_TKIP_DATA_OFFSET_ENCR_KEY;
- pr_debug("TKIP decrypt: Phase1 TA=%pM TK=", ta);
- for (i = 0; i < 16; i++)
- printk("%02x ",
- key->conf.key[key_offset + i]);
- printk("\n");
- pr_debug("TKIP decrypt: P1K=");
- for (i = 0; i < 5; i++)
- printk("%04x ", key->u.tkip.rx[queue].p1k[i]);
- printk("\n");
- }
-#endif
}
if (key->local->ops->update_tkip_key &&
key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
@@ -330,15 +298,6 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
}
tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key);
-#ifdef CONFIG_MAC80211_TKIP_DEBUG
- {
- int i;
- pr_debug("TKIP decrypt: Phase2 rc4key=");
- for (i = 0; i < 16; i++)
- printk("%02x ", rc4key[i]);
- printk("\n");
- }
-#endif
res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12);
done:
diff --git a/net/mac80211/trace.c b/net/mac80211/trace.c
new file mode 100644
index 000000000000..386e45d8a958
--- /dev/null
+++ b/net/mac80211/trace.c
@@ -0,0 +1,75 @@
+/* bug in tracepoint.h, it should include this */
+#include <linux/module.h>
+
+/* sparse isn't too happy with all macros... */
+#ifndef __CHECKER__
+#include <net/cfg80211.h>
+#include "driver-ops.h"
+#include "debug.h"
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
+#ifdef CONFIG_MAC80211_MESSAGE_TRACING
+void __sdata_info(const char *fmt, ...)
+{
+ struct va_format vaf = {
+ .fmt = fmt,
+ };
+ va_list args;
+
+ va_start(args, fmt);
+ vaf.va = &args;
+
+ pr_info("%pV", &vaf);
+ trace_mac80211_info(&vaf);
+ va_end(args);
+}
+
+void __sdata_dbg(bool print, const char *fmt, ...)
+{
+ struct va_format vaf = {
+ .fmt = fmt,
+ };
+ va_list args;
+
+ va_start(args, fmt);
+ vaf.va = &args;
+
+ if (print)
+ pr_debug("%pV", &vaf);
+ trace_mac80211_dbg(&vaf);
+ va_end(args);
+}
+
+void __sdata_err(const char *fmt, ...)
+{
+ struct va_format vaf = {
+ .fmt = fmt,
+ };
+ va_list args;
+
+ va_start(args, fmt);
+ vaf.va = &args;
+
+ pr_err("%pV", &vaf);
+ trace_mac80211_err(&vaf);
+ va_end(args);
+}
+
+void __wiphy_dbg(struct wiphy *wiphy, bool print, const char *fmt, ...)
+{
+ struct va_format vaf = {
+ .fmt = fmt,
+ };
+ va_list args;
+
+ va_start(args, fmt);
+ vaf.va = &args;
+
+ if (print)
+ wiphy_dbg(wiphy, "%pV", &vaf);
+ trace_mac80211_dbg(&vaf);
+ va_end(args);
+}
+#endif
+#endif
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/trace.h
index 6de00b2c268c..c6d33b55b2df 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/trace.h
@@ -306,7 +306,8 @@ TRACE_EVENT(drv_bss_info_changed,
__field(u8, dtimper)
__field(u16, bcnint)
__field(u16, assoc_cap)
- __field(u64, timestamp)
+ __field(u64, sync_tsf)
+ __field(u32, sync_device_ts)
__field(u32, basic_rates)
__field(u32, changed)
__field(bool, enable_beacon)
@@ -325,7 +326,8 @@ TRACE_EVENT(drv_bss_info_changed,
__entry->dtimper = info->dtim_period;
__entry->bcnint = info->beacon_int;
__entry->assoc_cap = info->assoc_capability;
- __entry->timestamp = info->last_tsf;
+ __entry->sync_tsf = info->sync_tsf;
+ __entry->sync_device_ts = info->sync_device_ts;
__entry->basic_rates = info->basic_rates;
__entry->enable_beacon = info->enable_beacon;
__entry->ht_operation_mode = info->ht_operation_mode;
@@ -1218,6 +1220,39 @@ DEFINE_EVENT(release_evt, drv_allow_buffered_frames,
TP_ARGS(local, sta, tids, num_frames, reason, more_data)
);
+TRACE_EVENT(drv_get_rssi,
+ TP_PROTO(struct ieee80211_local *local, struct ieee80211_sta *sta,
+ s8 rssi, int ret),
+
+ TP_ARGS(local, sta, rssi, ret),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ STA_ENTRY
+ __field(s8, rssi)
+ __field(int, ret)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ STA_ASSIGN;
+ __entry->rssi = rssi;
+ __entry->ret = ret;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT STA_PR_FMT " rssi:%d ret:%d",
+ LOCAL_PR_ARG, STA_PR_ARG, __entry->rssi, __entry->ret
+ )
+);
+
+DEFINE_EVENT(local_sdata_evt, drv_mgd_prepare_tx,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata),
+
+ TP_ARGS(local, sdata)
+);
+
/*
* Tracing for API calls that drivers call.
*/
@@ -1606,10 +1641,49 @@ TRACE_EVENT(stop_queue,
LOCAL_PR_ARG, __entry->queue, __entry->reason
)
);
+
+#ifdef CONFIG_MAC80211_MESSAGE_TRACING
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM mac80211_msg
+
+#define MAX_MSG_LEN 100
+
+DECLARE_EVENT_CLASS(mac80211_msg_event,
+ TP_PROTO(struct va_format *vaf),
+
+ TP_ARGS(vaf),
+
+ TP_STRUCT__entry(
+ __dynamic_array(char, msg, MAX_MSG_LEN)
+ ),
+
+ TP_fast_assign(
+ WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+ MAX_MSG_LEN, vaf->fmt,
+ *vaf->va) >= MAX_MSG_LEN);
+ ),
+
+ TP_printk("%s", __get_str(msg))
+);
+
+DEFINE_EVENT(mac80211_msg_event, mac80211_info,
+ TP_PROTO(struct va_format *vaf),
+ TP_ARGS(vaf)
+);
+DEFINE_EVENT(mac80211_msg_event, mac80211_dbg,
+ TP_PROTO(struct va_format *vaf),
+ TP_ARGS(vaf)
+);
+DEFINE_EVENT(mac80211_msg_event, mac80211_err,
+ TP_PROTO(struct va_format *vaf),
+ TP_ARGS(vaf)
+);
+#endif
+
#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
-#define TRACE_INCLUDE_FILE driver-trace
+#define TRACE_INCLUDE_FILE trace
#include <trace/define_trace.h>
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index af25c4e7ec5c..b755e778b0c4 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -140,6 +140,8 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
if (r->flags & IEEE80211_RATE_MANDATORY_A)
mrate = r->bitrate;
break;
+ case IEEE80211_BAND_60GHZ:
+ /* TODO, for now fall through */
case IEEE80211_NUM_BANDS:
WARN_ON(1);
break;
@@ -175,12 +177,6 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
return cpu_to_le16(dur);
}
-static inline int is_ieee80211_device(struct ieee80211_local *local,
- struct net_device *dev)
-{
- return local == wdev_priv(dev->ieee80211_ptr);
-}
-
/* tx handlers */
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
@@ -297,9 +293,10 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
if (unlikely(!assoc &&
ieee80211_is_data(hdr->frame_control))) {
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- pr_debug("%s: dropped data frame to not associated station %pM\n",
- tx->sdata->name, hdr->addr1);
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+ sdata_info(tx->sdata,
+ "dropped data frame to not associated station %pM\n",
+ hdr->addr1);
+#endif
I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
return TX_DROP;
}
@@ -366,10 +363,7 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
rcu_read_unlock();
local->total_ps_buffered = total;
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- wiphy_debug(local->hw.wiphy, "PS buffers full - purged %d frames\n",
- purged);
-#endif
+ ps_dbg_hw(&local->hw, "PS buffers full - purged %d frames\n", purged);
}
static ieee80211_tx_result
@@ -411,10 +405,8 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
purge_old_ps_buffers(tx->local);
if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >= AP_MAX_BC_BUFFER) {
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- net_dbg_ratelimited("%s: BC TX buffer full - dropping the oldest frame\n",
- tx->sdata->name);
-#endif
+ ps_dbg(tx->sdata,
+ "BC TX buffer full - dropping the oldest frame\n");
dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf));
} else
tx->local->total_ps_buffered++;
@@ -465,18 +457,15 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
return TX_CONTINUE;
}
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- pr_debug("STA %pM aid %d: PS buffer for AC %d\n",
- sta->sta.addr, sta->sta.aid, ac);
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+ ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n",
+ sta->sta.addr, sta->sta.aid, ac);
if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
purge_old_ps_buffers(tx->local);
if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) {
struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]);
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- net_dbg_ratelimited("%s: STA %pM TX buffer for AC %d full - dropping oldest frame\n",
- tx->sdata->name, sta->sta.addr, ac);
-#endif
+ ps_dbg(tx->sdata,
+ "STA %pM TX buffer for AC %d full - dropping oldest frame\n",
+ sta->sta.addr, ac);
dev_kfree_skb(old);
} else
tx->local->total_ps_buffered++;
@@ -498,13 +487,11 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
sta_info_recalc_tim(sta);
return TX_QUEUED;
+ } else if (unlikely(test_sta_flag(sta, WLAN_STA_PS_STA))) {
+ ps_dbg(tx->sdata,
+ "STA %pM in PS mode, but polling/in SP -> send frame\n",
+ sta->sta.addr);
}
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- else if (unlikely(test_sta_flag(sta, WLAN_STA_PS_STA))) {
- pr_debug("%s: STA %pM in PS mode, but polling/in SP -> send frame\n",
- tx->sdata->name, sta->sta.addr);
- }
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
return TX_CONTINUE;
}
@@ -536,7 +523,7 @@ ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx)
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
{
- struct ieee80211_key *key = NULL;
+ struct ieee80211_key *key;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
@@ -555,16 +542,23 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
else if (!is_multicast_ether_addr(hdr->addr1) &&
(key = rcu_dereference(tx->sdata->default_unicast_key)))
tx->key = key;
- else if (tx->sdata->drop_unencrypted &&
- (tx->skb->protocol != tx->sdata->control_port_protocol) &&
- !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
- (!ieee80211_is_robust_mgmt_frame(hdr) ||
- (ieee80211_is_action(hdr->frame_control) &&
- tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))) {
+ else if (info->flags & IEEE80211_TX_CTL_INJECTED)
+ tx->key = NULL;
+ else if (!tx->sdata->drop_unencrypted)
+ tx->key = NULL;
+ else if (tx->skb->protocol == tx->sdata->control_port_protocol)
+ tx->key = NULL;
+ else if (ieee80211_is_robust_mgmt_frame(hdr) &&
+ !(ieee80211_is_action(hdr->frame_control) &&
+ tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))
+ tx->key = NULL;
+ else if (ieee80211_is_mgmt(hdr->frame_control) &&
+ !ieee80211_is_robust_mgmt_frame(hdr))
+ tx->key = NULL;
+ else {
I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
return TX_DROP;
- } else
- tx->key = NULL;
+ }
if (tx->key) {
bool skip_hw = false;
@@ -972,8 +966,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
info->control.rates[1].idx = -1;
info->control.rates[2].idx = -1;
info->control.rates[3].idx = -1;
- info->control.rates[4].idx = -1;
- BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5);
+ BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 4);
info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE;
} else {
hdr->frame_control &= ~morefrags;
@@ -1308,11 +1301,8 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
break;
}
- if (local->ops->tx_frags)
- drv_tx_frags(local, vif, pubsta, skbs);
- else
- result = ieee80211_tx_frags(local, vif, pubsta, skbs,
- txpending);
+ result = ieee80211_tx_frags(local, vif, pubsta, skbs,
+ txpending);
ieee80211_tpt_led_trig_tx(local, fc, led_len);
ieee80211_led_tx(local, 1);
@@ -1963,7 +1953,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
(cpu_to_be16(ethertype) != sdata->control_port_protocol ||
!ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN)))) {
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- net_dbg_ratelimited("%s: dropped frame to %pM (unauthorized port)\n",
+ net_info_ratelimited("%s: dropped frame to %pM (unauthorized port)\n",
dev->name, hdr.addr1);
#endif
@@ -2435,9 +2425,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
*pos++ = WLAN_EID_SSID;
*pos++ = 0x0;
- if (ieee80211_add_srates_ie(&sdata->vif, skb, true) ||
+ if (ieee80211_add_srates_ie(sdata, skb, true) ||
mesh_add_ds_params_ie(skb, sdata) ||
- ieee80211_add_ext_srates_ie(&sdata->vif, skb, true) ||
+ ieee80211_add_ext_srates_ie(sdata, skb, true) ||
mesh_add_rsn_ie(skb, sdata) ||
mesh_add_ht_cap_ie(skb, sdata) ||
mesh_add_ht_oper_ie(skb, sdata) ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 1df4019f294b..39b82fee4904 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -268,6 +268,10 @@ EXPORT_SYMBOL(ieee80211_ctstoself_duration);
void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
{
struct ieee80211_sub_if_data *sdata;
+ int n_acs = IEEE80211_NUM_ACS;
+
+ if (local->hw.queues < IEEE80211_NUM_ACS)
+ n_acs = 1;
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
int ac;
@@ -279,7 +283,7 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
local->queue_stop_reasons[sdata->vif.cab_queue] != 0)
continue;
- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+ for (ac = 0; ac < n_acs; ac++) {
int ac_queue = sdata->vif.hw_queue[ac];
if (ac_queue == queue ||
@@ -341,6 +345,7 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
+ int n_acs = IEEE80211_NUM_ACS;
trace_stop_queue(local, queue, reason);
@@ -352,11 +357,14 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
__set_bit(reason, &local->queue_stop_reasons[queue]);
+ if (local->hw.queues < IEEE80211_NUM_ACS)
+ n_acs = 1;
+
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
int ac;
- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+ for (ac = 0; ac < n_acs; ac++) {
if (sdata->vif.hw_queue[ac] == queue ||
sdata->vif.cab_queue == queue)
netif_stop_subqueue(sdata->dev, ac);
@@ -521,6 +529,11 @@ void ieee80211_iterate_active_interfaces(
&sdata->vif);
}
+ sdata = rcu_dereference_protected(local->monitor_sdata,
+ lockdep_is_held(&local->iflist_mtx));
+ if (sdata)
+ iterator(data, sdata->vif.addr, &sdata->vif);
+
mutex_unlock(&local->iflist_mtx);
}
EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces);
@@ -549,6 +562,10 @@ void ieee80211_iterate_active_interfaces_atomic(
&sdata->vif);
}
+ sdata = rcu_dereference(local->monitor_sdata);
+ if (sdata)
+ iterator(data, sdata->vif.addr, &sdata->vif);
+
rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
@@ -991,6 +1008,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
int ext_rates_len;
sband = local->hw.wiphy->bands[band];
+ if (WARN_ON_ONCE(!sband))
+ return 0;
pos = buffer;
@@ -1072,6 +1091,10 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
pos += noffset - offset;
}
+ if (sband->vht_cap.vht_supported)
+ pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap,
+ sband->vht_cap.cap);
+
return pos - buffer;
}
@@ -1412,6 +1435,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
ieee80211_enable_keys(sdata);
wake_up:
+ local->in_reconfig = false;
+ barrier();
+
/*
* Clear the WLAN_STA_BLOCK_BA flag so new aggregation
* sessions can be established after a resume.
@@ -1696,6 +1722,27 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
return pos;
}
+u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
+ u32 cap)
+{
+ __le32 tmp;
+
+ *pos++ = WLAN_EID_VHT_CAPABILITY;
+ *pos++ = sizeof(struct ieee80211_vht_capabilities);
+ memset(pos, 0, sizeof(struct ieee80211_vht_capabilities));
+
+ /* capability flags */
+ tmp = cpu_to_le32(cap);
+ memcpy(pos, &tmp, sizeof(u32));
+ pos += sizeof(u32);
+
+ /* VHT MCS set */
+ memcpy(pos, &vht_cap->vht_mcs, sizeof(vht_cap->vht_mcs));
+ pos += sizeof(vht_cap->vht_mcs);
+
+ return pos;
+}
+
u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
struct ieee80211_channel *channel,
enum nl80211_channel_type channel_type,
@@ -1761,15 +1808,14 @@ ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper)
return channel_type;
}
-int ieee80211_add_srates_ie(struct ieee80211_vif *vif,
+int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, bool need_basic)
{
- struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband;
int rate;
u8 i, rates, *pos;
- u32 basic_rates = vif->bss_conf.basic_rates;
+ u32 basic_rates = sdata->vif.bss_conf.basic_rates;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
rates = sband->n_bitrates;
@@ -1793,15 +1839,14 @@ int ieee80211_add_srates_ie(struct ieee80211_vif *vif,
return 0;
}
-int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif,
+int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, bool need_basic)
{
- struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband;
int rate;
u8 i, exrates, *pos;
- u32 basic_rates = vif->bss_conf.basic_rates;
+ u32 basic_rates = sdata->vif.bss_conf.basic_rates;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
exrates = sband->n_bitrates;
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index c3d643a6536c..cea06e9f26f4 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -52,11 +52,11 @@ static int wme_downgrade_ac(struct sk_buff *skb)
}
}
-static u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
+static u16 ieee80211_downgrade_queue(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb)
{
/* in case we are a client verify acm is not set for this ac */
- while (unlikely(local->wmm_acm & BIT(skb->priority))) {
+ while (unlikely(sdata->wmm_acm & BIT(skb->priority))) {
if (wme_downgrade_ac(skb)) {
/*
* This should not really happen. The AP has marked all
@@ -73,10 +73,11 @@ static u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
}
/* Indicate which queue to use for this fully formed 802.11 frame */
-u16 ieee80211_select_queue_80211(struct ieee80211_local *local,
+u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb,
struct ieee80211_hdr *hdr)
{
+ struct ieee80211_local *local = sdata->local;
u8 *p;
if (local->hw.queues < IEEE80211_NUM_ACS)
@@ -94,7 +95,7 @@ u16 ieee80211_select_queue_80211(struct ieee80211_local *local,
p = ieee80211_get_qos_ctl(hdr);
skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
- return ieee80211_downgrade_queue(local, skb);
+ return ieee80211_downgrade_queue(sdata, skb);
}
/* Indicate which queue to use. */
@@ -156,7 +157,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
* data frame has */
skb->priority = cfg80211_classify8021d(skb);
- return ieee80211_downgrade_queue(local, skb);
+ return ieee80211_downgrade_queue(sdata, skb);
}
void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h
index ca80818b7b66..7fea4bb8acbc 100644
--- a/net/mac80211/wme.h
+++ b/net/mac80211/wme.h
@@ -15,7 +15,7 @@
extern const int ieee802_1d_to_ac[8];
-u16 ieee80211_select_queue_80211(struct ieee80211_local *local,
+u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb,
struct ieee80211_hdr *hdr);
u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 4177bb5104b9..ff749794bc5b 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -29,6 +29,8 @@
#include <linux/slab.h>
#include <linux/nfc.h>
+#include <net/genetlink.h>
+
#include "nfc.h"
#define VERSION "0.1"
@@ -560,6 +562,8 @@ EXPORT_SYMBOL(nfc_alloc_recv_skb);
* The device driver must call this function when one or many nfc targets
* are found. After calling this function, the device driver must stop
* polling for targets.
+ * NOTE: This function can be called with targets=NULL and n_targets=0 to
+ * notify a driver error, meaning that the polling operation cannot complete.
* IMPORTANT: this function must not be called from an atomic context.
* In addition, it must also not be called from a context that would prevent
* the NFC Core to call other nfc ops entry point concurrently.
@@ -571,23 +575,33 @@ int nfc_targets_found(struct nfc_dev *dev,
pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets);
- dev->polling = false;
-
for (i = 0; i < n_targets; i++)
targets[i].idx = dev->target_next_idx++;
device_lock(&dev->dev);
+ if (dev->polling == false) {
+ device_unlock(&dev->dev);
+ return 0;
+ }
+
+ dev->polling = false;
+
dev->targets_generation++;
kfree(dev->targets);
- dev->targets = kmemdup(targets, n_targets * sizeof(struct nfc_target),
- GFP_ATOMIC);
+ dev->targets = NULL;
- if (!dev->targets) {
- dev->n_targets = 0;
- device_unlock(&dev->dev);
- return -ENOMEM;
+ if (targets) {
+ dev->targets = kmemdup(targets,
+ n_targets * sizeof(struct nfc_target),
+ GFP_ATOMIC);
+
+ if (!dev->targets) {
+ dev->n_targets = 0;
+ device_unlock(&dev->dev);
+ return -ENOMEM;
+ }
}
dev->n_targets = n_targets;
@@ -651,6 +665,12 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)
}
EXPORT_SYMBOL(nfc_target_lost);
+inline void nfc_driver_failure(struct nfc_dev *dev, int err)
+{
+ nfc_targets_found(dev, NULL, 0);
+}
+EXPORT_SYMBOL(nfc_driver_failure);
+
static void nfc_release(struct device *d)
{
struct nfc_dev *dev = to_nfc_dev(d);
@@ -906,3 +926,5 @@ MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>");
MODULE_DESCRIPTION("NFC Core ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_NETPROTO(PF_NFC);
+MODULE_ALIAS_GENL_FAMILY(NFC_GENL_NAME);
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c
index 8729abf5f18b..46362ef979db 100644
--- a/net/nfc/hci/command.c
+++ b/net/nfc/hci/command.c
@@ -28,26 +28,14 @@
#include "hci.h"
-static int nfc_hci_result_to_errno(u8 result)
-{
- switch (result) {
- case NFC_HCI_ANY_OK:
- return 0;
- case NFC_HCI_ANY_E_TIMEOUT:
- return -ETIMEDOUT;
- default:
- return -1;
- }
-}
-
-static void nfc_hci_execute_cb(struct nfc_hci_dev *hdev, u8 result,
+static void nfc_hci_execute_cb(struct nfc_hci_dev *hdev, int err,
struct sk_buff *skb, void *cb_data)
{
struct hcp_exec_waiter *hcp_ew = (struct hcp_exec_waiter *)cb_data;
- pr_debug("HCI Cmd completed with HCI result=%d\n", result);
+ pr_debug("HCI Cmd completed with result=%d\n", err);
- hcp_ew->exec_result = nfc_hci_result_to_errno(result);
+ hcp_ew->exec_result = err;
if (hcp_ew->exec_result == 0)
hcp_ew->result_skb = skb;
else
@@ -311,9 +299,9 @@ int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev)
}
EXPORT_SYMBOL(nfc_hci_disconnect_all_gates);
-int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate)
+int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate,
+ u8 pipe)
{
- u8 pipe = NFC_HCI_INVALID_PIPE;
bool pipe_created = false;
int r;
@@ -322,6 +310,9 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate)
if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE)
return -EADDRINUSE;
+ if (pipe != NFC_HCI_INVALID_PIPE)
+ goto pipe_is_open;
+
switch (dest_gate) {
case NFC_HCI_LINK_MGMT_GATE:
pipe = NFC_HCI_LINK_MGMT_PIPE;
@@ -347,6 +338,7 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate)
return r;
}
+pipe_is_open:
hdev->gate2pipe[dest_gate] = pipe;
return 0;
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index a8b0b71e8f86..36717cebfbb6 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -32,6 +32,18 @@
/* Largest headroom needed for outgoing HCI commands */
#define HCI_CMDS_HEADROOM 1
+static int nfc_hci_result_to_errno(u8 result)
+{
+ switch (result) {
+ case NFC_HCI_ANY_OK:
+ return 0;
+ case NFC_HCI_ANY_E_TIMEOUT:
+ return -ETIME;
+ default:
+ return -1;
+ }
+}
+
static void nfc_hci_msg_tx_work(struct work_struct *work)
{
struct nfc_hci_dev *hdev = container_of(work, struct nfc_hci_dev,
@@ -46,7 +58,7 @@ static void nfc_hci_msg_tx_work(struct work_struct *work)
if (timer_pending(&hdev->cmd_timer) == 0) {
if (hdev->cmd_pending_msg->cb)
hdev->cmd_pending_msg->cb(hdev,
- NFC_HCI_ANY_E_TIMEOUT,
+ -ETIME,
NULL,
hdev->
cmd_pending_msg->
@@ -71,8 +83,7 @@ next_msg:
kfree_skb(skb);
skb_queue_purge(&msg->msg_frags);
if (msg->cb)
- msg->cb(hdev, NFC_HCI_ANY_E_NOK, NULL,
- msg->cb_context);
+ msg->cb(hdev, r, NULL, msg->cb_context);
kfree(msg);
break;
}
@@ -116,20 +127,13 @@ static void nfc_hci_msg_rx_work(struct work_struct *work)
}
}
-void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result,
- struct sk_buff *skb)
+static void __nfc_hci_cmd_completion(struct nfc_hci_dev *hdev, int err,
+ struct sk_buff *skb)
{
- mutex_lock(&hdev->msg_tx_mutex);
-
- if (hdev->cmd_pending_msg == NULL) {
- kfree_skb(skb);
- goto exit;
- }
-
del_timer_sync(&hdev->cmd_timer);
if (hdev->cmd_pending_msg->cb)
- hdev->cmd_pending_msg->cb(hdev, result, skb,
+ hdev->cmd_pending_msg->cb(hdev, err, skb,
hdev->cmd_pending_msg->cb_context);
else
kfree_skb(skb);
@@ -138,6 +142,19 @@ void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result,
hdev->cmd_pending_msg = NULL;
queue_work(hdev->msg_tx_wq, &hdev->msg_tx_work);
+}
+
+void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result,
+ struct sk_buff *skb)
+{
+ mutex_lock(&hdev->msg_tx_mutex);
+
+ if (hdev->cmd_pending_msg == NULL) {
+ kfree_skb(skb);
+ goto exit;
+ }
+
+ __nfc_hci_cmd_completion(hdev, nfc_hci_result_to_errno(result), skb);
exit:
mutex_unlock(&hdev->msg_tx_mutex);
@@ -213,7 +230,7 @@ static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate)
}
break;
case NFC_HCI_RF_READER_B_GATE:
- targets->supported_protocols = NFC_PROTO_ISO14443_MASK;
+ targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK;
break;
default:
if (hdev->ops->target_from_gate)
@@ -298,15 +315,15 @@ static void nfc_hci_cmd_timeout(unsigned long data)
}
static int hci_dev_connect_gates(struct nfc_hci_dev *hdev, u8 gate_count,
- u8 gates[])
+ struct nfc_hci_gate *gates)
{
int r;
- u8 *p = gates;
while (gate_count--) {
- r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, *p);
+ r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID,
+ gates->gate, gates->pipe);
if (r < 0)
return r;
- p++;
+ gates++;
}
return 0;
@@ -316,14 +333,13 @@ static int hci_dev_session_init(struct nfc_hci_dev *hdev)
{
struct sk_buff *skb = NULL;
int r;
- u8 hci_gates[] = { /* NFC_HCI_ADMIN_GATE MUST be first */
- NFC_HCI_ADMIN_GATE, NFC_HCI_LOOPBACK_GATE,
- NFC_HCI_ID_MGMT_GATE, NFC_HCI_LINK_MGMT_GATE,
- NFC_HCI_RF_READER_B_GATE, NFC_HCI_RF_READER_A_GATE
- };
+
+ if (hdev->init_data.gates[0].gate != NFC_HCI_ADMIN_GATE)
+ return -EPROTO;
r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID,
- NFC_HCI_ADMIN_GATE);
+ hdev->init_data.gates[0].gate,
+ hdev->init_data.gates[0].pipe);
if (r < 0)
goto exit;
@@ -351,10 +367,6 @@ static int hci_dev_session_init(struct nfc_hci_dev *hdev)
if (r < 0)
goto exit;
- r = hci_dev_connect_gates(hdev, sizeof(hci_gates), hci_gates);
- if (r < 0)
- goto disconnect_all;
-
r = hci_dev_connect_gates(hdev, hdev->init_data.gate_count,
hdev->init_data.gates);
if (r < 0)
@@ -717,6 +729,27 @@ void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev)
}
EXPORT_SYMBOL(nfc_hci_get_clientdata);
+static void nfc_hci_failure(struct nfc_hci_dev *hdev, int err)
+{
+ mutex_lock(&hdev->msg_tx_mutex);
+
+ if (hdev->cmd_pending_msg == NULL) {
+ nfc_driver_failure(hdev->ndev, err);
+ goto exit;
+ }
+
+ __nfc_hci_cmd_completion(hdev, err, NULL);
+
+exit:
+ mutex_unlock(&hdev->msg_tx_mutex);
+}
+
+void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err)
+{
+ nfc_hci_failure(hdev, err);
+}
+EXPORT_SYMBOL(nfc_hci_driver_failure);
+
void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb)
{
struct hcp_packet *packet;
@@ -727,16 +760,6 @@ void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb)
struct sk_buff *frag_skb;
int msg_len;
- if (skb == NULL) {
- /* TODO ELa: lower layer had permanent failure, need to
- * propagate that up
- */
-
- skb_queue_purge(&hdev->rx_hcp_frags);
-
- return;
- }
-
packet = (struct hcp_packet *)skb->data;
if ((packet->header & ~NFC_HCI_FRAGMENT) == 0) {
skb_queue_tail(&hdev->rx_hcp_frags, skb);
@@ -757,9 +780,8 @@ void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb)
hcp_skb = nfc_alloc_recv_skb(NFC_HCI_HCP_PACKET_HEADER_LEN +
msg_len, GFP_KERNEL);
if (hcp_skb == NULL) {
- /* TODO ELa: cannot deliver HCP message. How to
- * propagate error up?
- */
+ nfc_hci_failure(hdev, -ENOMEM);
+ return;
}
*skb_put(hcp_skb, NFC_HCI_HCP_PACKET_HEADER_LEN) = pipe;
diff --git a/net/nfc/hci/hci.h b/net/nfc/hci/hci.h
index 45f2fe4fd486..fa9a21e92239 100644
--- a/net/nfc/hci/hci.h
+++ b/net/nfc/hci/hci.h
@@ -37,10 +37,11 @@ struct hcp_packet {
/*
* HCI command execution completion callback.
- * result will be one of the HCI response codes.
- * skb contains the response data and must be disposed.
+ * result will be a standard linux error (may be converted from HCI response)
+ * skb contains the response data and must be disposed, or may be NULL if
+ * an error occured
*/
-typedef void (*hci_cmd_cb_t) (struct nfc_hci_dev *hdev, u8 result,
+typedef void (*hci_cmd_cb_t) (struct nfc_hci_dev *hdev, int result,
struct sk_buff *skb, void *cb_data);
struct hcp_exec_waiter {
@@ -131,9 +132,4 @@ void nfc_hci_hcp_message_rx(struct nfc_hci_dev *hdev, u8 pipe, u8 type,
#define NFC_HCI_ANY_E_REG_ACCESS_DENIED 0x0a
#define NFC_HCI_ANY_E_PIPE_ACCESS_DENIED 0x0b
-/* Pipes */
-#define NFC_HCI_INVALID_PIPE 0x80
-#define NFC_HCI_LINK_MGMT_PIPE 0x00
-#define NFC_HCI_ADMIN_PIPE 0x01
-
#endif /* __LOCAL_HCI_H */
diff --git a/net/nfc/hci/shdlc.c b/net/nfc/hci/shdlc.c
index 6b836e6242b7..6f840c18c892 100644
--- a/net/nfc/hci/shdlc.c
+++ b/net/nfc/hci/shdlc.c
@@ -340,15 +340,6 @@ static void nfc_shdlc_connect_complete(struct nfc_shdlc *shdlc, int r)
shdlc->state = SHDLC_CONNECTED;
} else {
shdlc->state = SHDLC_DISCONNECTED;
-
- /*
- * TODO: Could it be possible that there are pending
- * executing commands that are waiting for connect to complete
- * before they can be carried? As connect is a blocking
- * operation, it would require that the userspace process can
- * send commands on the same device from a second thread before
- * the device is up. I don't think that is possible, is it?
- */
}
shdlc->connect_result = r;
@@ -413,12 +404,12 @@ static void nfc_shdlc_rcv_u_frame(struct nfc_shdlc *shdlc,
r = nfc_shdlc_connect_send_ua(shdlc);
nfc_shdlc_connect_complete(shdlc, r);
}
- } else if (shdlc->state > SHDLC_NEGOCIATING) {
+ } else if (shdlc->state == SHDLC_CONNECTED) {
/*
- * TODO: Chip wants to reset link
- * send ua, empty skb lists, reset counters
- * propagate info to HCI layer
+ * Chip wants to reset link. This is unexpected and
+ * unsupported.
*/
+ shdlc->hard_fault = -ECONNRESET;
}
break;
case U_FRAME_UA:
@@ -523,10 +514,6 @@ static void nfc_shdlc_handle_send_queue(struct nfc_shdlc *shdlc)
r = shdlc->ops->xmit(shdlc, skb);
if (r < 0) {
- /*
- * TODO: Cannot send, shdlc machine is dead, we
- * must propagate the information up to HCI.
- */
shdlc->hard_fault = r;
break;
}
@@ -590,6 +577,11 @@ static void nfc_shdlc_sm_work(struct work_struct *work)
skb_queue_purge(&shdlc->ack_pending_q);
break;
case SHDLC_CONNECTING:
+ if (shdlc->hard_fault) {
+ nfc_shdlc_connect_complete(shdlc, shdlc->hard_fault);
+ break;
+ }
+
if (shdlc->connect_tries++ < 5)
r = nfc_shdlc_connect_initiate(shdlc);
else
@@ -610,6 +602,11 @@ static void nfc_shdlc_sm_work(struct work_struct *work)
}
nfc_shdlc_handle_rcv_queue(shdlc);
+
+ if (shdlc->hard_fault) {
+ nfc_shdlc_connect_complete(shdlc, shdlc->hard_fault);
+ break;
+ }
break;
case SHDLC_CONNECTED:
nfc_shdlc_handle_rcv_queue(shdlc);
@@ -637,10 +634,7 @@ static void nfc_shdlc_sm_work(struct work_struct *work)
}
if (shdlc->hard_fault) {
- /*
- * TODO: Handle hard_fault that occured during
- * this invocation of the shdlc worker
- */
+ nfc_hci_driver_failure(shdlc->hdev, shdlc->hard_fault);
}
break;
default:
@@ -923,8 +917,6 @@ void nfc_shdlc_free(struct nfc_shdlc *shdlc)
{
pr_debug("\n");
- /* TODO: Check that this cannot be called while still in use */
-
nfc_hci_unregister_device(shdlc->hdev);
nfc_hci_free_device(shdlc->hdev);
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 5d503eeb15a1..82f0f7588b46 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -45,7 +45,7 @@ void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk)
write_unlock(&l->lock);
}
-static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
+static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
{
struct sock *sk;
struct hlist_node *node, *tmp;
@@ -78,6 +78,11 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
sock_orphan(accept_sk);
}
+
+ if (listen == true) {
+ release_sock(sk);
+ continue;
+ }
}
sk->sk_state = LLCP_CLOSED;
@@ -106,7 +111,7 @@ static void local_release(struct kref *ref)
local = container_of(ref, struct nfc_llcp_local, ref);
list_del(&local->list);
- nfc_llcp_socket_release(local);
+ nfc_llcp_socket_release(local, false);
del_timer_sync(&local->link_timer);
skb_queue_purge(&local->tx_queue);
destroy_workqueue(local->tx_wq);
@@ -118,23 +123,48 @@ static void local_release(struct kref *ref)
int nfc_llcp_local_put(struct nfc_llcp_local *local)
{
- WARN_ON(local == NULL);
-
if (local == NULL)
return 0;
return kref_put(&local->ref, local_release);
}
-static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local)
+static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
+ u8 ssap, u8 dsap)
{
- mutex_lock(&local->sdp_lock);
+ struct sock *sk;
+ struct hlist_node *node;
+ struct nfc_llcp_sock *llcp_sock;
- local->local_wks = 0;
- local->local_sdp = 0;
- local->local_sap = 0;
+ pr_debug("ssap dsap %d %d\n", ssap, dsap);
- mutex_unlock(&local->sdp_lock);
+ if (ssap == 0 && dsap == 0)
+ return NULL;
+
+ read_lock(&local->sockets.lock);
+
+ llcp_sock = NULL;
+
+ sk_for_each(sk, node, &local->sockets.head) {
+ llcp_sock = nfc_llcp_sock(sk);
+
+ if (llcp_sock->ssap == ssap && llcp_sock->dsap == dsap)
+ break;
+ }
+
+ read_unlock(&local->sockets.lock);
+
+ if (llcp_sock == NULL)
+ return NULL;
+
+ sock_hold(&llcp_sock->sk);
+
+ return llcp_sock;
+}
+
+static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock)
+{
+ sock_put(&sock->sk);
}
static void nfc_llcp_timeout_work(struct work_struct *work)
@@ -197,6 +227,51 @@ static int nfc_llcp_wks_sap(char *service_name, size_t service_name_len)
return -EINVAL;
}
+static
+struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local,
+ u8 *sn, size_t sn_len)
+{
+ struct sock *sk;
+ struct hlist_node *node;
+ struct nfc_llcp_sock *llcp_sock, *tmp_sock;
+
+ pr_debug("sn %zd %p\n", sn_len, sn);
+
+ if (sn == NULL || sn_len == 0)
+ return NULL;
+
+ read_lock(&local->sockets.lock);
+
+ llcp_sock = NULL;
+
+ sk_for_each(sk, node, &local->sockets.head) {
+ tmp_sock = nfc_llcp_sock(sk);
+
+ pr_debug("llcp sock %p\n", tmp_sock);
+
+ if (tmp_sock->sk.sk_state != LLCP_LISTEN)
+ continue;
+
+ if (tmp_sock->service_name == NULL ||
+ tmp_sock->service_name_len == 0)
+ continue;
+
+ if (tmp_sock->service_name_len != sn_len)
+ continue;
+
+ if (memcmp(sn, tmp_sock->service_name, sn_len) == 0) {
+ llcp_sock = tmp_sock;
+ break;
+ }
+ }
+
+ read_unlock(&local->sockets.lock);
+
+ pr_debug("Found llcp sock %p\n", llcp_sock);
+
+ return llcp_sock;
+}
+
u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
struct nfc_llcp_sock *sock)
{
@@ -223,41 +298,26 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
}
/*
- * This is not a well known service,
- * we should try to find a local SDP free spot
+ * Check if there already is a non WKS socket bound
+ * to this service name.
*/
- ssap = find_first_zero_bit(&local->local_sdp, LLCP_SDP_NUM_SAP);
- if (ssap == LLCP_SDP_NUM_SAP) {
+ if (nfc_llcp_sock_from_sn(local, sock->service_name,
+ sock->service_name_len) != NULL) {
mutex_unlock(&local->sdp_lock);
return LLCP_SAP_MAX;
}
- pr_debug("SDP ssap %d\n", LLCP_WKS_NUM_SAP + ssap);
-
- set_bit(ssap, &local->local_sdp);
mutex_unlock(&local->sdp_lock);
- return LLCP_WKS_NUM_SAP + ssap;
-
- } else if (sock->ssap != 0) {
- if (sock->ssap < LLCP_WKS_NUM_SAP) {
- if (!test_bit(sock->ssap, &local->local_wks)) {
- set_bit(sock->ssap, &local->local_wks);
- mutex_unlock(&local->sdp_lock);
-
- return sock->ssap;
- }
+ return LLCP_SDP_UNBOUND;
- } else if (sock->ssap < LLCP_SDP_NUM_SAP) {
- if (!test_bit(sock->ssap - LLCP_WKS_NUM_SAP,
- &local->local_sdp)) {
- set_bit(sock->ssap - LLCP_WKS_NUM_SAP,
- &local->local_sdp);
- mutex_unlock(&local->sdp_lock);
+ } else if (sock->ssap != 0 && sock->ssap < LLCP_WKS_NUM_SAP) {
+ if (!test_bit(sock->ssap, &local->local_wks)) {
+ set_bit(sock->ssap, &local->local_wks);
+ mutex_unlock(&local->sdp_lock);
- return sock->ssap;
- }
+ return sock->ssap;
}
}
@@ -294,8 +354,34 @@ void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap)
local_ssap = ssap;
sdp = &local->local_wks;
} else if (ssap < LLCP_LOCAL_NUM_SAP) {
+ atomic_t *client_cnt;
+
local_ssap = ssap - LLCP_WKS_NUM_SAP;
sdp = &local->local_sdp;
+ client_cnt = &local->local_sdp_cnt[local_ssap];
+
+ pr_debug("%d clients\n", atomic_read(client_cnt));
+
+ mutex_lock(&local->sdp_lock);
+
+ if (atomic_dec_and_test(client_cnt)) {
+ struct nfc_llcp_sock *l_sock;
+
+ pr_debug("No more clients for SAP %d\n", ssap);
+
+ clear_bit(local_ssap, sdp);
+
+ /* Find the listening sock and set it back to UNBOUND */
+ l_sock = nfc_llcp_sock_get(local, ssap, LLCP_SAP_SDP);
+ if (l_sock) {
+ l_sock->ssap = LLCP_SDP_UNBOUND;
+ nfc_llcp_sock_put(l_sock);
+ }
+ }
+
+ mutex_unlock(&local->sdp_lock);
+
+ return;
} else if (ssap < LLCP_MAX_SAP) {
local_ssap = ssap - LLCP_LOCAL_NUM_SAP;
sdp = &local->local_sap;
@@ -310,19 +396,26 @@ void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap)
mutex_unlock(&local->sdp_lock);
}
-u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len)
+static u8 nfc_llcp_reserve_sdp_ssap(struct nfc_llcp_local *local)
{
- struct nfc_llcp_local *local;
+ u8 ssap;
- local = nfc_llcp_find_local(dev);
- if (local == NULL) {
- *general_bytes_len = 0;
- return NULL;
+ mutex_lock(&local->sdp_lock);
+
+ ssap = find_first_zero_bit(&local->local_sdp, LLCP_SDP_NUM_SAP);
+ if (ssap == LLCP_SDP_NUM_SAP) {
+ mutex_unlock(&local->sdp_lock);
+
+ return LLCP_SAP_MAX;
}
- *general_bytes_len = local->gb_len;
+ pr_debug("SDP ssap %d\n", LLCP_WKS_NUM_SAP + ssap);
- return local->gb;
+ set_bit(ssap, &local->local_sdp);
+
+ mutex_unlock(&local->sdp_lock);
+
+ return LLCP_WKS_NUM_SAP + ssap;
}
static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
@@ -386,6 +479,23 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
return 0;
}
+u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len)
+{
+ struct nfc_llcp_local *local;
+
+ local = nfc_llcp_find_local(dev);
+ if (local == NULL) {
+ *general_bytes_len = 0;
+ return NULL;
+ }
+
+ nfc_llcp_build_gb(local);
+
+ *general_bytes_len = local->gb_len;
+
+ return local->gb;
+}
+
int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
{
struct nfc_llcp_local *local = nfc_llcp_find_local(dev);
@@ -509,74 +619,12 @@ out:
return llcp_sock;
}
-static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
- u8 ssap, u8 dsap)
-{
- struct sock *sk;
- struct hlist_node *node;
- struct nfc_llcp_sock *llcp_sock;
-
- pr_debug("ssap dsap %d %d\n", ssap, dsap);
-
- if (ssap == 0 && dsap == 0)
- return NULL;
-
- read_lock(&local->sockets.lock);
-
- llcp_sock = NULL;
-
- sk_for_each(sk, node, &local->sockets.head) {
- llcp_sock = nfc_llcp_sock(sk);
-
- if (llcp_sock->ssap == ssap &&
- llcp_sock->dsap == dsap)
- break;
- }
-
- read_unlock(&local->sockets.lock);
-
- if (llcp_sock == NULL)
- return NULL;
-
- sock_hold(&llcp_sock->sk);
-
- return llcp_sock;
-}
-
static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local,
u8 *sn, size_t sn_len)
{
- struct sock *sk;
- struct hlist_node *node;
struct nfc_llcp_sock *llcp_sock;
- pr_debug("sn %zd\n", sn_len);
-
- if (sn == NULL || sn_len == 0)
- return NULL;
-
- read_lock(&local->sockets.lock);
-
- llcp_sock = NULL;
-
- sk_for_each(sk, node, &local->sockets.head) {
- llcp_sock = nfc_llcp_sock(sk);
-
- if (llcp_sock->sk.sk_state != LLCP_LISTEN)
- continue;
-
- if (llcp_sock->service_name == NULL ||
- llcp_sock->service_name_len == 0)
- continue;
-
- if (llcp_sock->service_name_len != sn_len)
- continue;
-
- if (memcmp(sn, llcp_sock->service_name, sn_len) == 0)
- break;
- }
-
- read_unlock(&local->sockets.lock);
+ llcp_sock = nfc_llcp_sock_from_sn(local, sn, sn_len);
if (llcp_sock == NULL)
return NULL;
@@ -586,11 +634,6 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local,
return llcp_sock;
}
-static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock)
-{
- sock_put(&sock->sk);
-}
-
static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len)
{
u8 *tlv = &skb->data[2], type, length;
@@ -662,6 +705,21 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
goto fail;
}
+ if (sock->ssap == LLCP_SDP_UNBOUND) {
+ u8 ssap = nfc_llcp_reserve_sdp_ssap(local);
+
+ pr_debug("First client, reserving %d\n", ssap);
+
+ if (ssap == LLCP_SAP_MAX) {
+ reason = LLCP_DM_REJ;
+ release_sock(&sock->sk);
+ sock_put(&sock->sk);
+ goto fail;
+ }
+
+ sock->ssap = ssap;
+ }
+
new_sk = nfc_llcp_sock_alloc(NULL, parent->sk_type, GFP_ATOMIC);
if (new_sk == NULL) {
reason = LLCP_DM_REJ;
@@ -675,9 +733,21 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
new_sock->local = nfc_llcp_local_get(local);
new_sock->miu = local->remote_miu;
new_sock->nfc_protocol = sock->nfc_protocol;
- new_sock->ssap = sock->ssap;
new_sock->dsap = ssap;
+ new_sock->target_idx = local->target_idx;
new_sock->parent = parent;
+ new_sock->ssap = sock->ssap;
+ if (sock->ssap < LLCP_LOCAL_NUM_SAP && sock->ssap >= LLCP_WKS_NUM_SAP) {
+ atomic_t *client_count;
+
+ pr_debug("reserved_ssap %d for %p\n", sock->ssap, new_sock);
+
+ client_count =
+ &local->local_sdp_cnt[sock->ssap - LLCP_WKS_NUM_SAP];
+
+ atomic_inc(client_count);
+ new_sock->reserved_ssap = sock->ssap;
+ }
nfc_llcp_parse_connection_tlv(new_sock, &skb->data[LLCP_HEADER_SIZE],
skb->len - LLCP_HEADER_SIZE);
@@ -886,6 +956,45 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb)
nfc_llcp_sock_put(llcp_sock);
}
+static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb)
+{
+ struct nfc_llcp_sock *llcp_sock;
+ struct sock *sk;
+ u8 dsap, ssap, reason;
+
+ dsap = nfc_llcp_dsap(skb);
+ ssap = nfc_llcp_ssap(skb);
+ reason = skb->data[2];
+
+ pr_debug("%d %d reason %d\n", ssap, dsap, reason);
+
+ switch (reason) {
+ case LLCP_DM_NOBOUND:
+ case LLCP_DM_REJ:
+ llcp_sock = nfc_llcp_connecting_sock_get(local, dsap);
+ break;
+
+ default:
+ llcp_sock = nfc_llcp_sock_get(local, dsap, ssap);
+ break;
+ }
+
+ if (llcp_sock == NULL) {
+ pr_err("Invalid DM\n");
+ return;
+ }
+
+ sk = &llcp_sock->sk;
+
+ sk->sk_err = ENXIO;
+ sk->sk_state = LLCP_CLOSED;
+ sk->sk_state_change(sk);
+
+ nfc_llcp_sock_put(llcp_sock);
+
+ return;
+}
+
static void nfc_llcp_rx_work(struct work_struct *work)
{
struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
@@ -929,6 +1038,11 @@ static void nfc_llcp_rx_work(struct work_struct *work)
nfc_llcp_recv_cc(local, skb);
break;
+ case LLCP_PDU_DM:
+ pr_debug("DM\n");
+ nfc_llcp_recv_dm(local, skb);
+ break;
+
case LLCP_PDU_I:
case LLCP_PDU_RR:
case LLCP_PDU_RNR:
@@ -985,10 +1099,8 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)
if (local == NULL)
return;
- nfc_llcp_clear_sdp(local);
-
/* Close and purge all existing sockets */
- nfc_llcp_socket_release(local);
+ nfc_llcp_socket_release(local, true);
}
void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index 7286c86982ff..83b8bba5a280 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -37,6 +37,7 @@ enum llcp_state {
#define LLCP_LOCAL_NUM_SAP 32
#define LLCP_LOCAL_SAP_OFFSET (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP)
#define LLCP_MAX_SAP (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP + LLCP_LOCAL_NUM_SAP)
+#define LLCP_SDP_UNBOUND (LLCP_MAX_SAP + 1)
struct nfc_llcp_sock;
@@ -69,6 +70,7 @@ struct nfc_llcp_local {
unsigned long local_wks; /* Well known services */
unsigned long local_sdp; /* Local services */
unsigned long local_sap; /* Local SAPs, not available for discovery */
+ atomic_t local_sdp_cnt[LLCP_SDP_NUM_SAP];
/* local */
u8 gb[NFC_MAX_GT_LEN];
@@ -113,6 +115,9 @@ struct nfc_llcp_sock {
/* Is the remote peer ready to receive */
u8 remote_ready;
+ /* Reserved source SAP */
+ u8 reserved_ssap;
+
struct sk_buff_head tx_queue;
struct sk_buff_head tx_pending_queue;
struct sk_buff_head tx_backlog_queue;
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 2c0b317344b7..ddeb9aa398f0 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -78,11 +78,11 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
struct sockaddr_nfc_llcp llcp_addr;
int len, ret = 0;
- pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family);
-
if (!addr || addr->sa_family != AF_NFC)
return -EINVAL;
+ pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family);
+
memset(&llcp_addr, 0, sizeof(llcp_addr));
len = min_t(unsigned int, sizeof(llcp_addr), alen);
memcpy(&llcp_addr, addr, len);
@@ -121,8 +121,12 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
GFP_KERNEL);
llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock);
- if (llcp_sock->ssap == LLCP_MAX_SAP)
+ if (llcp_sock->ssap == LLCP_SAP_MAX) {
+ ret = -EADDRINUSE;
goto put_dev;
+ }
+
+ llcp_sock->reserved_ssap = llcp_sock->ssap;
nfc_llcp_sock_link(&local->sockets, sk);
@@ -283,22 +287,28 @@ error:
return ret;
}
-static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr,
+static int llcp_sock_getname(struct socket *sock, struct sockaddr *uaddr,
int *len, int peer)
{
- struct sockaddr_nfc_llcp *llcp_addr = (struct sockaddr_nfc_llcp *)addr;
struct sock *sk = sock->sk;
struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
+ DECLARE_SOCKADDR(struct sockaddr_nfc_llcp *, llcp_addr, uaddr);
- pr_debug("%p\n", sk);
+ if (llcp_sock == NULL || llcp_sock->dev == NULL)
+ return -EBADFD;
+
+ pr_debug("%p %d %d %d\n", sk, llcp_sock->target_idx,
+ llcp_sock->dsap, llcp_sock->ssap);
- if (llcp_sock == NULL)
+ if (llcp_sock == NULL || llcp_sock->dev == NULL)
return -EBADFD;
- addr->sa_family = AF_NFC;
+ uaddr->sa_family = AF_NFC;
+
*len = sizeof(struct sockaddr_nfc_llcp);
llcp_addr->dev_idx = llcp_sock->dev->idx;
+ llcp_addr->target_idx = llcp_sock->target_idx;
llcp_addr->dsap = llcp_sock->dsap;
llcp_addr->ssap = llcp_sock->ssap;
llcp_addr->service_name_len = llcp_sock->service_name_len;
@@ -406,7 +416,8 @@ static int llcp_sock_release(struct socket *sock)
}
}
- nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap);
+ if (llcp_sock->reserved_ssap < LLCP_SAP_MAX)
+ nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap);
release_sock(sk);
@@ -486,6 +497,9 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
ret = -ENOMEM;
goto put_dev;
}
+
+ llcp_sock->reserved_ssap = llcp_sock->ssap;
+
if (addr->service_name_len == 0)
llcp_sock->dsap = addr->dsap;
else
@@ -687,6 +701,7 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
llcp_sock->send_n = llcp_sock->send_ack_n = 0;
llcp_sock->recv_n = llcp_sock->recv_ack_n = 0;
llcp_sock->remote_ready = 1;
+ llcp_sock->reserved_ssap = LLCP_SAP_MAX;
skb_queue_head_init(&llcp_sock->tx_queue);
skb_queue_head_init(&llcp_sock->tx_pending_queue);
skb_queue_head_init(&llcp_sock->tx_backlog_queue);
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 766a02b1dfa1..5bb4da680427 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -194,7 +194,7 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
}
if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
- (protocols & NFC_PROTO_ISO14443_MASK)) {
+ (protocols & NFC_PROTO_ISO14443_B_MASK)) {
cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
NCI_NFC_B_PASSIVE_POLL_MODE;
cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
@@ -486,7 +486,8 @@ static int nci_activate_target(struct nfc_dev *nfc_dev,
param.rf_protocol = NCI_RF_PROTOCOL_T2T;
else if (protocol == NFC_PROTO_FELICA)
param.rf_protocol = NCI_RF_PROTOCOL_T3T;
- else if (protocol == NFC_PROTO_ISO14443)
+ else if (protocol == NFC_PROTO_ISO14443 ||
+ protocol == NFC_PROTO_ISO14443_B)
param.rf_protocol = NCI_RF_PROTOCOL_ISO_DEP;
else
param.rf_protocol = NCI_RF_PROTOCOL_NFC_DEP;
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index cb2646179e5f..af7a93b04393 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -106,7 +106,7 @@ static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev,
nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data));
data += 2;
- nfca_poll->nfcid1_len = *data++;
+ nfca_poll->nfcid1_len = min_t(__u8, *data++, NFC_NFCID1_MAXSIZE);
pr_debug("sens_res 0x%x, nfcid1_len %d\n",
nfca_poll->sens_res, nfca_poll->nfcid1_len);
@@ -130,7 +130,7 @@ static __u8 *nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev,
struct rf_tech_specific_params_nfcb_poll *nfcb_poll,
__u8 *data)
{
- nfcb_poll->sensb_res_len = *data++;
+ nfcb_poll->sensb_res_len = min_t(__u8, *data++, NFC_SENSB_RES_MAXSIZE);
pr_debug("sensb_res_len %d\n", nfcb_poll->sensb_res_len);
@@ -145,7 +145,7 @@ static __u8 *nci_extract_rf_params_nfcf_passive_poll(struct nci_dev *ndev,
__u8 *data)
{
nfcf_poll->bit_rate = *data++;
- nfcf_poll->sensf_res_len = *data++;
+ nfcf_poll->sensf_res_len = min_t(__u8, *data++, NFC_SENSF_RES_MAXSIZE);
pr_debug("bit_rate %d, sensf_res_len %d\n",
nfcf_poll->bit_rate, nfcf_poll->sensf_res_len);
@@ -170,7 +170,10 @@ static int nci_add_new_protocol(struct nci_dev *ndev,
if (rf_protocol == NCI_RF_PROTOCOL_T2T)
protocol = NFC_PROTO_MIFARE_MASK;
else if (rf_protocol == NCI_RF_PROTOCOL_ISO_DEP)
- protocol = NFC_PROTO_ISO14443_MASK;
+ if (rf_tech_and_mode == NCI_NFC_A_PASSIVE_POLL_MODE)
+ protocol = NFC_PROTO_ISO14443_MASK;
+ else
+ protocol = NFC_PROTO_ISO14443_B_MASK;
else if (rf_protocol == NCI_RF_PROTOCOL_T3T)
protocol = NFC_PROTO_FELICA_MASK;
else
@@ -331,7 +334,7 @@ static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev,
switch (ntf->activation_rf_tech_and_mode) {
case NCI_NFC_A_PASSIVE_POLL_MODE:
nfca_poll = &ntf->activation_params.nfca_poll_iso_dep;
- nfca_poll->rats_res_len = *data++;
+ nfca_poll->rats_res_len = min_t(__u8, *data++, 20);
pr_debug("rats_res_len %d\n", nfca_poll->rats_res_len);
if (nfca_poll->rats_res_len > 0) {
memcpy(nfca_poll->rats_res,
@@ -341,7 +344,7 @@ static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev,
case NCI_NFC_B_PASSIVE_POLL_MODE:
nfcb_poll = &ntf->activation_params.nfcb_poll_iso_dep;
- nfcb_poll->attrib_res_len = *data++;
+ nfcb_poll->attrib_res_len = min_t(__u8, *data++, 50);
pr_debug("attrib_res_len %d\n", nfcb_poll->attrib_res_len);
if (nfcb_poll->attrib_res_len > 0) {
memcpy(nfcb_poll->attrib_res,
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 03c31db38f12..99bc6f7faa7b 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -634,6 +634,15 @@ static int nfc_genl_stop_poll(struct sk_buff *skb, struct genl_info *info)
if (!dev)
return -ENODEV;
+ device_lock(&dev->dev);
+
+ if (!dev->polling) {
+ device_unlock(&dev->dev);
+ return -EINVAL;
+ }
+
+ device_unlock(&dev->dev);
+
mutex_lock(&dev->genl_data.genl_data_mutex);
if (dev->genl_data.poll_req_pid != info->snd_pid) {
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c
index ec1134c9e07f..8b8a6a2b2bad 100644
--- a/net/nfc/rawsock.c
+++ b/net/nfc/rawsock.c
@@ -54,7 +54,10 @@ static int rawsock_release(struct socket *sock)
{
struct sock *sk = sock->sk;
- pr_debug("sock=%p\n", sock);
+ pr_debug("sock=%p sk=%p\n", sock, sk);
+
+ if (!sk)
+ return 0;
sock_orphan(sk);
sock_put(sk);
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 55a28ab21db9..0f7e0d621ab0 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_WEXT_SPY) += wext-spy.o
obj-$(CONFIG_WEXT_PRIV) += wext-priv.o
cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
-cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o
+cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o
cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o
diff --git a/net/wireless/ap.c b/net/wireless/ap.c
new file mode 100644
index 000000000000..fcc60d8dbefa
--- /dev/null
+++ b/net/wireless/ap.c
@@ -0,0 +1,46 @@
+#include <linux/ieee80211.h>
+#include <linux/export.h>
+#include <net/cfg80211.h>
+#include "nl80211.h"
+#include "core.h"
+
+
+static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
+ struct net_device *dev)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ int err;
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (!rdev->ops->stop_ap)
+ return -EOPNOTSUPP;
+
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+ dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ return -EOPNOTSUPP;
+
+ if (!wdev->beacon_interval)
+ return -ENOENT;
+
+ err = rdev->ops->stop_ap(&rdev->wiphy, dev);
+ if (!err) {
+ wdev->beacon_interval = 0;
+ wdev->channel = NULL;
+ }
+
+ return err;
+}
+
+int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
+ struct net_device *dev)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ int err;
+
+ wdev_lock(wdev);
+ err = __cfg80211_stop_ap(rdev, dev);
+ wdev_unlock(wdev);
+
+ return err;
+}
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index c1999e45a07c..1cc4b7cc7372 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -82,13 +82,71 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
int freq, enum nl80211_channel_type chantype)
{
struct ieee80211_channel *chan;
+ int err;
if (!rdev->ops->set_monitor_channel)
return -EOPNOTSUPP;
+ if (!cfg80211_has_monitors_only(rdev))
+ return -EBUSY;
chan = rdev_freq_to_chan(rdev, freq, chantype);
if (!chan)
return -EINVAL;
- return rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype);
+ err = rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype);
+ if (!err) {
+ rdev->monitor_channel = chan;
+ rdev->monitor_channel_type = chantype;
+ }
+
+ return err;
+}
+
+void
+cfg80211_get_chan_state(struct wireless_dev *wdev,
+ struct ieee80211_channel **chan,
+ enum cfg80211_chan_mode *chanmode)
+{
+ *chan = NULL;
+ *chanmode = CHAN_MODE_UNDEFINED;
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (!netif_running(wdev->netdev))
+ return;
+
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_ADHOC:
+ if (wdev->current_bss) {
+ *chan = wdev->current_bss->pub.channel;
+ *chanmode = wdev->ibss_fixed
+ ? CHAN_MODE_SHARED
+ : CHAN_MODE_EXCLUSIVE;
+ return;
+ }
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_P2P_CLIENT:
+ if (wdev->current_bss) {
+ *chan = wdev->current_bss->pub.channel;
+ *chanmode = CHAN_MODE_SHARED;
+ return;
+ }
+ break;
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_P2P_GO:
+ case NL80211_IFTYPE_MESH_POINT:
+ *chan = wdev->channel;
+ *chanmode = CHAN_MODE_SHARED;
+ return;
+ case NL80211_IFTYPE_MONITOR:
+ case NL80211_IFTYPE_AP_VLAN:
+ case NL80211_IFTYPE_WDS:
+ /* these interface types don't really have a channel */
+ return;
+ case NL80211_IFTYPE_UNSPECIFIED:
+ case NUM_NL80211_IFTYPES:
+ WARN_ON(1);
+ }
+
+ return;
}
diff --git a/net/wireless/core.c b/net/wireless/core.c
index a87d43552974..0557bb159025 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -96,69 +96,6 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
return &rdev->wiphy;
}
-/* requires cfg80211_mutex to be held! */
-struct cfg80211_registered_device *
-__cfg80211_rdev_from_info(struct genl_info *info)
-{
- int ifindex;
- struct cfg80211_registered_device *bywiphyidx = NULL, *byifidx = NULL;
- struct net_device *dev;
- int err = -EINVAL;
-
- assert_cfg80211_lock();
-
- if (info->attrs[NL80211_ATTR_WIPHY]) {
- bywiphyidx = cfg80211_rdev_by_wiphy_idx(
- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY]));
- err = -ENODEV;
- }
-
- if (info->attrs[NL80211_ATTR_IFINDEX]) {
- ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
- dev = dev_get_by_index(genl_info_net(info), ifindex);
- if (dev) {
- if (dev->ieee80211_ptr)
- byifidx =
- wiphy_to_dev(dev->ieee80211_ptr->wiphy);
- dev_put(dev);
- }
- err = -ENODEV;
- }
-
- if (bywiphyidx && byifidx) {
- if (bywiphyidx != byifidx)
- return ERR_PTR(-EINVAL);
- else
- return bywiphyidx; /* == byifidx */
- }
- if (bywiphyidx)
- return bywiphyidx;
-
- if (byifidx)
- return byifidx;
-
- return ERR_PTR(err);
-}
-
-struct cfg80211_registered_device *
-cfg80211_get_dev_from_info(struct genl_info *info)
-{
- struct cfg80211_registered_device *rdev;
-
- mutex_lock(&cfg80211_mutex);
- rdev = __cfg80211_rdev_from_info(info);
-
- /* if it is not an error we grab the lock on
- * it to assure it won't be going away while
- * we operate on it */
- if (!IS_ERR(rdev))
- mutex_lock(&rdev->mtx);
-
- mutex_unlock(&cfg80211_mutex);
-
- return rdev;
-}
-
struct cfg80211_registered_device *
cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
{
@@ -239,7 +176,9 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK))
return -EOPNOTSUPP;
- list_for_each_entry(wdev, &rdev->netdev_list, list) {
+ list_for_each_entry(wdev, &rdev->wdev_list, list) {
+ if (!wdev->netdev)
+ continue;
wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
err = dev_change_net_namespace(wdev->netdev, net, "wlan%d");
if (err)
@@ -251,8 +190,10 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
/* failed -- clean up to old netns */
net = wiphy_net(&rdev->wiphy);
- list_for_each_entry_continue_reverse(wdev, &rdev->netdev_list,
+ list_for_each_entry_continue_reverse(wdev, &rdev->wdev_list,
list) {
+ if (!wdev->netdev)
+ continue;
wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
err = dev_change_net_namespace(wdev->netdev, net,
"wlan%d");
@@ -289,8 +230,9 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
rtnl_lock();
mutex_lock(&rdev->devlist_mtx);
- list_for_each_entry(wdev, &rdev->netdev_list, list)
- dev_close(wdev->netdev);
+ list_for_each_entry(wdev, &rdev->wdev_list, list)
+ if (wdev->netdev)
+ dev_close(wdev->netdev);
mutex_unlock(&rdev->devlist_mtx);
rtnl_unlock();
@@ -367,7 +309,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
mutex_init(&rdev->mtx);
mutex_init(&rdev->devlist_mtx);
mutex_init(&rdev->sched_scan_mtx);
- INIT_LIST_HEAD(&rdev->netdev_list);
+ INIT_LIST_HEAD(&rdev->wdev_list);
spin_lock_init(&rdev->bss_lock);
INIT_LIST_HEAD(&rdev->bss_list);
INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
@@ -436,6 +378,14 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
if (WARN_ON(!c->num_different_channels))
return -EINVAL;
+ /*
+ * Put a sane limit on maximum number of different
+ * channels to simplify channel accounting code.
+ */
+ if (WARN_ON(c->num_different_channels >
+ CFG80211_MAX_NUM_DIFFERENT_CHANNELS))
+ return -EINVAL;
+
if (WARN_ON(!c->n_limits))
return -EINVAL;
@@ -484,9 +434,11 @@ int wiphy_register(struct wiphy *wiphy)
int i;
u16 ifmodes = wiphy->interface_modes;
+#ifdef CONFIG_PM
if (WARN_ON((wiphy->wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
!(wiphy->wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY)))
return -EINVAL;
+#endif
if (WARN_ON(wiphy->ap_sme_capa &&
!(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME)))
@@ -521,8 +473,14 @@ int wiphy_register(struct wiphy *wiphy)
continue;
sband->band = band;
-
- if (WARN_ON(!sband->n_channels || !sband->n_bitrates))
+ if (WARN_ON(!sband->n_channels))
+ return -EINVAL;
+ /*
+ * on 60gHz band, there are no legacy rates, so
+ * n_bitrates is 0
+ */
+ if (WARN_ON(band != IEEE80211_BAND_60GHZ &&
+ !sband->n_bitrates))
return -EINVAL;
/*
@@ -563,12 +521,14 @@ int wiphy_register(struct wiphy *wiphy)
return -EINVAL;
}
+#ifdef CONFIG_PM
if (rdev->wiphy.wowlan.n_patterns) {
if (WARN_ON(!rdev->wiphy.wowlan.pattern_min_len ||
rdev->wiphy.wowlan.pattern_min_len >
rdev->wiphy.wowlan.pattern_max_len))
return -EINVAL;
}
+#endif
/* check and set up bitrates */
ieee80211_set_bitrate_flags(wiphy);
@@ -667,7 +627,7 @@ void wiphy_unregister(struct wiphy *wiphy)
__count == 0; }));
mutex_lock(&rdev->devlist_mtx);
- BUG_ON(!list_empty(&rdev->netdev_list));
+ BUG_ON(!list_empty(&rdev->wdev_list));
mutex_unlock(&rdev->devlist_mtx);
/*
@@ -748,7 +708,7 @@ static void wdev_cleanup_work(struct work_struct *work)
cfg80211_lock_rdev(rdev);
- if (WARN_ON(rdev->scan_req && rdev->scan_req->dev == wdev->netdev)) {
+ if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
rdev->scan_req->aborted = true;
___cfg80211_scan_done(rdev, true);
}
@@ -776,6 +736,62 @@ static struct device_type wiphy_type = {
.name = "wlan",
};
+static struct ieee80211_channel *
+cfg80211_get_any_chan(struct cfg80211_registered_device *rdev)
+{
+ struct ieee80211_supported_band *sband;
+ int i;
+
+ for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
+ sband = rdev->wiphy.bands[i];
+ if (sband && sband->n_channels > 0)
+ return &sband->channels[0];
+ }
+
+ return NULL;
+}
+
+static void cfg80211_init_mon_chan(struct cfg80211_registered_device *rdev)
+{
+ struct ieee80211_channel *chan;
+
+ chan = cfg80211_get_any_chan(rdev);
+ if (WARN_ON(!chan))
+ return;
+
+ mutex_lock(&rdev->devlist_mtx);
+ WARN_ON(cfg80211_set_monitor_channel(rdev, chan->center_freq,
+ NL80211_CHAN_NO_HT));
+ mutex_unlock(&rdev->devlist_mtx);
+}
+
+void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
+ enum nl80211_iftype iftype, int num)
+{
+ bool has_monitors_only_old = cfg80211_has_monitors_only(rdev);
+ bool has_monitors_only_new;
+
+ ASSERT_RTNL();
+
+ rdev->num_running_ifaces += num;
+ if (iftype == NL80211_IFTYPE_MONITOR)
+ rdev->num_running_monitor_ifaces += num;
+
+ has_monitors_only_new = cfg80211_has_monitors_only(rdev);
+ if (has_monitors_only_new != has_monitors_only_old) {
+ if (rdev->ops->set_monitor_enabled)
+ rdev->ops->set_monitor_enabled(&rdev->wiphy,
+ has_monitors_only_new);
+
+ if (!has_monitors_only_new) {
+ rdev->monitor_channel = NULL;
+ rdev->monitor_channel_type = NL80211_CHAN_NO_HT;
+ } else {
+ cfg80211_init_mon_chan(rdev);
+ }
+ }
+}
+
static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
unsigned long state,
void *ndev)
@@ -810,7 +826,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
spin_lock_init(&wdev->mgmt_registrations_lock);
mutex_lock(&rdev->devlist_mtx);
- list_add_rcu(&wdev->list, &rdev->netdev_list);
+ wdev->identifier = ++rdev->wdev_id;
+ list_add_rcu(&wdev->list, &rdev->wdev_list);
rdev->devlist_generation++;
/* can only change netns with wiphy */
dev->features |= NETIF_F_NETNS_LOCAL;
@@ -869,12 +886,16 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
case NL80211_IFTYPE_MESH_POINT:
cfg80211_leave_mesh(rdev, dev);
break;
+ case NL80211_IFTYPE_AP:
+ cfg80211_stop_ap(rdev, dev);
+ break;
default:
break;
}
wdev->beacon_interval = 0;
break;
case NETDEV_DOWN:
+ cfg80211_update_iface_num(rdev, wdev->iftype, -1);
dev_hold(dev);
queue_work(cfg80211_wq, &wdev->cleanup_work);
break;
@@ -980,9 +1001,12 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
return notifier_from_errno(-EOPNOTSUPP);
if (rfkill_blocked(rdev->rfkill))
return notifier_from_errno(-ERFKILL);
+ mutex_lock(&rdev->devlist_mtx);
ret = cfg80211_can_add_interface(rdev, wdev->iftype);
+ mutex_unlock(&rdev->devlist_mtx);
if (ret)
return notifier_from_errno(ret);
+ cfg80211_update_iface_num(rdev, wdev->iftype, 1);
break;
}
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 9348a47562a4..bac97da751df 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -13,6 +13,7 @@
#include <linux/debugfs.h>
#include <linux/rfkill.h>
#include <linux/workqueue.h>
+#include <linux/rtnetlink.h>
#include <net/genetlink.h>
#include <net/cfg80211.h>
#include "reg.h"
@@ -46,16 +47,23 @@ struct cfg80211_registered_device {
/* wiphy index, internal only */
int wiphy_idx;
- /* associate netdev list */
+ /* associated wireless interfaces */
struct mutex devlist_mtx;
/* protected by devlist_mtx or RCU */
- struct list_head netdev_list;
- int devlist_generation;
+ struct list_head wdev_list;
+ int devlist_generation, wdev_id;
int opencount; /* also protected by devlist_mtx */
wait_queue_head_t dev_wait;
u32 ap_beacons_nlpid;
+ /* protected by RTNL only */
+ int num_running_ifaces;
+ int num_running_monitor_ifaces;
+
+ struct ieee80211_channel *monitor_channel;
+ enum nl80211_channel_type monitor_channel_type;
+
/* BSSes/scanning */
spinlock_t bss_lock;
struct list_head bss_list;
@@ -159,32 +167,6 @@ static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx);
int get_wiphy_idx(struct wiphy *wiphy);
-struct cfg80211_registered_device *
-__cfg80211_rdev_from_info(struct genl_info *info);
-
-/*
- * This function returns a pointer to the driver
- * that the genl_info item that is passed refers to.
- * If successful, it returns non-NULL and also locks
- * the driver's mutex!
- *
- * This means that you need to call cfg80211_unlock_rdev()
- * before being allowed to acquire &cfg80211_mutex!
- *
- * This is necessary because we need to lock the global
- * mutex to get an item off the list safely, and then
- * we lock the rdev mutex so it doesn't go away under us.
- *
- * We don't want to keep cfg80211_mutex locked
- * for all the time in order to allow requests on
- * other interfaces to go through at the same time.
- *
- * The result of this can be a PTR_ERR and hence must
- * be checked with IS_ERR() for errors.
- */
-extern struct cfg80211_registered_device *
-cfg80211_get_dev_from_info(struct genl_info *info);
-
/* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
@@ -223,6 +205,14 @@ static inline void wdev_unlock(struct wireless_dev *wdev)
#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx)
#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
+static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
+{
+ ASSERT_RTNL();
+
+ return rdev->num_running_ifaces == rdev->num_running_monitor_ifaces &&
+ rdev->num_running_ifaces > 0;
+}
+
enum cfg80211_event_type {
EVENT_CONNECT_RESULT,
EVENT_ROAMED,
@@ -267,6 +257,12 @@ struct cfg80211_cached_keys {
int def, defmgmt;
};
+enum cfg80211_chan_mode {
+ CHAN_MODE_UNDEFINED,
+ CHAN_MODE_SHARED,
+ CHAN_MODE_EXCLUSIVE,
+};
+
/* free object */
extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
@@ -315,6 +311,10 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, int freq,
enum nl80211_channel_type channel_type);
+/* AP */
+int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
+ struct net_device *dev);
+
/* MLME */
int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
struct net_device *dev,
@@ -372,7 +372,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);
void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
- struct net_device *dev,
+ struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type,
bool channel_type_valid, unsigned int wait,
@@ -430,9 +430,20 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
u32 *flags, struct vif_params *params);
void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
-int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev,
- enum nl80211_iftype iftype);
+int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ enum nl80211_iftype iftype,
+ struct ieee80211_channel *chan,
+ enum cfg80211_chan_mode chanmode);
+
+static inline int
+cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ enum nl80211_iftype iftype)
+{
+ return cfg80211_can_use_iftype_chan(rdev, wdev, iftype, NULL,
+ CHAN_MODE_UNDEFINED);
+}
static inline int
cfg80211_can_add_interface(struct cfg80211_registered_device *rdev,
@@ -441,6 +452,21 @@ cfg80211_can_add_interface(struct cfg80211_registered_device *rdev,
return cfg80211_can_change_interface(rdev, NULL, iftype);
}
+static inline int
+cfg80211_can_use_chan(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ struct ieee80211_channel *chan,
+ enum cfg80211_chan_mode chanmode)
+{
+ return cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
+ chan, chanmode);
+}
+
+void
+cfg80211_get_chan_state(struct wireless_dev *wdev,
+ struct ieee80211_channel **chan,
+ enum cfg80211_chan_mode *chanmode);
+
struct ieee80211_channel *
rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
int freq, enum nl80211_channel_type channel_type);
@@ -454,6 +480,11 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
u32 beacon_int);
+void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
+ enum nl80211_iftype iftype, int num);
+
+#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
+
#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
#define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond)
#else
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 89baa3328411..ca5672f6ee2f 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -113,10 +113,21 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
kfree(wdev->connect_keys);
wdev->connect_keys = connkeys;
+ wdev->ibss_fixed = params->channel_fixed;
#ifdef CONFIG_CFG80211_WEXT
wdev->wext.ibss.channel = params->channel;
#endif
wdev->sme_state = CFG80211_SME_CONNECTING;
+
+ err = cfg80211_can_use_chan(rdev, wdev, params->channel,
+ params->channel_fixed
+ ? CHAN_MODE_SHARED
+ : CHAN_MODE_EXCLUSIVE);
+ if (err) {
+ wdev->connect_keys = NULL;
+ return err;
+ }
+
err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
if (err) {
wdev->connect_keys = NULL;
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index b44c736bf9cf..c384e77ff77a 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -14,6 +14,9 @@
#define MESH_PATH_TIMEOUT 5000
#define MESH_RANN_INTERVAL 5000
+#define MESH_PATH_TO_ROOT_TIMEOUT 6000
+#define MESH_ROOT_INTERVAL 5000
+#define MESH_ROOT_CONFIRMATION_INTERVAL 2000
/*
* Minimum interval between two consecutive PREQs originated by the same
@@ -62,6 +65,9 @@ const struct mesh_config default_mesh_config = {
.dot11MeshForwarding = true,
.rssi_threshold = MESH_RSSI_THRESHOLD,
.ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED,
+ .dot11MeshHWMPactivePathToRootTimeout = MESH_PATH_TO_ROOT_TIMEOUT,
+ .dot11MeshHWMProotInterval = MESH_ROOT_INTERVAL,
+ .dot11MeshHWMPconfirmationInterval = MESH_ROOT_CONFIRMATION_INTERVAL,
};
const struct mesh_setup default_mesh_setup = {
@@ -149,10 +155,16 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
setup->channel_type))
return -EINVAL;
+ err = cfg80211_can_use_chan(rdev, wdev, setup->channel,
+ CHAN_MODE_SHARED);
+ if (err)
+ return err;
+
err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup);
if (!err) {
memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
wdev->mesh_id_len = setup->mesh_id_len;
+ wdev->channel = setup->channel;
}
return err;
@@ -166,9 +178,11 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
+ mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = __cfg80211_join_mesh(rdev, dev, setup, conf);
wdev_unlock(wdev);
+ mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -178,6 +192,7 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
enum nl80211_channel_type channel_type)
{
struct ieee80211_channel *channel;
+ int err;
channel = rdev_freq_to_chan(rdev, freq, channel_type);
if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy,
@@ -199,9 +214,19 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
if (!netif_running(wdev->netdev))
return -ENETDOWN;
- return rdev->ops->libertas_set_mesh_channel(&rdev->wiphy,
- wdev->netdev,
- channel);
+
+ err = cfg80211_can_use_chan(rdev, wdev, channel,
+ CHAN_MODE_SHARED);
+ if (err)
+ return err;
+
+ err = rdev->ops->libertas_set_mesh_channel(&rdev->wiphy,
+ wdev->netdev,
+ channel);
+ if (!err)
+ wdev->channel = channel;
+
+ return err;
}
if (wdev->mesh_id_len)
@@ -243,8 +268,11 @@ static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
return -ENOTCONN;
err = rdev->ops->leave_mesh(&rdev->wiphy, dev);
- if (!err)
+ if (!err) {
wdev->mesh_id_len = 0;
+ wdev->channel = NULL;
+ }
+
return err;
}
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index da4406f11929..abe9f82d5a82 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -302,8 +302,14 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
if (!req.bss)
return -ENOENT;
+ err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel,
+ CHAN_MODE_SHARED);
+ if (err)
+ goto out;
+
err = rdev->ops->auth(&rdev->wiphy, dev, &req);
+out:
cfg80211_put_bss(req.bss);
return err;
}
@@ -317,11 +323,13 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
{
int err;
+ mutex_lock(&rdev->devlist_mtx);
wdev_lock(dev->ieee80211_ptr);
err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
ssid, ssid_len, ie, ie_len,
key, key_len, key_idx);
wdev_unlock(dev->ieee80211_ptr);
+ mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -397,8 +405,14 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
return -ENOENT;
}
+ err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel,
+ CHAN_MODE_SHARED);
+ if (err)
+ goto out;
+
err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
+out:
if (err) {
if (was_connected)
wdev->sme_state = CFG80211_SME_CONNECTED;
@@ -421,11 +435,13 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
+ mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
ssid, ssid_len, ie, ie_len, use_mfp, crypt,
assoc_flags, ht_capa, ht_capa_mask);
wdev_unlock(wdev);
+ mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -551,29 +567,28 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
}
}
-void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie,
+void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_remain_on_channel(rdev, dev, cookie, chan, channel_type,
+ nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, channel_type,
duration, gfp);
}
EXPORT_SYMBOL(cfg80211_ready_on_channel);
-void cfg80211_remain_on_channel_expired(struct net_device *dev,
- u64 cookie,
+void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
gfp_t gfp)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_remain_on_channel_cancel(rdev, dev, cookie, chan,
+ nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan,
channel_type, gfp);
}
EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
@@ -662,8 +677,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
list_add(&nreg->list, &wdev->mgmt_registrations);
if (rdev->ops->mgmt_frame_register)
- rdev->ops->mgmt_frame_register(wiphy, wdev->netdev,
- frame_type, true);
+ rdev->ops->mgmt_frame_register(wiphy, wdev, frame_type, true);
out:
spin_unlock_bh(&wdev->mgmt_registrations_lock);
@@ -686,7 +700,7 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid)
if (rdev->ops->mgmt_frame_register) {
u16 frame_type = le16_to_cpu(reg->frame_type);
- rdev->ops->mgmt_frame_register(wiphy, wdev->netdev,
+ rdev->ops->mgmt_frame_register(wiphy, wdev,
frame_type, false);
}
@@ -715,14 +729,14 @@ void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
}
int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
- struct net_device *dev,
+ struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type,
bool channel_type_valid, unsigned int wait,
const u8 *buf, size_t len, bool no_cck,
bool dont_wait_for_ack, u64 *cookie)
{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct net_device *dev = wdev->netdev;
const struct ieee80211_mgmt *mgmt;
u16 stype;
@@ -809,16 +823,15 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
return -EINVAL;
/* Transmit the Action frame as requested by user space */
- return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, offchan,
+ return rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan,
channel_type, channel_type_valid,
wait, buf, len, no_cck, dont_wait_for_ack,
cookie);
}
-bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_mbm,
+bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
const u8 *buf, size_t len, gfp_t gfp)
{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
struct cfg80211_mgmt_registration *reg;
@@ -855,7 +868,7 @@ bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_mbm,
/* found match! */
/* Indicate the received Action frame to user space */
- if (nl80211_send_mgmt(rdev, dev, reg->nlpid,
+ if (nl80211_send_mgmt(rdev, wdev, reg->nlpid,
freq, sig_mbm,
buf, len, gfp))
continue;
@@ -870,15 +883,14 @@ bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_mbm,
}
EXPORT_SYMBOL(cfg80211_rx_mgmt);
-void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie,
+void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
const u8 *buf, size_t len, bool ack, gfp_t gfp)
{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
/* Indicate TX status of the Action frame to user space */
- nl80211_send_mgmt_tx_status(rdev, dev, cookie, buf, len, ack, gfp);
+ nl80211_send_mgmt_tx_status(rdev, wdev, cookie, buf, len, ack, gfp);
}
EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
@@ -947,6 +959,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
if (WARN_ON(!chan))
goto out;
+ wdev->channel = chan;
nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL);
out:
wdev_unlock(wdev);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 7ae54b82291f..6472c7f928dc 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -46,28 +46,175 @@ static struct genl_family nl80211_fam = {
.post_doit = nl80211_post_doit,
};
-/* internal helper: get rdev and dev */
-static int get_rdev_dev_by_ifindex(struct net *netns, struct nlattr **attrs,
- struct cfg80211_registered_device **rdev,
- struct net_device **dev)
+/* returns ERR_PTR values */
+static struct wireless_dev *
+__cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
{
- int ifindex;
+ struct cfg80211_registered_device *rdev;
+ struct wireless_dev *result = NULL;
+ bool have_ifidx = attrs[NL80211_ATTR_IFINDEX];
+ bool have_wdev_id = attrs[NL80211_ATTR_WDEV];
+ u64 wdev_id;
+ int wiphy_idx = -1;
+ int ifidx = -1;
- if (!attrs[NL80211_ATTR_IFINDEX])
- return -EINVAL;
+ assert_cfg80211_lock();
- ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
- *dev = dev_get_by_index(netns, ifindex);
- if (!*dev)
- return -ENODEV;
+ if (!have_ifidx && !have_wdev_id)
+ return ERR_PTR(-EINVAL);
- *rdev = cfg80211_get_dev_from_ifindex(netns, ifindex);
- if (IS_ERR(*rdev)) {
- dev_put(*dev);
- return PTR_ERR(*rdev);
+ if (have_ifidx)
+ ifidx = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
+ if (have_wdev_id) {
+ wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
+ wiphy_idx = wdev_id >> 32;
}
- return 0;
+ list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
+ struct wireless_dev *wdev;
+
+ if (wiphy_net(&rdev->wiphy) != netns)
+ continue;
+
+ if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
+ continue;
+
+ mutex_lock(&rdev->devlist_mtx);
+ list_for_each_entry(wdev, &rdev->wdev_list, list) {
+ if (have_ifidx && wdev->netdev &&
+ wdev->netdev->ifindex == ifidx) {
+ result = wdev;
+ break;
+ }
+ if (have_wdev_id && wdev->identifier == (u32)wdev_id) {
+ result = wdev;
+ break;
+ }
+ }
+ mutex_unlock(&rdev->devlist_mtx);
+
+ if (result)
+ break;
+ }
+
+ if (result)
+ return result;
+ return ERR_PTR(-ENODEV);
+}
+
+static struct cfg80211_registered_device *
+__cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
+{
+ struct cfg80211_registered_device *rdev = NULL, *tmp;
+ struct net_device *netdev;
+
+ assert_cfg80211_lock();
+
+ if (!attrs[NL80211_ATTR_WIPHY] &&
+ !attrs[NL80211_ATTR_IFINDEX] &&
+ !attrs[NL80211_ATTR_WDEV])
+ return ERR_PTR(-EINVAL);
+
+ if (attrs[NL80211_ATTR_WIPHY])
+ rdev = cfg80211_rdev_by_wiphy_idx(
+ nla_get_u32(attrs[NL80211_ATTR_WIPHY]));
+
+ if (attrs[NL80211_ATTR_WDEV]) {
+ u64 wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
+ struct wireless_dev *wdev;
+ bool found = false;
+
+ tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
+ if (tmp) {
+ /* make sure wdev exists */
+ mutex_lock(&tmp->devlist_mtx);
+ list_for_each_entry(wdev, &tmp->wdev_list, list) {
+ if (wdev->identifier != (u32)wdev_id)
+ continue;
+ found = true;
+ break;
+ }
+ mutex_unlock(&tmp->devlist_mtx);
+
+ if (!found)
+ tmp = NULL;
+
+ if (rdev && tmp != rdev)
+ return ERR_PTR(-EINVAL);
+ rdev = tmp;
+ }
+ }
+
+ if (attrs[NL80211_ATTR_IFINDEX]) {
+ int ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
+ netdev = dev_get_by_index(netns, ifindex);
+ if (netdev) {
+ if (netdev->ieee80211_ptr)
+ tmp = wiphy_to_dev(
+ netdev->ieee80211_ptr->wiphy);
+ else
+ tmp = NULL;
+
+ dev_put(netdev);
+
+ /* not wireless device -- return error */
+ if (!tmp)
+ return ERR_PTR(-EINVAL);
+
+ /* mismatch -- return error */
+ if (rdev && tmp != rdev)
+ return ERR_PTR(-EINVAL);
+
+ rdev = tmp;
+ }
+ }
+
+ if (!rdev)
+ return ERR_PTR(-ENODEV);
+
+ if (netns != wiphy_net(&rdev->wiphy))
+ return ERR_PTR(-ENODEV);
+
+ return rdev;
+}
+
+/*
+ * This function returns a pointer to the driver
+ * that the genl_info item that is passed refers to.
+ * If successful, it returns non-NULL and also locks
+ * the driver's mutex!
+ *
+ * This means that you need to call cfg80211_unlock_rdev()
+ * before being allowed to acquire &cfg80211_mutex!
+ *
+ * This is necessary because we need to lock the global
+ * mutex to get an item off the list safely, and then
+ * we lock the rdev mutex so it doesn't go away under us.
+ *
+ * We don't want to keep cfg80211_mutex locked
+ * for all the time in order to allow requests on
+ * other interfaces to go through at the same time.
+ *
+ * The result of this can be a PTR_ERR and hence must
+ * be checked with IS_ERR() for errors.
+ */
+static struct cfg80211_registered_device *
+cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev;
+
+ mutex_lock(&cfg80211_mutex);
+ rdev = __cfg80211_rdev_from_attrs(netns, info->attrs);
+
+ /* if it is not an error we grab the lock on
+ * it to assure it won't be going away while
+ * we operate on it */
+ if (!IS_ERR(rdev))
+ mutex_lock(&rdev->mtx);
+
+ mutex_unlock(&cfg80211_mutex);
+
+ return rdev;
}
/* policy for the attributes */
@@ -115,7 +262,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
[NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
[NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
- .len = IEEE80211_MAX_MESH_ID_LEN },
+ .len = IEEE80211_MAX_MESH_ID_LEN },
[NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
[NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 },
@@ -206,6 +353,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
[NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
+ [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
};
/* policy for the key attributes */
@@ -250,8 +398,9 @@ nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
static const struct nla_policy
nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
- [NL80211_ATTR_SCHED_SCAN_MATCH_SSID] = { .type = NLA_BINARY,
+ [NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY,
.len = IEEE80211_MAX_SSID_LEN },
+ [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
};
/* ifidx get helper */
@@ -832,6 +981,15 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
dev->wiphy.bands[band]->ht_cap.ampdu_density)))
goto nla_put_failure;
+ /* add VHT info */
+ if (dev->wiphy.bands[band]->vht_cap.vht_supported &&
+ (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
+ sizeof(dev->wiphy.bands[band]->vht_cap.vht_mcs),
+ &dev->wiphy.bands[band]->vht_cap.vht_mcs) ||
+ nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
+ dev->wiphy.bands[band]->vht_cap.cap)))
+ goto nla_put_failure;
+
/* add frequencies */
nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
if (!nl_freqs)
@@ -1023,6 +1181,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
nla_nest_end(msg, nl_ifs);
}
+#ifdef CONFIG_PM
if (dev->wiphy.wowlan.flags || dev->wiphy.wowlan.n_patterns) {
struct nlattr *nl_wowlan;
@@ -1063,6 +1222,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
nla_nest_end(msg, nl_wowlan);
}
+#endif
if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
dev->wiphy.software_iftypes))
@@ -1334,7 +1494,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
}
if (!netdev) {
- rdev = __cfg80211_rdev_from_info(info);
+ rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
+ info->attrs);
if (IS_ERR(rdev)) {
mutex_unlock(&cfg80211_mutex);
return PTR_ERR(rdev);
@@ -1567,37 +1728,42 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
return result;
}
+static inline u64 wdev_id(struct wireless_dev *wdev)
+{
+ return (u64)wdev->identifier |
+ ((u64)wiphy_to_dev(wdev->wiphy)->wiphy_idx << 32);
+}
static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
struct cfg80211_registered_device *rdev,
- struct net_device *dev)
+ struct wireless_dev *wdev)
{
+ struct net_device *dev = wdev->netdev;
void *hdr;
hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE);
if (!hdr)
return -1;
- if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
- nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
- nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name) ||
- nla_put_u32(msg, NL80211_ATTR_IFTYPE,
- dev->ieee80211_ptr->iftype) ||
+ if (dev &&
+ (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
+ nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name) ||
+ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dev->dev_addr)))
+ goto nla_put_failure;
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+ nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) ||
+ nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
nla_put_u32(msg, NL80211_ATTR_GENERATION,
rdev->devlist_generation ^
(cfg80211_rdev_list_generation << 2)))
goto nla_put_failure;
- if (rdev->ops->get_channel) {
- struct ieee80211_channel *chan;
- enum nl80211_channel_type channel_type;
-
- chan = rdev->ops->get_channel(&rdev->wiphy, &channel_type);
- if (chan &&
- (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
- chan->center_freq) ||
- nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
- channel_type)))
+ if (rdev->monitor_channel) {
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
+ rdev->monitor_channel->center_freq) ||
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
+ rdev->monitor_channel_type))
goto nla_put_failure;
}
@@ -1628,14 +1794,14 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
if_idx = 0;
mutex_lock(&rdev->devlist_mtx);
- list_for_each_entry(wdev, &rdev->netdev_list, list) {
+ list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (if_idx < if_start) {
if_idx++;
continue;
}
if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
- rdev, wdev->netdev) < 0) {
+ rdev, wdev) < 0) {
mutex_unlock(&rdev->devlist_mtx);
goto out;
}
@@ -1658,14 +1824,14 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
{
struct sk_buff *msg;
struct cfg80211_registered_device *dev = info->user_ptr[0];
- struct net_device *netdev = info->user_ptr[1];
+ struct wireless_dev *wdev = info->user_ptr[1];
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
return -ENOMEM;
if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0,
- dev, netdev) < 0) {
+ dev, wdev) < 0) {
nlmsg_free(msg);
return -ENOBUFS;
}
@@ -1805,7 +1971,8 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct vif_params params;
- struct net_device *dev;
+ struct wireless_dev *wdev;
+ struct sk_buff *msg;
int err;
enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
u32 flags;
@@ -1832,19 +1999,23 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
return err;
}
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
&flags);
- dev = rdev->ops->add_virtual_intf(&rdev->wiphy,
+ wdev = rdev->ops->add_virtual_intf(&rdev->wiphy,
nla_data(info->attrs[NL80211_ATTR_IFNAME]),
type, err ? NULL : &flags, &params);
- if (IS_ERR(dev))
- return PTR_ERR(dev);
+ if (IS_ERR(wdev)) {
+ nlmsg_free(msg);
+ return PTR_ERR(wdev);
+ }
if (type == NL80211_IFTYPE_MESH_POINT &&
info->attrs[NL80211_ATTR_MESH_ID]) {
- struct wireless_dev *wdev = dev->ieee80211_ptr;
-
wdev_lock(wdev);
BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
IEEE80211_MAX_MESH_ID_LEN);
@@ -1855,18 +2026,34 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
wdev_unlock(wdev);
}
- return 0;
+ if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0,
+ rdev, wdev) < 0) {
+ nlmsg_free(msg);
+ return -ENOBUFS;
+ }
+
+ return genlmsg_reply(msg, info);
}
static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = info->user_ptr[1];
if (!rdev->ops->del_virtual_intf)
return -EOPNOTSUPP;
- return rdev->ops->del_virtual_intf(&rdev->wiphy, dev);
+ /*
+ * If we remove a wireless device without a netdev then clear
+ * user_ptr[1] so that nl80211_post_doit won't dereference it
+ * to check if it needs to do dev_put(). Otherwise it crashes
+ * since the wdev has been freed, unlike with a netdev where
+ * we need the dev_put() for the netdev to really be freed.
+ */
+ if (!wdev->netdev)
+ info->user_ptr[1] = NULL;
+
+ return rdev->ops->del_virtual_intf(&rdev->wiphy, wdev);
}
static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
@@ -2246,6 +2433,33 @@ static int nl80211_parse_beacon(struct genl_info *info,
return 0;
}
+static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
+ struct cfg80211_ap_settings *params)
+{
+ struct wireless_dev *wdev;
+ bool ret = false;
+
+ mutex_lock(&rdev->devlist_mtx);
+
+ list_for_each_entry(wdev, &rdev->wdev_list, list) {
+ if (wdev->iftype != NL80211_IFTYPE_AP &&
+ wdev->iftype != NL80211_IFTYPE_P2P_GO)
+ continue;
+
+ if (!wdev->preset_chan)
+ continue;
+
+ params->channel = wdev->preset_chan;
+ params->channel_type = wdev->preset_chantype;
+ ret = true;
+ break;
+ }
+
+ mutex_unlock(&rdev->devlist_mtx);
+
+ return ret;
+}
+
static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -2348,16 +2562,28 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
} else if (wdev->preset_chan) {
params.channel = wdev->preset_chan;
params.channel_type = wdev->preset_chantype;
- } else
+ } else if (!nl80211_get_ap_channel(rdev, &params))
return -EINVAL;
if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel,
params.channel_type))
return -EINVAL;
+ mutex_lock(&rdev->devlist_mtx);
+ err = cfg80211_can_use_chan(rdev, wdev, params.channel,
+ CHAN_MODE_SHARED);
+ mutex_unlock(&rdev->devlist_mtx);
+
+ if (err)
+ return err;
+
err = rdev->ops->start_ap(&rdev->wiphy, dev, &params);
- if (!err)
+ if (!err) {
+ wdev->preset_chan = params.channel;
+ wdev->preset_chantype = params.channel_type;
wdev->beacon_interval = params.beacon_interval;
+ wdev->channel = params.channel;
+ }
return err;
}
@@ -2390,23 +2616,8 @@ static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct net_device *dev = info->user_ptr[1];
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- int err;
-
- if (!rdev->ops->stop_ap)
- return -EOPNOTSUPP;
-
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
- return -EOPNOTSUPP;
- if (!wdev->beacon_interval)
- return -ENOENT;
-
- err = rdev->ops->stop_ap(&rdev->wiphy, dev);
- if (!err)
- wdev->beacon_interval = 0;
- return err;
+ return cfg80211_stop_ap(rdev, dev);
}
static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
@@ -2498,7 +2709,8 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
int attr)
{
struct nlattr *rate;
- u16 bitrate;
+ u32 bitrate;
+ u16 bitrate_compat;
rate = nla_nest_start(msg, attr);
if (!rate)
@@ -2506,8 +2718,12 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
bitrate = cfg80211_calculate_bitrate(info);
+ /* report 16-bit bitrate only if we can */
+ bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
if ((bitrate > 0 &&
- nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate)) ||
+ nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate)) ||
+ (bitrate_compat > 0 &&
+ nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat)) ||
((info->flags & RATE_INFO_FLAGS_MCS) &&
nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) ||
((info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) &&
@@ -3469,7 +3685,13 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
nla_put_u32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
cur_params.rssi_threshold) ||
nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE,
- cur_params.ht_opmode))
+ cur_params.ht_opmode) ||
+ nla_put_u32(msg, NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
+ cur_params.dot11MeshHWMPactivePathToRootTimeout) ||
+ nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
+ cur_params.dot11MeshHWMProotInterval) ||
+ nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
+ cur_params.dot11MeshHWMPconfirmationInterval))
goto nla_put_failure;
nla_nest_end(msg, pinfoattr);
genlmsg_end(msg, hdr);
@@ -3492,7 +3714,6 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
[NL80211_MESHCONF_ELEMENT_TTL] = { .type = NLA_U8 },
[NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 },
[NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] = { .type = NLA_U32 },
-
[NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
[NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
[NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 },
@@ -3504,8 +3725,11 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
[NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 },
[NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },
[NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 },
- [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32},
- [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16},
+ [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32 },
+ [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 },
+ [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },
+ [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] = { .type = NLA_U16 },
+ [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 },
};
static const struct nla_policy
@@ -3515,7 +3739,7 @@ static const struct nla_policy
[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
[NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
[NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY,
- .len = IEEE80211_MAX_DATA_LEN },
+ .len = IEEE80211_MAX_DATA_LEN },
[NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
};
@@ -3548,63 +3772,82 @@ do {\
/* Fill in the params struct */
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout,
- mask, NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
+ mask, NL80211_MESHCONF_RETRY_TIMEOUT,
+ nla_get_u16);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout,
- mask, NL80211_MESHCONF_CONFIRM_TIMEOUT, nla_get_u16);
+ mask, NL80211_MESHCONF_CONFIRM_TIMEOUT,
+ nla_get_u16);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout,
- mask, NL80211_MESHCONF_HOLDING_TIMEOUT, nla_get_u16);
+ mask, NL80211_MESHCONF_HOLDING_TIMEOUT,
+ nla_get_u16);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks,
- mask, NL80211_MESHCONF_MAX_PEER_LINKS, nla_get_u16);
+ mask, NL80211_MESHCONF_MAX_PEER_LINKS,
+ nla_get_u16);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries,
- mask, NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
+ mask, NL80211_MESHCONF_MAX_RETRIES,
+ nla_get_u8);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL,
- mask, NL80211_MESHCONF_TTL, nla_get_u8);
+ mask, NL80211_MESHCONF_TTL, nla_get_u8);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl,
- mask, NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8);
+ mask, NL80211_MESHCONF_ELEMENT_TTL,
+ nla_get_u8);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks,
- mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, nla_get_u8);
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
- mask, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
- nla_get_u32);
+ mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
+ nla_get_u8);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor, mask,
+ NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
+ nla_get_u32);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries,
- mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
- nla_get_u8);
+ mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
+ nla_get_u8);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time,
- mask, NL80211_MESHCONF_PATH_REFRESH_TIME, nla_get_u32);
+ mask, NL80211_MESHCONF_PATH_REFRESH_TIME,
+ nla_get_u32);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout,
- mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
- nla_get_u16);
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
- mask, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
- nla_get_u32);
+ mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
+ nla_get_u16);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout, mask,
+ NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
+ nla_get_u32);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval,
- mask, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
- nla_get_u16);
+ mask, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
+ nla_get_u16);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval,
- mask, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
- nla_get_u16);
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
- dot11MeshHWMPnetDiameterTraversalTime,
- mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
- nla_get_u16);
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
- dot11MeshHWMPRootMode, mask,
- NL80211_MESHCONF_HWMP_ROOTMODE,
- nla_get_u8);
+ mask, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
+ nla_get_u16);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
- dot11MeshHWMPRannInterval, mask,
- NL80211_MESHCONF_HWMP_RANN_INTERVAL,
- nla_get_u16);
+ dot11MeshHWMPnetDiameterTraversalTime, mask,
+ NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
+ nla_get_u16);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, mask,
+ NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, mask,
+ NL80211_MESHCONF_HWMP_RANN_INTERVAL,
+ nla_get_u16);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
- dot11MeshGateAnnouncementProtocol, mask,
- NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
- nla_get_u8);
+ dot11MeshGateAnnouncementProtocol, mask,
+ NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
+ nla_get_u8);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding,
- mask, NL80211_MESHCONF_FORWARDING, nla_get_u8);
+ mask, NL80211_MESHCONF_FORWARDING,
+ nla_get_u8);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold,
- mask, NL80211_MESHCONF_RSSI_THRESHOLD, nla_get_u32);
+ mask, NL80211_MESHCONF_RSSI_THRESHOLD,
+ nla_get_u32);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode,
- mask, NL80211_MESHCONF_HT_OPMODE, nla_get_u16);
+ mask, NL80211_MESHCONF_HT_OPMODE,
+ nla_get_u16);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout,
+ mask,
+ NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
+ nla_get_u32);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval,
+ mask, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
+ nla_get_u16);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
+ dot11MeshHWMPconfirmationInterval, mask,
+ NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
+ nla_get_u16);
if (mask_out)
*mask_out = mask;
@@ -3887,7 +4130,7 @@ static int validate_scan_freqs(struct nlattr *freqs)
static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = info->user_ptr[1];
struct cfg80211_scan_request *request;
struct nlattr *attr;
struct wiphy *wiphy;
@@ -4047,15 +4290,16 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
request->no_cck =
nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
- request->dev = dev;
+ request->wdev = wdev;
request->wiphy = &rdev->wiphy;
rdev->scan_req = request;
- err = rdev->ops->scan(&rdev->wiphy, dev, request);
+ err = rdev->ops->scan(&rdev->wiphy, request);
if (!err) {
- nl80211_send_scan_start(rdev, dev);
- dev_hold(dev);
+ nl80211_send_scan_start(rdev, wdev);
+ if (wdev->netdev)
+ dev_hold(wdev->netdev);
} else {
out_free:
rdev->scan_req = NULL;
@@ -4241,12 +4485,12 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
nla_for_each_nested(attr,
info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
tmp) {
- struct nlattr *ssid;
+ struct nlattr *ssid, *rssi;
nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
nla_data(attr), nla_len(attr),
nl80211_match_policy);
- ssid = tb[NL80211_ATTR_SCHED_SCAN_MATCH_SSID];
+ ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
if (ssid) {
if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
err = -EINVAL;
@@ -4257,6 +4501,12 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
request->match_sets[i].ssid.ssid_len =
nla_len(ssid);
}
+ rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
+ if (rssi)
+ request->rssi_thold = nla_get_u32(rssi);
+ else
+ request->rssi_thold =
+ NL80211_SCAN_RSSI_THOLD_OFF;
i++;
}
}
@@ -5114,21 +5364,18 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
nl80211_policy);
if (err)
return err;
- if (nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]) {
- phy_idx = nla_get_u32(
- nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]);
- } else {
- struct net_device *netdev;
- err = get_rdev_dev_by_ifindex(sock_net(skb->sk),
- nl80211_fam.attrbuf,
- &rdev, &netdev);
- if (err)
- return err;
- dev_put(netdev);
- phy_idx = rdev->wiphy_idx;
- cfg80211_unlock_rdev(rdev);
+ mutex_lock(&cfg80211_mutex);
+ rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
+ nl80211_fam.attrbuf);
+ if (IS_ERR(rdev)) {
+ mutex_unlock(&cfg80211_mutex);
+ return PTR_ERR(rdev);
}
+ phy_idx = rdev->wiphy_idx;
+ rdev = NULL;
+ mutex_unlock(&cfg80211_mutex);
+
if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
cb->args[1] =
(long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA];
@@ -5530,7 +5777,7 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = info->user_ptr[1];
struct ieee80211_channel *chan;
struct sk_buff *msg;
void *hdr;
@@ -5578,7 +5825,7 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
goto free_msg;
}
- err = rdev->ops->remain_on_channel(&rdev->wiphy, dev, chan,
+ err = rdev->ops->remain_on_channel(&rdev->wiphy, wdev, chan,
channel_type, duration, &cookie);
if (err)
@@ -5602,7 +5849,7 @@ static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = info->user_ptr[1];
u64 cookie;
if (!info->attrs[NL80211_ATTR_COOKIE])
@@ -5613,7 +5860,7 @@ static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
- return rdev->ops->cancel_remain_on_channel(&rdev->wiphy, dev, cookie);
+ return rdev->ops->cancel_remain_on_channel(&rdev->wiphy, wdev, cookie);
}
static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
@@ -5762,7 +6009,7 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = info->user_ptr[1];
u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION;
if (!info->attrs[NL80211_ATTR_FRAME_MATCH])
@@ -5771,21 +6018,24 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_FRAME_TYPE])
frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]);
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_P2P_CLIENT:
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_AP_VLAN:
+ case NL80211_IFTYPE_MESH_POINT:
+ case NL80211_IFTYPE_P2P_GO:
+ break;
+ default:
return -EOPNOTSUPP;
+ }
/* not much point in registering if we can't reply */
if (!rdev->ops->mgmt_tx)
return -EOPNOTSUPP;
- return cfg80211_mlme_register_mgmt(dev->ieee80211_ptr, info->snd_pid,
- frame_type,
+ return cfg80211_mlme_register_mgmt(wdev, info->snd_pid, frame_type,
nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]));
}
@@ -5793,7 +6043,7 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = info->user_ptr[1];
struct ieee80211_channel *chan;
enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
bool channel_type_valid = false;
@@ -5814,14 +6064,18 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
if (!rdev->ops->mgmt_tx)
return -EOPNOTSUPP;
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_P2P_CLIENT:
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_AP_VLAN:
+ case NL80211_IFTYPE_MESH_POINT:
+ case NL80211_IFTYPE_P2P_GO:
+ break;
+ default:
return -EOPNOTSUPP;
+ }
if (info->attrs[NL80211_ATTR_DURATION]) {
if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
@@ -5870,7 +6124,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
}
}
- err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, offchan, channel_type,
+ err = cfg80211_mlme_mgmt_tx(rdev, wdev, chan, offchan, channel_type,
channel_type_valid, wait,
nla_data(info->attrs[NL80211_ATTR_FRAME]),
nla_len(info->attrs[NL80211_ATTR_FRAME]),
@@ -5898,7 +6152,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = info->user_ptr[1];
u64 cookie;
if (!info->attrs[NL80211_ATTR_COOKIE])
@@ -5907,17 +6161,21 @@ static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *in
if (!rdev->ops->mgmt_tx_cancel_wait)
return -EOPNOTSUPP;
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_P2P_CLIENT:
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_AP_VLAN:
+ case NL80211_IFTYPE_P2P_GO:
+ break;
+ default:
return -EOPNOTSUPP;
+ }
cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
- return rdev->ops->mgmt_tx_cancel_wait(&rdev->wiphy, dev, cookie);
+ return rdev->ops->mgmt_tx_cancel_wait(&rdev->wiphy, wdev, cookie);
}
static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
@@ -6126,6 +6384,7 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
return cfg80211_leave_mesh(rdev, dev);
}
+#ifdef CONFIG_PM
static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -6354,6 +6613,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
kfree(new_triggers.patterns);
return err;
}
+#endif
static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
{
@@ -6498,44 +6758,75 @@ static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
#define NL80211_FLAG_CHECK_NETDEV_UP 0x08
#define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\
NL80211_FLAG_CHECK_NETDEV_UP)
+#define NL80211_FLAG_NEED_WDEV 0x10
+/* If a netdev is associated, it must be UP */
+#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
+ NL80211_FLAG_CHECK_NETDEV_UP)
static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info)
{
struct cfg80211_registered_device *rdev;
+ struct wireless_dev *wdev;
struct net_device *dev;
- int err;
bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL;
if (rtnl)
rtnl_lock();
if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) {
- rdev = cfg80211_get_dev_from_info(info);
+ rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
if (IS_ERR(rdev)) {
if (rtnl)
rtnl_unlock();
return PTR_ERR(rdev);
}
info->user_ptr[0] = rdev;
- } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
- err = get_rdev_dev_by_ifindex(genl_info_net(info), info->attrs,
- &rdev, &dev);
- if (err) {
+ } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
+ ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
+ mutex_lock(&cfg80211_mutex);
+ wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
+ info->attrs);
+ if (IS_ERR(wdev)) {
+ mutex_unlock(&cfg80211_mutex);
if (rtnl)
rtnl_unlock();
- return err;
+ return PTR_ERR(wdev);
}
- if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
- !netif_running(dev)) {
- cfg80211_unlock_rdev(rdev);
- dev_put(dev);
- if (rtnl)
- rtnl_unlock();
- return -ENETDOWN;
+
+ dev = wdev->netdev;
+ rdev = wiphy_to_dev(wdev->wiphy);
+
+ if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
+ if (!dev) {
+ mutex_unlock(&cfg80211_mutex);
+ if (rtnl)
+ rtnl_unlock();
+ return -EINVAL;
+ }
+
+ info->user_ptr[1] = dev;
+ } else {
+ info->user_ptr[1] = wdev;
}
+
+ if (dev) {
+ if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
+ !netif_running(dev)) {
+ mutex_unlock(&cfg80211_mutex);
+ if (rtnl)
+ rtnl_unlock();
+ return -ENETDOWN;
+ }
+
+ dev_hold(dev);
+ }
+
+ cfg80211_lock_rdev(rdev);
+
+ mutex_unlock(&cfg80211_mutex);
+
info->user_ptr[0] = rdev;
- info->user_ptr[1] = dev;
}
return 0;
@@ -6546,8 +6837,16 @@ static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
{
if (info->user_ptr[0])
cfg80211_unlock_rdev(info->user_ptr[0]);
- if (info->user_ptr[1])
- dev_put(info->user_ptr[1]);
+ if (info->user_ptr[1]) {
+ if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
+ struct wireless_dev *wdev = info->user_ptr[1];
+
+ if (wdev->netdev)
+ dev_put(wdev->netdev);
+ } else {
+ dev_put(info->user_ptr[1]);
+ }
+ }
if (ops->internal_flags & NL80211_FLAG_NEED_RTNL)
rtnl_unlock();
}
@@ -6574,7 +6873,7 @@ static struct genl_ops nl80211_ops[] = {
.dumpit = nl80211_dump_interface,
.policy = nl80211_policy,
/* can be retrieved by unprivileged users */
- .internal_flags = NL80211_FLAG_NEED_NETDEV,
+ .internal_flags = NL80211_FLAG_NEED_WDEV,
},
{
.cmd = NL80211_CMD_SET_INTERFACE,
@@ -6597,7 +6896,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_del_interface,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_WDEV |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6768,7 +7067,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_trigger_scan,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6909,7 +7208,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_remain_on_channel,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6917,7 +7216,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_cancel_remain_on_channel,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6933,7 +7232,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_register_mgmt,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_WDEV |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6941,7 +7240,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_tx_mgmt,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6949,7 +7248,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_tx_mgmt_cancel_wait,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -7008,6 +7307,7 @@ static struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
+#ifdef CONFIG_PM
{
.cmd = NL80211_CMD_GET_WOWLAN,
.doit = nl80211_get_wowlan,
@@ -7024,6 +7324,7 @@ static struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_WIPHY |
NL80211_FLAG_NEED_RTNL,
},
+#endif
{
.cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
.doit = nl80211_set_rekey_data,
@@ -7158,7 +7459,7 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
static int nl80211_send_scan_msg(struct sk_buff *msg,
struct cfg80211_registered_device *rdev,
- struct net_device *netdev,
+ struct wireless_dev *wdev,
u32 pid, u32 seq, int flags,
u32 cmd)
{
@@ -7169,7 +7470,9 @@ static int nl80211_send_scan_msg(struct sk_buff *msg,
return -1;
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
- nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
+ (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
+ wdev->netdev->ifindex)) ||
+ nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
goto nla_put_failure;
/* ignore errors and send incomplete event anyway */
@@ -7206,7 +7509,7 @@ nl80211_send_sched_scan_msg(struct sk_buff *msg,
}
void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
- struct net_device *netdev)
+ struct wireless_dev *wdev)
{
struct sk_buff *msg;
@@ -7214,7 +7517,7 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
if (!msg)
return;
- if (nl80211_send_scan_msg(msg, rdev, netdev, 0, 0, 0,
+ if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
NL80211_CMD_TRIGGER_SCAN) < 0) {
nlmsg_free(msg);
return;
@@ -7225,7 +7528,7 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
}
void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
- struct net_device *netdev)
+ struct wireless_dev *wdev)
{
struct sk_buff *msg;
@@ -7233,7 +7536,7 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
if (!msg)
return;
- if (nl80211_send_scan_msg(msg, rdev, netdev, 0, 0, 0,
+ if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
nlmsg_free(msg);
return;
@@ -7244,7 +7547,7 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
}
void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
- struct net_device *netdev)
+ struct wireless_dev *wdev)
{
struct sk_buff *msg;
@@ -7252,7 +7555,7 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
if (!msg)
return;
- if (nl80211_send_scan_msg(msg, rdev, netdev, 0, 0, 0,
+ if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
NL80211_CMD_SCAN_ABORTED) < 0) {
nlmsg_free(msg);
return;
@@ -7775,7 +8078,7 @@ nla_put_failure:
static void nl80211_send_remain_on_chan_event(
int cmd, struct cfg80211_registered_device *rdev,
- struct net_device *netdev, u64 cookie,
+ struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp)
@@ -7794,7 +8097,9 @@ static void nl80211_send_remain_on_chan_event(
}
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
- nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+ (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
+ wdev->netdev->ifindex)) ||
+ nla_put_u32(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) ||
nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, channel_type) ||
nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
@@ -7816,23 +8121,24 @@ static void nl80211_send_remain_on_chan_event(
}
void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, u64 cookie,
+ struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp)
{
nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
- rdev, netdev, cookie, chan,
+ rdev, wdev, cookie, chan,
channel_type, duration, gfp);
}
void nl80211_send_remain_on_channel_cancel(
- struct cfg80211_registered_device *rdev, struct net_device *netdev,
+ struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
u64 cookie, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type, gfp_t gfp)
{
nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
- rdev, netdev, cookie, chan,
+ rdev, wdev, cookie, chan,
channel_type, 0, gfp);
}
@@ -7946,10 +8252,11 @@ bool nl80211_unexpected_4addr_frame(struct net_device *dev,
}
int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, u32 nlpid,
+ struct wireless_dev *wdev, u32 nlpid,
int freq, int sig_dbm,
const u8 *buf, size_t len, gfp_t gfp)
{
+ struct net_device *netdev = wdev->netdev;
struct sk_buff *msg;
void *hdr;
@@ -7964,7 +8271,8 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
}
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
- nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+ (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
+ netdev->ifindex)) ||
nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||
(sig_dbm &&
nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
@@ -7982,10 +8290,11 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
}
void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, u64 cookie,
+ struct wireless_dev *wdev, u64 cookie,
const u8 *buf, size_t len, bool ack,
gfp_t gfp)
{
+ struct net_device *netdev = wdev->netdev;
struct sk_buff *msg;
void *hdr;
@@ -8000,7 +8309,8 @@ void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev,
}
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
- nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+ (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
+ netdev->ifindex)) ||
nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) ||
(ack && nla_put_flag(msg, NL80211_ATTR_ACK)))
@@ -8324,7 +8634,7 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
rcu_read_lock();
list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
- list_for_each_entry_rcu(wdev, &rdev->netdev_list, list)
+ list_for_each_entry_rcu(wdev, &rdev->wdev_list, list)
cfg80211_mlme_unregister_socket(wdev, notify->pid);
if (rdev->ap_beacons_nlpid == notify->pid)
rdev->ap_beacons_nlpid = 0;
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 01a1122c3b33..89ce99675e61 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -7,11 +7,11 @@ int nl80211_init(void);
void nl80211_exit(void);
void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
- struct net_device *netdev);
+ struct wireless_dev *wdev);
void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
- struct net_device *netdev);
+ struct wireless_dev *wdev);
void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
- struct net_device *netdev);
+ struct wireless_dev *wdev);
void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
struct net_device *netdev, u32 cmd);
void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
@@ -74,13 +74,13 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
gfp_t gfp);
void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev,
- struct net_device *netdev,
- u64 cookie,
+ struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp);
void nl80211_send_remain_on_channel_cancel(
- struct cfg80211_registered_device *rdev, struct net_device *netdev,
+ struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
u64 cookie, struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type, gfp_t gfp);
@@ -92,11 +92,11 @@ void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev,
gfp_t gfp);
int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, u32 nlpid,
+ struct wireless_dev *wdev, u32 nlpid,
int freq, int sig_dbm,
const u8 *buf, size_t len, gfp_t gfp);
void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, u64 cookie,
+ struct wireless_dev *wdev, u64 cookie,
const u8 *buf, size_t len, bool ack,
gfp_t gfp);
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 15f347477a99..b2b32229b607 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -129,7 +129,7 @@ static DECLARE_DELAYED_WORK(reg_timeout, reg_timeout_work);
/* We keep a static world regulatory domain in case of the absence of CRDA */
static const struct ieee80211_regdomain world_regdom = {
- .n_reg_rules = 5,
+ .n_reg_rules = 6,
.alpha2 = "00",
.reg_rules = {
/* IEEE 802.11b/g, channels 1..11 */
@@ -156,6 +156,9 @@ static const struct ieee80211_regdomain world_regdom = {
REG_RULE(5745-10, 5825+10, 40, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS),
+
+ /* IEEE 802.11ad (60gHz), channels 1..3 */
+ REG_RULE(56160+2160*1-1080, 56160+2160*3+1080, 2160, 0, 0, 0),
}
};
@@ -1389,7 +1392,7 @@ static void reg_set_request_processed(void)
spin_unlock(&reg_requests_lock);
if (last_request->initiator == NL80211_REGDOM_SET_BY_USER)
- cancel_delayed_work_sync(&reg_timeout);
+ cancel_delayed_work(&reg_timeout);
if (need_more_processing)
schedule_work(&reg_work);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index af2b1caa37fa..848523a2b22f 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -23,7 +23,7 @@
void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
{
struct cfg80211_scan_request *request;
- struct net_device *dev;
+ struct wireless_dev *wdev;
#ifdef CONFIG_CFG80211_WEXT
union iwreq_data wrqu;
#endif
@@ -35,29 +35,31 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
if (!request)
return;
- dev = request->dev;
+ wdev = request->wdev;
/*
* This must be before sending the other events!
* Otherwise, wpa_supplicant gets completely confused with
* wext events.
*/
- cfg80211_sme_scan_done(dev);
+ if (wdev->netdev)
+ cfg80211_sme_scan_done(wdev->netdev);
if (request->aborted)
- nl80211_send_scan_aborted(rdev, dev);
+ nl80211_send_scan_aborted(rdev, wdev);
else
- nl80211_send_scan_done(rdev, dev);
+ nl80211_send_scan_done(rdev, wdev);
#ifdef CONFIG_CFG80211_WEXT
- if (!request->aborted) {
+ if (wdev->netdev && !request->aborted) {
memset(&wrqu, 0, sizeof(wrqu));
- wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
+ wireless_send_event(wdev->netdev, SIOCGIWSCAN, &wrqu, NULL);
}
#endif
- dev_put(dev);
+ if (wdev->netdev)
+ dev_put(wdev->netdev);
rdev->scan_req = NULL;
@@ -955,7 +957,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
}
creq->wiphy = wiphy;
- creq->dev = dev;
+ creq->wdev = dev->ieee80211_ptr;
/* SSIDs come after channels */
creq->ssids = (void *)&creq->channels[n_channels];
creq->n_channels = n_channels;
@@ -1024,12 +1026,12 @@ int cfg80211_wext_siwscan(struct net_device *dev,
creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
rdev->scan_req = creq;
- err = rdev->ops->scan(wiphy, dev, creq);
+ err = rdev->ops->scan(wiphy, creq);
if (err) {
rdev->scan_req = NULL;
/* creq will be freed below */
} else {
- nl80211_send_scan_start(rdev, dev);
+ nl80211_send_scan_start(rdev, dev->ieee80211_ptr);
/* creq now owned by driver */
creq = NULL;
dev_hold(dev);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index f7e937ff8978..6f39cb808302 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -51,7 +51,7 @@ static bool cfg80211_is_all_idle(void)
*/
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
cfg80211_lock_rdev(rdev);
- list_for_each_entry(wdev, &rdev->netdev_list, list) {
+ list_for_each_entry(wdev, &rdev->wdev_list, list) {
wdev_lock(wdev);
if (wdev->sme_state != CFG80211_SME_IDLE)
is_all_idle = false;
@@ -136,15 +136,15 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
wdev->conn->params.ssid_len);
request->ssids[0].ssid_len = wdev->conn->params.ssid_len;
- request->dev = wdev->netdev;
+ request->wdev = wdev;
request->wiphy = &rdev->wiphy;
rdev->scan_req = request;
- err = rdev->ops->scan(wdev->wiphy, wdev->netdev, request);
+ err = rdev->ops->scan(wdev->wiphy, request);
if (!err) {
wdev->conn->state = CFG80211_CONN_SCANNING;
- nl80211_send_scan_start(rdev, wdev->netdev);
+ nl80211_send_scan_start(rdev, wdev);
dev_hold(wdev->netdev);
} else {
rdev->scan_req = NULL;
@@ -221,7 +221,7 @@ void cfg80211_conn_work(struct work_struct *work)
cfg80211_lock_rdev(rdev);
mutex_lock(&rdev->devlist_mtx);
- list_for_each_entry(wdev, &rdev->netdev_list, list) {
+ list_for_each_entry(wdev, &rdev->wdev_list, list) {
wdev_lock(wdev);
if (!netif_running(wdev->netdev)) {
wdev_unlock(wdev);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 8f2d68fc3a44..26f8cd30f712 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -35,19 +35,29 @@ int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band)
{
/* see 802.11 17.3.8.3.2 and Annex J
* there are overlapping channel numbers in 5GHz and 2GHz bands */
- if (band == IEEE80211_BAND_5GHZ) {
- if (chan >= 182 && chan <= 196)
- return 4000 + chan * 5;
- else
- return 5000 + chan * 5;
- } else { /* IEEE80211_BAND_2GHZ */
+ if (chan <= 0)
+ return 0; /* not supported */
+ switch (band) {
+ case IEEE80211_BAND_2GHZ:
if (chan == 14)
return 2484;
else if (chan < 14)
return 2407 + chan * 5;
+ break;
+ case IEEE80211_BAND_5GHZ:
+ if (chan >= 182 && chan <= 196)
+ return 4000 + chan * 5;
else
- return 0; /* not supported */
+ return 5000 + chan * 5;
+ break;
+ case IEEE80211_BAND_60GHZ:
+ if (chan < 5)
+ return 56160 + chan * 2160;
+ break;
+ default:
+ ;
}
+ return 0; /* not supported */
}
EXPORT_SYMBOL(ieee80211_channel_to_frequency);
@@ -60,8 +70,12 @@ int ieee80211_frequency_to_channel(int freq)
return (freq - 2407) / 5;
else if (freq >= 4910 && freq <= 4980)
return (freq - 4000) / 5;
- else
+ else if (freq <= 45000) /* DMG band lower limit */
return (freq - 5000) / 5;
+ else if (freq >= 58320 && freq <= 64800)
+ return (freq - 56160) / 2160;
+ else
+ return 0;
}
EXPORT_SYMBOL(ieee80211_frequency_to_channel);
@@ -137,6 +151,11 @@ static void set_mandatory_flags_band(struct ieee80211_supported_band *sband,
}
WARN_ON(want != 0 && want != 3 && want != 6);
break;
+ case IEEE80211_BAND_60GHZ:
+ /* check for mandatory HT MCS 1..4 */
+ WARN_ON(!sband->ht_cap.ht_supported);
+ WARN_ON((sband->ht_cap.mcs.rx_mask[0] & 0x1e) != 0x1e);
+ break;
case IEEE80211_NUM_BANDS:
WARN_ON(1);
break;
@@ -774,7 +793,7 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
mutex_lock(&rdev->devlist_mtx);
- list_for_each_entry(wdev, &rdev->netdev_list, list)
+ list_for_each_entry(wdev, &rdev->wdev_list, list)
cfg80211_process_wdev_events(wdev);
mutex_unlock(&rdev->devlist_mtx);
@@ -804,9 +823,11 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
ntype == NL80211_IFTYPE_P2P_CLIENT))
return -EBUSY;
- if (ntype != otype) {
+ if (ntype != otype && netif_running(dev)) {
+ mutex_lock(&rdev->devlist_mtx);
err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr,
ntype);
+ mutex_unlock(&rdev->devlist_mtx);
if (err)
return err;
@@ -814,6 +835,9 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
dev->ieee80211_ptr->mesh_id_up_len = 0;
switch (otype) {
+ case NL80211_IFTYPE_AP:
+ cfg80211_stop_ap(rdev, dev);
+ break;
case NL80211_IFTYPE_ADHOC:
cfg80211_leave_ibss(rdev, dev, false);
break;
@@ -868,15 +892,69 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
}
}
+ if (!err && ntype != otype && netif_running(dev)) {
+ cfg80211_update_iface_num(rdev, ntype, 1);
+ cfg80211_update_iface_num(rdev, otype, -1);
+ }
+
return err;
}
-u16 cfg80211_calculate_bitrate(struct rate_info *rate)
+static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate)
+{
+ static const u32 __mcs2bitrate[] = {
+ /* control PHY */
+ [0] = 275,
+ /* SC PHY */
+ [1] = 3850,
+ [2] = 7700,
+ [3] = 9625,
+ [4] = 11550,
+ [5] = 12512, /* 1251.25 mbps */
+ [6] = 15400,
+ [7] = 19250,
+ [8] = 23100,
+ [9] = 25025,
+ [10] = 30800,
+ [11] = 38500,
+ [12] = 46200,
+ /* OFDM PHY */
+ [13] = 6930,
+ [14] = 8662, /* 866.25 mbps */
+ [15] = 13860,
+ [16] = 17325,
+ [17] = 20790,
+ [18] = 27720,
+ [19] = 34650,
+ [20] = 41580,
+ [21] = 45045,
+ [22] = 51975,
+ [23] = 62370,
+ [24] = 67568, /* 6756.75 mbps */
+ /* LP-SC PHY */
+ [25] = 6260,
+ [26] = 8340,
+ [27] = 11120,
+ [28] = 12510,
+ [29] = 16680,
+ [30] = 22240,
+ [31] = 25030,
+ };
+
+ if (WARN_ON_ONCE(rate->mcs >= ARRAY_SIZE(__mcs2bitrate)))
+ return 0;
+
+ return __mcs2bitrate[rate->mcs];
+}
+
+u32 cfg80211_calculate_bitrate(struct rate_info *rate)
{
int modulation, streams, bitrate;
if (!(rate->flags & RATE_INFO_FLAGS_MCS))
return rate->legacy;
+ if (rate->flags & RATE_INFO_FLAGS_60G)
+ return cfg80211_calculate_bitrate_60g(rate);
/* the formula below does only work for MCS values smaller than 32 */
if (WARN_ON_ONCE(rate->mcs >= 32))
@@ -916,7 +994,7 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
mutex_lock(&rdev->devlist_mtx);
- list_for_each_entry(wdev, &rdev->netdev_list, list) {
+ list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (!wdev->beacon_interval)
continue;
if (wdev->beacon_interval != beacon_int) {
@@ -930,28 +1008,49 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
return res;
}
-int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev,
- enum nl80211_iftype iftype)
+int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ enum nl80211_iftype iftype,
+ struct ieee80211_channel *chan,
+ enum cfg80211_chan_mode chanmode)
{
struct wireless_dev *wdev_iter;
u32 used_iftypes = BIT(iftype);
int num[NUM_NL80211_IFTYPES];
+ struct ieee80211_channel
+ *used_channels[CFG80211_MAX_NUM_DIFFERENT_CHANNELS];
+ struct ieee80211_channel *ch;
+ enum cfg80211_chan_mode chmode;
+ int num_different_channels = 0;
int total = 1;
int i, j;
ASSERT_RTNL();
+ lockdep_assert_held(&rdev->devlist_mtx);
/* Always allow software iftypes */
if (rdev->wiphy.software_iftypes & BIT(iftype))
return 0;
memset(num, 0, sizeof(num));
+ memset(used_channels, 0, sizeof(used_channels));
num[iftype] = 1;
- mutex_lock(&rdev->devlist_mtx);
- list_for_each_entry(wdev_iter, &rdev->netdev_list, list) {
+ switch (chanmode) {
+ case CHAN_MODE_UNDEFINED:
+ break;
+ case CHAN_MODE_SHARED:
+ WARN_ON(!chan);
+ used_channels[0] = chan;
+ num_different_channels++;
+ break;
+ case CHAN_MODE_EXCLUSIVE:
+ num_different_channels++;
+ break;
+ }
+
+ list_for_each_entry(wdev_iter, &rdev->wdev_list, list) {
if (wdev_iter == wdev)
continue;
if (!netif_running(wdev_iter->netdev))
@@ -960,11 +1059,42 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype))
continue;
+ /*
+ * We may be holding the "wdev" mutex, but now need to lock
+ * wdev_iter. This is OK because once we get here wdev_iter
+ * is not wdev (tested above), but we need to use the nested
+ * locking for lockdep.
+ */
+ mutex_lock_nested(&wdev_iter->mtx, 1);
+ __acquire(wdev_iter->mtx);
+ cfg80211_get_chan_state(wdev_iter, &ch, &chmode);
+ wdev_unlock(wdev_iter);
+
+ switch (chmode) {
+ case CHAN_MODE_UNDEFINED:
+ break;
+ case CHAN_MODE_SHARED:
+ for (i = 0; i < CFG80211_MAX_NUM_DIFFERENT_CHANNELS; i++)
+ if (!used_channels[i] || used_channels[i] == ch)
+ break;
+
+ if (i == CFG80211_MAX_NUM_DIFFERENT_CHANNELS)
+ return -EBUSY;
+
+ if (used_channels[i] == NULL) {
+ used_channels[i] = ch;
+ num_different_channels++;
+ }
+ break;
+ case CHAN_MODE_EXCLUSIVE:
+ num_different_channels++;
+ break;
+ }
+
num[wdev_iter->iftype]++;
total++;
used_iftypes |= BIT(wdev_iter->iftype);
}
- mutex_unlock(&rdev->devlist_mtx);
if (total == 1)
return 0;
@@ -976,12 +1106,15 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
c = &rdev->wiphy.iface_combinations[i];
+ if (total > c->max_interfaces)
+ continue;
+ if (num_different_channels > c->num_different_channels)
+ continue;
+
limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits,
GFP_KERNEL);
if (!limits)
return -ENOMEM;
- if (total > c->max_interfaces)
- goto cont;
for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
if (rdev->wiphy.software_iftypes & BIT(iftype))
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index bc879833b21f..7df42f541873 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -827,8 +827,6 @@ static int cfg80211_wext_giwfreq(struct net_device *dev,
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
- struct ieee80211_channel *chan;
- enum nl80211_channel_type channel_type;
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
@@ -836,13 +834,10 @@ static int cfg80211_wext_giwfreq(struct net_device *dev,
case NL80211_IFTYPE_ADHOC:
return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
case NL80211_IFTYPE_MONITOR:
- if (!rdev->ops->get_channel)
+ if (!rdev->monitor_channel)
return -EINVAL;
- chan = rdev->ops->get_channel(wdev->wiphy, &channel_type);
- if (!chan)
- return -EINVAL;
- freq->m = chan->center_freq;
+ freq->m = rdev->monitor_channel->center_freq;
freq->e = 6;
return 0;
default: