summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller2013-04-24 22:27:02 +0200
committerDavid S. Miller2013-04-24 22:27:02 +0200
commit8bfadc32b7ef56ac6245b7ae0a06f5ece193004b (patch)
tree571c0c29cee15aa59088cf9a66f798b20005c1f5
parentnetlink: fix compilation after memory mapped patches (diff)
parentMerge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linvil... (diff)
downloadkernel-qcow2-linux-8bfadc32b7ef56ac6245b7ae0a06f5ece193004b.tar.gz
kernel-qcow2-linux-8bfadc32b7ef56ac6245b7ae0a06f5ece193004b.tar.xz
kernel-qcow2-linux-8bfadc32b7ef56ac6245b7ae0a06f5ece193004b.zip
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
John W. Linville says: ==================== Here is one last(?) big wireless bits pull request before the merge window... Regarding the mac80211 bits, Johannes says: "Here's another big pull request for the -next stream. This one has a ton of driver updates, which hopefully addresses all drivers, but maybe you have more new drivers than I have in my tree? Not entirely sure, let me know if this is the case and then I can merge wireless-next. I'm including a large number of small changes, see the shortlog. The two bigger things are making VHT compatible with not using channel contexts (from Karl) and the stop-while-suspended fixes I developed together with Stanislaw." ...and... "This time I have a relatively large number of fixes and small improvements, the most important one being Bob's RCU fix. The two big things are Felix's work on rate scaling tables (with a big thanks to Karl too) and my own work on CSA handling to finally properly handle HT (and some VHT.)" As for the iwlwifi bits, Johannes says: "The biggest work here is Bluetooth coexistence and power saving. Other than that, I have a few small fixes that weren't really needed for 3.9 and a new PCI ID." About the NFC bits, Samuel says: "With this one we have: - A major pn533 update. The pn533 framing support has been changed in order to easily support all pn533 derivatives. For example we now support the ACR122 USB dongle. - An NFC MEI physical layer code factorization through the mei_phy NFC API. Both the microread and the pn544 drivers now use it. - LLCP aggregation support. This allows NFC p2p devices to send aggregated frames containing all sort of LLCP frames except SYMM and aggregation frames. - More LLCP socket options for getting the remote device link parameters. - Fixes for the LLCP socket option code added with the first pull request for 3.10. - Some support for LLCP corner cases like 0 length SDUs and general DISC (tagged with a 0,0 dsap ssap couple) handling. - RFKILL support for NFC." For the b43 bits, RafaƂ says: "Let me remind the changes for b43: > Changes include: > 1) Minor improvements for HT-PHY code (BCM4331) > 2) Code cleaning for HT-PHY and N-PHY" Concerning the bluetooth bits, Gustavo says: "A set of changes intended for 3.10. The biggest changes here are from David Herrmann, he rewrote most of the HIDP layer making it more reliable. Marcel added a driver setup stage for device that need special handling on their early initialization. Other than that we have the usual clean ups, bugfixes and small improvements." Along with all that, there is the usual collection of random/various updates to ath9k, mwifiex, brcmfmac, brcmsmac, rt2x00, and wil6210. I also included a pull of the wireless tree to resolve a merge conflict. Please let me know if there are problems! ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/bluetooth/ath3k.c2
-rw-r--r--drivers/bluetooth/btusb.c41
-rw-r--r--drivers/bluetooth/hci_h4.c3
-rw-r--r--drivers/bluetooth/hci_ldisc.c15
-rw-r--r--drivers/net/wireless/adm8211.c3
-rw-r--r--drivers/net/wireless/at76c50x-usb.c4
-rw-r--r--drivers/net/wireless/ath/ar5523/ar5523.c14
-rw-r--r--drivers/net/wireless/ath/ath5k/Makefile1
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/mac80211-ops.c4
-rw-r--r--drivers/net/wireless/ath/ath5k/trace.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c92
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_hw.c17
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h9
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/common.c19
-rw-r--r--drivers/net/wireless/ath/ath9k/common.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c43
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pri_detector.c49
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pri_detector.h27
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_beacon.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c15
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h13
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/link.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c19
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c170
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c137
-rw-r--r--drivers/net/wireless/ath/carl9170/debug.c4
-rw-r--r--drivers/net/wireless/ath/carl9170/mac.c8
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c9
-rw-r--r--drivers/net/wireless/ath/carl9170/phy.c4
-rw-r--r--drivers/net/wireless/ath/hw.c6
-rw-r--r--drivers/net/wireless/ath/reg.h4
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c29
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.h49
-rw-r--r--drivers/net/wireless/b43/b43.h2
-rw-r--r--drivers/net/wireless/b43/main.c8
-rw-r--r--drivers/net/wireless/b43/phy_ht.c124
-rw-r--r--drivers/net/wireless/b43/phy_ht.h6
-rw-r--r--drivers/net/wireless/b43/phy_lcn.c5
-rw-r--r--drivers/net/wireless/b43/phy_lp.c4
-rw-r--r--drivers/net/wireless/b43/phy_n.c710
-rw-r--r--drivers/net/wireless/b43/phy_n.h146
-rw-r--r--drivers/net/wireless/b43/radio_2059.c39
-rw-r--r--drivers/net/wireless/b43/radio_2059.h14
-rw-r--r--drivers/net/wireless/b43/tables_nphy.c97
-rw-r--r--drivers/net/wireless/b43/tables_nphy.h29
-rw-r--r--drivers/net/wireless/b43legacy/main.c9
-rw-r--r--drivers/net/wireless/brcm80211/Kconfig9
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/Makefile3
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c243
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c118
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/btcoex.c497
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/btcoex.h29
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd.h1
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c11
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c659
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c256
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/p2p.c98
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c369
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h101
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h32
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c197
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h14
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/Makefile11
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/channel.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c6
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmutil/Makefile9
-rw-r--r--drivers/net/wireless/brcm80211/brcmutil/d11.c162
-rw-r--r--drivers/net/wireless/brcm80211/brcmutil/utils.c12
-rw-r--r--drivers/net/wireless/brcm80211/include/brcm_hw_ids.h2
-rw-r--r--drivers/net/wireless/brcm80211/include/brcmu_d11.h145
-rw-r--r--drivers/net/wireless/brcm80211/include/chipcommon.h14
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c32
-rw-r--r--drivers/net/wireless/iwlegacy/3945-rs.c2
-rw-r--r--drivers/net/wireless/iwlegacy/4965-mac.c32
-rw-r--r--drivers/net/wireless/iwlegacy/4965-rs.c2
-rw-r--r--drivers/net/wireless/iwlegacy/4965.c2
-rw-r--r--drivers/net/wireless/iwlegacy/common.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/agn.h6
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/devices.c10
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/lib.c16
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c27
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rs.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rxon.c11
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/tx.c45
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/bt-coex.c333
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/d3.c9
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c119
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-power.h64
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h33
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c12
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c31
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h27
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power.c115
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c36
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.c8
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.c10
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c14
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/utils.c2
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/drv.c1
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/tx.c2
-rw-r--r--drivers/net/wireless/libertas_tf/main.c8
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c114
-rw-r--r--drivers/net/wireless/mwifiex/11ac.c2
-rw-r--r--drivers/net/wireless/mwifiex/11n_aggr.c14
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.c2
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c25
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c2
-rw-r--r--drivers/net/wireless/mwifiex/init.c21
-rw-r--r--drivers/net/wireless/mwifiex/main.h1
-rw-r--r--drivers/net/wireless/mwifiex/pcie.c4
-rw-r--r--drivers/net/wireless/mwifiex/scan.c37
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c17
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c160
-rw-r--r--drivers/net/wireless/mwifiex/wmm.h3
-rw-r--r--drivers/net/wireless/mwl8k.c46
-rw-r--r--drivers/net/wireless/p54/fwio.c4
-rw-r--r--drivers/net/wireless/p54/main.c4
-rw-r--r--drivers/net/wireless/p54/txrx.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c323
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c353
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c35
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c636
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c277
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c66
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h72
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c10
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00debug.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c24
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00firmware.c25
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00leds.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c17
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mmio.c52
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mmio.h52
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c14
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c47
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00soc.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c24
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c550
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c32
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/dev.c4
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/grf5101.c3
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/max2820.c2
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/rtl8225.c3
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/sa2400.c3
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/dev.c4
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/rtl8225.c3
-rw-r--r--drivers/net/wireless/rtlwifi/base.c8
-rw-r--r--drivers/net/wireless/rtlwifi/core.c6
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8188ee/hw.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8188ee/trx.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/trx.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/trx.c8
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/trx.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/trx.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/trx.c4
-rw-r--r--drivers/net/wireless/ti/wl1251/main.c5
-rw-r--r--drivers/net/wireless/ti/wl12xx/cmd.c2
-rw-r--r--drivers/net/wireless/ti/wl18xx/cmd.c6
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c4
-rw-r--r--drivers/nfc/Kconfig10
-rw-r--r--drivers/nfc/Makefile1
-rw-r--r--drivers/nfc/mei_phy.c164
-rw-r--r--drivers/nfc/mei_phy.h30
-rw-r--r--drivers/nfc/microread/Kconfig2
-rw-r--r--drivers/nfc/microread/mei.c139
-rw-r--r--drivers/nfc/pn533.c653
-rw-r--r--drivers/nfc/pn544/Kconfig13
-rw-r--r--drivers/nfc/pn544/Makefile2
-rw-r--r--drivers/nfc/pn544/mei.c121
-rw-r--r--include/linux/bcma/bcma.h1
-rw-r--r--include/linux/bcma/bcma_driver_chipcommon.h3
-rw-r--r--include/linux/bcma/bcma_regs.h1
-rw-r--r--include/linux/ieee80211.h73
-rw-r--r--include/linux/platform_data/brcmfmac-sdio.h124
-rw-r--r--include/net/bluetooth/bluetooth.h5
-rw-r--r--include/net/bluetooth/hci.h9
-rw-r--r--include/net/bluetooth/hci_core.h98
-rw-r--r--include/net/bluetooth/l2cap.h15
-rw-r--r--include/net/cfg80211.h38
-rw-r--r--include/net/mac80211.h127
-rw-r--r--include/net/nfc/nfc.h2
-rw-r--r--include/uapi/linux/nfc.h7
-rw-r--r--include/uapi/linux/nl80211.h39
-rw-r--r--include/uapi/linux/rfkill.h2
-rw-r--r--net/bluetooth/hci_conn.c38
-rw-r--r--net/bluetooth/hci_core.c239
-rw-r--r--net/bluetooth/hci_event.c184
-rw-r--r--net/bluetooth/hci_sysfs.c17
-rw-r--r--net/bluetooth/hidp/core.c992
-rw-r--r--net/bluetooth/hidp/hidp.h67
-rw-r--r--net/bluetooth/hidp/sock.c22
-rw-r--r--net/bluetooth/l2cap_core.c127
-rw-r--r--net/bluetooth/l2cap_sock.c6
-rw-r--r--net/bluetooth/mgmt.c17
-rw-r--r--net/bluetooth/sco.c49
-rw-r--r--net/bluetooth/smp.c2
-rw-r--r--net/mac80211/cfg.c57
-rw-r--r--net/mac80211/chan.c54
-rw-r--r--net/mac80211/debugfs_netdev.c11
-rw-r--r--net/mac80211/debugfs_sta.c2
-rw-r--r--net/mac80211/ibss.c146
-rw-r--r--net/mac80211/ieee80211_i.h49
-rw-r--r--net/mac80211/iface.c121
-rw-r--r--net/mac80211/main.c82
-rw-r--r--net/mac80211/mesh.c6
-rw-r--r--net/mac80211/mesh.h3
-rw-r--r--net/mac80211/mesh_hwmp.c28
-rw-r--r--net/mac80211/mesh_pathtbl.c56
-rw-r--r--net/mac80211/mesh_plink.c6
-rw-r--r--net/mac80211/mlme.c442
-rw-r--r--net/mac80211/offchannel.c6
-rw-r--r--net/mac80211/pm.c11
-rw-r--r--net/mac80211/rate.c324
-rw-r--r--net/mac80211/rc80211_minstrel.c206
-rw-r--r--net/mac80211/rc80211_minstrel.h7
-rw-r--r--net/mac80211/rc80211_minstrel_debugfs.c4
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c172
-rw-r--r--net/mac80211/rc80211_minstrel_ht.h2
-rw-r--r--net/mac80211/rx.c24
-rw-r--r--net/mac80211/scan.c13
-rw-r--r--net/mac80211/trace.h51
-rw-r--r--net/mac80211/tx.c153
-rw-r--r--net/mac80211/util.c103
-rw-r--r--net/nfc/core.c43
-rw-r--r--net/nfc/llcp/commands.c30
-rw-r--r--net/nfc/llcp/llcp.c127
-rw-r--r--net/nfc/llcp/llcp.h5
-rw-r--r--net/nfc/llcp/sock.c43
-rw-r--r--net/rfkill/core.c4
-rw-r--r--net/rfkill/rfkill-gpio.c7
-rw-r--r--net/wireless/core.h3
-rw-r--r--net/wireless/mlme.c5
-rw-r--r--net/wireless/nl80211.c285
-rw-r--r--net/wireless/rdev-ops.h24
-rw-r--r--net/wireless/reg.c2
-rw-r--r--net/wireless/trace.h35
-rw-r--r--net/wireless/util.c28
257 files changed, 9897 insertions, 5629 deletions
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 6aab00ef4379..11f467c00d0a 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -90,6 +90,7 @@ static struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x13d3, 0x3393) },
{ USB_DEVICE(0x0489, 0xe04e) },
{ USB_DEVICE(0x0489, 0xe056) },
+ { USB_DEVICE(0x0489, 0xe04d) },
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE02C) },
@@ -126,6 +127,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU22 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 2cc5f774a29c..3d684d20b584 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -148,6 +148,7 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
@@ -926,6 +927,22 @@ static void btusb_waker(struct work_struct *work)
usb_autopm_put_interface(data->intf);
}
+static int btusb_setup_bcm92035(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+ u8 val = 0x00;
+
+ BT_DBG("%s", hdev->name);
+
+ skb = __hci_cmd_sync(hdev, 0xfc3b, 1, &val, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb))
+ BT_ERR("BCM92035 command failed (%ld)", -PTR_ERR(skb));
+ else
+ kfree_skb(skb);
+
+ return 0;
+}
+
static int btusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -1022,11 +1039,14 @@ static int btusb_probe(struct usb_interface *intf,
SET_HCIDEV_DEV(hdev, &intf->dev);
- hdev->open = btusb_open;
- hdev->close = btusb_close;
- hdev->flush = btusb_flush;
- hdev->send = btusb_send_frame;
- hdev->notify = btusb_notify;
+ hdev->open = btusb_open;
+ hdev->close = btusb_close;
+ hdev->flush = btusb_flush;
+ hdev->send = btusb_send_frame;
+ hdev->notify = btusb_notify;
+
+ if (id->driver_info & BTUSB_BCM92035)
+ hdev->setup = btusb_setup_bcm92035;
/* Interface numbers are hardcoded in the specification */
data->isoc = usb_ifnum_to_if(data->udev, 1);
@@ -1065,17 +1085,6 @@ static int btusb_probe(struct usb_interface *intf,
data->isoc = NULL;
}
- if (id->driver_info & BTUSB_BCM92035) {
- unsigned char cmd[] = { 0x3b, 0xfc, 0x01, 0x00 };
- struct sk_buff *skb;
-
- skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
- if (skb) {
- memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd));
- skb_queue_tail(&hdev->driver_init, skb);
- }
- }
-
if (data->isoc) {
err = usb_driver_claim_interface(&btusb_driver,
data->isoc, data);
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index c60623f206d4..8ae9f1ea2bb5 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -153,6 +153,9 @@ static int h4_recv(struct hci_uart *hu, void *data, int count)
{
int ret;
+ if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
+ return -EUNATCH;
+
ret = hci_recv_stream_fragment(hu->hdev, data, count);
if (ret < 0) {
BT_ERR("Frame Reassembly Failed");
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index ed0fade46aed..bc68a440d432 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -260,12 +260,12 @@ static int hci_uart_send_frame(struct sk_buff *skb)
/* ------ LDISC part ------ */
/* hci_uart_tty_open
- *
+ *
* Called when line discipline changed to HCI_UART.
*
* Arguments:
* tty pointer to tty info structure
- * Return Value:
+ * Return Value:
* 0 if success, otherwise error code
*/
static int hci_uart_tty_open(struct tty_struct *tty)
@@ -365,15 +365,15 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
}
/* hci_uart_tty_receive()
- *
+ *
* Called by tty low level driver when receive data is
* available.
- *
+ *
* Arguments: tty pointer to tty isntance data
* data pointer to received data
* flags pointer to flags for data
* count count of received data in bytes
- *
+ *
* Return Value: None
*/
static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
@@ -388,7 +388,10 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f
spin_lock(&hu->rx_lock);
hu->proto->recv(hu, (void *) data, count);
- hu->hdev->stat.byte_rx += count;
+
+ if (hu->hdev)
+ hu->hdev->stat.byte_rx += count;
+
spin_unlock(&hu->rx_lock);
tty_unthrottle(tty);
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index 3d339e04efb7..f9a24e599dee 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -1293,7 +1293,8 @@ static int adm8211_config(struct ieee80211_hw *dev, u32 changed)
{
struct adm8211_priv *priv = dev->priv;
struct ieee80211_conf *conf = &dev->conf;
- int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ int channel =
+ ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
if (channel != priv->channel) {
priv->channel = channel;
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index 5ac5f7ae2721..34c8a33cac06 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -1943,12 +1943,12 @@ static int at76_config(struct ieee80211_hw *hw, u32 changed)
struct at76_priv *priv = hw->priv;
at76_dbg(DBG_MAC80211, "%s(): channel %d",
- __func__, hw->conf.channel->hw_value);
+ __func__, hw->conf.chandef.chan->hw_value);
at76_dbg_dump(DBG_MAC80211, priv->bssid, ETH_ALEN, "bssid:");
mutex_lock(&priv->mtx);
- priv->channel = hw->conf.channel->hw_value;
+ priv->channel = hw->conf.chandef.chan->hw_value;
if (is_valid_ether_addr(priv->bssid))
at76_join(priv);
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c
index afd1e36d308f..17d7fece35d2 100644
--- a/drivers/net/wireless/ath/ar5523/ar5523.c
+++ b/drivers/net/wireless/ath/ar5523/ar5523.c
@@ -457,14 +457,14 @@ static int ar5523_set_chan(struct ar5523 *ar)
memset(&reset, 0, sizeof(reset));
reset.flags |= cpu_to_be32(UATH_CHAN_2GHZ);
reset.flags |= cpu_to_be32(UATH_CHAN_OFDM);
- reset.freq = cpu_to_be32(conf->channel->center_freq);
+ reset.freq = cpu_to_be32(conf->chandef.chan->center_freq);
reset.maxrdpower = cpu_to_be32(50); /* XXX */
reset.channelchange = cpu_to_be32(1);
reset.keeprccontent = cpu_to_be32(0);
ar5523_dbg(ar, "set chan flags 0x%x freq %d\n",
be32_to_cpu(reset.flags),
- conf->channel->center_freq);
+ conf->chandef.chan->center_freq);
return ar5523_cmd_write(ar, WDCMSG_RESET, &reset, sizeof(reset), 0);
}
@@ -594,7 +594,7 @@ static void ar5523_data_rx_cb(struct urb *urb)
rx_status = IEEE80211_SKB_RXCB(data->skb);
memset(rx_status, 0, sizeof(*rx_status));
rx_status->freq = be32_to_cpu(desc->channel);
- rx_status->band = hw->conf.channel->band;
+ rx_status->band = hw->conf.chandef.chan->band;
rx_status->signal = -95 + be32_to_cpu(desc->rssi);
ieee80211_rx_irqsafe(hw, data->skb);
@@ -1153,13 +1153,13 @@ static int ar5523_get_wlan_mode(struct ar5523 *ar,
struct ieee80211_sta *sta;
u32 sta_rate_set;
- band = ar->hw->wiphy->bands[ar->hw->conf.channel->band];
+ band = ar->hw->wiphy->bands[ar->hw->conf.chandef.chan->band];
sta = ieee80211_find_sta(ar->vif, bss_conf->bssid);
if (!sta) {
ar5523_info(ar, "STA not found!\n");
return WLAN_MODE_11b;
}
- sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band];
+ sta_rate_set = sta->supp_rates[ar->hw->conf.chandef.chan->band];
for (bit = 0; bit < band->n_bitrates; bit++) {
if (sta_rate_set & 1) {
@@ -1197,11 +1197,11 @@ static void ar5523_create_rateset(struct ar5523 *ar,
ar5523_info(ar, "STA not found. Cannot set rates\n");
sta_rate_set = bss_conf->basic_rates;
} else
- sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band];
+ sta_rate_set = sta->supp_rates[ar->hw->conf.chandef.chan->band];
ar5523_dbg(ar, "sta rate_set = %08x\n", sta_rate_set);
- band = ar->hw->wiphy->bands[ar->hw->conf.channel->band];
+ band = ar->hw->wiphy->bands[ar->hw->conf.chandef.chan->band];
for (bit = 0; bit < band->n_bitrates; bit++) {
BUG_ON(i >= AR5523_MAX_NRATES);
ar5523_dbg(ar, "Considering rate %d : %d\n",
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile
index f60b3899afc4..1b3a34f7f224 100644
--- a/drivers/net/wireless/ath/ath5k/Makefile
+++ b/drivers/net/wireless/ath/ath5k/Makefile
@@ -10,6 +10,7 @@ ath5k-y += phy.o
ath5k-y += reset.o
ath5k-y += attach.o
ath5k-y += base.o
+CFLAGS_base.o += -I$(src)
ath5k-y += led.o
ath5k-y += rfkill.o
ath5k-y += ani.o
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 1d264c0f5a9b..9b20d9ee2719 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2639,7 +2639,7 @@ int ath5k_start(struct ieee80211_hw *hw)
* be followed by initialization of the appropriate bits
* and then setup of the interrupt mask.
*/
- ah->curchan = ah->hw->conf.channel;
+ ah->curchan = ah->hw->conf.chandef.chan;
ah->imask = AR5K_INT_RXOK
| AR5K_INT_RXERR
| AR5K_INT_RXEOL
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 4264341533ea..06f86f435711 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -202,7 +202,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock(&ah->lock);
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
- ret = ath5k_chan_set(ah, conf->channel);
+ ret = ath5k_chan_set(ah, conf->chandef.chan);
if (ret < 0)
goto unlock;
}
@@ -678,7 +678,7 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
memcpy(survey, &ah->survey, sizeof(*survey));
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->noise = ah->ah_noise_floor;
survey->filled = SURVEY_INFO_NOISE_DBM |
SURVEY_INFO_CHANNEL_TIME |
diff --git a/drivers/net/wireless/ath/ath5k/trace.h b/drivers/net/wireless/ath/ath5k/trace.h
index 00f015819344..c6eef519bb61 100644
--- a/drivers/net/wireless/ath/ath5k/trace.h
+++ b/drivers/net/wireless/ath/ath5k/trace.h
@@ -97,7 +97,7 @@ TRACE_EVENT(ath5k_tx_complete,
#if defined(CONFIG_ATH5K_TRACER) && !defined(__CHECKER__)
#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH ../../drivers/net/wireless/ath/ath5k
+#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE trace
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index fd69376ecc83..391da5ad6a99 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -18,6 +18,7 @@
#include "hw-ops.h"
#include "../regd.h"
#include "ar9002_phy.h"
+#include "ar5008_initvals.h"
/* All code below is for AR5008, AR9001, AR9002 */
@@ -43,23 +44,16 @@ static const int m2ThreshLowExt_off = 127;
static const int m1ThreshExt_off = 127;
static const int m2ThreshExt_off = 127;
+static const struct ar5416IniArray bank0 = STATIC_INI_ARRAY(ar5416Bank0);
+static const struct ar5416IniArray bank1 = STATIC_INI_ARRAY(ar5416Bank1);
+static const struct ar5416IniArray bank2 = STATIC_INI_ARRAY(ar5416Bank2);
+static const struct ar5416IniArray bank3 = STATIC_INI_ARRAY(ar5416Bank3);
+static const struct ar5416IniArray bank7 = STATIC_INI_ARRAY(ar5416Bank7);
-static void ar5008_rf_bank_setup(u32 *bank, struct ar5416IniArray *array,
- int col)
-{
- int i;
-
- for (i = 0; i < array->ia_rows; i++)
- bank[i] = INI_RA(array, i, col);
-}
-
-
-#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) \
- ar5008_write_rf_array(ah, iniarray, regData, &(regWr))
-
-static void ar5008_write_rf_array(struct ath_hw *ah, struct ar5416IniArray *array,
- u32 *data, unsigned int *writecnt)
+static void ar5008_write_bank6(struct ath_hw *ah, unsigned int *writecnt)
{
+ struct ar5416IniArray *array = &ah->iniBank6;
+ u32 *data = ah->analogBank6Data;
int r;
ENABLE_REGWRITE_BUFFER(ah);
@@ -165,7 +159,7 @@ static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq)
ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3);
/* write Bank 6 with new params */
- REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes);
+ ar5008_write_bank6(ah, &reg_writes);
}
/**
@@ -469,31 +463,16 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah,
*/
static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah)
{
-#define ATH_ALLOC_BANK(bank, size) do { \
- bank = devm_kzalloc(ah->dev, sizeof(u32) * size, GFP_KERNEL); \
- if (!bank) \
- goto error; \
- } while (0);
-
- struct ath_common *common = ath9k_hw_common(ah);
+ int size = ah->iniBank6.ia_rows * sizeof(u32);
if (AR_SREV_9280_20_OR_LATER(ah))
return 0;
- ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows);
- ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows);
- ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows);
- ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows);
- ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows);
- ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows);
- ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows);
- ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows);
+ ah->analogBank6Data = devm_kzalloc(ah->dev, size, GFP_KERNEL);
+ if (!ah->analogBank6Data)
+ return -ENOMEM;
return 0;
-#undef ATH_ALLOC_BANK
-error:
- ath_err(common, "Cannot allocate RF banks\n");
- return -ENOMEM;
}
@@ -517,6 +496,7 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
u32 ob5GHz = 0, db5GHz = 0;
u32 ob2GHz = 0, db2GHz = 0;
int regWrites = 0;
+ int i;
/*
* Software does not need to program bank data
@@ -529,25 +509,8 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
/* Setup rf parameters */
eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV);
- /* Setup Bank 0 Write */
- ar5008_rf_bank_setup(ah->analogBank0Data, &ah->iniBank0, 1);
-
- /* Setup Bank 1 Write */
- ar5008_rf_bank_setup(ah->analogBank1Data, &ah->iniBank1, 1);
-
- /* Setup Bank 2 Write */
- ar5008_rf_bank_setup(ah->analogBank2Data, &ah->iniBank2, 1);
-
- /* Setup Bank 6 Write */
- ar5008_rf_bank_setup(ah->analogBank3Data, &ah->iniBank3,
- modesIndex);
- {
- int i;
- for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) {
- ah->analogBank6Data[i] =
- INI_RA(&ah->iniBank6TPC, i, modesIndex);
- }
- }
+ for (i = 0; i < ah->iniBank6.ia_rows; i++)
+ ah->analogBank6Data[i] = INI_RA(&ah->iniBank6, i, modesIndex);
/* Only the 5 or 2 GHz OB/DB need to be set for a mode */
if (eepMinorRev >= 2) {
@@ -568,22 +531,13 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
}
}
- /* Setup Bank 7 Setup */
- ar5008_rf_bank_setup(ah->analogBank7Data, &ah->iniBank7, 1);
-
/* Write Analog registers */
- REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data,
- regWrites);
- REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data,
- regWrites);
- REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data,
- regWrites);
- REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data,
- regWrites);
- REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data,
- regWrites);
- REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data,
- regWrites);
+ REG_WRITE_ARRAY(&bank0, 1, regWrites);
+ REG_WRITE_ARRAY(&bank1, 1, regWrites);
+ REG_WRITE_ARRAY(&bank2, 1, regWrites);
+ REG_WRITE_ARRAY(&bank3, modesIndex, regWrites);
+ ar5008_write_bank6(ah, &regWrites);
+ REG_WRITE_ARRAY(&bank7, 1, regWrites);
return true;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index f053d978540e..830daa12feb6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -67,12 +67,10 @@ static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
} else if (AR_SREV_9100_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100);
- INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100);
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100);
} else {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common);
- INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC);
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac);
}
@@ -80,20 +78,11 @@ static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
/* Common for AR5416, AR913x, AR9160 */
INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain);
- INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0);
- INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1);
- INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2);
- INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3);
- INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7);
-
- /* Common for AR5416, AR9160 */
- if (!AR_SREV_9100(ah))
- INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6);
-
/* Common for AR913x, AR9160 */
if (!AR_SREV_5416(ah))
- INIT_INI_ARRAY(&ah->iniBank6TPC,
- ar5416Bank6TPC_9100);
+ INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC_9100);
+ else
+ INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC);
}
/* iniAddac needs to be modified for these chips */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index a56b2416e2f9..8a1888d02070 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -234,6 +234,7 @@ struct ath_buf {
dma_addr_t bf_daddr; /* physical addr of desc */
dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
bool bf_stale;
+ struct ieee80211_tx_rate rates[4];
struct ath_buf_state bf_state;
};
@@ -311,6 +312,7 @@ struct ath_rx_edma {
struct ath_rx {
u8 defant;
u8 rxotherant;
+ bool discard_next;
u32 *rxlink;
u32 num_pkts;
unsigned int rxfilter;
@@ -657,11 +659,10 @@ enum sc_op_flags {
struct ath_rate_table;
struct ath9k_vif_iter_data {
- const u8 *hw_macaddr; /* phy's hardware address, set
- * before starting iteration for
- * valid bssid mask.
- */
+ u8 hw_macaddr[ETH_ALEN]; /* address of the first vif */
u8 mask[ETH_ALEN]; /* bssid mask */
+ bool has_hw_macaddr;
+
int naps; /* number of AP vifs */
int nmeshes; /* number of mesh vifs */
int nstations; /* number of station vifs */
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 5f05c26d1ec4..2ff570f7f8ff 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -79,7 +79,7 @@ static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
u8 chainmask = ah->txchainmask;
u8 rate = 0;
- sband = &sc->sbands[common->hw->conf.channel->band];
+ sband = &sc->sbands[common->hw->conf.chandef.chan->band];
rate = sband->bitrates[rateidx].hw_value;
if (vif->bss_conf.use_short_preamble)
rate |= sband->bitrates[rateidx].hw_value_short;
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 7bdd726c7a8f..7304e7585009 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -208,7 +208,7 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
return true;
ath_dbg(common, CALIBRATE, "Resetting Cal %d state for channel %u\n",
- currCal->calData->calType, conf->channel->center_freq);
+ currCal->calData->calType, conf->chandef.chan->center_freq);
ah->caldata->CalValid &= ~currCal->calData->calType;
currCal->calState = CAL_WAITING;
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index 60dcb6c22db9..3d70b8c2bcdd 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -33,6 +33,12 @@ struct ar5416IniArray {
u32 ia_columns;
};
+#define STATIC_INI_ARRAY(array) { \
+ .ia_array = (u32 *)(array), \
+ .ia_rows = ARRAY_SIZE(array), \
+ .ia_columns = ARRAY_SIZE(array[0]), \
+ }
+
#define INIT_INI_ARRAY(iniarray, array) do { \
(iniarray)->ia_array = (u32 *)(array); \
(iniarray)->ia_rows = ARRAY_SIZE(array); \
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index 905f1b313961..344fdde1d7a3 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -27,20 +27,6 @@ MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
MODULE_LICENSE("Dual BSD/GPL");
-int ath9k_cmn_padpos(__le16 frame_control)
-{
- int padpos = 24;
- if (ieee80211_has_a4(frame_control)) {
- padpos += ETH_ALEN;
- }
- if (ieee80211_is_data_qos(frame_control)) {
- padpos += IEEE80211_QOS_CTL_LEN;
- }
-
- return padpos;
-}
-EXPORT_SYMBOL(ath9k_cmn_padpos);
-
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -133,13 +119,14 @@ EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
struct ath_hw *ah)
{
- struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
struct ath9k_channel *channel;
u8 chan_idx;
chan_idx = curchan->hw_value;
channel = &ah->channels[chan_idx];
- ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type);
+ ath9k_cmn_update_ichannel(channel, curchan,
+ cfg80211_get_chandef_type(&hw->conf.chandef));
return channel;
}
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index 6102476a65de..207d06995b15 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -42,7 +42,6 @@
#define ATH_EP_RND(x, mul) \
(((x) + ((mul)/2)) / (mul))
-int ath9k_cmn_padpos(__le16 frame_control);
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
struct ieee80211_channel *chan,
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c
index 508f8b33f0ef..7187d3671512 100644
--- a/drivers/net/wireless/ath/ath9k/dfs.c
+++ b/drivers/net/wireless/ath/ath9k/dfs.c
@@ -55,12 +55,6 @@ ath9k_postprocess_radar_event(struct ath_softc *sc,
u8 rssi;
u16 dur;
- ath_dbg(ath9k_hw_common(sc->sc_ah), DFS,
- "pulse_bw_info=0x%x, pri,ext len/rssi=(%u/%u, %u/%u)\n",
- ard->pulse_bw_info,
- ard->pulse_length_pri, ard->rssi,
- ard->pulse_length_ext, ard->ext_rssi);
-
/*
* Only the last 2 bits of the BW info are relevant, they indicate
* which channel the radar was detected in.
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
index 73fe8d6db566..491305c81fce 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
@@ -19,6 +19,7 @@
#include "dfs_pattern_detector.h"
#include "dfs_pri_detector.h"
+#include "ath9k.h"
/*
* tolerated deviation of radar time stamp in usecs on both sides
@@ -142,6 +143,7 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
{
u32 sz, i;
struct channel_detector *cd;
+ struct ath_common *common = ath9k_hw_common(dpd->ah);
cd = kmalloc(sizeof(*cd), GFP_ATOMIC);
if (cd == NULL)
@@ -165,7 +167,8 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
return cd;
fail:
- pr_err("failed to allocate channel_detector for freq=%d\n", freq);
+ ath_dbg(common, DFS,
+ "failed to allocate channel_detector for freq=%d\n", freq);
channel_detector_exit(dpd, cd);
return NULL;
}
@@ -216,34 +219,34 @@ static bool
dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event)
{
u32 i;
- bool ts_wraparound;
struct channel_detector *cd;
- if (dpd->region == NL80211_DFS_UNSET) {
- /*
- * pulses received for a non-supported or un-initialized
- * domain are treated as detected radars
- */
+ /*
+ * pulses received for a non-supported or un-initialized
+ * domain are treated as detected radars for fail-safety
+ */
+ if (dpd->region == NL80211_DFS_UNSET)
return true;
- }
cd = channel_detector_get(dpd, event->freq);
if (cd == NULL)
return false;
- ts_wraparound = (event->ts < dpd->last_pulse_ts);
dpd->last_pulse_ts = event->ts;
- if (ts_wraparound) {
- /*
- * reset detector on time stamp wraparound
- * with monotonic time stamps, this should never happen
- */
- pr_warn("DFS: time stamp wraparound detected, resetting\n");
+ /* reset detector on time stamp wraparound, caused by TSF reset */
+ if (event->ts < dpd->last_pulse_ts)
dpd_reset(dpd);
- }
+
/* do type individual pattern matching */
for (i = 0; i < dpd->num_radar_types; i++) {
- if (cd->detectors[i]->add_pulse(cd->detectors[i], event) != 0) {
+ struct pri_detector *pd = cd->detectors[i];
+ struct pri_sequence *ps = pd->add_pulse(pd, event);
+ if (ps != NULL) {
+ ath_dbg(ath9k_hw_common(dpd->ah), DFS,
+ "DFS: radar found on freq=%d: id=%d, pri=%d, "
+ "count=%d, count_false=%d\n",
+ event->freq, pd->rs->type_id,
+ ps->pri, ps->count, ps->count_falses);
channel_detector_reset(dpd, cd);
return true;
}
@@ -285,9 +288,10 @@ static struct dfs_pattern_detector default_dpd = {
};
struct dfs_pattern_detector *
-dfs_pattern_detector_init(enum nl80211_dfs_regions region)
+dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region)
{
struct dfs_pattern_detector *dpd;
+ struct ath_common *common = ath9k_hw_common(ah);
dpd = kmalloc(sizeof(*dpd), GFP_KERNEL);
if (dpd == NULL)
@@ -296,10 +300,11 @@ dfs_pattern_detector_init(enum nl80211_dfs_regions region)
*dpd = default_dpd;
INIT_LIST_HEAD(&dpd->channel_detectors);
+ dpd->ah = ah;
if (dpd->set_dfs_domain(dpd, region))
return dpd;
- pr_err("Could not set DFS domain to %d. ", region);
+ ath_dbg(common, DFS,"Could not set DFS domain to %d", region);
kfree(dpd);
return NULL;
}
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
index cda52f39f28a..90a5abcc4265 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
+++ b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
@@ -80,6 +80,8 @@ struct dfs_pattern_detector {
enum nl80211_dfs_regions region;
u8 num_radar_types;
u64 last_pulse_ts;
+ /* needed for ath_dbg() */
+ struct ath_hw *ah;
const struct radar_detector_specs *radar_spec;
struct list_head channel_detectors;
@@ -92,10 +94,10 @@ struct dfs_pattern_detector {
*/
#if defined(CONFIG_ATH9K_DFS_CERTIFIED)
extern struct dfs_pattern_detector *
-dfs_pattern_detector_init(enum nl80211_dfs_regions region);
+dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region);
#else
static inline struct dfs_pattern_detector *
-dfs_pattern_detector_init(enum nl80211_dfs_regions region)
+dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region)
{
return NULL;
}
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
index 5e48c5515b8c..5ba4b6fe37c0 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
@@ -23,28 +23,6 @@
#include "dfs_debug.h"
/**
- * struct pri_sequence - sequence of pulses matching one PRI
- * @head: list_head
- * @pri: pulse repetition interval (PRI) in usecs
- * @dur: duration of sequence in usecs
- * @count: number of pulses in this sequence
- * @count_falses: number of not matching pulses in this sequence
- * @first_ts: time stamp of first pulse in usecs
- * @last_ts: time stamp of last pulse in usecs
- * @deadline_ts: deadline when this sequence becomes invalid (first_ts + dur)
- */
-struct pri_sequence {
- struct list_head head;
- u32 pri;
- u32 dur;
- u32 count;
- u32 count_falses;
- u64 first_ts;
- u64 last_ts;
- u64 deadline_ts;
-};
-
-/**
* struct pulse_elem - elements in pulse queue
* @ts: time stamp in usecs
*/
@@ -393,8 +371,8 @@ static void pri_detector_exit(struct pri_detector *de)
kfree(de);
}
-static bool pri_detector_add_pulse(struct pri_detector *de,
- struct pulse_event *event)
+static struct pri_sequence *pri_detector_add_pulse(struct pri_detector *de,
+ struct pulse_event *event)
{
u32 max_updated_seq;
struct pri_sequence *ps;
@@ -403,38 +381,33 @@ static bool pri_detector_add_pulse(struct pri_detector *de,
/* ignore pulses not within width range */
if ((rs->width_min > event->width) || (rs->width_max < event->width))
- return false;
+ return NULL;
if ((ts - de->last_ts) < rs->max_pri_tolerance)
/* if delta to last pulse is too short, don't use this pulse */
- return false;
+ return NULL;
de->last_ts = ts;
max_updated_seq = pseq_handler_add_to_existing_seqs(de, ts);
if (!pseq_handler_create_sequences(de, ts, max_updated_seq)) {
- pr_err("failed to create pulse sequences\n");
pri_detector_reset(de, ts);
return false;
}
ps = pseq_handler_check_detection(de);
- if (ps != NULL) {
- pr_info("DFS: radar found: pri=%d, count=%d, count_false=%d\n",
- ps->pri, ps->count, ps->count_falses);
- pri_detector_reset(de, ts);
- return true;
- }
- pulse_queue_enqueue(de, ts);
- return false;
+ if (ps == NULL)
+ pulse_queue_enqueue(de, ts);
+
+ return ps;
}
-struct pri_detector *
-pri_detector_init(const struct radar_detector_specs *rs)
+struct pri_detector *pri_detector_init(const struct radar_detector_specs *rs)
{
struct pri_detector *de;
- de = kzalloc(sizeof(*de), GFP_KERNEL);
+
+ de = kzalloc(sizeof(*de), GFP_ATOMIC);
if (de == NULL)
return NULL;
de->exit = pri_detector_exit;
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h
index 81cde9f28e44..723962d1abc6 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h
+++ b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h
@@ -20,9 +20,31 @@
#include <linux/list.h>
/**
+ * struct pri_sequence - sequence of pulses matching one PRI
+ * @head: list_head
+ * @pri: pulse repetition interval (PRI) in usecs
+ * @dur: duration of sequence in usecs
+ * @count: number of pulses in this sequence
+ * @count_falses: number of not matching pulses in this sequence
+ * @first_ts: time stamp of first pulse in usecs
+ * @last_ts: time stamp of last pulse in usecs
+ * @deadline_ts: deadline when this sequence becomes invalid (first_ts + dur)
+ */
+struct pri_sequence {
+ struct list_head head;
+ u32 pri;
+ u32 dur;
+ u32 count;
+ u32 count_falses;
+ u64 first_ts;
+ u64 last_ts;
+ u64 deadline_ts;
+};
+
+/**
* struct pri_detector - PRI detector element for a dedicated radar type
* @exit(): destructor
- * @add_pulse(): add pulse event, returns true if pattern was detected
+ * @add_pulse(): add pulse event, returns pri_sequence if pattern was detected
* @reset(): clear states and reset to given time stamp
* @rs: detector specs for this detector element
* @last_ts: last pulse time stamp considered for this element in usecs
@@ -34,7 +56,8 @@
*/
struct pri_detector {
void (*exit) (struct pri_detector *de);
- bool (*add_pulse)(struct pri_detector *de, struct pulse_event *e);
+ struct pri_sequence *
+ (*add_pulse)(struct pri_detector *de, struct pulse_event *e);
void (*reset) (struct pri_detector *de, u64 ts);
/* private: internal use only */
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index d0ce1f5bba10..f13f458dd656 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -308,7 +308,7 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv,
while(skb) {
hdr = (struct ieee80211_hdr *) skb->data;
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(hdr->frame_control);
padsize = padpos & 3;
if (padsize && skb->len > padpos) {
if (skb_headroom(skb) < padsize) {
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index a8016d70088a..0743a47cef8f 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -190,7 +190,7 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)
{
struct ath_hw *ah = priv->ah;
struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_channel *channel = priv->hw->conf.channel;
+ struct ieee80211_channel *channel = priv->hw->conf.chandef.chan;
struct ath9k_hw_cal_data *caldata = NULL;
enum htc_phymode mode;
__be16 htc_mode;
@@ -250,7 +250,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &common->hw->conf;
bool fastcc;
- struct ieee80211_channel *channel = hw->conf.channel;
+ struct ieee80211_channel *channel = hw->conf.chandef.chan;
struct ath9k_hw_cal_data *caldata = NULL;
enum htc_phymode mode;
__be16 htc_mode;
@@ -602,7 +602,7 @@ static void ath9k_htc_setup_rate(struct ath9k_htc_priv *priv,
u32 caps = 0;
int i, j;
- sband = priv->hw->wiphy->bands[priv->hw->conf.channel->band];
+ sband = priv->hw->wiphy->bands[priv->hw->conf.chandef.chan->band];
for (i = 0, j = 0; i < sband->n_bitrates; i++) {
if (sta->supp_rates[sband->band] & BIT(i)) {
@@ -866,7 +866,7 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw,
hdr = (struct ieee80211_hdr *) skb->data;
/* Add the padding after the header if this is not already done */
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(hdr->frame_control);
padsize = padpos & 3;
if (padsize && skb->len > padpos) {
if (skb_headroom(skb) < padsize) {
@@ -904,7 +904,7 @@ static int ath9k_htc_start(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);
- struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
struct ath9k_channel *init_channel;
int ret = 0;
enum htc_phymode mode;
@@ -1193,15 +1193,17 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
}
if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || chip_reset) {
- struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&hw->conf.chandef);
int pos = curchan->hw_value;
ath_dbg(common, CONFIG, "Set channel: %d MHz\n",
curchan->center_freq);
ath9k_cmn_update_ichannel(&priv->ah->channels[pos],
- hw->conf.channel,
- hw->conf.channel_type);
+ hw->conf.chandef.chan,
+ channel_type);
if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
ath_err(common, "Unable to set channel\n");
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index bd8251c1c749..6bd0e92ea2aa 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -490,7 +490,7 @@ static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv,
if (txs->ts_flags & ATH9K_HTC_TXSTAT_SGI)
rate->flags |= IEEE80211_TX_RC_SHORT_GI;
} else {
- if (cur_conf->channel->band == IEEE80211_BAND_5GHZ)
+ if (cur_conf->chandef.chan->band == IEEE80211_BAND_5GHZ)
rate->idx += 4; /* No CCK rates */
}
@@ -939,7 +939,7 @@ static void ath9k_process_rate(struct ieee80211_hw *hw,
return;
}
- band = hw->conf.channel->band;
+ band = hw->conf.chandef.chan->band;
sband = hw->wiphy->bands[band];
for (i = 0; i < sband->n_bitrates; i++) {
@@ -966,7 +966,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
struct sk_buff *skb = rxbuf->skb;
struct ath_common *common = ath9k_hw_common(priv->ah);
struct ath_htc_rx_status *rxstatus;
- int hdrlen, padpos, padsize;
+ int hdrlen, padsize;
int last_rssi = ATH_RSSI_DUMMY_MARKER;
__le16 fc;
@@ -996,11 +996,9 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
fc = hdr->frame_control;
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
- padpos = ath9k_cmn_padpos(fc);
-
- padsize = padpos & 3;
- if (padsize && skb->len >= padpos+padsize+FCS_LEN) {
- memmove(skb->data + padsize, skb->data, padpos);
+ padsize = hdrlen & 3;
+ if (padsize && skb->len >= hdrlen+padsize+FCS_LEN) {
+ memmove(skb->data + padsize, skb->data, hdrlen);
skb_pull(skb, padsize);
}
@@ -1082,8 +1080,8 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
}
rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
- rx_status->band = hw->conf.channel->band;
- rx_status->freq = hw->conf.channel->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
rx_status->antenna = rxbuf->rxstatus.rs_antenna;
rx_status->flag |= RX_FLAG_MACTIME_END;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 3473a797651a..7f25da8444fe 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -139,7 +139,7 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah)
clockrate = 117;
else if (!ah->curchan) /* should really check for CCK instead */
clockrate = ATH9K_CLOCK_RATE_CCK;
- else if (conf->channel->band == IEEE80211_BAND_2GHZ)
+ else if (conf->chandef.chan->band == IEEE80211_BAND_2GHZ)
clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
@@ -1100,7 +1100,8 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
}
/* As defined by IEEE 802.11-2007 17.3.8.6 */
- acktimeout = slottime + sifstime + 3 * ah->coverage_class + ack_offset;
+ slottime += 3 * ah->coverage_class;
+ acktimeout = slottime + sifstime + ack_offset;
ctstimeout = acktimeout;
/*
@@ -1110,7 +1111,8 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
* BA frames in some implementations, but it has been found to fix ACK
* timeout issues in other cases as well.
*/
- if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ &&
+ if (conf->chandef.chan &&
+ conf->chandef.chan->band == IEEE80211_BAND_2GHZ &&
!IS_CHAN_HALF_RATE(chan) && !IS_CHAN_QUARTER_RATE(chan)) {
acktimeout += 64 - sifstime - ah->slottime;
ctstimeout += 48 - sifstime - ah->slottime;
@@ -1697,12 +1699,11 @@ static void ath9k_hw_reset_opmode(struct ath_hw *ah,
ENABLE_REGWRITE_BUFFER(ah);
- REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
- REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4)
- | macStaId1
+ REG_RMW(ah, AR_STA_ID1, macStaId1
| AR_STA_ID1_RTS_USE_DEF
| (ah->config.ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
- | ah->sta_id1_defaults);
+ | ah->sta_id1_defaults,
+ ~AR_STA_ID1_SADH_MASK);
ath_hw_setbssidmask(common);
REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
ath9k_hw_write_associd(ah);
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 30e62d92d46d..ae3034374bc4 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -847,14 +847,7 @@ struct ath_hw {
struct ath_hw_ops ops;
/* Used to program the radio on non single-chip devices */
- u32 *analogBank0Data;
- u32 *analogBank1Data;
- u32 *analogBank2Data;
- u32 *analogBank3Data;
u32 *analogBank6Data;
- u32 *analogBank6TPCData;
- u32 *analogBank7Data;
- u32 *bank6Temp;
int coverage_class;
u32 slottime;
@@ -885,14 +878,8 @@ struct ath_hw {
struct ar5416IniArray iniModes;
struct ar5416IniArray iniCommon;
- struct ar5416IniArray iniBank0;
struct ar5416IniArray iniBB_RfGain;
- struct ar5416IniArray iniBank1;
- struct ar5416IniArray iniBank2;
- struct ar5416IniArray iniBank3;
struct ar5416IniArray iniBank6;
- struct ar5416IniArray iniBank6TPC;
- struct ar5416IniArray iniBank7;
struct ar5416IniArray iniAddac;
struct ar5416IniArray iniPcieSerdes;
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 3be2eb0da84a..0237b2868961 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -577,7 +577,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
atomic_set(&ah->intr_ref_cnt, -1);
sc->sc_ah = ah;
- sc->dfs_detector = dfs_pattern_detector_init(NL80211_DFS_UNSET);
+ sc->dfs_detector = dfs_pattern_detector_init(ah, NL80211_DFS_UNSET);
if (!pdata) {
ah->ah_flags |= AH_USE_EEPROM;
@@ -766,7 +766,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK |
IEEE80211_HW_SPECTRUM_MGMT |
- IEEE80211_HW_REPORTS_TX_ACK_STATUS;
+ IEEE80211_HW_REPORTS_TX_ACK_STATUS |
+ IEEE80211_HW_SUPPORTS_RC_TABLE;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index 7fdac6c7b3ea..849259b07370 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -214,7 +214,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
txctl.txq = sc->tx.txq_map[IEEE80211_AC_BE];
memset(tx_info, 0, sizeof(*tx_info));
- tx_info->band = hw->conf.channel->band;
+ tx_info->band = hw->conf.chandef.chan->band;
tx_info->flags |= IEEE80211_TX_CTL_NO_ACK;
tx_info->control.rates[0].idx = 0;
tx_info->control.rates[0].count = 1;
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 811007ec07a7..498fee04afa0 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -615,6 +615,14 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
rs->rs_status |= ATH9K_RXERR_DECRYPT;
else if (ads.ds_rxstatus8 & AR_MichaelErr)
rs->rs_status |= ATH9K_RXERR_MIC;
+ } else {
+ if (ads.ds_rxstatus8 &
+ (AR_CRCErr | AR_PHYErr | AR_DecryptCRCErr | AR_MichaelErr))
+ rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC;
+
+ /* Only up to MCS16 supported, everything above is invalid */
+ if (rs->rs_rate >= 0x90)
+ rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC;
}
if (ads.ds_rxstatus8 & AR_KeyMiss)
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 1ff817061ebc..5865f92998e1 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -183,6 +183,7 @@ struct ath_htc_rx_status {
#define ATH9K_RXERR_DECRYPT 0x08
#define ATH9K_RXERR_MIC 0x10
#define ATH9K_RXERR_KEYMISS 0x20
+#define ATH9K_RXERR_CORRUPT_DESC 0x40
#define ATH9K_RX_MORE 0x01
#define ATH9K_RX_MORE_AGGR 0x02
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 1bf52c88004a..6963862a1872 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -589,7 +589,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
struct ath9k_channel *init_channel;
int r;
@@ -839,10 +839,14 @@ static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
struct ath9k_vif_iter_data *iter_data = data;
int i;
- if (iter_data->hw_macaddr)
+ if (iter_data->has_hw_macaddr) {
for (i = 0; i < ETH_ALEN; i++)
iter_data->mask[i] &=
~(iter_data->hw_macaddr[i] ^ mac[i]);
+ } else {
+ memcpy(iter_data->hw_macaddr, mac, ETH_ALEN);
+ iter_data->has_hw_macaddr = true;
+ }
switch (vif->type) {
case NL80211_IFTYPE_AP:
@@ -891,7 +895,6 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
* together with the BSSID mask when matching addresses.
*/
memset(iter_data, 0, sizeof(*iter_data));
- iter_data->hw_macaddr = common->macaddr;
memset(&iter_data->mask, 0xff, ETH_ALEN);
if (vif)
@@ -901,6 +904,8 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
ieee80211_iterate_active_interfaces_atomic(
sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
ath9k_vif_iter, iter_data);
+
+ memcpy(common->macaddr, iter_data->hw_macaddr, ETH_ALEN);
}
/* Called with sc->mutex held. */
@@ -1188,7 +1193,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
}
if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) {
- struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&conf->chandef);
int pos = curchan->hw_value;
int old_pos = -1;
unsigned long flags;
@@ -1197,7 +1204,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
old_pos = ah->curchan - &ah->channels[0];
ath_dbg(common, CONFIG, "Set channel: %d MHz type: %d\n",
- curchan->center_freq, conf->channel_type);
+ curchan->center_freq, channel_type);
/* update survey stats for the old channel before switching */
spin_lock_irqsave(&common->cc_lock, flags);
@@ -1212,7 +1219,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
ath9k_hw_getnf(ah, ah->curchan);
ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
- curchan, conf->channel_type);
+ curchan, channel_type);
/*
* If the operating channel changes, change the survey in-use flags
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 96ac433ba7f6..aa4d368d8d3d 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -814,7 +814,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
* So, set fourth rate in series to be same as third one for
* above conditions.
*/
- if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) &&
+ if ((sc->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) &&
(conf_is_ht(&sc->hw->conf))) {
u8 dot11rate = rate_table->info[rix].dot11rate;
u8 phy = rate_table->info[rix].phy;
@@ -1328,7 +1328,7 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG,
"Operating HT Bandwidth changed to: %d\n",
- sc->hw->conf.channel_type);
+ cfg80211_get_chandef_type(&sc->hw->conf.chandef));
}
}
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index ee7ca5aecdb0..8be2b5d8c155 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -124,13 +124,13 @@ static bool ath_rx_edma_buf_link(struct ath_softc *sc,
SKB_CB_ATHBUF(skb) = bf;
ath9k_hw_addrxbuf_edma(ah, bf->bf_buf_addr, qtype);
- skb_queue_tail(&rx_edma->rx_fifo, skb);
+ __skb_queue_tail(&rx_edma->rx_fifo, skb);
return true;
}
static void ath_rx_addbuffer_edma(struct ath_softc *sc,
- enum ath9k_rx_qtype qtype, int size)
+ enum ath9k_rx_qtype qtype)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_buf *bf, *tbf;
@@ -155,7 +155,7 @@ static void ath_rx_remove_buffer(struct ath_softc *sc,
rx_edma = &sc->rx.rx_edma[qtype];
- while ((skb = skb_dequeue(&rx_edma->rx_fifo)) != NULL) {
+ while ((skb = __skb_dequeue(&rx_edma->rx_fifo)) != NULL) {
bf = SKB_CB_ATHBUF(skb);
BUG_ON(!bf);
list_add_tail(&bf->list, &sc->rx.rxbuf);
@@ -250,15 +250,9 @@ rx_init_fail:
static void ath_edma_start_recv(struct ath_softc *sc)
{
ath9k_hw_rxena(sc->sc_ah);
-
- ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP,
- sc->rx.rx_edma[ATH9K_RX_QUEUE_HP].rx_fifo_hwsize);
-
- ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP,
- sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize);
-
+ ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP);
+ ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP);
ath_opmode_init(sc);
-
ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
}
@@ -280,49 +274,47 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
sc->sc_ah->caps.rx_status_len;
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
return ath_rx_edma_init(sc, nbufs);
- } else {
- ath_dbg(common, CONFIG, "cachelsz %u rxbufsize %u\n",
- common->cachelsz, common->rx_bufsize);
- /* Initialize rx descriptors */
+ ath_dbg(common, CONFIG, "cachelsz %u rxbufsize %u\n",
+ common->cachelsz, common->rx_bufsize);
- error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
- "rx", nbufs, 1, 0);
- if (error != 0) {
- ath_err(common,
- "failed to allocate rx descriptors: %d\n",
- error);
+ /* Initialize rx descriptors */
+
+ error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
+ "rx", nbufs, 1, 0);
+ if (error != 0) {
+ ath_err(common,
+ "failed to allocate rx descriptors: %d\n",
+ error);
+ goto err;
+ }
+
+ list_for_each_entry(bf, &sc->rx.rxbuf, list) {
+ skb = ath_rxbuf_alloc(common, common->rx_bufsize,
+ GFP_KERNEL);
+ if (skb == NULL) {
+ error = -ENOMEM;
goto err;
}
- list_for_each_entry(bf, &sc->rx.rxbuf, list) {
- skb = ath_rxbuf_alloc(common, common->rx_bufsize,
- GFP_KERNEL);
- if (skb == NULL) {
- error = -ENOMEM;
- goto err;
- }
-
- bf->bf_mpdu = skb;
- bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
- common->rx_bufsize,
- DMA_FROM_DEVICE);
- if (unlikely(dma_mapping_error(sc->dev,
- bf->bf_buf_addr))) {
- dev_kfree_skb_any(skb);
- bf->bf_mpdu = NULL;
- bf->bf_buf_addr = 0;
- ath_err(common,
- "dma_mapping_error() on RX init\n");
- error = -ENOMEM;
- goto err;
- }
+ bf->bf_mpdu = skb;
+ bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+ common->rx_bufsize,
+ DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(sc->dev,
+ bf->bf_buf_addr))) {
+ dev_kfree_skb_any(skb);
+ bf->bf_mpdu = NULL;
+ bf->bf_buf_addr = 0;
+ ath_err(common,
+ "dma_mapping_error() on RX init\n");
+ error = -ENOMEM;
+ goto err;
}
- sc->rx.rxlink = NULL;
}
-
+ sc->rx.rxlink = NULL;
err:
if (error)
ath_rx_cleanup(sc);
@@ -340,17 +332,17 @@ void ath_rx_cleanup(struct ath_softc *sc)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
ath_rx_edma_cleanup(sc);
return;
- } else {
- list_for_each_entry(bf, &sc->rx.rxbuf, list) {
- skb = bf->bf_mpdu;
- if (skb) {
- dma_unmap_single(sc->dev, bf->bf_buf_addr,
- common->rx_bufsize,
- DMA_FROM_DEVICE);
- dev_kfree_skb(skb);
- bf->bf_buf_addr = 0;
- bf->bf_mpdu = NULL;
- }
+ }
+
+ list_for_each_entry(bf, &sc->rx.rxbuf, list) {
+ skb = bf->bf_mpdu;
+ if (skb) {
+ dma_unmap_single(sc->dev, bf->bf_buf_addr,
+ common->rx_bufsize,
+ DMA_FROM_DEVICE);
+ dev_kfree_skb(skb);
+ bf->bf_buf_addr = 0;
+ bf->bf_mpdu = NULL;
}
}
}
@@ -727,6 +719,13 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
ret = ath9k_hw_rxprocdesc(ah, tds, &trs);
if (ret == -EINPROGRESS)
return NULL;
+
+ /*
+ * mark descriptor as zero-length and set the 'more'
+ * flag to ensure that both buffers get discarded
+ */
+ rs->rs_datalen = 0;
+ rs->rs_more = true;
}
list_del(&bf->list);
@@ -863,7 +862,7 @@ static int ath9k_process_rate(struct ath_common *common,
unsigned int i = 0;
struct ath_softc __maybe_unused *sc = common->priv;
- band = hw->conf.channel->band;
+ band = hw->conf.chandef.chan->band;
sband = hw->wiphy->bands[band];
if (rx_stats->rs_rate & 0x80) {
@@ -933,14 +932,20 @@ static void ath9k_process_rssi(struct ath_common *common,
* up the frame up to let mac80211 handle the actual error case, be it no
* decryption key or real decryption error. This let us keep statistics there.
*/
-static int ath9k_rx_skb_preprocess(struct ath_common *common,
- struct ieee80211_hw *hw,
+static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
struct ieee80211_hdr *hdr,
struct ath_rx_status *rx_stats,
struct ieee80211_rx_status *rx_status,
bool *decrypt_error)
{
- struct ath_hw *ah = common->ah;
+ struct ieee80211_hw *hw = sc->hw;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ bool discard_current = sc->rx.discard_next;
+
+ sc->rx.discard_next = rx_stats->rs_more;
+ if (discard_current)
+ return -EINVAL;
/*
* everything but the rate is checked here, the rate check is done
@@ -958,14 +963,15 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
if (ath9k_process_rate(common, hw, rx_stats, rx_status))
return -EINVAL;
- rx_status->band = hw->conf.channel->band;
- rx_status->freq = hw->conf.channel->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
rx_status->signal = ah->noise + rx_stats->rs_rssi;
rx_status->antenna = rx_stats->rs_antenna;
rx_status->flag |= RX_FLAG_MACTIME_END;
if (rx_stats->rs_moreaggr)
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
+ sc->rx.discard_next = false;
return 0;
}
@@ -985,7 +991,7 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common,
hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
fc = hdr->frame_control;
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(fc);
/* The MAC header is padded to have 32-bit boundary if the
* packet payload is non-zero. The general calculation for
@@ -1166,6 +1172,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
u64 tsf = 0;
u32 tsf_lower = 0;
unsigned long flags;
+ dma_addr_t new_buf_addr;
if (edma)
dma_type = DMA_BIDIRECTIONAL;
@@ -1242,8 +1249,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
}
}
- retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
- rxs, &decrypt_error);
+ retval = ath9k_rx_skb_preprocess(sc, hdr, &rs, rxs,
+ &decrypt_error);
if (retval)
goto requeue_drop_frag;
@@ -1264,10 +1271,20 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
goto requeue_drop_frag;
}
+ /* We will now give hardware our shiny new allocated skb */
+ new_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
+ common->rx_bufsize, dma_type);
+ if (unlikely(dma_mapping_error(sc->dev, new_buf_addr))) {
+ dev_kfree_skb_any(requeue_skb);
+ goto requeue_drop_frag;
+ }
+
/* Unmap the frame */
dma_unmap_single(sc->dev, bf->bf_buf_addr,
- common->rx_bufsize,
- dma_type);
+ common->rx_bufsize, dma_type);
+
+ bf->bf_mpdu = requeue_skb;
+ bf->bf_buf_addr = new_buf_addr;
skb_put(skb, rs.rs_datalen + ah->caps.rx_status_len);
if (ah->caps.rx_status_len)
@@ -1277,21 +1294,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
ath9k_rx_skb_postprocess(common, hdr_skb, &rs,
rxs, decrypt_error);
- /* We will now give hardware our shiny new allocated skb */
- bf->bf_mpdu = requeue_skb;
- bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
- common->rx_bufsize,
- dma_type);
- if (unlikely(dma_mapping_error(sc->dev,
- bf->bf_buf_addr))) {
- dev_kfree_skb_any(requeue_skb);
- bf->bf_mpdu = NULL;
- bf->bf_buf_addr = 0;
- ath_err(common, "dma_mapping_error() on RX\n");
- ieee80211_rx(hw, skb);
- break;
- }
-
if (rs.rs_more) {
RX_STAT_INC(rx_frags);
/*
@@ -1309,6 +1311,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
sc->rx.frag = skb;
goto requeue;
}
+ if (rs.rs_status & ATH9K_RXERR_CORRUPT_DESC)
+ goto requeue_drop_frag;
if (sc->rx.frag) {
int space = skb->len - skb_tailroom(hdr_skb);
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 5929850649f0..5c4ab5026dca 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -1493,9 +1493,6 @@ enum {
#define AR9271_RADIO_RF_RST 0x20
#define AR9271_GATE_MAC_CTL 0x4000
-#define AR_STA_ID0 0x8000
-#define AR_STA_ID1 0x8004
-#define AR_STA_ID1_SADH_MASK 0x0000FFFF
#define AR_STA_ID1_STA_AP 0x00010000
#define AR_STA_ID1_ADHOC 0x00020000
#define AR_STA_ID1_PWR_SAV 0x00040000
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 89a64411b82e..eab0fcb7ded6 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -157,6 +157,13 @@ static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno)
seqno << IEEE80211_SEQ_SEQ_SHIFT);
}
+static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ath_buf *bf)
+{
+ ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates,
+ ARRAY_SIZE(bf->rates));
+}
+
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
struct ath_txq *txq = tid->ac->txq;
@@ -189,6 +196,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
sendbar = true;
} else {
+ ath_set_rates(tid->an->vif, tid->an->sta, bf);
ath_tx_send_normal(sc, txq, NULL, skb);
}
}
@@ -407,7 +415,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
tx_info = IEEE80211_SKB_CB(skb);
- memcpy(rates, tx_info->control.rates, sizeof(rates));
+ memcpy(rates, bf->rates, sizeof(rates));
retries = ts->ts_longretry + 1;
for (i = 0; i < ts->ts_rateindex; i++)
@@ -516,8 +524,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* not a holding desc.
*/
INIT_LIST_HEAD(&bf_head);
- if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
- bf_next != NULL || !bf_last->bf_stale)
+ if (bf_next != NULL || !bf_last->bf_stale)
list_move_tail(&bf->list, &bf_head);
if (!txpending || (tid->state & AGGR_CLEANUP)) {
@@ -537,8 +544,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
!txfail);
} else {
/* retry the un-acked ones */
- if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
- bf->bf_next == NULL && bf_last->bf_stale) {
+ if (bf->bf_next == NULL && bf_last->bf_stale) {
struct ath_buf *tbf;
tbf = ath_clone_txbuf(sc, bf_last);
@@ -738,8 +744,6 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
bool first_subfrm)
{
#define FIRST_DESC_NDELIMS 60
- struct sk_buff *skb = bf->bf_mpdu;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
u32 nsymbits, nsymbols;
u16 minlen;
u8 flags, rix;
@@ -780,8 +784,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
if (tid->an->mpdudensity == 0)
return ndelim;
- rix = tx_info->control.rates[0].idx;
- flags = tx_info->control.rates[0].flags;
+ rix = bf->rates[0].idx;
+ flags = bf->rates[0].flags;
width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0;
half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
@@ -860,6 +864,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
bf_first = bf;
if (!rl) {
+ ath_set_rates(tid->an->vif, tid->an->sta, bf);
aggr_limit = ath_lookup_rate(sc, bf, tid);
rl = 1;
}
@@ -1000,14 +1005,14 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
skb = bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb);
- rates = tx_info->control.rates;
+ rates = bf->rates;
hdr = (struct ieee80211_hdr *)skb->data;
/* set dur_update_en for l-sig computation except for PS-Poll frames */
info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
info->rtscts_rate = fi->rtscts_rate;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < ARRAY_SIZE(bf->rates); i++) {
bool is_40, is_sgi, is_sp;
int phy;
@@ -1745,6 +1750,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
return;
}
+ ath_set_rates(tid->an->vif, tid->an->sta, bf);
bf->bf_state.bf_type = BUF_AMPDU;
INIT_LIST_HEAD(&bf_head);
list_add(&bf->list, &bf_head);
@@ -1894,49 +1900,6 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
return bf;
}
-/* FIXME: tx power */
-static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
- struct ath_tx_control *txctl)
-{
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ath_atx_tid *tid = NULL;
- struct ath_buf *bf;
- u8 tidno;
-
- if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) {
- tidno = ieee80211_get_qos_ctl(hdr)[0] &
- IEEE80211_QOS_CTL_TID_MASK;
- tid = ATH_AN_2_TID(txctl->an, tidno);
-
- WARN_ON(tid->ac->txq != txctl->txq);
- }
-
- if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
- /*
- * Try aggregation if it's a unicast data frame
- * and the destination is HT capable.
- */
- ath_tx_send_ampdu(sc, tid, skb, txctl);
- } else {
- bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
- if (!bf) {
- if (txctl->paprd)
- dev_kfree_skb_any(skb);
- else
- ieee80211_free_txskb(sc->hw, skb);
- return;
- }
-
- bf->bf_state.bfs_paprd = txctl->paprd;
-
- if (txctl->paprd)
- bf->bf_state.bfs_paprd_timestamp = jiffies;
-
- ath_tx_send_normal(sc, txctl->txq, tid, skb);
- }
-}
-
/* Upon failure caller should free skb */
int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath_tx_control *txctl)
@@ -1947,8 +1910,11 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_vif *vif = info->control.vif;
struct ath_softc *sc = hw->priv;
struct ath_txq *txq = txctl->txq;
+ struct ath_atx_tid *tid = NULL;
+ struct ath_buf *bf;
int padpos, padsize;
int frmlen = skb->len + FCS_LEN;
+ u8 tidno;
int q;
/* NOTE: sta can be NULL according to net/mac80211.h */
@@ -1971,7 +1937,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
}
/* Add the padding after the header if this is not already done */
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(hdr->frame_control);
padsize = padpos & 3;
if (padsize && skb->len > padpos) {
if (skb_headroom(skb) < padsize)
@@ -2004,8 +1970,41 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
txq->stopped = true;
}
- ath_tx_start_dma(sc, skb, txctl);
+ if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) {
+ tidno = ieee80211_get_qos_ctl(hdr)[0] &
+ IEEE80211_QOS_CTL_TID_MASK;
+ tid = ATH_AN_2_TID(txctl->an, tidno);
+
+ WARN_ON(tid->ac->txq != txctl->txq);
+ }
+
+ if ((info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
+ /*
+ * Try aggregation if it's a unicast data frame
+ * and the destination is HT capable.
+ */
+ ath_tx_send_ampdu(sc, tid, skb, txctl);
+ goto out;
+ }
+ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+ if (!bf) {
+ if (txctl->paprd)
+ dev_kfree_skb_any(skb);
+ else
+ ieee80211_free_txskb(sc->hw, skb);
+ goto out;
+ }
+
+ bf->bf_state.bfs_paprd = txctl->paprd;
+
+ if (txctl->paprd)
+ bf->bf_state.bfs_paprd_timestamp = jiffies;
+
+ ath_set_rates(vif, sta, bf);
+ ath_tx_send_normal(sc, txctl->txq, tid, skb);
+
+out:
ath_txq_unlock(sc, txq);
return 0;
@@ -2033,7 +2032,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
/* Frame was ACKed */
tx_info->flags |= IEEE80211_TX_STAT_ACK;
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(hdr->frame_control);
padsize = padpos & 3;
if (padsize && skb->len>padpos+padsize) {
/*
@@ -2264,6 +2263,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
struct ath_txq *txq;
struct ath_buf *bf, *lastbf;
struct list_head bf_head;
+ struct list_head *fifo_list;
int status;
for (;;) {
@@ -2291,20 +2291,24 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
TX_STAT_INC(txq->axq_qnum, txprocdesc);
- if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+ fifo_list = &txq->txq_fifo[txq->txq_tailidx];
+ if (list_empty(fifo_list)) {
ath_txq_unlock(sc, txq);
return;
}
- bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
- struct ath_buf, list);
+ bf = list_first_entry(fifo_list, struct ath_buf, list);
+ if (bf->bf_stale) {
+ list_del(&bf->list);
+ ath_tx_return_buffer(sc, bf);
+ bf = list_first_entry(fifo_list, struct ath_buf, list);
+ }
+
lastbf = bf->bf_lastbf;
INIT_LIST_HEAD(&bf_head);
- list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
- &lastbf->list);
-
- if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+ if (list_is_last(&lastbf->list, fifo_list)) {
+ list_splice_tail_init(fifo_list, &bf_head);
INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
if (!list_empty(&txq->axq_q)) {
@@ -2315,6 +2319,11 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
list_splice_tail_init(&txq->axq_q, &bf_q);
ath_tx_txqaddbuf(sc, txq, &bf_q, true);
}
+ } else {
+ lastbf->bf_stale = true;
+ if (bf != lastbf)
+ list_cut_position(&bf_head, fifo_list,
+ lastbf->list.prev);
}
ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c
index 40109be81f7c..3d70cd277fd7 100644
--- a/drivers/net/wireless/ath/carl9170/debug.c
+++ b/drivers/net/wireless/ath/carl9170/debug.c
@@ -654,8 +654,8 @@ static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf,
goto out;
case 'P':
- err = carl9170_set_channel(ar, ar->hw->conf.channel,
- ar->hw->conf.channel_type);
+ err = carl9170_set_channel(ar, ar->hw->conf.chandef.chan,
+ cfg80211_get_chandef_type(&ar->hw->conf.chandef));
if (err < 0)
count = err;
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c
index 24d75ab94f0d..a2f005703c04 100644
--- a/drivers/net/wireless/ath/carl9170/mac.c
+++ b/drivers/net/wireless/ath/carl9170/mac.c
@@ -48,7 +48,7 @@ int carl9170_set_dyn_sifs_ack(struct ar9170 *ar)
if (conf_is_ht40(&ar->hw->conf))
val = 0x010a;
else {
- if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ)
+ if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ)
val = 0x105;
else
val = 0x104;
@@ -66,7 +66,7 @@ int carl9170_set_rts_cts_rate(struct ar9170 *ar)
rts_rate = 0x1da;
cts_rate = 0x10a;
} else {
- if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
+ if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) {
/* 11 mbit CCK */
rts_rate = 033;
cts_rate = 003;
@@ -93,7 +93,7 @@ int carl9170_set_slot_time(struct ar9170 *ar)
return 0;
}
- if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) ||
+ if ((ar->hw->conf.chandef.chan->band == IEEE80211_BAND_5GHZ) ||
vif->bss_conf.use_short_slot)
slottime = 9;
@@ -120,7 +120,7 @@ int carl9170_set_mac_rates(struct ar9170 *ar)
basic |= (vif->bss_conf.basic_rates & 0xff0) << 4;
rcu_read_unlock();
- if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ)
+ if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_5GHZ)
mandatory = 0xff00; /* OFDM 6/9/12/18/24/36/48/54 */
else
mandatory = 0xff0f; /* OFDM (6/9../54) + CCK (1/2/5.5/11) */
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 699c557bc2c7..e9010a481dfd 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -929,6 +929,9 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&hw->conf.chandef);
+
/* adjust slot time for 5 GHz */
err = carl9170_set_slot_time(ar);
if (err)
@@ -938,8 +941,8 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
if (err)
goto out;
- err = carl9170_set_channel(ar, hw->conf.channel,
- hw->conf.channel_type);
+ err = carl9170_set_channel(ar, hw->conf.chandef.chan,
+ channel_type);
if (err)
goto out;
@@ -957,7 +960,7 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
}
if (changed & IEEE80211_CONF_CHANGE_POWER) {
- err = carl9170_set_mac_tpc(ar, ar->hw->conf.channel);
+ err = carl9170_set_mac_tpc(ar, ar->hw->conf.chandef.chan);
if (err)
goto out;
}
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
index 07f82234c860..ab4ee7d39ad3 100644
--- a/drivers/net/wireless/ath/carl9170/phy.c
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -1331,7 +1331,7 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw)
* CTL_ETSI for 2GHz and CTL_FCC for 5GHz.
*/
ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory,
- ar->hw->conf.channel->band);
+ ar->hw->conf.chandef.chan->band);
/* ctl group not found - either invalid band (NO_CTL) or ww roaming */
if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL)
@@ -1341,7 +1341,7 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw)
/* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */
return;
- if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
+ if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) {
modes = mode_list_2ghz;
nr_modes = ARRAY_SIZE(mode_list_2ghz);
} else {
diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c
index 39e8a590d7fc..eae9abf540a7 100644
--- a/drivers/net/wireless/ath/hw.c
+++ b/drivers/net/wireless/ath/hw.c
@@ -118,6 +118,12 @@
void ath_hw_setbssidmask(struct ath_common *common)
{
void *ah = common->ah;
+ u32 id1;
+
+ REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
+ id1 = REG_READ(ah, AR_STA_ID1) & ~AR_STA_ID1_SADH_MASK;
+ id1 |= get_unaligned_le16(common->macaddr + 4);
+ REG_WRITE(ah, AR_STA_ID1, id1);
REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(common->bssidmask));
REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(common->bssidmask + 4));
diff --git a/drivers/net/wireless/ath/reg.h b/drivers/net/wireless/ath/reg.h
index 298e53f3fa48..3ad4c774bd22 100644
--- a/drivers/net/wireless/ath/reg.h
+++ b/drivers/net/wireless/ath/reg.h
@@ -23,6 +23,10 @@
#define AR_MIBC_CMC 0x00000004
#define AR_MIBC_MCS 0x00000008
+#define AR_STA_ID0 0x8000
+#define AR_STA_ID1 0x8004
+#define AR_STA_ID1_SADH_MASK 0x0000ffff
+
/*
* BSSID mask registers. See ath_hw_set_bssid_mask()
* for detailed documentation about these registers.
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 79d4e3271b00..797024507c71 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -191,8 +191,7 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring,
* - Phy info
*/
static void wil_rx_add_radiotap_header(struct wil6210_priv *wil,
- struct sk_buff *skb,
- volatile struct vring_rx_desc *d)
+ struct sk_buff *skb)
{
struct wireless_dev *wdev = wil->wdev;
struct wil6210_rtap {
@@ -216,6 +215,7 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil,
__le16 vendor_skip;
u8 vendor_data[0];
} __packed;
+ struct vring_rx_desc *d = wil_skb_rxdesc(skb);
struct wil6210_rtap_vendor *rtap_vendor;
int rtap_len = sizeof(struct wil6210_rtap);
int phy_length = 0; /* phy info header size, bytes */
@@ -312,6 +312,8 @@ static void wil_swap_ethaddr(void *data)
/**
* reap 1 frame from @swhead
*
+ * Rx descriptor copied to skb->cb
+ *
* Safe to call from IRQ
*/
static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
@@ -320,12 +322,15 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
struct device *dev = wil_to_dev(wil);
struct net_device *ndev = wil_to_ndev(wil);
volatile struct vring_rx_desc *d;
+ struct vring_rx_desc *d1;
struct sk_buff *skb;
dma_addr_t pa;
unsigned int sz = RX_BUF_LEN;
u8 ftype;
u8 ds_bits;
+ BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb));
+
if (wil_vring_is_empty(vring))
return NULL;
@@ -340,11 +345,14 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE);
skb_trim(skb, d->dma.length);
- wil->stats.last_mcs_rx = wil_rxdesc_mcs(d);
+ d1 = wil_skb_rxdesc(skb);
+ *d1 = *d;
+
+ wil->stats.last_mcs_rx = wil_rxdesc_mcs(d1);
/* use radiotap header only if required */
if (ndev->type == ARPHRD_IEEE80211_RADIOTAP)
- wil_rx_add_radiotap_header(wil, skb, d);
+ wil_rx_add_radiotap_header(wil, skb);
wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length);
wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4,
@@ -360,7 +368,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
* Driver should recognize it by frame type, that is found
* in Rx descriptor. If type is not data, it is 802.11 frame as is
*/
- ftype = wil_rxdesc_ftype(d) << 2;
+ ftype = wil_rxdesc_ftype(d1) << 2;
if (ftype != IEEE80211_FTYPE_DATA) {
wil_dbg_txrx(wil, "Non-data frame ftype 0x%08x\n", ftype);
/* TODO: process it */
@@ -375,7 +383,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
return NULL;
}
- ds_bits = wil_rxdesc_ds_bits(d);
+ ds_bits = wil_rxdesc_ds_bits(d1);
if (ds_bits == 1) {
/*
* HW bug - in ToDS mode, i.e. Rx on AP side,
@@ -517,6 +525,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
.vring_cfg = {
.tx_sw_ring = {
.max_mpdu_size = cpu_to_le16(TX_BUF_LEN),
+ .ring_size = cpu_to_le16(size),
},
.ringid = id,
.cidxtid = (cid & 0xf) | ((tid & 0xf) << 4),
@@ -548,7 +557,6 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
goto out;
cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
- cmd.vring_cfg.tx_sw_ring.ring_size = cpu_to_le16(vring->size);
rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd),
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
@@ -779,9 +787,14 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid)
wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid);
while (!wil_vring_is_empty(vring)) {
- volatile struct vring_tx_desc *d = &vring->va[vring->swtail].tx;
+ volatile struct vring_tx_desc *d1 =
+ &vring->va[vring->swtail].tx;
+ struct vring_tx_desc dd, *d = &dd;
dma_addr_t pa;
struct sk_buff *skb;
+
+ dd = *d1;
+
if (!(d->dma.status & TX_DMA_STATUS_DU))
break;
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
index 45a61f597c5c..adef12fb2aee 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.h
+++ b/drivers/net/wireless/ath/wil6210/txrx.h
@@ -339,24 +339,59 @@ union vring_desc {
struct vring_rx_desc rx;
} __packed;
-static inline int wil_rxdesc_phy_length(volatile struct vring_rx_desc *d)
+static inline int wil_rxdesc_tid(struct vring_rx_desc *d)
{
- return WIL_GET_BITS(d->dma.d0, 16, 29);
+ return WIL_GET_BITS(d->mac.d0, 0, 3);
}
-static inline int wil_rxdesc_mcs(volatile struct vring_rx_desc *d)
+static inline int wil_rxdesc_cid(struct vring_rx_desc *d)
{
- return WIL_GET_BITS(d->mac.d1, 21, 24);
+ return WIL_GET_BITS(d->mac.d0, 4, 6);
}
-static inline int wil_rxdesc_ds_bits(volatile struct vring_rx_desc *d)
+static inline int wil_rxdesc_mid(struct vring_rx_desc *d)
{
- return WIL_GET_BITS(d->mac.d1, 8, 9);
+ return WIL_GET_BITS(d->mac.d0, 8, 9);
}
-static inline int wil_rxdesc_ftype(volatile struct vring_rx_desc *d)
+static inline int wil_rxdesc_ftype(struct vring_rx_desc *d)
{
return WIL_GET_BITS(d->mac.d0, 10, 11);
}
+static inline int wil_rxdesc_subtype(struct vring_rx_desc *d)
+{
+ return WIL_GET_BITS(d->mac.d0, 12, 15);
+}
+
+static inline int wil_rxdesc_seq(struct vring_rx_desc *d)
+{
+ return WIL_GET_BITS(d->mac.d0, 16, 27);
+}
+
+static inline int wil_rxdesc_ext_subtype(struct vring_rx_desc *d)
+{
+ return WIL_GET_BITS(d->mac.d0, 28, 31);
+}
+
+static inline int wil_rxdesc_ds_bits(struct vring_rx_desc *d)
+{
+ return WIL_GET_BITS(d->mac.d1, 8, 9);
+}
+
+static inline int wil_rxdesc_mcs(struct vring_rx_desc *d)
+{
+ return WIL_GET_BITS(d->mac.d1, 21, 24);
+}
+
+static inline int wil_rxdesc_phy_length(struct vring_rx_desc *d)
+{
+ return WIL_GET_BITS(d->dma.d0, 16, 29);
+}
+
+static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb)
+{
+ return (void *)skb->cb;
+}
+
#endif /* WIL6210_TXRX_H */
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index f5e840104f4b..7f3d461f7e8d 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -980,7 +980,7 @@ static inline int b43_is_mode(struct b43_wl *wl, int type)
*/
static inline enum ieee80211_band b43_current_band(struct b43_wl *wl)
{
- return wl->hw->conf.channel->band;
+ return wl->hw->conf.chandef.chan->band;
}
static inline int b43_bus_may_powerdown(struct b43_wldev *wldev)
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 4ac73d2f8605..d377f77d30b5 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3852,7 +3852,7 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
dev = wl->current_dev;
/* Switch the band (if necessary). This might change the active core. */
- err = b43_switch_band(wl, conf->channel);
+ err = b43_switch_band(wl, conf->chandef.chan);
if (err)
goto out_unlock_mutex;
@@ -3882,8 +3882,8 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
/* Switch to the requested channel.
* The firmware takes care of races with the TX handler. */
- if (conf->channel->hw_value != phy->channel)
- b43_switch_channel(dev, conf->channel->hw_value);
+ if (conf->chandef.chan->hw_value != phy->channel)
+ b43_switch_channel(dev, conf->chandef.chan->hw_value);
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR);
@@ -5006,7 +5006,7 @@ static int b43_op_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = dev->stats.link_noise;
diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c
index b8667706fc27..5d6833f18498 100644
--- a/drivers/net/wireless/b43/phy_ht.c
+++ b/drivers/net/wireless/b43/phy_ht.c
@@ -30,6 +30,17 @@
#include "radio_2059.h"
#include "main.h"
+/* Force values to keep compatibility with wl */
+enum ht_rssi_type {
+ HT_RSSI_W1 = 0,
+ HT_RSSI_W2 = 1,
+ HT_RSSI_NB = 2,
+ HT_RSSI_IQ = 3,
+ HT_RSSI_TSSI_2G = 4,
+ HT_RSSI_TSSI_5G = 5,
+ HT_RSSI_TBD = 6,
+};
+
/**************************************************
* Radio 2059.
**************************************************/
@@ -37,8 +48,9 @@
static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
const struct b43_phy_ht_channeltab_e_radio2059 *e)
{
- u8 i;
- u16 routing;
+ static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3, };
+ u16 r;
+ int core;
b43_radio_write(dev, 0x16, e->radio_syn16);
b43_radio_write(dev, 0x17, e->radio_syn17);
@@ -53,25 +65,17 @@ static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
b43_radio_write(dev, 0x41, e->radio_syn41);
b43_radio_write(dev, 0x43, e->radio_syn43);
b43_radio_write(dev, 0x47, e->radio_syn47);
- b43_radio_write(dev, 0x4a, e->radio_syn4a);
- b43_radio_write(dev, 0x58, e->radio_syn58);
- b43_radio_write(dev, 0x5a, e->radio_syn5a);
- b43_radio_write(dev, 0x6a, e->radio_syn6a);
- b43_radio_write(dev, 0x6d, e->radio_syn6d);
- b43_radio_write(dev, 0x6e, e->radio_syn6e);
- b43_radio_write(dev, 0x92, e->radio_syn92);
- b43_radio_write(dev, 0x98, e->radio_syn98);
-
- for (i = 0; i < 2; i++) {
- routing = i ? R2059_RXRX1 : R2059_TXRX0;
- b43_radio_write(dev, routing | 0x4a, e->radio_rxtx4a);
- b43_radio_write(dev, routing | 0x58, e->radio_rxtx58);
- b43_radio_write(dev, routing | 0x5a, e->radio_rxtx5a);
- b43_radio_write(dev, routing | 0x6a, e->radio_rxtx6a);
- b43_radio_write(dev, routing | 0x6d, e->radio_rxtx6d);
- b43_radio_write(dev, routing | 0x6e, e->radio_rxtx6e);
- b43_radio_write(dev, routing | 0x92, e->radio_rxtx92);
- b43_radio_write(dev, routing | 0x98, e->radio_rxtx98);
+
+ for (core = 0; core < 3; core++) {
+ r = routing[core];
+ b43_radio_write(dev, r | 0x4a, e->radio_rxtx4a);
+ b43_radio_write(dev, r | 0x58, e->radio_rxtx58);
+ b43_radio_write(dev, r | 0x5a, e->radio_rxtx5a);
+ b43_radio_write(dev, r | 0x6a, e->radio_rxtx6a);
+ b43_radio_write(dev, r | 0x6d, e->radio_rxtx6d);
+ b43_radio_write(dev, r | 0x6e, e->radio_rxtx6e);
+ b43_radio_write(dev, r | 0x92, e->radio_rxtx92);
+ b43_radio_write(dev, r | 0x98, e->radio_rxtx98);
}
udelay(50);
@@ -87,7 +91,7 @@ static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
static void b43_radio_2059_init(struct b43_wldev *dev)
{
- const u16 routing[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1 };
+ const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3 };
const u16 radio_values[3][2] = {
{ 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 },
};
@@ -106,17 +110,17 @@ static void b43_radio_2059_init(struct b43_wldev *dev)
b43_radio_mask(dev, 0xc0, ~0x0080);
if (1) { /* FIXME */
- b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x1);
+ b43_radio_set(dev, R2059_C3 | 0x4, 0x1);
udelay(10);
- b43_radio_set(dev, R2059_RXRX1 | 0x0BF, 0x1);
- b43_radio_maskset(dev, R2059_RXRX1 | 0x19B, 0x3, 0x2);
+ b43_radio_set(dev, R2059_C3 | 0x0BF, 0x1);
+ b43_radio_maskset(dev, R2059_C3 | 0x19B, 0x3, 0x2);
- b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x2);
+ b43_radio_set(dev, R2059_C3 | 0x4, 0x2);
udelay(100);
- b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x2);
+ b43_radio_mask(dev, R2059_C3 | 0x4, ~0x2);
for (i = 0; i < 10000; i++) {
- if (b43_radio_read(dev, R2059_RXRX1 | 0x145) & 1) {
+ if (b43_radio_read(dev, R2059_C3 | 0x145) & 1) {
i = 0;
break;
}
@@ -125,7 +129,7 @@ static void b43_radio_2059_init(struct b43_wldev *dev)
if (i)
b43err(dev->wl, "radio 0x945 timeout\n");
- b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x1);
+ b43_radio_mask(dev, R2059_C3 | 0x4, ~0x1);
b43_radio_set(dev, 0xa, 0x60);
for (i = 0; i < 3; i++) {
@@ -390,14 +394,14 @@ static void b43_phy_ht_tx_tone(struct b43_wldev *dev)
**************************************************/
static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel,
- u8 rssi_type)
+ enum ht_rssi_type rssi_type)
{
static const u16 ctl_regs[3][2] = {
{ B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER, },
{ B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER, },
{ B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER, },
};
- static const u16 radio_r[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1, };
+ static const u16 radio_r[] = { R2059_C1, R2059_C2, R2059_C3, };
int core;
if (core_sel == 0) {
@@ -411,13 +415,13 @@ static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel,
continue;
switch (rssi_type) {
- case 4:
+ case HT_RSSI_TSSI_2G:
b43_phy_set(dev, ctl_regs[core][0], 0x3 << 8);
b43_phy_set(dev, ctl_regs[core][0], 0x3 << 10);
b43_phy_set(dev, ctl_regs[core][1], 0x1 << 9);
b43_phy_set(dev, ctl_regs[core][1], 0x1 << 10);
- b43_radio_set(dev, R2059_RXRX1 | 0xbf, 0x1);
+ b43_radio_set(dev, R2059_C3 | 0xbf, 0x1);
b43_radio_write(dev, radio_r[core] | 0x159,
0x11);
break;
@@ -429,8 +433,8 @@ static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel,
}
}
-static void b43_phy_ht_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
- u8 nsamp)
+static void b43_phy_ht_poll_rssi(struct b43_wldev *dev, enum ht_rssi_type type,
+ s32 *buf, u8 nsamp)
{
u16 phy_regs_values[12];
static const u16 phy_regs_to_save[] = {
@@ -504,15 +508,17 @@ static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable)
static const u16 cmd_regs[3] = { B43_PHY_HT_TXPCTL_CMD_C1,
B43_PHY_HT_TXPCTL_CMD_C2,
B43_PHY_HT_TXPCTL_CMD_C3 };
+ static const u16 status_regs[3] = { B43_PHY_HT_TX_PCTL_STATUS_C1,
+ B43_PHY_HT_TX_PCTL_STATUS_C2,
+ B43_PHY_HT_TX_PCTL_STATUS_C3 };
int i;
if (!enable) {
if (b43_phy_read(dev, B43_PHY_HT_TXPCTL_CMD_C1) & en_bits) {
/* We disable enabled TX pwr ctl, save it's state */
- /*
- * TODO: find the registers. On N-PHY they were 0x1ed
- * and 0x1ee, we need 3 such a registers for HT-PHY
- */
+ for (i = 0; i < 3; i++)
+ phy_ht->tx_pwr_idx[i] =
+ b43_phy_read(dev, status_regs[i]);
}
b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, ~en_bits);
} else {
@@ -536,13 +542,25 @@ static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable)
static void b43_phy_ht_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
{
struct b43_phy_ht *phy_ht = dev->phy.ht;
+ static const u16 base[] = { 0x840, 0x860, 0x880 };
+ u16 save_regs[3][3];
s32 rssi_buf[6];
+ int core;
+
+ for (core = 0; core < 3; core++) {
+ save_regs[core][1] = b43_phy_read(dev, base[core] + 6);
+ save_regs[core][2] = b43_phy_read(dev, base[core] + 7);
+ save_regs[core][0] = b43_phy_read(dev, base[core] + 0);
- /* TODO */
+ b43_phy_write(dev, base[core] + 6, 0);
+ b43_phy_mask(dev, base[core] + 7, ~0xF); /* 0xF? Or just 0x6? */
+ b43_phy_set(dev, base[core] + 0, 0x0400);
+ b43_phy_set(dev, base[core] + 0, 0x1000);
+ }
b43_phy_ht_tx_tone(dev);
udelay(20);
- b43_phy_ht_poll_rssi(dev, 4, rssi_buf, 1);
+ b43_phy_ht_poll_rssi(dev, HT_RSSI_TSSI_2G, rssi_buf, 1);
b43_phy_ht_stop_playback(dev);
b43_phy_ht_reset_cca(dev);
@@ -550,7 +568,23 @@ static void b43_phy_ht_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
phy_ht->idle_tssi[1] = rssi_buf[2] & 0xff;
phy_ht->idle_tssi[2] = rssi_buf[4] & 0xff;
- /* TODO */
+ for (core = 0; core < 3; core++) {
+ b43_phy_write(dev, base[core] + 0, save_regs[core][0]);
+ b43_phy_write(dev, base[core] + 6, save_regs[core][1]);
+ b43_phy_write(dev, base[core] + 7, save_regs[core][2]);
+ }
+}
+
+static void b43_phy_ht_tssi_setup(struct b43_wldev *dev)
+{
+ static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3, };
+ int core;
+
+ /* 0x159 is probably TX_SSI_MUX or TSSIG (by comparing to N-PHY) */
+ for (core = 0; core < 3; core++) {
+ b43_radio_set(dev, 0x8bf, 0x1);
+ b43_radio_write(dev, routing[core] | 0x0159, 0x0011);
+ }
}
static void b43_phy_ht_tx_power_ctl_setup(struct b43_wldev *dev)
@@ -946,6 +980,7 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev)
b43_phy_ht_tx_power_ctl(dev, false);
b43_phy_ht_tx_power_ctl_idle_tssi(dev);
b43_phy_ht_tx_power_ctl_setup(dev);
+ b43_phy_ht_tssi_setup(dev);
b43_phy_ht_tx_power_ctl(dev, saved_tx_pwr_ctl);
return 0;
@@ -1011,8 +1046,9 @@ static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on)
static int b43_phy_ht_op_switch_channel(struct b43_wldev *dev,
unsigned int new_channel)
{
- struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
- enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
+ struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
if ((new_channel < 1) || (new_channel > 14))
diff --git a/drivers/net/wireless/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h
index 9b2408efb224..6cae370d1018 100644
--- a/drivers/net/wireless/b43/phy_ht.h
+++ b/drivers/net/wireless/b43/phy_ht.h
@@ -23,6 +23,9 @@
#define B43_PHY_HT_SAMP_WAIT_CNT 0x0C5 /* Sample wait count */
#define B43_PHY_HT_SAMP_DEP_CNT 0x0C6 /* Sample depth count */
#define B43_PHY_HT_SAMP_STAT 0x0C7 /* Sample status */
+#define B43_PHY_HT_EST_PWR_C1 0x118
+#define B43_PHY_HT_EST_PWR_C2 0x119
+#define B43_PHY_HT_EST_PWR_C3 0x11A
#define B43_PHY_HT_TSSIMODE 0x122 /* TSSI mode */
#define B43_PHY_HT_TSSIMODE_EN 0x0001 /* TSSI enable */
#define B43_PHY_HT_TSSIMODE_PDEN 0x0002 /* Power det enable */
@@ -53,6 +56,8 @@
#define B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT 0
#define B43_PHY_HT_TXPCTL_TARG_PWR_C2 0xFF00 /* Power 1 */
#define B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT 8
+#define B43_PHY_HT_TX_PCTL_STATUS_C1 0x1ED
+#define B43_PHY_HT_TX_PCTL_STATUS_C2 0x1EE
#define B43_PHY_HT_TXPCTL_CMD_C2 0x222
#define B43_PHY_HT_TXPCTL_CMD_C2_INIT 0x007F
#define B43_PHY_HT_RSSI_C1 0x219
@@ -97,6 +102,7 @@
#define B43_PHY_HT_TXPCTL_TARG_PWR2 B43_PHY_EXTG(0x166) /* TX power control target power */
#define B43_PHY_HT_TXPCTL_TARG_PWR2_C3 0x00FF
#define B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT 0
+#define B43_PHY_HT_TX_PCTL_STATUS_C3 B43_PHY_EXTG(0x169)
#define B43_PHY_HT_TEST B43_PHY_N_BMODE(0x00A)
diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c
index a13e28ef6246..0bafa3b17035 100644
--- a/drivers/net/wireless/b43/phy_lcn.c
+++ b/drivers/net/wireless/b43/phy_lcn.c
@@ -808,8 +808,9 @@ static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on)
static int b43_phy_lcn_op_switch_channel(struct b43_wldev *dev,
unsigned int new_channel)
{
- struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
- enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
+ struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
if ((new_channel < 1) || (new_channel > 14))
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 5ed352ddae9e..92190dacf689 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -281,8 +281,8 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xFFC0, 0x000A);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xC0FF, 0x0B00);
} else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ ||
- (dev->dev->board_type == 0x048A) || ((dev->phy.rev == 0) &&
- (sprom->boardflags_lo & B43_BFL_FEM))) {
+ (dev->dev->board_type == SSB_BOARD_BU4312) ||
+ (dev->phy.rev == 0 && (sprom->boardflags_lo & B43_BFL_FEM))) {
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0001);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0400);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0001);
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 63cca9c2bf97..7c970d3ae358 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -69,14 +69,27 @@ enum b43_nphy_rf_sequence {
B43_RFSEQ_UPDATE_GAINU,
};
-enum b43_nphy_rssi_type {
- B43_NPHY_RSSI_X = 0,
- B43_NPHY_RSSI_Y,
- B43_NPHY_RSSI_Z,
- B43_NPHY_RSSI_PWRDET,
- B43_NPHY_RSSI_TSSI_I,
- B43_NPHY_RSSI_TSSI_Q,
- B43_NPHY_RSSI_TBD,
+enum n_intc_override {
+ N_INTC_OVERRIDE_OFF = 0,
+ N_INTC_OVERRIDE_TRSW = 1,
+ N_INTC_OVERRIDE_PA = 2,
+ N_INTC_OVERRIDE_EXT_LNA_PU = 3,
+ N_INTC_OVERRIDE_EXT_LNA_GAIN = 4,
+};
+
+enum n_rssi_type {
+ N_RSSI_W1 = 0,
+ N_RSSI_W2,
+ N_RSSI_NB,
+ N_RSSI_IQ,
+ N_RSSI_TSSI_2G,
+ N_RSSI_TSSI_5G,
+ N_RSSI_TBD,
+};
+
+enum n_rail_type {
+ N_RAIL_I = 0,
+ N_RAIL_Q = 1,
};
static inline bool b43_nphy_ipa(struct b43_wldev *dev)
@@ -94,7 +107,7 @@ static u8 b43_nphy_get_rx_core_state(struct b43_wldev *dev)
}
/**************************************************
- * RF (just without b43_nphy_rf_control_intc_override)
+ * RF (just without b43_nphy_rf_ctl_intc_override)
**************************************************/
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
@@ -128,9 +141,9 @@ ok:
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */
-static void b43_nphy_rf_control_override_rev7(struct b43_wldev *dev, u16 field,
- u16 value, u8 core, bool off,
- u8 override)
+static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field,
+ u16 value, u8 core, bool off,
+ u8 override)
{
const struct nphy_rf_control_override_rev7 *e;
u16 en_addrs[3][2] = {
@@ -168,8 +181,8 @@ static void b43_nphy_rf_control_override_rev7(struct b43_wldev *dev, u16 field,
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
-static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
- u16 value, u8 core, bool off)
+static void b43_nphy_rf_ctl_override(struct b43_wldev *dev, u16 field,
+ u16 value, u8 core, bool off)
{
int i;
u8 index = fls(field);
@@ -244,14 +257,14 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
-static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
- u16 value, u8 core)
+static void b43_nphy_rf_ctl_intc_override(struct b43_wldev *dev,
+ enum n_intc_override intc_override,
+ u16 value, u8 core)
{
u8 i, j;
u16 reg, tmp, val;
B43_WARN_ON(dev->phy.rev < 3);
- B43_WARN_ON(field > 4);
for (i = 0; i < 2; i++) {
if ((core == 1 && i == 1) || (core == 2 && !i))
@@ -261,12 +274,12 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
b43_phy_set(dev, reg, 0x400);
- switch (field) {
- case 0:
+ switch (intc_override) {
+ case N_INTC_OVERRIDE_OFF:
b43_phy_write(dev, reg, 0);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
break;
- case 1:
+ case N_INTC_OVERRIDE_TRSW:
if (!i) {
b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1,
0xFC3F, (value << 6));
@@ -307,7 +320,7 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
0xFFFE);
}
break;
- case 2:
+ case N_INTC_OVERRIDE_PA:
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
tmp = 0x0020;
val = value << 5;
@@ -317,7 +330,7 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
}
b43_phy_maskset(dev, reg, ~tmp, val);
break;
- case 3:
+ case N_INTC_OVERRIDE_EXT_LNA_PU:
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
tmp = 0x0001;
val = value;
@@ -327,7 +340,7 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
}
b43_phy_maskset(dev, reg, ~tmp, val);
break;
- case 4:
+ case N_INTC_OVERRIDE_EXT_LNA_GAIN:
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
tmp = 0x0002;
val = value << 1;
@@ -1011,7 +1024,7 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
if (sprom->revision < 4)
workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM
- && dev->dev->board_type == 0x46D
+ && dev->dev->board_type == SSB_BOARD_CB2_4321
&& dev->dev->board_rev >= 0x41);
else
workaround =
@@ -1207,8 +1220,9 @@ static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
- s8 offset, u8 core, u8 rail,
- enum b43_nphy_rssi_type type)
+ s8 offset, u8 core,
+ enum n_rail_type rail,
+ enum n_rssi_type rssi_type)
{
u16 tmp;
bool core1or5 = (core == 1) || (core == 5);
@@ -1217,63 +1231,74 @@ static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
offset = clamp_val(offset, -32, 31);
tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
- if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
- if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
- if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
- if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
-
- if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
- if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
- if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
- if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
-
- if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
- if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
- if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
- if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
-
- if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
- if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
- if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
- if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
-
- if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
- if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
- if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
- if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
-
- if (core1or5 && (type == B43_NPHY_RSSI_TSSI_I))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
- if (core2or5 && (type == B43_NPHY_RSSI_TSSI_I))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
-
- if (core1or5 && (type == B43_NPHY_RSSI_TSSI_Q))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
- if (core2or5 && (type == B43_NPHY_RSSI_TSSI_Q))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
+ switch (rssi_type) {
+ case N_RSSI_NB:
+ if (core1or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
+ if (core1or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
+ if (core2or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
+ if (core2or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
+ break;
+ case N_RSSI_W1:
+ if (core1or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
+ if (core1or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
+ if (core2or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
+ if (core2or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
+ break;
+ case N_RSSI_W2:
+ if (core1or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
+ if (core1or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
+ if (core2or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
+ if (core2or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
+ break;
+ case N_RSSI_TBD:
+ if (core1or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
+ if (core1or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
+ if (core2or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
+ if (core2or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
+ break;
+ case N_RSSI_IQ:
+ if (core1or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
+ if (core1or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
+ if (core2or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
+ if (core2or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
+ break;
+ case N_RSSI_TSSI_2G:
+ if (core1or5)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
+ if (core2or5)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
+ break;
+ case N_RSSI_TSSI_5G:
+ if (core1or5)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
+ if (core2or5)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
+ break;
+ }
}
-static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
+static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code,
+ enum n_rssi_type rssi_type)
{
u8 i;
u16 reg, val;
@@ -1296,7 +1321,9 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER;
b43_phy_maskset(dev, reg, 0xFDFF, 0x0200);
- if (type < 3) {
+ if (rssi_type == N_RSSI_W1 ||
+ rssi_type == N_RSSI_W2 ||
+ rssi_type == N_RSSI_NB) {
reg = (i == 0) ?
B43_NPHY_AFECTL_C1 :
B43_NPHY_AFECTL_C2;
@@ -1307,9 +1334,9 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
B43_NPHY_RFCTL_LUT_TRSW_UP2;
b43_phy_maskset(dev, reg, 0xFFC3, 0);
- if (type == 0)
+ if (rssi_type == N_RSSI_W1)
val = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 4 : 8;
- else if (type == 1)
+ else if (rssi_type == N_RSSI_W2)
val = 16;
else
val = 32;
@@ -1320,9 +1347,9 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
B43_NPHY_TXF_40CO_B32S1;
b43_phy_set(dev, reg, 0x0020);
} else {
- if (type == 6)
+ if (rssi_type == N_RSSI_TBD)
val = 0x0100;
- else if (type == 3)
+ else if (rssi_type == N_RSSI_IQ)
val = 0x0200;
else
val = 0x0300;
@@ -1334,7 +1361,8 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
b43_phy_maskset(dev, reg, 0xFCFF, val);
b43_phy_maskset(dev, reg, 0xF3FF, val << 2);
- if (type != 3 && type != 6) {
+ if (rssi_type != N_RSSI_IQ &&
+ rssi_type != N_RSSI_TBD) {
enum ieee80211_band band =
b43_current_band(dev->wl);
@@ -1344,7 +1372,7 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
val = 0x11;
reg = (i == 0) ? 0x2000 : 0x3000;
reg |= B2055_PADDRV;
- b43_radio_write16(dev, reg, val);
+ b43_radio_write(dev, reg, val);
reg = (i == 0) ?
B43_NPHY_AFECTL_OVER1 :
@@ -1356,33 +1384,43 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
}
}
-static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
+static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code,
+ enum n_rssi_type rssi_type)
{
u16 val;
+ bool rssi_w1_w2_nb = false;
- if (type < 3)
+ switch (rssi_type) {
+ case N_RSSI_W1:
+ case N_RSSI_W2:
+ case N_RSSI_NB:
val = 0;
- else if (type == 6)
+ rssi_w1_w2_nb = true;
+ break;
+ case N_RSSI_TBD:
val = 1;
- else if (type == 3)
+ break;
+ case N_RSSI_IQ:
val = 2;
- else
+ break;
+ default:
val = 3;
+ }
val = (val << 12) | (val << 14);
b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);
- if (type < 3) {
+ if (rssi_w1_w2_nb) {
b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
- (type + 1) << 4);
+ (rssi_type + 1) << 4);
b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
- (type + 1) << 4);
+ (rssi_type + 1) << 4);
}
if (code == 0) {
b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000);
- if (type < 3) {
+ if (rssi_w1_w2_nb) {
b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
~(B43_NPHY_RFCTL_CMD_RXEN |
B43_NPHY_RFCTL_CMD_CORESEL));
@@ -1398,7 +1436,7 @@ static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
}
} else {
b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000);
- if (type < 3) {
+ if (rssi_w1_w2_nb) {
b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
~(B43_NPHY_RFCTL_CMD_RXEN |
B43_NPHY_RFCTL_CMD_CORESEL),
@@ -1418,7 +1456,8 @@ static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
-static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
+static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code,
+ enum n_rssi_type type)
{
if (dev->phy.rev >= 3)
b43_nphy_rev3_rssi_select(dev, code, type);
@@ -1427,11 +1466,12 @@ static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
-static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf)
+static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev,
+ enum n_rssi_type rssi_type, u8 *buf)
{
int i;
for (i = 0; i < 2; i++) {
- if (type == 2) {
+ if (rssi_type == N_RSSI_NB) {
if (i == 0) {
b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM,
0xFC, buf[0]);
@@ -1455,8 +1495,8 @@ static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf)
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
-static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
- u8 nsamp)
+static int b43_nphy_poll_rssi(struct b43_wldev *dev, enum n_rssi_type rssi_type,
+ s32 *buf, u8 nsamp)
{
int i;
int out;
@@ -1487,7 +1527,7 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
save_regs_phy[8] = 0;
}
- b43_nphy_rssi_select(dev, 5, type);
+ b43_nphy_rssi_select(dev, 5, rssi_type);
if (dev->phy.rev < 2) {
save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL);
@@ -1574,7 +1614,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
u16 r; /* routing */
u8 rx_core_state;
- u8 core, i, j;
+ int core, i, j, vcm;
class = b43_nphy_classifier(dev, 0, 0);
b43_nphy_classifier(dev, 7, 4);
@@ -1586,19 +1626,19 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
for (i = 0; i < ARRAY_SIZE(regs_to_store); i++)
saved_regs_phy[i] = b43_phy_read(dev, regs_to_store[i]);
- b43_nphy_rf_control_intc_override(dev, 0, 0, 7);
- b43_nphy_rf_control_intc_override(dev, 1, 1, 7);
- b43_nphy_rf_control_override(dev, 0x1, 0, 0, false);
- b43_nphy_rf_control_override(dev, 0x2, 1, 0, false);
- b43_nphy_rf_control_override(dev, 0x80, 1, 0, false);
- b43_nphy_rf_control_override(dev, 0x40, 1, 0, false);
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_OFF, 0, 7);
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 1, 7);
+ b43_nphy_rf_ctl_override(dev, 0x1, 0, 0, false);
+ b43_nphy_rf_ctl_override(dev, 0x2, 1, 0, false);
+ b43_nphy_rf_ctl_override(dev, 0x80, 1, 0, false);
+ b43_nphy_rf_ctl_override(dev, 0x40, 1, 0, false);
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- b43_nphy_rf_control_override(dev, 0x20, 0, 0, false);
- b43_nphy_rf_control_override(dev, 0x10, 1, 0, false);
+ b43_nphy_rf_ctl_override(dev, 0x20, 0, 0, false);
+ b43_nphy_rf_ctl_override(dev, 0x10, 1, 0, false);
} else {
- b43_nphy_rf_control_override(dev, 0x10, 0, 0, false);
- b43_nphy_rf_control_override(dev, 0x20, 1, 0, false);
+ b43_nphy_rf_ctl_override(dev, 0x10, 0, 0, false);
+ b43_nphy_rf_ctl_override(dev, 0x20, 1, 0, false);
}
rx_core_state = b43_nphy_get_rx_core_state(dev);
@@ -1606,35 +1646,44 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
if (!(rx_core_state & (1 << core)))
continue;
r = core ? B2056_RX1 : B2056_RX0;
- b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 0, 2);
- b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 1, 2);
- for (i = 0; i < 8; i++) {
+ b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, N_RAIL_I,
+ N_RSSI_NB);
+ b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, N_RAIL_Q,
+ N_RSSI_NB);
+
+ /* Grab RSSI results for every possible VCM */
+ for (vcm = 0; vcm < 8; vcm++) {
b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, 0xE3,
- i << 2);
- b43_nphy_poll_rssi(dev, 2, results[i], 8);
+ vcm << 2);
+ b43_nphy_poll_rssi(dev, N_RSSI_NB, results[vcm], 8);
}
+
+ /* Find out which VCM got the best results */
for (i = 0; i < 4; i += 2) {
- s32 curr;
+ s32 currd;
s32 mind = 0x100000;
s32 minpoll = 249;
u8 minvcm = 0;
if (2 * core != i)
continue;
- for (j = 0; j < 8; j++) {
- curr = results[j][i] * results[j][i] +
- results[j][i + 1] * results[j][i];
- if (curr < mind) {
- mind = curr;
- minvcm = j;
+ for (vcm = 0; vcm < 8; vcm++) {
+ currd = results[vcm][i] * results[vcm][i] +
+ results[vcm][i + 1] * results[vcm][i];
+ if (currd < mind) {
+ mind = currd;
+ minvcm = vcm;
}
- if (results[j][i] < minpoll)
- minpoll = results[j][i];
+ if (results[vcm][i] < minpoll)
+ minpoll = results[vcm][i];
}
vcm_final = minvcm;
results_min[i] = minpoll;
}
+
+ /* Select the best VCM */
b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, 0xE3,
vcm_final << 2);
+
for (i = 0; i < 4; i++) {
if (core != i / 2)
continue;
@@ -1647,16 +1696,19 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
offset[i] = -32;
b43_nphy_scale_offset_rssi(dev, 0, offset[i],
(i / 2 == 0) ? 1 : 2,
- (i % 2 == 0) ? 0 : 1,
- 2);
+ (i % 2 == 0) ? N_RAIL_I : N_RAIL_Q,
+ N_RSSI_NB);
}
}
+
for (core = 0; core < 2; core++) {
if (!(rx_core_state & (1 << core)))
continue;
for (i = 0; i < 2; i++) {
- b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 0, i);
- b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 1, i);
+ b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1,
+ N_RAIL_I, i);
+ b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1,
+ N_RAIL_Q, i);
b43_nphy_poll_rssi(dev, i, poll_results, 8);
for (j = 0; j < 4; j++) {
if (j / 2 == core) {
@@ -1696,8 +1748,13 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
}
- rssical_radio_regs[0] = b43_radio_read(dev, 0x602B);
- rssical_radio_regs[0] = b43_radio_read(dev, 0x702B);
+ if (dev->phy.rev >= 7) {
+ } else {
+ rssical_radio_regs[0] = b43_radio_read(dev, B2056_RX0 |
+ B2056_RX_RSSI_MISC);
+ rssical_radio_regs[1] = b43_radio_read(dev, B2056_RX1 |
+ B2056_RX_RSSI_MISC);
+ }
rssical_phy_regs[0] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Z);
rssical_phy_regs[1] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z);
rssical_phy_regs[2] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Z);
@@ -1723,9 +1780,9 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
-static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
+static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, enum n_rssi_type type)
{
- int i, j;
+ int i, j, vcm;
u8 state[4];
u8 code, val;
u16 class, override;
@@ -1743,10 +1800,10 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
s32 results[4][4] = { };
s32 miniq[4][2] = { };
- if (type == 2) {
+ if (type == N_RSSI_NB) {
code = 0;
val = 6;
- } else if (type < 2) {
+ } else if (type == N_RSSI_W1 || type == N_RSSI_W2) {
code = 25;
val = 4;
} else {
@@ -1765,63 +1822,63 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
override = 0x110;
regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
- regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX);
+ regs_save_radio[0] = b43_radio_read(dev, B2055_C1_PD_RXTX);
b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override);
- b43_radio_write16(dev, B2055_C1_PD_RXTX, val);
+ b43_radio_write(dev, B2055_C1_PD_RXTX, val);
regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
- regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX);
+ regs_save_radio[1] = b43_radio_read(dev, B2055_C2_PD_RXTX);
b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override);
- b43_radio_write16(dev, B2055_C2_PD_RXTX, val);
+ b43_radio_write(dev, B2055_C2_PD_RXTX, val);
- state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07;
- state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07;
+ state[0] = b43_radio_read(dev, B2055_C1_PD_RSSIMISC) & 0x07;
+ state[1] = b43_radio_read(dev, B2055_C2_PD_RSSIMISC) & 0x07;
b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8);
b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8);
- state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07;
- state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07;
+ state[2] = b43_radio_read(dev, B2055_C1_SP_RSSI) & 0x07;
+ state[3] = b43_radio_read(dev, B2055_C2_SP_RSSI) & 0x07;
b43_nphy_rssi_select(dev, 5, type);
- b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type);
- b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type);
+ b43_nphy_scale_offset_rssi(dev, 0, 0, 5, N_RAIL_I, type);
+ b43_nphy_scale_offset_rssi(dev, 0, 0, 5, N_RAIL_Q, type);
- for (i = 0; i < 4; i++) {
+ for (vcm = 0; vcm < 4; vcm++) {
u8 tmp[4];
for (j = 0; j < 4; j++)
- tmp[j] = i;
- if (type != 1)
+ tmp[j] = vcm;
+ if (type != N_RSSI_W2)
b43_nphy_set_rssi_2055_vcm(dev, type, tmp);
- b43_nphy_poll_rssi(dev, type, results[i], 8);
- if (type < 2)
+ b43_nphy_poll_rssi(dev, type, results[vcm], 8);
+ if (type == N_RSSI_W1 || type == N_RSSI_W2)
for (j = 0; j < 2; j++)
- miniq[i][j] = min(results[i][2 * j],
- results[i][2 * j + 1]);
+ miniq[vcm][j] = min(results[vcm][2 * j],
+ results[vcm][2 * j + 1]);
}
for (i = 0; i < 4; i++) {
s32 mind = 0x100000;
u8 minvcm = 0;
s32 minpoll = 249;
- s32 curr;
- for (j = 0; j < 4; j++) {
- if (type == 2)
- curr = abs(results[j][i]);
+ s32 currd;
+ for (vcm = 0; vcm < 4; vcm++) {
+ if (type == N_RSSI_NB)
+ currd = abs(results[vcm][i] - code * 8);
else
- curr = abs(miniq[j][i / 2] - code * 8);
+ currd = abs(miniq[vcm][i / 2] - code * 8);
- if (curr < mind) {
- mind = curr;
- minvcm = j;
+ if (currd < mind) {
+ mind = currd;
+ minvcm = vcm;
}
- if (results[j][i] < minpoll)
- minpoll = results[j][i];
+ if (results[vcm][i] < minpoll)
+ minpoll = results[vcm][i];
}
results_min[i] = minpoll;
vcm_final[i] = minvcm;
}
- if (type != 1)
+ if (type != N_RSSI_W2)
b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final);
for (i = 0; i < 4; i++) {
@@ -1836,7 +1893,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
offset[i] = code - 32;
core = (i / 2) ? 2 : 1;
- rail = (i % 2) ? 1 : 0;
+ rail = (i % 2) ? N_RAIL_Q : N_RAIL_I;
b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail,
type);
@@ -1847,37 +1904,37 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
switch (state[2]) {
case 1:
- b43_nphy_rssi_select(dev, 1, 2);
+ b43_nphy_rssi_select(dev, 1, N_RSSI_NB);
break;
case 4:
- b43_nphy_rssi_select(dev, 1, 0);
+ b43_nphy_rssi_select(dev, 1, N_RSSI_W1);
break;
case 2:
- b43_nphy_rssi_select(dev, 1, 1);
+ b43_nphy_rssi_select(dev, 1, N_RSSI_W2);
break;
default:
- b43_nphy_rssi_select(dev, 1, 1);
+ b43_nphy_rssi_select(dev, 1, N_RSSI_W2);
break;
}
switch (state[3]) {
case 1:
- b43_nphy_rssi_select(dev, 2, 2);
+ b43_nphy_rssi_select(dev, 2, N_RSSI_NB);
break;
case 4:
- b43_nphy_rssi_select(dev, 2, 0);
+ b43_nphy_rssi_select(dev, 2, N_RSSI_W1);
break;
default:
- b43_nphy_rssi_select(dev, 2, 1);
+ b43_nphy_rssi_select(dev, 2, N_RSSI_W2);
break;
}
b43_nphy_rssi_select(dev, 0, type);
b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]);
- b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
+ b43_radio_write(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]);
- b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]);
+ b43_radio_write(dev, B2055_C2_PD_RXTX, regs_save_radio[1]);
b43_nphy_classifier(dev, 7, class);
b43_nphy_write_clip_detection(dev, clip_state);
@@ -1895,9 +1952,9 @@ static void b43_nphy_rssi_cal(struct b43_wldev *dev)
if (dev->phy.rev >= 3) {
b43_nphy_rev3_rssi_cal(dev);
} else {
- b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Z);
- b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_X);
- b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Y);
+ b43_nphy_rev2_rssi_cal(dev, N_RSSI_NB);
+ b43_nphy_rev2_rssi_cal(dev, N_RSSI_W1);
+ b43_nphy_rev2_rssi_cal(dev, N_RSSI_W2);
}
}
@@ -1930,10 +1987,8 @@ static void b43_nphy_gain_ctl_workarounds_rev3plus(struct b43_wldev *dev)
b43_phy_set(dev, B43_NPHY_RXCTL, 0x0040);
/* Set Clip 2 detect */
- b43_phy_set(dev, B43_NPHY_C1_CGAINI,
- B43_NPHY_C1_CGAINI_CL2DETECT);
- b43_phy_set(dev, B43_NPHY_C2_CGAINI,
- B43_NPHY_C2_CGAINI_CL2DETECT);
+ b43_phy_set(dev, B43_NPHY_C1_CGAINI, B43_NPHY_C1_CGAINI_CL2DETECT);
+ b43_phy_set(dev, B43_NPHY_C2_CGAINI, B43_NPHY_C2_CGAINI_CL2DETECT);
b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC,
0x17);
@@ -1967,22 +2022,22 @@ static void b43_nphy_gain_ctl_workarounds_rev3plus(struct b43_wldev *dev)
b43_ntab_write_bulk(dev, B43_NTAB8(2, 0x40), 6, lpf_bits);
b43_ntab_write_bulk(dev, B43_NTAB8(3, 0x40), 6, lpf_bits);
- b43_phy_write(dev, B43_NPHY_C1_INITGAIN, e->init_gain);
- b43_phy_write(dev, 0x2A7, e->init_gain);
+ b43_phy_write(dev, B43_NPHY_REV3_C1_INITGAIN_A, e->init_gain);
+ b43_phy_write(dev, B43_NPHY_REV3_C2_INITGAIN_A, e->init_gain);
+
b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x106), 2,
e->rfseq_init);
- /* TODO: check defines. Do not match variables names */
- b43_phy_write(dev, B43_NPHY_C1_CLIP1_MEDGAIN, e->cliphi_gain);
- b43_phy_write(dev, 0x2A9, e->cliphi_gain);
- b43_phy_write(dev, B43_NPHY_C1_CLIP2_GAIN, e->clipmd_gain);
- b43_phy_write(dev, 0x2AB, e->clipmd_gain);
- b43_phy_write(dev, B43_NPHY_C2_CLIP1_HIGAIN, e->cliplo_gain);
- b43_phy_write(dev, 0x2AD, e->cliplo_gain);
-
- b43_phy_maskset(dev, 0x27D, 0xFF00, e->crsmin);
- b43_phy_maskset(dev, 0x280, 0xFF00, e->crsminl);
- b43_phy_maskset(dev, 0x283, 0xFF00, e->crsminu);
+ b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_HIGAIN_A, e->cliphi_gain);
+ b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_HIGAIN_A, e->cliphi_gain);
+ b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_MEDGAIN_A, e->clipmd_gain);
+ b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_MEDGAIN_A, e->clipmd_gain);
+ b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_LOGAIN_A, e->cliplo_gain);
+ b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_LOGAIN_A, e->cliplo_gain);
+
+ b43_phy_maskset(dev, B43_NPHY_CRSMINPOWER0, 0xFF00, e->crsmin);
+ b43_phy_maskset(dev, B43_NPHY_CRSMINPOWERL0, 0xFF00, e->crsminl);
+ b43_phy_maskset(dev, B43_NPHY_CRSMINPOWERU0, 0xFF00, e->crsminu);
b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, e->nbclip);
b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, e->nbclip);
b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
@@ -2164,8 +2219,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000);
}
if (phy->rev <= 8) {
- b43_phy_write(dev, 0x23F, 0x1B0);
- b43_phy_write(dev, 0x240, 0x1B0);
+ b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0);
+ b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0);
}
if (phy->rev >= 8)
b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72);
@@ -2182,8 +2237,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
- b43_phy_maskset(dev, 0x299, 0x3FFF, 0x4000);
- b43_phy_maskset(dev, 0x29D, 0x3FFF, 0x4000);
+ b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000);
+ b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000);
lpf_20 = b43_nphy_read_lpf_ctl(dev, 0x154);
lpf_40 = b43_nphy_read_lpf_ctl(dev, 0x159);
@@ -2260,11 +2315,11 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16),
rx2tx_lut_40_11n);
}
- b43_nphy_rf_control_override_rev7(dev, 16, 1, 3, false, 2);
+ b43_nphy_rf_ctl_override_rev7(dev, 16, 1, 3, false, 2);
}
b43_phy_write(dev, 0x32F, 0x3);
if (phy->radio_rev == 4 || phy->radio_rev == 6)
- b43_nphy_rf_control_override_rev7(dev, 4, 1, 3, false, 0);
+ b43_nphy_rf_ctl_override_rev7(dev, 4, 1, 3, false, 0);
if (phy->radio_rev == 3 || phy->radio_rev == 4 || phy->radio_rev == 6) {
if (sprom->revision &&
@@ -2450,8 +2505,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
u16 tmp16;
u32 tmp32;
- b43_phy_write(dev, 0x23f, 0x1f8);
- b43_phy_write(dev, 0x240, 0x1f8);
+ b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1f8);
+ b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1f8);
tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
tmp32 &= 0xffffff;
@@ -2464,8 +2519,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
- b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C);
- b43_phy_write(dev, 0x2AE, 0x000C);
+ b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_LOGAIN_B, 0x000C);
+ b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_LOGAIN_B, 0x000C);
/* TX to RX */
b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
@@ -2490,7 +2545,7 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
0x2 : 0x9C40;
b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
- b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
+ b43_phy_maskset(dev, B43_NPHY_SGILTRNOFFSET, 0xF0FF, 0x0700);
if (!dev->phy.is_40mhz) {
b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
@@ -2542,18 +2597,18 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
}
/* Dropped probably-always-true condition */
- b43_phy_write(dev, 0x224, 0x03eb);
- b43_phy_write(dev, 0x225, 0x03eb);
- b43_phy_write(dev, 0x226, 0x0341);
- b43_phy_write(dev, 0x227, 0x0341);
- b43_phy_write(dev, 0x228, 0x042b);
- b43_phy_write(dev, 0x229, 0x042b);
- b43_phy_write(dev, 0x22a, 0x0381);
- b43_phy_write(dev, 0x22b, 0x0381);
- b43_phy_write(dev, 0x22c, 0x042b);
- b43_phy_write(dev, 0x22d, 0x042b);
- b43_phy_write(dev, 0x22e, 0x0381);
- b43_phy_write(dev, 0x22f, 0x0381);
+ b43_phy_write(dev, B43_NPHY_ED_CRS40ASSERTTHRESH0, 0x03eb);
+ b43_phy_write(dev, B43_NPHY_ED_CRS40ASSERTTHRESH1, 0x03eb);
+ b43_phy_write(dev, B43_NPHY_ED_CRS40DEASSERTTHRESH1, 0x0341);
+ b43_phy_write(dev, B43_NPHY_ED_CRS40DEASSERTTHRESH1, 0x0341);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20LASSERTTHRESH0, 0x042b);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20LASSERTTHRESH1, 0x042b);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20LDEASSERTTHRESH0, 0x0381);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20LDEASSERTTHRESH1, 0x0381);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20UASSERTTHRESH0, 0x042b);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20UASSERTTHRESH1, 0x042b);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20UDEASSERTTHRESH0, 0x0381);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20UDEASSERTTHRESH1, 0x0381);
if (dev->phy.rev >= 6 && sprom->boardflags2_lo & B43_BFL2_SINGLEANT_CCK)
; /* TODO: 0x0080000000000000 HF */
@@ -2572,7 +2627,7 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
- dev->dev->board_type == 0x8B) {
+ dev->dev->board_type == BCMA_BOARD_TYPE_BCM943224M93) {
delays1[0] = 0x1;
delays1[5] = 0x14;
}
@@ -3120,21 +3175,21 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
b43_nphy_ipa_internal_tssi_setup(dev);
if (phy->rev >= 7)
- b43_nphy_rf_control_override_rev7(dev, 0x2000, 0, 3, false, 0);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 0, 3, false, 0);
else if (phy->rev >= 3)
- b43_nphy_rf_control_override(dev, 0x2000, 0, 3, false);
+ b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, false);
b43_nphy_stop_playback(dev);
b43_nphy_tx_tone(dev, 0xFA0, 0, false, false);
udelay(20);
- tmp = b43_nphy_poll_rssi(dev, 4, rssi, 1);
+ tmp = b43_nphy_poll_rssi(dev, N_RSSI_TSSI_2G, rssi, 1);
b43_nphy_stop_playback(dev);
- b43_nphy_rssi_select(dev, 0, 0);
+ b43_nphy_rssi_select(dev, 0, N_RSSI_W1);
if (phy->rev >= 7)
- b43_nphy_rf_control_override_rev7(dev, 0x2000, 0, 3, true, 0);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 0, 3, true, 0);
else if (phy->rev >= 3)
- b43_nphy_rf_control_override(dev, 0x2000, 0, 3, true);
+ b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true);
if (phy->rev >= 3) {
nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF;
@@ -3573,8 +3628,8 @@ static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007);
}
- b43_nphy_rf_control_intc_override(dev, 2, 0, 3);
- b43_nphy_rf_control_override(dev, 8, 0, 3, false);
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 0, 3);
+ b43_nphy_rf_ctl_override(dev, 8, 0, 3, false);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
if (core == 0) {
@@ -3584,8 +3639,10 @@ static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
rxval = 4;
txval = 2;
}
- b43_nphy_rf_control_intc_override(dev, 1, rxval, (core + 1));
- b43_nphy_rf_control_intc_override(dev, 1, txval, (2 - core));
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, rxval,
+ core + 1);
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, txval,
+ 2 - core);
}
#endif
@@ -3847,9 +3904,13 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
}
- /* TODO use some definitions */
- b43_radio_maskset(dev, 0x602B, 0xE3, rssical_radio_regs[0]);
- b43_radio_maskset(dev, 0x702B, 0xE3, rssical_radio_regs[1]);
+ if (dev->phy.rev >= 7) {
+ } else {
+ b43_radio_maskset(dev, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3,
+ rssical_radio_regs[0]);
+ b43_radio_maskset(dev, B2056_RX1 | B2056_RX_RSSI_MISC, 0xE3,
+ rssical_radio_regs[1]);
+ }
b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]);
b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]);
@@ -3880,75 +3941,75 @@ static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
tmp = (i == 0) ? 0x2000 : 0x3000;
offset = i * 11;
- save[offset + 0] = b43_radio_read16(dev, B2055_CAL_RVARCTL);
- save[offset + 1] = b43_radio_read16(dev, B2055_CAL_LPOCTL);
- save[offset + 2] = b43_radio_read16(dev, B2055_CAL_TS);
- save[offset + 3] = b43_radio_read16(dev, B2055_CAL_RCCALRTS);
- save[offset + 4] = b43_radio_read16(dev, B2055_CAL_RCALRTS);
- save[offset + 5] = b43_radio_read16(dev, B2055_PADDRV);
- save[offset + 6] = b43_radio_read16(dev, B2055_XOCTL1);
- save[offset + 7] = b43_radio_read16(dev, B2055_XOCTL2);
- save[offset + 8] = b43_radio_read16(dev, B2055_XOREGUL);
- save[offset + 9] = b43_radio_read16(dev, B2055_XOMISC);
- save[offset + 10] = b43_radio_read16(dev, B2055_PLL_LFC1);
+ save[offset + 0] = b43_radio_read(dev, B2055_CAL_RVARCTL);
+ save[offset + 1] = b43_radio_read(dev, B2055_CAL_LPOCTL);
+ save[offset + 2] = b43_radio_read(dev, B2055_CAL_TS);
+ save[offset + 3] = b43_radio_read(dev, B2055_CAL_RCCALRTS);
+ save[offset + 4] = b43_radio_read(dev, B2055_CAL_RCALRTS);
+ save[offset + 5] = b43_radio_read(dev, B2055_PADDRV);
+ save[offset + 6] = b43_radio_read(dev, B2055_XOCTL1);
+ save[offset + 7] = b43_radio_read(dev, B2055_XOCTL2);
+ save[offset + 8] = b43_radio_read(dev, B2055_XOREGUL);
+ save[offset + 9] = b43_radio_read(dev, B2055_XOMISC);
+ save[offset + 10] = b43_radio_read(dev, B2055_PLL_LFC1);
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x0A);
- b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
- b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
- b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
- b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
+ b43_radio_write(dev, tmp | B2055_CAL_RVARCTL, 0x0A);
+ b43_radio_write(dev, tmp | B2055_CAL_LPOCTL, 0x40);
+ b43_radio_write(dev, tmp | B2055_CAL_TS, 0x55);
+ b43_radio_write(dev, tmp | B2055_CAL_RCCALRTS, 0);
+ b43_radio_write(dev, tmp | B2055_CAL_RCALRTS, 0);
if (nphy->ipa5g_on) {
- b43_radio_write16(dev, tmp | B2055_PADDRV, 4);
- b43_radio_write16(dev, tmp | B2055_XOCTL1, 1);
+ b43_radio_write(dev, tmp | B2055_PADDRV, 4);
+ b43_radio_write(dev, tmp | B2055_XOCTL1, 1);
} else {
- b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
- b43_radio_write16(dev, tmp | B2055_XOCTL1, 0x2F);
+ b43_radio_write(dev, tmp | B2055_PADDRV, 0);
+ b43_radio_write(dev, tmp | B2055_XOCTL1, 0x2F);
}
- b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
+ b43_radio_write(dev, tmp | B2055_XOCTL2, 0);
} else {
- b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x06);
- b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
- b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
- b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
- b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
- b43_radio_write16(dev, tmp | B2055_XOCTL1, 0);
+ b43_radio_write(dev, tmp | B2055_CAL_RVARCTL, 0x06);
+ b43_radio_write(dev, tmp | B2055_CAL_LPOCTL, 0x40);
+ b43_radio_write(dev, tmp | B2055_CAL_TS, 0x55);
+ b43_radio_write(dev, tmp | B2055_CAL_RCCALRTS, 0);
+ b43_radio_write(dev, tmp | B2055_CAL_RCALRTS, 0);
+ b43_radio_write(dev, tmp | B2055_XOCTL1, 0);
if (nphy->ipa2g_on) {
- b43_radio_write16(dev, tmp | B2055_PADDRV, 6);
- b43_radio_write16(dev, tmp | B2055_XOCTL2,
+ b43_radio_write(dev, tmp | B2055_PADDRV, 6);
+ b43_radio_write(dev, tmp | B2055_XOCTL2,
(dev->phy.rev < 5) ? 0x11 : 0x01);
} else {
- b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
- b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
+ b43_radio_write(dev, tmp | B2055_PADDRV, 0);
+ b43_radio_write(dev, tmp | B2055_XOCTL2, 0);
}
}
- b43_radio_write16(dev, tmp | B2055_XOREGUL, 0);
- b43_radio_write16(dev, tmp | B2055_XOMISC, 0);
- b43_radio_write16(dev, tmp | B2055_PLL_LFC1, 0);
+ b43_radio_write(dev, tmp | B2055_XOREGUL, 0);
+ b43_radio_write(dev, tmp | B2055_XOMISC, 0);
+ b43_radio_write(dev, tmp | B2055_PLL_LFC1, 0);
}
} else {
- save[0] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL1);
- b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL1, 0x29);
+ save[0] = b43_radio_read(dev, B2055_C1_TX_RF_IQCAL1);
+ b43_radio_write(dev, B2055_C1_TX_RF_IQCAL1, 0x29);
- save[1] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL2);
- b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL2, 0x54);
+ save[1] = b43_radio_read(dev, B2055_C1_TX_RF_IQCAL2);
+ b43_radio_write(dev, B2055_C1_TX_RF_IQCAL2, 0x54);
- save[2] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL1);
- b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL1, 0x29);
+ save[2] = b43_radio_read(dev, B2055_C2_TX_RF_IQCAL1);
+ b43_radio_write(dev, B2055_C2_TX_RF_IQCAL1, 0x29);
- save[3] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL2);
- b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL2, 0x54);
+ save[3] = b43_radio_read(dev, B2055_C2_TX_RF_IQCAL2);
+ b43_radio_write(dev, B2055_C2_TX_RF_IQCAL2, 0x54);
- save[3] = b43_radio_read16(dev, B2055_C1_PWRDET_RXTX);
- save[4] = b43_radio_read16(dev, B2055_C2_PWRDET_RXTX);
+ save[3] = b43_radio_read(dev, B2055_C1_PWRDET_RXTX);
+ save[4] = b43_radio_read(dev, B2055_C2_PWRDET_RXTX);
if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) &
B43_NPHY_BANDCTL_5GHZ)) {
- b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x04);
- b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x04);
+ b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x04);
+ b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x04);
} else {
- b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x20);
- b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x20);
+ b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x20);
+ b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x20);
}
if (dev->phy.rev < 2) {
@@ -4144,9 +4205,9 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
- b43_nphy_rf_control_intc_override(dev, 2, 1, 3);
- b43_nphy_rf_control_intc_override(dev, 1, 2, 1);
- b43_nphy_rf_control_intc_override(dev, 1, 8, 2);
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 1, 3);
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 2, 1);
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 8, 2);
regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
@@ -4679,7 +4740,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |
(cur_lna << 2));
- b43_nphy_rf_control_override(dev, 0x400, tmp[0], 3,
+ b43_nphy_rf_ctl_override(dev, 0x400, tmp[0], 3,
false);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
b43_nphy_stop_playback(dev);
@@ -4728,7 +4789,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
break;
}
- b43_nphy_rf_control_override(dev, 0x400, 0, 3, true);
+ b43_nphy_rf_ctl_override(dev, 0x400, 0, 3, true);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
@@ -4797,18 +4858,6 @@ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
* N-PHY init
**************************************************/
-/*
- * Upload the N-PHY tables.
- * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
- */
-static void b43_nphy_tables_init(struct b43_wldev *dev)
-{
- if (dev->phy.rev < 3)
- b43_nphy_rev0_1_2_tables_init(dev);
- else
- b43_nphy_rev3plus_tables_init(dev);
-}
-
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble)
{
@@ -4958,7 +5007,7 @@ static int b43_phy_initn(struct b43_wldev *dev)
if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
(dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
- dev->dev->board_type == 0x8B))
+ dev->dev->board_type == BCMA_BOARD_TYPE_BCM943224M93))
b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
else
b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
@@ -5100,63 +5149,11 @@ static void b43_chantab_phy_upload(struct b43_wldev *dev,
/* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */
static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)
{
- struct bcma_drv_cc __maybe_unused *cc;
- u32 __maybe_unused pmu_ctl;
-
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA:
- cc = &dev->dev->bdev->bus->drv_cc;
- if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
- if (avoid) {
- bcma_chipco_pll_write(cc, 0x0, 0x11500010);
- bcma_chipco_pll_write(cc, 0x1, 0x000C0C06);
- bcma_chipco_pll_write(cc, 0x2, 0x0F600a08);
- bcma_chipco_pll_write(cc, 0x3, 0x00000000);
- bcma_chipco_pll_write(cc, 0x4, 0x2001E920);
- bcma_chipco_pll_write(cc, 0x5, 0x88888815);
- } else {
- bcma_chipco_pll_write(cc, 0x0, 0x11100010);
- bcma_chipco_pll_write(cc, 0x1, 0x000c0c06);
- bcma_chipco_pll_write(cc, 0x2, 0x03000a08);
- bcma_chipco_pll_write(cc, 0x3, 0x00000000);
- bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
- bcma_chipco_pll_write(cc, 0x5, 0x88888815);
- }
- pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD;
- } else if (dev->dev->chip_id == 0x4716) {
- if (avoid) {
- bcma_chipco_pll_write(cc, 0x0, 0x11500060);
- bcma_chipco_pll_write(cc, 0x1, 0x080C0C06);
- bcma_chipco_pll_write(cc, 0x2, 0x0F600000);
- bcma_chipco_pll_write(cc, 0x3, 0x00000000);
- bcma_chipco_pll_write(cc, 0x4, 0x2001E924);
- bcma_chipco_pll_write(cc, 0x5, 0x88888815);
- } else {
- bcma_chipco_pll_write(cc, 0x0, 0x11100060);
- bcma_chipco_pll_write(cc, 0x1, 0x080c0c06);
- bcma_chipco_pll_write(cc, 0x2, 0x03000000);
- bcma_chipco_pll_write(cc, 0x3, 0x00000000);
- bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
- bcma_chipco_pll_write(cc, 0x5, 0x88888815);
- }
- pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD |
- BCMA_CC_PMU_CTL_NOILPONW;
- } else if (dev->dev->chip_id == 0x4322 ||
- dev->dev->chip_id == 0x4340 ||
- dev->dev->chip_id == 0x4341) {
- bcma_chipco_pll_write(cc, 0x0, 0x11100070);
- bcma_chipco_pll_write(cc, 0x1, 0x1014140a);
- bcma_chipco_pll_write(cc, 0x5, 0x88888854);
- if (avoid)
- bcma_chipco_pll_write(cc, 0x2, 0x05201828);
- else
- bcma_chipco_pll_write(cc, 0x2, 0x05001828);
- pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD;
- } else {
- return;
- }
- bcma_cc_set32(cc, BCMA_CC_PMU_CTL, pmu_ctl);
+ bcma_pmu_spuravoid_pllupdate(&dev->dev->bdev->bus->drv_cc,
+ avoid);
break;
#endif
#ifdef CONFIG_B43_SSB
@@ -5527,8 +5524,9 @@ static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
unsigned int new_channel)
{
- struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
- enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
+ struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
if ((new_channel < 1) || (new_channel > 14))
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h
index 092c0140c249..9a5b6bc27d24 100644
--- a/drivers/net/wireless/b43/phy_n.h
+++ b/drivers/net/wireless/b43/phy_n.h
@@ -54,10 +54,15 @@
#define B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT 7
#define B43_NPHY_C1_INITGAIN_TRRX 0x1000 /* TR RX index */
#define B43_NPHY_C1_INITGAIN_TRTX 0x2000 /* TR TX index */
+#define B43_NPHY_REV3_C1_INITGAIN_A B43_PHY_N(0x020)
#define B43_NPHY_C1_CLIP1_HIGAIN B43_PHY_N(0x021) /* Core 1 clip1 high gain code */
+#define B43_NPHY_REV3_C1_INITGAIN_B B43_PHY_N(0x021)
#define B43_NPHY_C1_CLIP1_MEDGAIN B43_PHY_N(0x022) /* Core 1 clip1 medium gain code */
+#define B43_NPHY_REV3_C1_CLIP_HIGAIN_A B43_PHY_N(0x022)
#define B43_NPHY_C1_CLIP1_LOGAIN B43_PHY_N(0x023) /* Core 1 clip1 low gain code */
+#define B43_NPHY_REV3_C1_CLIP_HIGAIN_B B43_PHY_N(0x023)
#define B43_NPHY_C1_CLIP2_GAIN B43_PHY_N(0x024) /* Core 1 clip2 gain code */
+#define B43_NPHY_REV3_C1_CLIP_MEDGAIN_A B43_PHY_N(0x024)
#define B43_NPHY_C1_FILTERGAIN B43_PHY_N(0x025) /* Core 1 filter gain */
#define B43_NPHY_C1_LPF_QHPF_BW B43_PHY_N(0x026) /* Core 1 LPF Q HP F bandwidth */
#define B43_NPHY_C1_CLIPWBTHRES B43_PHY_N(0x027) /* Core 1 clip wideband threshold */
@@ -107,10 +112,15 @@
#define B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT 7
#define B43_NPHY_C2_INITGAIN_TRRX 0x1000 /* TR RX index */
#define B43_NPHY_C2_INITGAIN_TRTX 0x2000 /* TR TX index */
+#define B43_NPHY_REV3_C1_CLIP_MEDGAIN_B B43_PHY_N(0x036)
#define B43_NPHY_C2_CLIP1_HIGAIN B43_PHY_N(0x037) /* Core 2 clip1 high gain code */
+#define B43_NPHY_REV3_C1_CLIP_LOGAIN_A B43_PHY_N(0x037)
#define B43_NPHY_C2_CLIP1_MEDGAIN B43_PHY_N(0x038) /* Core 2 clip1 medium gain code */
+#define B43_NPHY_REV3_C1_CLIP_LOGAIN_B B43_PHY_N(0x038)
#define B43_NPHY_C2_CLIP1_LOGAIN B43_PHY_N(0x039) /* Core 2 clip1 low gain code */
+#define B43_NPHY_REV3_C1_CLIP2_GAIN_A B43_PHY_N(0x039)
#define B43_NPHY_C2_CLIP2_GAIN B43_PHY_N(0x03A) /* Core 2 clip2 gain code */
+#define B43_NPHY_REV3_C1_CLIP2_GAIN_B B43_PHY_N(0x03A)
#define B43_NPHY_C2_FILTERGAIN B43_PHY_N(0x03B) /* Core 2 filter gain */
#define B43_NPHY_C2_LPF_QHPF_BW B43_PHY_N(0x03C) /* Core 2 LPF Q HP F bandwidth */
#define B43_NPHY_C2_CLIPWBTHRES B43_PHY_N(0x03D) /* Core 2 clip wideband threshold */
@@ -706,10 +716,146 @@
#define B43_NPHY_TXPCTL_INIT B43_PHY_N(0x222) /* TX power control init */
#define B43_NPHY_TXPCTL_INIT_PIDXI1 0x00FF /* Power index init 1 */
#define B43_NPHY_TXPCTL_INIT_PIDXI1_SHIFT 0
+#define B43_NPHY_ED_CRSEN B43_PHY_N(0x223)
+#define B43_NPHY_ED_CRS40ASSERTTHRESH0 B43_PHY_N(0x224)
+#define B43_NPHY_ED_CRS40ASSERTTHRESH1 B43_PHY_N(0x225)
+#define B43_NPHY_ED_CRS40DEASSERTTHRESH0 B43_PHY_N(0x226)
+#define B43_NPHY_ED_CRS40DEASSERTTHRESH1 B43_PHY_N(0x227)
+#define B43_NPHY_ED_CRS20LASSERTTHRESH0 B43_PHY_N(0x228)
+#define B43_NPHY_ED_CRS20LASSERTTHRESH1 B43_PHY_N(0x229)
+#define B43_NPHY_ED_CRS20LDEASSERTTHRESH0 B43_PHY_N(0x22A)
+#define B43_NPHY_ED_CRS20LDEASSERTTHRESH1 B43_PHY_N(0x22B)
+#define B43_NPHY_ED_CRS20UASSERTTHRESH0 B43_PHY_N(0x22C)
+#define B43_NPHY_ED_CRS20UASSERTTHRESH1 B43_PHY_N(0x22D)
+#define B43_NPHY_ED_CRS20UDEASSERTTHRESH0 B43_PHY_N(0x22E)
+#define B43_NPHY_ED_CRS20UDEASSERTTHRESH1 B43_PHY_N(0x22F)
+#define B43_NPHY_ED_CRS B43_PHY_N(0x230)
+#define B43_NPHY_TIMEOUTEN B43_PHY_N(0x231)
+#define B43_NPHY_OFDMPAYDECODETIMEOUTLEN B43_PHY_N(0x232)
+#define B43_NPHY_CCKPAYDECODETIMEOUTLEN B43_PHY_N(0x233)
+#define B43_NPHY_NONPAYDECODETIMEOUTLEN B43_PHY_N(0x234)
+#define B43_NPHY_TIMEOUTSTATUS B43_PHY_N(0x235)
+#define B43_NPHY_RFCTRLCORE0GPIO0 B43_PHY_N(0x236)
+#define B43_NPHY_RFCTRLCORE0GPIO1 B43_PHY_N(0x237)
+#define B43_NPHY_RFCTRLCORE0GPIO2 B43_PHY_N(0x238)
+#define B43_NPHY_RFCTRLCORE0GPIO3 B43_PHY_N(0x239)
+#define B43_NPHY_RFCTRLCORE1GPIO0 B43_PHY_N(0x23A)
+#define B43_NPHY_RFCTRLCORE1GPIO1 B43_PHY_N(0x23B)
+#define B43_NPHY_RFCTRLCORE1GPIO2 B43_PHY_N(0x23C)
+#define B43_NPHY_RFCTRLCORE1GPIO3 B43_PHY_N(0x23D)
+#define B43_NPHY_BPHYTESTCONTROL B43_PHY_N(0x23E)
+/* REV3+ */
+#define B43_NPHY_FORCEFRONT0 B43_PHY_N(0x23F)
+#define B43_NPHY_FORCEFRONT1 B43_PHY_N(0x240)
+#define B43_NPHY_NORMVARHYSTTH B43_PHY_N(0x241)
+#define B43_NPHY_TXCCKERROR B43_PHY_N(0x242)
+#define B43_NPHY_AFESEQINITDACGAIN B43_PHY_N(0x243)
+#define B43_NPHY_TXANTSWLUT B43_PHY_N(0x244)
+#define B43_NPHY_CORECONFIG B43_PHY_N(0x245)
+#define B43_NPHY_ANTENNADIVDWELLTIME B43_PHY_N(0x246)
+#define B43_NPHY_ANTENNACCKDIVDWELLTIME B43_PHY_N(0x247)
+#define B43_NPHY_ANTENNADIVBACKOFFGAIN B43_PHY_N(0x248)
+#define B43_NPHY_ANTENNADIVMINGAIN B43_PHY_N(0x249)
+#define B43_NPHY_BRDSEL_NORMVARHYSTTH B43_PHY_N(0x24A)
+#define B43_NPHY_RXANTSWITCHCTRL B43_PHY_N(0x24B)
+#define B43_NPHY_ENERGYDROPTIMEOUTLEN2 B43_PHY_N(0x24C)
+#define B43_NPHY_ML_LOG_TXEVM0 B43_PHY_N(0x250)
+#define B43_NPHY_ML_LOG_TXEVM1 B43_PHY_N(0x251)
+#define B43_NPHY_ML_LOG_TXEVM2 B43_PHY_N(0x252)
+#define B43_NPHY_ML_LOG_TXEVM3 B43_PHY_N(0x253)
+#define B43_NPHY_ML_LOG_TXEVM4 B43_PHY_N(0x254)
+#define B43_NPHY_ML_LOG_TXEVM5 B43_PHY_N(0x255)
+#define B43_NPHY_ML_LOG_TXEVM6 B43_PHY_N(0x256)
+#define B43_NPHY_ML_LOG_TXEVM7 B43_PHY_N(0x257)
+#define B43_NPHY_ML_SCALE_TWEAK B43_PHY_N(0x258)
+#define B43_NPHY_MLUA B43_PHY_N(0x259)
+#define B43_NPHY_ZFUA B43_PHY_N(0x25A)
+#define B43_NPHY_CHANUPSYM01 B43_PHY_N(0x25B)
+#define B43_NPHY_CHANUPSYM2 B43_PHY_N(0x25C)
+#define B43_NPHY_RXSTRNFILT20NUM00 B43_PHY_N(0x25D)
+#define B43_NPHY_RXSTRNFILT20NUM01 B43_PHY_N(0x25E)
+#define B43_NPHY_RXSTRNFILT20NUM02 B43_PHY_N(0x25F)
+#define B43_NPHY_RXSTRNFILT20DEN00 B43_PHY_N(0x260)
+#define B43_NPHY_RXSTRNFILT20DEN01 B43_PHY_N(0x261)
+#define B43_NPHY_RXSTRNFILT20NUM10 B43_PHY_N(0x262)
+#define B43_NPHY_RXSTRNFILT20NUM11 B43_PHY_N(0x263)
+#define B43_NPHY_RXSTRNFILT20NUM12 B43_PHY_N(0x264)
+#define B43_NPHY_RXSTRNFILT20DEN10 B43_PHY_N(0x265)
+#define B43_NPHY_RXSTRNFILT20DEN11 B43_PHY_N(0x266)
+#define B43_NPHY_RXSTRNFILT40NUM00 B43_PHY_N(0x267)
+#define B43_NPHY_RXSTRNFILT40NUM01 B43_PHY_N(0x268)
+#define B43_NPHY_RXSTRNFILT40NUM02 B43_PHY_N(0x269)
+#define B43_NPHY_RXSTRNFILT40DEN00 B43_PHY_N(0x26A)
+#define B43_NPHY_RXSTRNFILT40DEN01 B43_PHY_N(0x26B)
+#define B43_NPHY_RXSTRNFILT40NUM10 B43_PHY_N(0x26C)
+#define B43_NPHY_RXSTRNFILT40NUM11 B43_PHY_N(0x26D)
+#define B43_NPHY_RXSTRNFILT40NUM12 B43_PHY_N(0x26E)
+#define B43_NPHY_RXSTRNFILT40DEN10 B43_PHY_N(0x26F)
+#define B43_NPHY_RXSTRNFILT40DEN11 B43_PHY_N(0x270)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD1 B43_PHY_N(0x271)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD2 B43_PHY_N(0x272)
+#define B43_NPHY_CRSHIGHLOWPOWTHRESHOLD B43_PHY_N(0x273)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD1L B43_PHY_N(0x274)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD2L B43_PHY_N(0x275)
+#define B43_NPHY_CRSHIGHLOWPOWTHRESHOLDL B43_PHY_N(0x276)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD1U B43_PHY_N(0x277)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD2U B43_PHY_N(0x278)
+#define B43_NPHY_CRSHIGHLOWPOWTHRESHOLDU B43_PHY_N(0x279)
+#define B43_NPHY_CRSACIDETECTTHRESH B43_PHY_N(0x27A)
+#define B43_NPHY_CRSACIDETECTTHRESHL B43_PHY_N(0x27B)
+#define B43_NPHY_CRSACIDETECTTHRESHU B43_PHY_N(0x27C)
+#define B43_NPHY_CRSMINPOWER0 B43_PHY_N(0x27D)
+#define B43_NPHY_CRSMINPOWER1 B43_PHY_N(0x27E)
+#define B43_NPHY_CRSMINPOWER2 B43_PHY_N(0x27F)
+#define B43_NPHY_CRSMINPOWERL0 B43_PHY_N(0x280)
+#define B43_NPHY_CRSMINPOWERL1 B43_PHY_N(0x281)
+#define B43_NPHY_CRSMINPOWERL2 B43_PHY_N(0x282)
+#define B43_NPHY_CRSMINPOWERU0 B43_PHY_N(0x283)
+#define B43_NPHY_CRSMINPOWERU1 B43_PHY_N(0x284)
+#define B43_NPHY_CRSMINPOWERU2 B43_PHY_N(0x285)
+#define B43_NPHY_STRPARAM B43_PHY_N(0x286)
+#define B43_NPHY_STRPARAML B43_PHY_N(0x287)
+#define B43_NPHY_STRPARAMU B43_PHY_N(0x288)
+#define B43_NPHY_BPHYCRSMINPOWER0 B43_PHY_N(0x289)
+#define B43_NPHY_BPHYCRSMINPOWER1 B43_PHY_N(0x28A)
+#define B43_NPHY_BPHYCRSMINPOWER2 B43_PHY_N(0x28B)
+#define B43_NPHY_BPHYFILTDEN0COEF B43_PHY_N(0x28C)
+#define B43_NPHY_BPHYFILTDEN1COEF B43_PHY_N(0x28D)
+#define B43_NPHY_BPHYFILTDEN2COEF B43_PHY_N(0x28E)
+#define B43_NPHY_BPHYFILTNUM0COEF B43_PHY_N(0x28F)
+#define B43_NPHY_BPHYFILTNUM1COEF B43_PHY_N(0x290)
+#define B43_NPHY_BPHYFILTNUM2COEF B43_PHY_N(0x291)
+#define B43_NPHY_BPHYFILTNUM01COEF2 B43_PHY_N(0x292)
+#define B43_NPHY_BPHYFILTBYPASS B43_PHY_N(0x293)
+#define B43_NPHY_SGILTRNOFFSET B43_PHY_N(0x294)
+#define B43_NPHY_RADAR_T2_MIN B43_PHY_N(0x295)
+#define B43_NPHY_TXPWRCTRLDAMPING B43_PHY_N(0x296)
#define B43_NPHY_PAPD_EN0 B43_PHY_N(0x297) /* PAPD Enable0 TBD */
#define B43_NPHY_EPS_TABLE_ADJ0 B43_PHY_N(0x298) /* EPS Table Adj0 TBD */
+#define B43_NPHY_EPS_OVERRIDEI_0 B43_PHY_N(0x299)
+#define B43_NPHY_EPS_OVERRIDEQ_0 B43_PHY_N(0x29A)
#define B43_NPHY_PAPD_EN1 B43_PHY_N(0x29B) /* PAPD Enable1 TBD */
#define B43_NPHY_EPS_TABLE_ADJ1 B43_PHY_N(0x29C) /* EPS Table Adj1 TBD */
+#define B43_NPHY_EPS_OVERRIDEI_1 B43_PHY_N(0x29D)
+#define B43_NPHY_EPS_OVERRIDEQ_1 B43_PHY_N(0x29E)
+#define B43_NPHY_PAPD_CAL_ADDRESS B43_PHY_N(0x29F)
+#define B43_NPHY_PAPD_CAL_YREFEPSILON B43_PHY_N(0x2A0)
+#define B43_NPHY_PAPD_CAL_SETTLE B43_PHY_N(0x2A1)
+#define B43_NPHY_PAPD_CAL_CORRELATE B43_PHY_N(0x2A2)
+#define B43_NPHY_PAPD_CAL_SHIFTS0 B43_PHY_N(0x2A3)
+#define B43_NPHY_PAPD_CAL_SHIFTS1 B43_PHY_N(0x2A4)
+#define B43_NPHY_SAMPLE_START_ADDR B43_PHY_N(0x2A5)
+#define B43_NPHY_RADAR_ADC_TO_DBM B43_PHY_N(0x2A6)
+#define B43_NPHY_REV3_C2_INITGAIN_A B43_PHY_N(0x2A7)
+#define B43_NPHY_REV3_C2_INITGAIN_B B43_PHY_N(0x2A8)
+#define B43_NPHY_REV3_C2_CLIP_HIGAIN_A B43_PHY_N(0x2A9)
+#define B43_NPHY_REV3_C2_CLIP_HIGAIN_B B43_PHY_N(0x2AA)
+#define B43_NPHY_REV3_C2_CLIP_MEDGAIN_A B43_PHY_N(0x2AB)
+#define B43_NPHY_REV3_C2_CLIP_MEDGAIN_B B43_PHY_N(0x2AC)
+#define B43_NPHY_REV3_C2_CLIP_LOGAIN_A B43_PHY_N(0x2AD)
+#define B43_NPHY_REV3_C2_CLIP_LOGAIN_B B43_PHY_N(0x2AE)
+#define B43_NPHY_REV3_C2_CLIP2_GAIN_A B43_PHY_N(0x2AF)
+#define B43_NPHY_REV3_C2_CLIP2_GAIN_B B43_PHY_N(0x2B0)
#define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */
#define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A)
diff --git a/drivers/net/wireless/b43/radio_2059.c b/drivers/net/wireless/b43/radio_2059.c
index d4ce8a12ff9a..38e31d857e3e 100644
--- a/drivers/net/wireless/b43/radio_2059.c
+++ b/drivers/net/wireless/b43/radio_2059.c
@@ -27,7 +27,7 @@
#define RADIOREGS(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
- r20, r21, r22, r23, r24, r25, r26, r27, r28) \
+ r20) \
.radio_syn16 = r00, \
.radio_syn17 = r01, \
.radio_syn22 = r02, \
@@ -41,22 +41,14 @@
.radio_syn41 = r10, \
.radio_syn43 = r11, \
.radio_syn47 = r12, \
- .radio_syn4a = r13, \
- .radio_syn58 = r14, \
- .radio_syn5a = r15, \
- .radio_syn6a = r16, \
- .radio_syn6d = r17, \
- .radio_syn6e = r18, \
- .radio_syn92 = r19, \
- .radio_syn98 = r20, \
- .radio_rxtx4a = r21, \
- .radio_rxtx58 = r22, \
- .radio_rxtx5a = r23, \
- .radio_rxtx6a = r24, \
- .radio_rxtx6d = r25, \
- .radio_rxtx6e = r26, \
- .radio_rxtx92 = r27, \
- .radio_rxtx98 = r28
+ .radio_rxtx4a = r13, \
+ .radio_rxtx58 = r14, \
+ .radio_rxtx5a = r15, \
+ .radio_rxtx6a = r16, \
+ .radio_rxtx6d = r17, \
+ .radio_rxtx6e = r18, \
+ .radio_rxtx92 = r19, \
+ .radio_rxtx98 = r20
#define PHYREGS(r0, r1, r2, r3, r4, r5) \
.phy_regs.bw1 = r0, \
@@ -70,91 +62,78 @@ static const struct b43_phy_ht_channeltab_e_radio2059 b43_phy_ht_channeltab_radi
{ .freq = 2412,
RADIOREGS(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
},
{ .freq = 2417,
RADIOREGS(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
},
{ .freq = 2422,
RADIOREGS(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
},
{ .freq = 2427,
RADIOREGS(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
},
{ .freq = 2432,
RADIOREGS(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
},
{ .freq = 2437,
RADIOREGS(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
},
{ .freq = 2442,
RADIOREGS(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
},
{ .freq = 2447,
RADIOREGS(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
},
{ .freq = 2452,
RADIOREGS(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
},
{ .freq = 2457,
RADIOREGS(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
},
{ .freq = 2462,
RADIOREGS(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
},
{ .freq = 2467,
RADIOREGS(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
},
{ .freq = 2472,
RADIOREGS(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
},
diff --git a/drivers/net/wireless/b43/radio_2059.h b/drivers/net/wireless/b43/radio_2059.h
index e4d69e55e9fe..40a82d7f510c 100644
--- a/drivers/net/wireless/b43/radio_2059.h
+++ b/drivers/net/wireless/b43/radio_2059.h
@@ -5,9 +5,9 @@
#include "phy_ht.h"
-#define R2059_SYN 0x000
-#define R2059_TXRX0 0x400
-#define R2059_RXRX1 0x800
+#define R2059_C1 0x000
+#define R2059_C2 0x400
+#define R2059_C3 0x800
#define R2059_ALL 0xC00
/* Values for various registers uploaded on channel switching */
@@ -28,14 +28,6 @@ struct b43_phy_ht_channeltab_e_radio2059 {
u8 radio_syn41;
u8 radio_syn43;
u8 radio_syn47;
- u8 radio_syn4a;
- u8 radio_syn58;
- u8 radio_syn5a;
- u8 radio_syn6a;
- u8 radio_syn6d;
- u8 radio_syn6e;
- u8 radio_syn92;
- u8 radio_syn98;
u8 radio_rxtx4a;
u8 radio_rxtx58;
u8 radio_rxtx5a;
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index 110510d53958..94c755fdda14 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -2174,7 +2174,7 @@ static const u16 b43_ntab_loftlt1_r3[] = {
/* volatile tables, PHY revision >= 3 */
/* indexed by antswctl2g */
-static const u16 b43_ntab_antswctl2g_r3[4][32] = {
+static const u16 b43_ntab_antswctl_r3[4][32] = {
{
0x0082, 0x0082, 0x0211, 0x0222, 0x0328,
0x0000, 0x0000, 0x0000, 0x0144, 0x0000,
@@ -3095,9 +3095,55 @@ void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
}
#define ntab_upload(dev, offset, data) do { \
- b43_ntab_write_bulk(dev, offset, offset##_SIZE, data); \
+ b43_ntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
} while (0)
-void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev)
+
+static void b43_nphy_tables_init_rev3(struct b43_wldev *dev)
+{
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
+ u8 antswlut;
+
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
+ antswlut = sprom->fem.ghz5.antswlut;
+ else
+ antswlut = sprom->fem.ghz2.antswlut;
+
+ /* Static tables */
+ ntab_upload(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
+ ntab_upload(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
+ ntab_upload(dev, B43_NTAB_TMAP_R3, b43_ntab_tmap_r3);
+ ntab_upload(dev, B43_NTAB_INTLEVEL_R3, b43_ntab_intlevel_r3);
+ ntab_upload(dev, B43_NTAB_TDTRN_R3, b43_ntab_tdtrn_r3);
+ ntab_upload(dev, B43_NTAB_NOISEVAR0_R3, b43_ntab_noisevar0_r3);
+ ntab_upload(dev, B43_NTAB_NOISEVAR1_R3, b43_ntab_noisevar1_r3);
+ ntab_upload(dev, B43_NTAB_MCS_R3, b43_ntab_mcs_r3);
+ ntab_upload(dev, B43_NTAB_TDI20A0_R3, b43_ntab_tdi20a0_r3);
+ ntab_upload(dev, B43_NTAB_TDI20A1_R3, b43_ntab_tdi20a1_r3);
+ ntab_upload(dev, B43_NTAB_TDI40A0_R3, b43_ntab_tdi40a0_r3);
+ ntab_upload(dev, B43_NTAB_TDI40A1_R3, b43_ntab_tdi40a1_r3);
+ ntab_upload(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
+ ntab_upload(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
+ ntab_upload(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
+ ntab_upload(dev, B43_NTAB_C0_ESTPLT_R3, b43_ntab_estimatepowerlt0_r3);
+ ntab_upload(dev, B43_NTAB_C1_ESTPLT_R3, b43_ntab_estimatepowerlt1_r3);
+ ntab_upload(dev, B43_NTAB_C0_ADJPLT_R3, b43_ntab_adjustpower0_r3);
+ ntab_upload(dev, B43_NTAB_C1_ADJPLT_R3, b43_ntab_adjustpower1_r3);
+ ntab_upload(dev, B43_NTAB_C0_GAINCTL_R3, b43_ntab_gainctl0_r3);
+ ntab_upload(dev, B43_NTAB_C1_GAINCTL_R3, b43_ntab_gainctl1_r3);
+ ntab_upload(dev, B43_NTAB_C0_IQLT_R3, b43_ntab_iqlt0_r3);
+ ntab_upload(dev, B43_NTAB_C1_IQLT_R3, b43_ntab_iqlt1_r3);
+ ntab_upload(dev, B43_NTAB_C0_LOFEEDTH_R3, b43_ntab_loftlt0_r3);
+ ntab_upload(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
+
+ /* Volatile tables */
+ if (antswlut < ARRAY_SIZE(b43_ntab_antswctl_r3))
+ ntab_upload(dev, B43_NTAB_ANT_SW_CTL_R3,
+ b43_ntab_antswctl_r3[antswlut]);
+ else
+ B43_WARN_ON(1);
+}
+
+static void b43_nphy_tables_init_rev0(struct b43_wldev *dev)
{
/* Static tables */
ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct);
@@ -3130,48 +3176,13 @@ void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev)
ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1);
}
-#define ntab_upload_r3(dev, offset, data) do { \
- b43_ntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
- } while (0)
-void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables */
+void b43_nphy_tables_init(struct b43_wldev *dev)
{
- struct ssb_sprom *sprom = dev->dev->bus_sprom;
-
- /* Static tables */
- ntab_upload_r3(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
- ntab_upload_r3(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
- ntab_upload_r3(dev, B43_NTAB_TMAP_R3, b43_ntab_tmap_r3);
- ntab_upload_r3(dev, B43_NTAB_INTLEVEL_R3, b43_ntab_intlevel_r3);
- ntab_upload_r3(dev, B43_NTAB_TDTRN_R3, b43_ntab_tdtrn_r3);
- ntab_upload_r3(dev, B43_NTAB_NOISEVAR0_R3, b43_ntab_noisevar0_r3);
- ntab_upload_r3(dev, B43_NTAB_NOISEVAR1_R3, b43_ntab_noisevar1_r3);
- ntab_upload_r3(dev, B43_NTAB_MCS_R3, b43_ntab_mcs_r3);
- ntab_upload_r3(dev, B43_NTAB_TDI20A0_R3, b43_ntab_tdi20a0_r3);
- ntab_upload_r3(dev, B43_NTAB_TDI20A1_R3, b43_ntab_tdi20a1_r3);
- ntab_upload_r3(dev, B43_NTAB_TDI40A0_R3, b43_ntab_tdi40a0_r3);
- ntab_upload_r3(dev, B43_NTAB_TDI40A1_R3, b43_ntab_tdi40a1_r3);
- ntab_upload_r3(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
- ntab_upload_r3(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
- ntab_upload_r3(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
- ntab_upload_r3(dev, B43_NTAB_C0_ESTPLT_R3,
- b43_ntab_estimatepowerlt0_r3);
- ntab_upload_r3(dev, B43_NTAB_C1_ESTPLT_R3,
- b43_ntab_estimatepowerlt1_r3);
- ntab_upload_r3(dev, B43_NTAB_C0_ADJPLT_R3, b43_ntab_adjustpower0_r3);
- ntab_upload_r3(dev, B43_NTAB_C1_ADJPLT_R3, b43_ntab_adjustpower1_r3);
- ntab_upload_r3(dev, B43_NTAB_C0_GAINCTL_R3, b43_ntab_gainctl0_r3);
- ntab_upload_r3(dev, B43_NTAB_C1_GAINCTL_R3, b43_ntab_gainctl1_r3);
- ntab_upload_r3(dev, B43_NTAB_C0_IQLT_R3, b43_ntab_iqlt0_r3);
- ntab_upload_r3(dev, B43_NTAB_C1_IQLT_R3, b43_ntab_iqlt1_r3);
- ntab_upload_r3(dev, B43_NTAB_C0_LOFEEDTH_R3, b43_ntab_loftlt0_r3);
- ntab_upload_r3(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
-
- /* Volatile tables */
- if (sprom->fem.ghz2.antswlut < ARRAY_SIZE(b43_ntab_antswctl2g_r3))
- ntab_upload_r3(dev, B43_NTAB_ANT_SW_CTL_R3,
- b43_ntab_antswctl2g_r3[sprom->fem.ghz2.antswlut]);
+ if (dev->phy.rev >= 3)
+ b43_nphy_tables_init_rev3(dev);
else
- B43_WARN_ON(1);
+ b43_nphy_tables_init_rev0(dev);
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h
index c600700ceedc..9ff33adcff89 100644
--- a/drivers/net/wireless/b43/tables_nphy.h
+++ b/drivers/net/wireless/b43/tables_nphy.h
@@ -115,22 +115,22 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
#define B43_NTAB_NOISEVAR11_SIZE 256
#define B43_NTAB_C0_ESTPLT B43_NTAB8 (0x1A, 0x000) /* Estimate Power Lookup Table Core 0 */
#define B43_NTAB_C0_ESTPLT_SIZE 64
-#define B43_NTAB_C1_ESTPLT B43_NTAB8 (0x1B, 0x000) /* Estimate Power Lookup Table Core 1 */
-#define B43_NTAB_C1_ESTPLT_SIZE 64
#define B43_NTAB_C0_ADJPLT B43_NTAB8 (0x1A, 0x040) /* Adjust Power Lookup Table Core 0 */
#define B43_NTAB_C0_ADJPLT_SIZE 128
-#define B43_NTAB_C1_ADJPLT B43_NTAB8 (0x1B, 0x040) /* Adjust Power Lookup Table Core 1 */
-#define B43_NTAB_C1_ADJPLT_SIZE 128
#define B43_NTAB_C0_GAINCTL B43_NTAB32(0x1A, 0x0C0) /* Gain Control Lookup Table Core 0 */
#define B43_NTAB_C0_GAINCTL_SIZE 128
-#define B43_NTAB_C1_GAINCTL B43_NTAB32(0x1B, 0x0C0) /* Gain Control Lookup Table Core 1 */
-#define B43_NTAB_C1_GAINCTL_SIZE 128
#define B43_NTAB_C0_IQLT B43_NTAB32(0x1A, 0x140) /* IQ Lookup Table Core 0 */
#define B43_NTAB_C0_IQLT_SIZE 128
-#define B43_NTAB_C1_IQLT B43_NTAB32(0x1B, 0x140) /* IQ Lookup Table Core 1 */
-#define B43_NTAB_C1_IQLT_SIZE 128
#define B43_NTAB_C0_LOFEEDTH B43_NTAB16(0x1A, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 0 */
#define B43_NTAB_C0_LOFEEDTH_SIZE 128
+#define B43_NTAB_C1_ESTPLT B43_NTAB8 (0x1B, 0x000) /* Estimate Power Lookup Table Core 1 */
+#define B43_NTAB_C1_ESTPLT_SIZE 64
+#define B43_NTAB_C1_ADJPLT B43_NTAB8 (0x1B, 0x040) /* Adjust Power Lookup Table Core 1 */
+#define B43_NTAB_C1_ADJPLT_SIZE 128
+#define B43_NTAB_C1_GAINCTL B43_NTAB32(0x1B, 0x0C0) /* Gain Control Lookup Table Core 1 */
+#define B43_NTAB_C1_GAINCTL_SIZE 128
+#define B43_NTAB_C1_IQLT B43_NTAB32(0x1B, 0x140) /* IQ Lookup Table Core 1 */
+#define B43_NTAB_C1_IQLT_SIZE 128
#define B43_NTAB_C1_LOFEEDTH B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */
#define B43_NTAB_C1_LOFEEDTH_SIZE 128
@@ -154,15 +154,17 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
#define B43_NTAB_CHANEST_R3 B43_NTAB32(22, 0) /* channel estimate */
#define B43_NTAB_FRAMELT_R3 B43_NTAB8(24, 0) /* frame lookup */
#define B43_NTAB_C0_ESTPLT_R3 B43_NTAB8(26, 0) /* estimated power lookup 0 */
-#define B43_NTAB_C1_ESTPLT_R3 B43_NTAB8(27, 0) /* estimated power lookup 1 */
#define B43_NTAB_C0_ADJPLT_R3 B43_NTAB8(26, 64) /* adjusted power lookup 0 */
-#define B43_NTAB_C1_ADJPLT_R3 B43_NTAB8(27, 64) /* adjusted power lookup 1 */
#define B43_NTAB_C0_GAINCTL_R3 B43_NTAB32(26, 192) /* gain control lookup 0 */
-#define B43_NTAB_C1_GAINCTL_R3 B43_NTAB32(27, 192) /* gain control lookup 1 */
#define B43_NTAB_C0_IQLT_R3 B43_NTAB32(26, 320) /* I/Q lookup 0 */
-#define B43_NTAB_C1_IQLT_R3 B43_NTAB32(27, 320) /* I/Q lookup 1 */
#define B43_NTAB_C0_LOFEEDTH_R3 B43_NTAB16(26, 448) /* Local Oscillator Feed Through lookup 0 */
+#define B43_NTAB_C0_PAPD_COMP_R3 B43_NTAB16(26, 576)
+#define B43_NTAB_C1_ESTPLT_R3 B43_NTAB8(27, 0) /* estimated power lookup 1 */
+#define B43_NTAB_C1_ADJPLT_R3 B43_NTAB8(27, 64) /* adjusted power lookup 1 */
+#define B43_NTAB_C1_GAINCTL_R3 B43_NTAB32(27, 192) /* gain control lookup 1 */
+#define B43_NTAB_C1_IQLT_R3 B43_NTAB32(27, 320) /* I/Q lookup 1 */
#define B43_NTAB_C1_LOFEEDTH_R3 B43_NTAB16(27, 448) /* Local Oscillator Feed Through lookup 1 */
+#define B43_NTAB_C1_PAPD_COMP_R3 B43_NTAB16(27, 576)
#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_40_SIZE 18
#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_20_SIZE 18
@@ -182,8 +184,7 @@ void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value);
void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, const void *_data);
-void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev);
-void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev);
+void b43_nphy_tables_init(struct b43_wldev *dev);
const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev);
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 8c3f70e1a013..572668821862 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -2720,7 +2720,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
goto out_unlock_mutex;
/* Switch the PHY mode (if necessary). */
- switch (conf->channel->band) {
+ switch (conf->chandef.chan->band) {
case IEEE80211_BAND_2GHZ:
if (phy->type == B43legacy_PHYTYPE_B)
new_phymode = B43legacy_PHYMODE_B;
@@ -2748,8 +2748,9 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
/* Switch to the requested channel.
* The firmware takes care of races with the TX handler. */
- if (conf->channel->hw_value != phy->channel)
- b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0);
+ if (conf->chandef.chan->hw_value != phy->channel)
+ b43legacy_radio_selectchannel(dev, conf->chandef.chan->hw_value,
+ 0);
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR);
@@ -3558,7 +3559,7 @@ static int b43legacy_op_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = dev->stats.link_noise;
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index 747e9317dabd..fc8a0fa6d3b2 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -37,15 +37,6 @@ config BRCMFMAC_SDIO
IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
use the driver for a SDIO wireless card.
-config BRCMFMAC_SDIO_OOB
- bool "Out of band interrupt support for SDIO interface chipset"
- depends on BRCMFMAC_SDIO
- ---help---
- This option enables out-of-band interrupt support for Broadcom
- SDIO Wifi chipset using fullmac in order to gain better
- performance and deep sleep wake up capability on certain
- platforms. Say N if you are unsure.
-
config BRCMFMAC_USB
bool "USB bus interface support for FullMAC driver"
depends on USB
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index 598c8e2f8d2b..8e9b1221b32c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -30,7 +30,8 @@ brcmfmac-objs += \
p2p.o \
dhd_cdc.o \
dhd_common.o \
- dhd_linux.o
+ dhd_linux.o \
+ btcoex.o
brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
dhd_sdio.o \
bcmsdh.o \
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index f3149debede0..4891e3df2058 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -25,6 +25,7 @@
#include <linux/mmc/sdio.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/card.h>
+#include <linux/platform_data/brcmfmac-sdio.h>
#include <defs.h>
#include <brcm_hw_ids.h>
@@ -37,16 +38,15 @@
#define SDIOH_API_ACCESS_RETRY_LIMIT 2
-#ifdef CONFIG_BRCMFMAC_SDIO_OOB
-static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id)
+
+static irqreturn_t brcmf_sdio_oob_irqhandler(int irq, void *dev_id)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev_id);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- brcmf_dbg(INTR, "oob intr triggered\n");
+ brcmf_dbg(INTR, "OOB intr triggered\n");
- /*
- * out-of-band interrupt is level-triggered which won't
+ /* out-of-band interrupt is level-triggered which won't
* be cleared until dpc
*/
if (sdiodev->irq_en) {
@@ -59,72 +59,12 @@ static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id)
return IRQ_HANDLED;
}
-int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
-{
- int ret = 0;
- u8 data;
- unsigned long flags;
-
- brcmf_dbg(SDIO, "Entering: irq %d\n", sdiodev->irq);
-
- ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler,
- sdiodev->irq_flags, "brcmf_oob_intr",
- &sdiodev->func[1]->dev);
- if (ret != 0)
- return ret;
- spin_lock_init(&sdiodev->irq_en_lock);
- spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
- sdiodev->irq_en = true;
- spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
-
- ret = enable_irq_wake(sdiodev->irq);
- if (ret != 0)
- return ret;
- sdiodev->irq_wake = true;
-
- sdio_claim_host(sdiodev->func[1]);
-
- /* must configure SDIO_CCCR_IENx to enable irq */
- data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
- data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
- brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
-
- /* redirect, configure and enable io for interrupt signal */
- data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
- if (sdiodev->irq_flags & IRQF_TRIGGER_HIGH)
- data |= SDIO_SEPINT_ACT_HI;
- brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
-
- sdio_release_host(sdiodev->func[1]);
-
- return 0;
-}
-
-int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
-{
- brcmf_dbg(SDIO, "Entering\n");
-
- sdio_claim_host(sdiodev->func[1]);
- brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
- brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
- sdio_release_host(sdiodev->func[1]);
-
- if (sdiodev->irq_wake) {
- disable_irq_wake(sdiodev->irq);
- sdiodev->irq_wake = false;
- }
- free_irq(sdiodev->irq, &sdiodev->func[1]->dev);
- sdiodev->irq_en = false;
-
- return 0;
-}
-#else /* CONFIG_BRCMFMAC_SDIO_OOB */
-static void brcmf_sdio_irqhandler(struct sdio_func *func)
+static void brcmf_sdio_ib_irqhandler(struct sdio_func *func)
{
struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- brcmf_dbg(INTR, "ib intr triggered\n");
+ brcmf_dbg(INTR, "IB intr triggered\n");
brcmf_sdbrcm_isr(sdiodev->bus);
}
@@ -136,12 +76,56 @@ static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func)
int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
{
- brcmf_dbg(SDIO, "Entering\n");
+ int ret = 0;
+ u8 data;
+ unsigned long flags;
- sdio_claim_host(sdiodev->func[1]);
- sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler);
- sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler);
- sdio_release_host(sdiodev->func[1]);
+ if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
+ brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n",
+ sdiodev->pdata->oob_irq_nr);
+ ret = request_irq(sdiodev->pdata->oob_irq_nr,
+ brcmf_sdio_oob_irqhandler,
+ sdiodev->pdata->oob_irq_flags,
+ "brcmf_oob_intr",
+ &sdiodev->func[1]->dev);
+ if (ret != 0) {
+ brcmf_err("request_irq failed %d\n", ret);
+ return ret;
+ }
+ sdiodev->oob_irq_requested = true;
+ spin_lock_init(&sdiodev->irq_en_lock);
+ spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
+ sdiodev->irq_en = true;
+ spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
+
+ ret = enable_irq_wake(sdiodev->pdata->oob_irq_nr);
+ if (ret != 0) {
+ brcmf_err("enable_irq_wake failed %d\n", ret);
+ return ret;
+ }
+ sdiodev->irq_wake = true;
+
+ sdio_claim_host(sdiodev->func[1]);
+
+ /* must configure SDIO_CCCR_IENx to enable irq */
+ data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
+ data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
+ brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
+
+ /* redirect, configure and enable io for interrupt signal */
+ data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
+ if (sdiodev->pdata->oob_irq_flags & IRQF_TRIGGER_HIGH)
+ data |= SDIO_SEPINT_ACT_HI;
+ brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
+
+ sdio_release_host(sdiodev->func[1]);
+ } else {
+ brcmf_dbg(SDIO, "Entering\n");
+ sdio_claim_host(sdiodev->func[1]);
+ sdio_claim_irq(sdiodev->func[1], brcmf_sdio_ib_irqhandler);
+ sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler);
+ sdio_release_host(sdiodev->func[1]);
+ }
return 0;
}
@@ -150,14 +134,31 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
{
brcmf_dbg(SDIO, "Entering\n");
- sdio_claim_host(sdiodev->func[1]);
- sdio_release_irq(sdiodev->func[2]);
- sdio_release_irq(sdiodev->func[1]);
- sdio_release_host(sdiodev->func[1]);
+ if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
+ sdio_claim_host(sdiodev->func[1]);
+ brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
+ brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
+ sdio_release_host(sdiodev->func[1]);
+
+ if (sdiodev->oob_irq_requested) {
+ sdiodev->oob_irq_requested = false;
+ if (sdiodev->irq_wake) {
+ disable_irq_wake(sdiodev->pdata->oob_irq_nr);
+ sdiodev->irq_wake = false;
+ }
+ free_irq(sdiodev->pdata->oob_irq_nr,
+ &sdiodev->func[1]->dev);
+ sdiodev->irq_en = false;
+ }
+ } else {
+ sdio_claim_host(sdiodev->func[1]);
+ sdio_release_irq(sdiodev->func[2]);
+ sdio_release_irq(sdiodev->func[1]);
+ sdio_release_host(sdiodev->func[1]);
+ }
return 0;
}
-#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
int
brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
@@ -457,36 +458,80 @@ done:
return err;
}
-int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
- u8 *buf, uint nbytes)
+int
+brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
+ u8 *data, uint size)
{
- struct sk_buff *mypkt;
- bool write = rw ? SDIOH_WRITE : SDIOH_READ;
- int err;
+ int bcmerror = 0;
+ struct sk_buff *pkt;
+ u32 sdaddr;
+ uint dsize;
+
+ dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
+ pkt = dev_alloc_skb(dsize);
+ if (!pkt) {
+ brcmf_err("dev_alloc_skb failed: len %d\n", dsize);
+ return -EIO;
+ }
+ pkt->priority = 0;
- addr &= SBSDIO_SB_OFT_ADDR_MASK;
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+ /* Determine initial transfer parameters */
+ sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
+ if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
+ dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
+ else
+ dsize = size;
- mypkt = brcmu_pkt_buf_get_skb(nbytes);
- if (!mypkt) {
- brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n",
- nbytes);
- return -EIO;
+ sdio_claim_host(sdiodev->func[1]);
+
+ /* Do the transfer(s) */
+ while (size) {
+ /* Set the backplane window to include the start address */
+ bcmerror = brcmf_sdcard_set_sbaddr_window(sdiodev, address);
+ if (bcmerror)
+ break;
+
+ brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
+ write ? "write" : "read", dsize,
+ sdaddr, address & SBSDIO_SBWINDOW_MASK);
+
+ sdaddr &= SBSDIO_SB_OFT_ADDR_MASK;
+ sdaddr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+ skb_put(pkt, dsize);
+ if (write)
+ memcpy(pkt->data, data, dsize);
+ bcmerror = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC,
+ write, SDIO_FUNC_1,
+ sdaddr, pkt);
+ if (bcmerror) {
+ brcmf_err("membytes transfer failed\n");
+ break;
+ }
+ if (!write)
+ memcpy(data, pkt->data, dsize);
+ skb_trim(pkt, dsize);
+
+ /* Adjust for next transfer (if any) */
+ size -= dsize;
+ if (size) {
+ data += dsize;
+ address += dsize;
+ sdaddr = 0;
+ dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
+ }
}
- /* For a write, copy the buffer data into the packet. */
- if (write)
- memcpy(mypkt->data, buf, nbytes);
+ dev_kfree_skb(pkt);
- err = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC, write,
- SDIO_FUNC_1, addr, mypkt);
+ /* Return the window to backplane enumeration space for core access */
+ if (brcmf_sdcard_set_sbaddr_window(sdiodev, sdiodev->sbwad))
+ brcmf_err("FAILED to set window back to 0x%x\n",
+ sdiodev->sbwad);
- /* For a read, copy the packet data back to the buffer. */
- if (!err && !write)
- memcpy(buf, mypkt->data, nbytes);
+ sdio_release_host(sdiodev->func[1]);
- brcmu_pkt_buf_free_skb(mypkt);
- return err;
+ return bcmerror;
}
int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 716548989e4f..44fa0cdbf97b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -26,6 +26,7 @@
#include <linux/sched.h> /* request_irq() */
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/platform_data/brcmfmac-sdio.h>
#include <net/cfg80211.h>
#include <defs.h>
@@ -40,32 +41,30 @@
#define DMA_ALIGN_MASK 0x03
+#define SDIO_DEVICE_ID_BROADCOM_43143 43143
#define SDIO_DEVICE_ID_BROADCOM_43241 0x4324
#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
#define SDIO_DEVICE_ID_BROADCOM_4330 0x4330
#define SDIO_DEVICE_ID_BROADCOM_4334 0x4334
+#define SDIO_DEVICE_ID_BROADCOM_4335 0x4335
#define SDIO_FUNC1_BLOCKSIZE 64
#define SDIO_FUNC2_BLOCKSIZE 512
/* devices we support, null terminated */
static const struct sdio_device_id brcmf_sdmmc_ids[] = {
+ {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)},
{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)},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4335)},
{ /* end: all zeroes */ },
};
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
-#ifdef CONFIG_BRCMFMAC_SDIO_OOB
-static struct list_head oobirq_lh;
-struct brcmf_sdio_oobirq {
- unsigned int irq;
- unsigned long flags;
- struct list_head list;
-};
-#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
+static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata;
+
static bool
brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
@@ -424,33 +423,6 @@ void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
}
-#ifdef CONFIG_BRCMFMAC_SDIO_OOB
-static int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
-{
- struct brcmf_sdio_oobirq *oobirq_entry;
-
- if (list_empty(&oobirq_lh)) {
- brcmf_err("no valid oob irq resource\n");
- return -ENXIO;
- }
-
- oobirq_entry = list_first_entry(&oobirq_lh, struct brcmf_sdio_oobirq,
- list);
-
- sdiodev->irq = oobirq_entry->irq;
- sdiodev->irq_flags = oobirq_entry->flags;
- list_del(&oobirq_entry->list);
- kfree(oobirq_entry);
-
- return 0;
-}
-#else
-static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
-{
- return 0;
-}
-#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
-
static int brcmf_ops_sdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
@@ -491,15 +463,13 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
dev_set_drvdata(&func->dev, bus_if);
dev_set_drvdata(&sdiodev->func[1]->dev, bus_if);
sdiodev->dev = &sdiodev->func[1]->dev;
+ sdiodev->pdata = brcmfmac_sdio_pdata;
atomic_set(&sdiodev->suspend, false);
init_waitqueue_head(&sdiodev->request_byte_wait);
init_waitqueue_head(&sdiodev->request_word_wait);
init_waitqueue_head(&sdiodev->request_chain_wait);
init_waitqueue_head(&sdiodev->request_buffer_wait);
- err = brcmf_sdio_getintrcfg(sdiodev);
- if (err)
- goto fail;
brcmf_dbg(SDIO, "F2 found, calling brcmf_sdio_probe...\n");
err = brcmf_sdio_probe(sdiodev);
@@ -594,7 +564,7 @@ static const struct dev_pm_ops brcmf_sdio_pm_ops = {
static struct sdio_driver brcmf_sdmmc_driver = {
.probe = brcmf_ops_sdio_probe,
.remove = brcmf_ops_sdio_remove,
- .name = "brcmfmac",
+ .name = BRCMFMAC_SDIO_PDATA_NAME,
.id_table = brcmf_sdmmc_ids,
#ifdef CONFIG_PM_SLEEP
.drv = {
@@ -603,72 +573,51 @@ static struct sdio_driver brcmf_sdmmc_driver = {
#endif /* CONFIG_PM_SLEEP */
};
-#ifdef CONFIG_BRCMFMAC_SDIO_OOB
static int brcmf_sdio_pd_probe(struct platform_device *pdev)
{
- struct resource *res;
- struct brcmf_sdio_oobirq *oobirq_entry;
- int i, ret;
+ int ret;
- INIT_LIST_HEAD(&oobirq_lh);
+ brcmf_dbg(SDIO, "Enter\n");
- for (i = 0; ; i++) {
- res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
- if (!res)
- break;
+ brcmfmac_sdio_pdata = pdev->dev.platform_data;
- oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq),
- GFP_KERNEL);
- if (!oobirq_entry)
- return -ENOMEM;
- oobirq_entry->irq = res->start;
- oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK;
- list_add_tail(&oobirq_entry->list, &oobirq_lh);
- }
- if (i == 0)
- return -ENXIO;
+ if (brcmfmac_sdio_pdata->power_on)
+ brcmfmac_sdio_pdata->power_on();
ret = sdio_register_driver(&brcmf_sdmmc_driver);
-
if (ret)
brcmf_err("sdio_register_driver failed: %d\n", ret);
return ret;
}
-static struct platform_driver brcmf_sdio_pd = {
- .probe = brcmf_sdio_pd_probe,
- .driver = {
- .name = "brcmf_sdio_pd"
- }
-};
-
-void brcmf_sdio_exit(void)
+static int brcmf_sdio_pd_remove(struct platform_device *pdev)
{
brcmf_dbg(SDIO, "Enter\n");
+ if (brcmfmac_sdio_pdata->power_off)
+ brcmfmac_sdio_pdata->power_off();
+
sdio_unregister_driver(&brcmf_sdmmc_driver);
- platform_driver_unregister(&brcmf_sdio_pd);
+ return 0;
}
-void brcmf_sdio_init(void)
-{
- int ret;
-
- brcmf_dbg(SDIO, "Enter\n");
-
- ret = platform_driver_register(&brcmf_sdio_pd);
+static struct platform_driver brcmf_sdio_pd = {
+ .remove = brcmf_sdio_pd_remove,
+ .driver = {
+ .name = BRCMFMAC_SDIO_PDATA_NAME
+ }
+};
- if (ret)
- brcmf_err("platform_driver_register failed: %d\n", ret);
-}
-#else
void brcmf_sdio_exit(void)
{
brcmf_dbg(SDIO, "Enter\n");
- sdio_unregister_driver(&brcmf_sdmmc_driver);
+ if (brcmfmac_sdio_pdata)
+ platform_driver_unregister(&brcmf_sdio_pd);
+ else
+ sdio_unregister_driver(&brcmf_sdmmc_driver);
}
void brcmf_sdio_init(void)
@@ -677,9 +626,12 @@ void brcmf_sdio_init(void)
brcmf_dbg(SDIO, "Enter\n");
- ret = sdio_register_driver(&brcmf_sdmmc_driver);
+ ret = platform_driver_probe(&brcmf_sdio_pd, brcmf_sdio_pd_probe);
+ if (ret == -ENODEV) {
+ brcmf_dbg(SDIO, "No platform data available, registering without.\n");
+ ret = sdio_register_driver(&brcmf_sdmmc_driver);
+ }
if (ret)
- brcmf_err("sdio_register_driver failed: %d\n", ret);
+ brcmf_err("driver registration failed: %d\n", ret);
}
-#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
new file mode 100644
index 000000000000..0cb591b050b3
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2013 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/slab.h>
+#include <linux/netdevice.h>
+#include <net/cfg80211.h>
+
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+#include <defs.h>
+#include <dhd.h>
+#include <dhd_dbg.h>
+#include "fwil.h"
+#include "fwil_types.h"
+#include "btcoex.h"
+#include "p2p.h"
+#include "wl_cfg80211.h"
+
+/* T1 start SCO/eSCO priority suppression */
+#define BRCMF_BTCOEX_OPPR_WIN_TIME 2000
+
+/* BT registers values during DHCP */
+#define BRCMF_BT_DHCP_REG50 0x8022
+#define BRCMF_BT_DHCP_REG51 0
+#define BRCMF_BT_DHCP_REG64 0
+#define BRCMF_BT_DHCP_REG65 0
+#define BRCMF_BT_DHCP_REG71 0
+#define BRCMF_BT_DHCP_REG66 0x2710
+#define BRCMF_BT_DHCP_REG41 0x33
+#define BRCMF_BT_DHCP_REG68 0x190
+
+/* number of samples for SCO detection */
+#define BRCMF_BT_SCO_SAMPLES 12
+
+/**
+* enum brcmf_btcoex_state - BT coex DHCP state machine states
+* @BRCMF_BT_DHCP_IDLE: DCHP is idle
+* @BRCMF_BT_DHCP_START: DHCP started, wait before
+* boosting wifi priority
+* @BRCMF_BT_DHCP_OPPR_WIN: graceful DHCP opportunity ended,
+* boost wifi priority
+* @BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT: wifi priority boost end,
+* restore defaults
+*/
+enum brcmf_btcoex_state {
+ BRCMF_BT_DHCP_IDLE,
+ BRCMF_BT_DHCP_START,
+ BRCMF_BT_DHCP_OPPR_WIN,
+ BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT
+};
+
+/**
+ * struct brcmf_btcoex_info - BT coex related information
+ * @vif: interface for which request was done.
+ * @timer: timer for DHCP state machine
+ * @timeout: configured timeout.
+ * @timer_on: DHCP timer active
+ * @dhcp_done: DHCP finished before T1/T2 timer expiration
+ * @bt_state: DHCP state machine state
+ * @work: DHCP state machine work
+ * @cfg: driver private data for cfg80211 interface
+ * @reg66: saved value of btc_params 66
+ * @reg41: saved value of btc_params 41
+ * @reg68: saved value of btc_params 68
+ * @saved_regs_part1: flag indicating regs 66,41,68
+ * have been saved
+ * @reg51: saved value of btc_params 51
+ * @reg64: saved value of btc_params 64
+ * @reg65: saved value of btc_params 65
+ * @reg71: saved value of btc_params 71
+ * @saved_regs_part1: flag indicating regs 50,51,64,65,71
+ * have been saved
+ */
+struct brcmf_btcoex_info {
+ struct brcmf_cfg80211_vif *vif;
+ struct timer_list timer;
+ u16 timeout;
+ bool timer_on;
+ bool dhcp_done;
+ enum brcmf_btcoex_state bt_state;
+ struct work_struct work;
+ struct brcmf_cfg80211_info *cfg;
+ u32 reg66;
+ u32 reg41;
+ u32 reg68;
+ bool saved_regs_part1;
+ u32 reg50;
+ u32 reg51;
+ u32 reg64;
+ u32 reg65;
+ u32 reg71;
+ bool saved_regs_part2;
+};
+
+/**
+ * brcmf_btcoex_params_write() - write btc_params firmware variable
+ * @ifp: interface
+ * @addr: btc_params register number
+ * @data: data to write
+ */
+static s32 brcmf_btcoex_params_write(struct brcmf_if *ifp, u32 addr, u32 data)
+{
+ struct {
+ __le32 addr;
+ __le32 data;
+ } reg_write;
+
+ reg_write.addr = cpu_to_le32(addr);
+ reg_write.data = cpu_to_le32(data);
+ return brcmf_fil_iovar_data_set(ifp, "btc_params",
+ &reg_write, sizeof(reg_write));
+}
+
+/**
+ * brcmf_btcoex_params_read() - read btc_params firmware variable
+ * @ifp: interface
+ * @addr: btc_params register number
+ * @data: read data
+ */
+static s32 brcmf_btcoex_params_read(struct brcmf_if *ifp, u32 addr, u32 *data)
+{
+ *data = addr;
+
+ return brcmf_fil_iovar_int_get(ifp, "btc_params", data);
+}
+
+/**
+ * brcmf_btcoex_boost_wifi() - control BT SCO/eSCO parameters
+ * @btci: BT coex info
+ * @trump_sco:
+ * true - set SCO/eSCO parameters for compatibility
+ * during DHCP window
+ * false - restore saved parameter values
+ *
+ * Enhanced BT COEX settings for eSCO compatibility during DHCP window
+ */
+static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci,
+ bool trump_sco)
+{
+ struct brcmf_if *ifp = btci->cfg->pub->iflist[0];
+
+ if (trump_sco && !btci->saved_regs_part2) {
+ /* this should reduce eSCO agressive
+ * retransmit w/o breaking it
+ */
+
+ /* save current */
+ brcmf_dbg(TRACE, "new SCO/eSCO coex algo {save & override}\n");
+ brcmf_btcoex_params_read(ifp, 50, &btci->reg50);
+ brcmf_btcoex_params_read(ifp, 51, &btci->reg51);
+ brcmf_btcoex_params_read(ifp, 64, &btci->reg64);
+ brcmf_btcoex_params_read(ifp, 65, &btci->reg65);
+ brcmf_btcoex_params_read(ifp, 71, &btci->reg71);
+
+ btci->saved_regs_part2 = true;
+ brcmf_dbg(TRACE,
+ "saved bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ btci->reg50, btci->reg51, btci->reg64,
+ btci->reg65, btci->reg71);
+
+ /* pacify the eSco */
+ brcmf_btcoex_params_write(ifp, 50, BRCMF_BT_DHCP_REG50);
+ brcmf_btcoex_params_write(ifp, 51, BRCMF_BT_DHCP_REG51);
+ brcmf_btcoex_params_write(ifp, 64, BRCMF_BT_DHCP_REG64);
+ brcmf_btcoex_params_write(ifp, 65, BRCMF_BT_DHCP_REG65);
+ brcmf_btcoex_params_write(ifp, 71, BRCMF_BT_DHCP_REG71);
+
+ } else if (btci->saved_regs_part2) {
+ /* restore previously saved bt params */
+ brcmf_dbg(TRACE, "Do new SCO/eSCO coex algo {restore}\n");
+ brcmf_btcoex_params_write(ifp, 50, btci->reg50);
+ brcmf_btcoex_params_write(ifp, 51, btci->reg51);
+ brcmf_btcoex_params_write(ifp, 64, btci->reg64);
+ brcmf_btcoex_params_write(ifp, 65, btci->reg65);
+ brcmf_btcoex_params_write(ifp, 71, btci->reg71);
+
+ brcmf_dbg(TRACE,
+ "restored bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ btci->reg50, btci->reg51, btci->reg64,
+ btci->reg65, btci->reg71);
+
+ btci->saved_regs_part2 = false;
+ } else {
+ brcmf_err("attempted to restore not saved BTCOEX params\n");
+ }
+}
+
+/**
+ * brcmf_btcoex_is_sco_active() - check if SCO/eSCO is active
+ * @ifp: interface
+ *
+ * return: true if SCO/eSCO session is active
+ */
+static bool brcmf_btcoex_is_sco_active(struct brcmf_if *ifp)
+{
+ int ioc_res = 0;
+ bool res = false;
+ int sco_id_cnt = 0;
+ u32 param27;
+ int i;
+
+ for (i = 0; i < BRCMF_BT_SCO_SAMPLES; i++) {
+ ioc_res = brcmf_btcoex_params_read(ifp, 27, &param27);
+
+ if (ioc_res < 0) {
+ brcmf_err("ioc read btc params error\n");
+ break;
+ }
+
+ brcmf_dbg(TRACE, "sample[%d], btc_params 27:%x\n", i, param27);
+
+ if ((param27 & 0x6) == 2) { /* count both sco & esco */
+ sco_id_cnt++;
+ }
+
+ if (sco_id_cnt > 2) {
+ brcmf_dbg(TRACE,
+ "sco/esco detected, pkt id_cnt:%d samples:%d\n",
+ sco_id_cnt, i);
+ res = true;
+ break;
+ }
+ }
+ brcmf_dbg(TRACE, "exit: result=%d\n", res);
+ return res;
+}
+
+/**
+ * btcmf_btcoex_save_part1() - save first step parameters.
+ */
+static void btcmf_btcoex_save_part1(struct brcmf_btcoex_info *btci)
+{
+ struct brcmf_if *ifp = btci->vif->ifp;
+
+ if (!btci->saved_regs_part1) {
+ /* Retrieve and save original reg value */
+ brcmf_btcoex_params_read(ifp, 66, &btci->reg66);
+ brcmf_btcoex_params_read(ifp, 41, &btci->reg41);
+ brcmf_btcoex_params_read(ifp, 68, &btci->reg68);
+ btci->saved_regs_part1 = true;
+ brcmf_dbg(TRACE,
+ "saved btc_params regs (66,41,68) 0x%x 0x%x 0x%x\n",
+ btci->reg66, btci->reg41,
+ btci->reg68);
+ }
+}
+
+/**
+ * brcmf_btcoex_restore_part1() - restore first step parameters.
+ */
+static void brcmf_btcoex_restore_part1(struct brcmf_btcoex_info *btci)
+{
+ struct brcmf_if *ifp;
+
+ if (btci->saved_regs_part1) {
+ btci->saved_regs_part1 = false;
+ ifp = btci->vif->ifp;
+ brcmf_btcoex_params_write(ifp, 66, btci->reg66);
+ brcmf_btcoex_params_write(ifp, 41, btci->reg41);
+ brcmf_btcoex_params_write(ifp, 68, btci->reg68);
+ brcmf_dbg(TRACE,
+ "restored btc_params regs {66,41,68} 0x%x 0x%x 0x%x\n",
+ btci->reg66, btci->reg41,
+ btci->reg68);
+ }
+}
+
+/**
+ * brcmf_btcoex_timerfunc() - BT coex timer callback
+ */
+static void brcmf_btcoex_timerfunc(ulong data)
+{
+ struct brcmf_btcoex_info *bt_local = (struct brcmf_btcoex_info *)data;
+ brcmf_dbg(TRACE, "enter\n");
+
+ bt_local->timer_on = false;
+ schedule_work(&bt_local->work);
+}
+
+/**
+ * brcmf_btcoex_handler() - BT coex state machine work handler
+ * @work: work
+ */
+static void brcmf_btcoex_handler(struct work_struct *work)
+{
+ struct brcmf_btcoex_info *btci;
+ btci = container_of(work, struct brcmf_btcoex_info, work);
+ if (btci->timer_on) {
+ btci->timer_on = false;
+ del_timer_sync(&btci->timer);
+ }
+
+ switch (btci->bt_state) {
+ case BRCMF_BT_DHCP_START:
+ /* DHCP started provide OPPORTUNITY window
+ to get DHCP address
+ */
+ brcmf_dbg(TRACE, "DHCP started\n");
+ btci->bt_state = BRCMF_BT_DHCP_OPPR_WIN;
+ if (btci->timeout < BRCMF_BTCOEX_OPPR_WIN_TIME) {
+ mod_timer(&btci->timer, btci->timer.expires);
+ } else {
+ btci->timeout -= BRCMF_BTCOEX_OPPR_WIN_TIME;
+ mod_timer(&btci->timer,
+ jiffies +
+ msecs_to_jiffies(BRCMF_BTCOEX_OPPR_WIN_TIME));
+ }
+ btci->timer_on = true;
+ break;
+
+ case BRCMF_BT_DHCP_OPPR_WIN:
+ if (btci->dhcp_done) {
+ brcmf_dbg(TRACE, "DHCP done before T1 expiration\n");
+ goto idle;
+ }
+
+ /* DHCP is not over yet, start lowering BT priority */
+ brcmf_dbg(TRACE, "DHCP T1:%d expired\n",
+ BRCMF_BTCOEX_OPPR_WIN_TIME);
+ brcmf_btcoex_boost_wifi(btci, true);
+
+ btci->bt_state = BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT;
+ mod_timer(&btci->timer,
+ jiffies + msecs_to_jiffies(btci->timeout));
+ btci->timer_on = true;
+ break;
+
+ case BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT:
+ if (btci->dhcp_done)
+ brcmf_dbg(TRACE, "DHCP done before T2 expiration\n");
+ else
+ brcmf_dbg(TRACE, "DHCP T2:%d expired\n",
+ BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT);
+
+ goto idle;
+
+ default:
+ brcmf_err("invalid state=%d !!!\n", btci->bt_state);
+ goto idle;
+ }
+
+ return;
+
+idle:
+ btci->bt_state = BRCMF_BT_DHCP_IDLE;
+ btci->timer_on = false;
+ brcmf_btcoex_boost_wifi(btci, false);
+ cfg80211_crit_proto_stopped(&btci->vif->wdev, GFP_KERNEL);
+ brcmf_btcoex_restore_part1(btci);
+ btci->vif = NULL;
+}
+
+/**
+ * brcmf_btcoex_attach() - initialize BT coex data
+ * @cfg: driver private cfg80211 data
+ *
+ * return: 0 on success
+ */
+int brcmf_btcoex_attach(struct brcmf_cfg80211_info *cfg)
+{
+ struct brcmf_btcoex_info *btci = NULL;
+ brcmf_dbg(TRACE, "enter\n");
+
+ btci = kmalloc(sizeof(struct brcmf_btcoex_info), GFP_KERNEL);
+ if (!btci)
+ return -ENOMEM;
+
+ btci->bt_state = BRCMF_BT_DHCP_IDLE;
+
+ /* Set up timer for BT */
+ btci->timer_on = false;
+ btci->timeout = BRCMF_BTCOEX_OPPR_WIN_TIME;
+ init_timer(&btci->timer);
+ btci->timer.data = (ulong)btci;
+ btci->timer.function = brcmf_btcoex_timerfunc;
+ btci->cfg = cfg;
+ btci->saved_regs_part1 = false;
+ btci->saved_regs_part2 = false;
+
+ INIT_WORK(&btci->work, brcmf_btcoex_handler);
+
+ cfg->btcoex = btci;
+ return 0;
+}
+
+/**
+ * brcmf_btcoex_detach - clean BT coex data
+ * @cfg: driver private cfg80211 data
+ */
+void brcmf_btcoex_detach(struct brcmf_cfg80211_info *cfg)
+{
+ brcmf_dbg(TRACE, "enter\n");
+
+ if (!cfg->btcoex)
+ return;
+
+ if (cfg->btcoex->timer_on) {
+ cfg->btcoex->timer_on = false;
+ del_timer_sync(&cfg->btcoex->timer);
+ }
+
+ cancel_work_sync(&cfg->btcoex->work);
+
+ brcmf_btcoex_boost_wifi(cfg->btcoex, false);
+ brcmf_btcoex_restore_part1(cfg->btcoex);
+
+ kfree(cfg->btcoex);
+ cfg->btcoex = NULL;
+}
+
+static void brcmf_btcoex_dhcp_start(struct brcmf_btcoex_info *btci)
+{
+ struct brcmf_if *ifp = btci->vif->ifp;
+
+ btcmf_btcoex_save_part1(btci);
+ /* set new regs values */
+ brcmf_btcoex_params_write(ifp, 66, BRCMF_BT_DHCP_REG66);
+ brcmf_btcoex_params_write(ifp, 41, BRCMF_BT_DHCP_REG41);
+ brcmf_btcoex_params_write(ifp, 68, BRCMF_BT_DHCP_REG68);
+ btci->dhcp_done = false;
+ btci->bt_state = BRCMF_BT_DHCP_START;
+ schedule_work(&btci->work);
+ brcmf_dbg(TRACE, "enable BT DHCP Timer\n");
+}
+
+static void brcmf_btcoex_dhcp_end(struct brcmf_btcoex_info *btci)
+{
+ /* Stop any bt timer because DHCP session is done */
+ btci->dhcp_done = true;
+ if (btci->timer_on) {
+ brcmf_dbg(TRACE, "disable BT DHCP Timer\n");
+ btci->timer_on = false;
+ del_timer_sync(&btci->timer);
+
+ /* schedule worker if transition to IDLE is needed */
+ if (btci->bt_state != BRCMF_BT_DHCP_IDLE) {
+ brcmf_dbg(TRACE, "bt_state:%d\n",
+ btci->bt_state);
+ schedule_work(&btci->work);
+ }
+ } else {
+ /* Restore original values */
+ brcmf_btcoex_restore_part1(btci);
+ }
+}
+
+/**
+ * brcmf_btcoex_set_mode - set BT coex mode
+ * @cfg: driver private cfg80211 data
+ * @mode: Wifi-Bluetooth coexistence mode
+ *
+ * return: 0 on success
+ */
+int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
+ enum brcmf_btcoex_mode mode, u16 duration)
+{
+ struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy);
+ struct brcmf_btcoex_info *btci = cfg->btcoex;
+ struct brcmf_if *ifp = cfg->pub->iflist[0];
+
+ switch (mode) {
+ case BRCMF_BTCOEX_DISABLED:
+ brcmf_dbg(TRACE, "DHCP session starts\n");
+ if (btci->bt_state != BRCMF_BT_DHCP_IDLE)
+ return -EBUSY;
+ /* Start BT timer only for SCO connection */
+ if (brcmf_btcoex_is_sco_active(ifp)) {
+ btci->timeout = duration;
+ btci->vif = vif;
+ brcmf_btcoex_dhcp_start(btci);
+ }
+ break;
+
+ case BRCMF_BTCOEX_ENABLED:
+ brcmf_dbg(TRACE, "DHCP session ends\n");
+ if (btci->bt_state != BRCMF_BT_DHCP_IDLE &&
+ vif == btci->vif) {
+ brcmf_btcoex_dhcp_end(btci);
+ }
+ break;
+ default:
+ brcmf_dbg(TRACE, "Unknown mode, ignored\n");
+ }
+ return 0;
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.h b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.h
new file mode 100644
index 000000000000..19647c68aa9e
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 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.
+ */
+#ifndef WL_BTCOEX_H_
+#define WL_BTCOEX_H_
+
+enum brcmf_btcoex_mode {
+ BRCMF_BTCOEX_DISABLED,
+ BRCMF_BTCOEX_ENABLED
+};
+
+int brcmf_btcoex_attach(struct brcmf_cfg80211_info *cfg);
+void brcmf_btcoex_detach(struct brcmf_cfg80211_info *cfg);
+int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
+ enum brcmf_btcoex_mode mode, u16 duration);
+
+#endif /* WL_BTCOEX_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 5249c67b466c..28db9cf39672 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -28,6 +28,7 @@
/*******************************************************************************
* IO codes that are interpreted by dongle firmware
******************************************************************************/
+#define BRCMF_C_GET_VERSION 1
#define BRCMF_C_UP 2
#define BRCMF_C_DOWN 3
#define BRCMF_C_SET_PROMISC 10
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index 763a84eba216..59c25463e428 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -754,14 +754,14 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
/* this is P2P_DEVICE interface */
brcmf_dbg(INFO, "allocate non-netdev interface\n");
ifp = kzalloc(sizeof(*ifp), GFP_KERNEL);
+ if (!ifp)
+ return ERR_PTR(-ENOMEM);
} else {
brcmf_dbg(INFO, "allocate netdev interface\n");
/* Allocate netdev, including space for private structure */
ndev = alloc_netdev(sizeof(*ifp), name, ether_setup);
- if (!ndev) {
- brcmf_err("OOM - alloc_netdev\n");
+ if (!ndev)
return ERR_PTR(-ENOMEM);
- }
ifp = netdev_priv(ndev);
ifp->ndev = ndev;
@@ -899,7 +899,10 @@ int brcmf_bus_start(struct device *dev)
goto fail;
drvr->fw_signals = true;
- (void)brcmf_fws_init(drvr);
+ ret = brcmf_fws_init(drvr);
+ if (ret < 0)
+ goto fail;
+
brcmf_fws_add_interface(ifp);
drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 4ff2d3c52ee6..d2487518bd2a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -31,6 +31,7 @@
#include <linux/bcma/bcma.h>
#include <linux/debugfs.h>
#include <linux/vmalloc.h>
+#include <linux/platform_data/brcmfmac-sdio.h>
#include <asm/unaligned.h>
#include <defs.h>
#include <brcmu_wifi.h>
@@ -324,6 +325,9 @@ MODULE_FIRMWARE(BRCMF_SDIO_NV_NAME);
*/
#define BRCMF_IDLE_INTERVAL 1
+#define KSO_WAIT_US 50
+#define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US)
+
/*
* Conversion of 802.1D priority to precedence level
*/
@@ -333,95 +337,6 @@ static uint prio2prec(u32 prio)
(prio^2) : prio;
}
-/* core registers */
-struct sdpcmd_regs {
- u32 corecontrol; /* 0x00, rev8 */
- u32 corestatus; /* rev8 */
- u32 PAD[1];
- u32 biststatus; /* rev8 */
-
- /* PCMCIA access */
- u16 pcmciamesportaladdr; /* 0x010, rev8 */
- u16 PAD[1];
- u16 pcmciamesportalmask; /* rev8 */
- u16 PAD[1];
- u16 pcmciawrframebc; /* rev8 */
- u16 PAD[1];
- u16 pcmciaunderflowtimer; /* rev8 */
- u16 PAD[1];
-
- /* interrupt */
- u32 intstatus; /* 0x020, rev8 */
- u32 hostintmask; /* rev8 */
- u32 intmask; /* rev8 */
- u32 sbintstatus; /* rev8 */
- u32 sbintmask; /* rev8 */
- u32 funcintmask; /* rev4 */
- u32 PAD[2];
- u32 tosbmailbox; /* 0x040, rev8 */
- u32 tohostmailbox; /* rev8 */
- u32 tosbmailboxdata; /* rev8 */
- u32 tohostmailboxdata; /* rev8 */
-
- /* synchronized access to registers in SDIO clock domain */
- u32 sdioaccess; /* 0x050, rev8 */
- u32 PAD[3];
-
- /* PCMCIA frame control */
- u8 pcmciaframectrl; /* 0x060, rev8 */
- u8 PAD[3];
- u8 pcmciawatermark; /* rev8 */
- u8 PAD[155];
-
- /* interrupt batching control */
- u32 intrcvlazy; /* 0x100, rev8 */
- u32 PAD[3];
-
- /* counters */
- u32 cmd52rd; /* 0x110, rev8 */
- u32 cmd52wr; /* rev8 */
- u32 cmd53rd; /* rev8 */
- u32 cmd53wr; /* rev8 */
- u32 abort; /* rev8 */
- u32 datacrcerror; /* rev8 */
- u32 rdoutofsync; /* rev8 */
- u32 wroutofsync; /* rev8 */
- u32 writebusy; /* rev8 */
- u32 readwait; /* rev8 */
- u32 readterm; /* rev8 */
- u32 writeterm; /* rev8 */
- u32 PAD[40];
- u32 clockctlstatus; /* rev8 */
- u32 PAD[7];
-
- u32 PAD[128]; /* DMA engines */
-
- /* SDIO/PCMCIA CIS region */
- char cis[512]; /* 0x400-0x5ff, rev6 */
-
- /* PCMCIA function control registers */
- char pcmciafcr[256]; /* 0x600-6ff, rev6 */
- u16 PAD[55];
-
- /* PCMCIA backplane access */
- u16 backplanecsr; /* 0x76E, rev6 */
- u16 backplaneaddr0; /* rev6 */
- u16 backplaneaddr1; /* rev6 */
- u16 backplaneaddr2; /* rev6 */
- u16 backplaneaddr3; /* rev6 */
- u16 backplanedata0; /* rev6 */
- u16 backplanedata1; /* rev6 */
- u16 backplanedata2; /* rev6 */
- u16 backplanedata3; /* rev6 */
- u16 PAD[31];
-
- /* sprom "size" & "blank" info */
- u16 spromstatus; /* 0x7BE, rev2 */
- u32 PAD[464];
-
- u16 PAD[0x80];
-};
-
#ifdef DEBUG
/* Device console log buffer state */
struct brcmf_console {
@@ -588,12 +503,14 @@ struct brcmf_sdio {
bool txoff; /* Transmit flow-controlled */
struct brcmf_sdio_count sdcnt;
+ bool sr_enabled; /* SaveRestore enabled */
+ bool sleeping; /* SDIO bus sleeping */
};
/* clkstate */
#define CLK_NONE 0
#define CLK_SDONLY 1
-#define CLK_PENDING 2 /* Not used yet */
+#define CLK_PENDING 2
#define CLK_AVAIL 3
#ifdef DEBUG
@@ -601,7 +518,7 @@ static int qcount[NUMPRIO];
static int tx_packets[NUMPRIO];
#endif /* DEBUG */
-#define SDIO_DRIVE_STRENGTH 6 /* in milliamps */
+#define DEFAULT_SDIO_DRIVE_STRENGTH 6 /* in milliamps */
#define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL)
@@ -665,6 +582,62 @@ w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset)
return ret;
}
+static int
+brcmf_sdbrcm_kso_control(struct brcmf_sdio *bus, bool on)
+{
+ u8 wr_val = 0, rd_val, cmp_val, bmask;
+ int err = 0;
+ int try_cnt = 0;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
+ /* 1st KSO write goes to AOS wake up core if device is asleep */
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+ wr_val, &err);
+ if (err) {
+ brcmf_err("SDIO_AOS KSO write error: %d\n", err);
+ return err;
+ }
+
+ if (on) {
+ /* device WAKEUP through KSO:
+ * write bit 0 & read back until
+ * both bits 0 (kso bit) & 1 (dev on status) are set
+ */
+ cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK |
+ SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK;
+ bmask = cmp_val;
+ usleep_range(2000, 3000);
+ } else {
+ /* Put device to sleep, turn off KSO */
+ cmp_val = 0;
+ /* only check for bit0, bit1(dev on status) may not
+ * get cleared right away
+ */
+ bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK;
+ }
+
+ do {
+ /* reliable KSO bit set/clr:
+ * the sdiod sleep write access is synced to PMU 32khz clk
+ * just one write attempt may fail,
+ * read it back until it matches written value
+ */
+ rd_val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+ &err);
+ if (((rd_val & bmask) == cmp_val) && !err)
+ break;
+ brcmf_dbg(SDIO, "KSO wr/rd retry:%d (max: %d) ERR:%x\n",
+ try_cnt, MAX_KSO_ATTEMPTS, err);
+ udelay(KSO_WAIT_US);
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+ wr_val, &err);
+ } while (try_cnt++ < MAX_KSO_ATTEMPTS);
+
+ return err;
+}
+
#define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND)
#define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE)
@@ -680,6 +653,11 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
clkctl = 0;
+ if (bus->sr_enabled) {
+ bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY);
+ return 0;
+ }
+
if (on) {
/* Request HT Avail */
clkreq =
@@ -856,6 +834,63 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
return 0;
}
+static int
+brcmf_sdbrcm_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok)
+{
+ int err = 0;
+ brcmf_dbg(TRACE, "Enter\n");
+ brcmf_dbg(SDIO, "request %s currently %s\n",
+ (sleep ? "SLEEP" : "WAKE"),
+ (bus->sleeping ? "SLEEP" : "WAKE"));
+
+ /* If SR is enabled control bus state with KSO */
+ if (bus->sr_enabled) {
+ /* Done if we're already in the requested state */
+ if (sleep == bus->sleeping)
+ goto end;
+
+ /* Going to sleep */
+ if (sleep) {
+ /* Don't sleep if something is pending */
+ if (atomic_read(&bus->intstatus) ||
+ atomic_read(&bus->ipend) > 0 ||
+ (!atomic_read(&bus->fcstate) &&
+ brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
+ data_ok(bus)))
+ return -EBUSY;
+ err = brcmf_sdbrcm_kso_control(bus, false);
+ /* disable watchdog */
+ if (!err)
+ brcmf_sdbrcm_wd_timer(bus, 0);
+ } else {
+ bus->idlecount = 0;
+ err = brcmf_sdbrcm_kso_control(bus, true);
+ }
+ if (!err) {
+ /* Change state */
+ bus->sleeping = sleep;
+ brcmf_dbg(SDIO, "new state %s\n",
+ (sleep ? "SLEEP" : "WAKE"));
+ } else {
+ brcmf_err("error while changing bus sleep state %d\n",
+ err);
+ return err;
+ }
+ }
+
+end:
+ /* control clocks */
+ if (sleep) {
+ if (!bus->sr_enabled)
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, pendok);
+ } else {
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, pendok);
+ }
+
+ return err;
+
+}
+
static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
{
u32 intstatus = 0;
@@ -1960,7 +1995,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
sdio_claim_host(bus->sdiodev->func[1]);
/* Enable clock for device interrupts */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ brcmf_sdbrcm_bus_sleep(bus, false, false);
/* Disable and clear interrupts at the chip level also */
w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask));
@@ -2012,23 +2047,19 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
bus->tx_seq = bus->rx_seq = 0;
}
-#ifdef CONFIG_BRCMFMAC_SDIO_OOB
static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
{
unsigned long flags;
- spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags);
- if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) {
- enable_irq(bus->sdiodev->irq);
- bus->sdiodev->irq_en = true;
+ if (bus->sdiodev->oob_irq_requested) {
+ spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags);
+ if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) {
+ enable_irq(bus->sdiodev->pdata->oob_irq_nr);
+ bus->sdiodev->irq_en = true;
+ }
+ spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
}
- spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
-}
-#else
-static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
-{
}
-#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus)
{
@@ -2096,7 +2127,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
sdio_claim_host(bus->sdiodev->func[1]);
/* If waiting for HTAVAIL, check status */
- if (bus->clkstate == CLK_PENDING) {
+ if (!bus->sr_enabled && bus->clkstate == CLK_PENDING) {
u8 clkctl, devctl = 0;
#ifdef DEBUG
@@ -2142,7 +2173,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
}
/* Make sure backplane clock is on */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
+ brcmf_sdbrcm_bus_sleep(bus, false, true);
/* Pending interrupt indicates new device status */
if (atomic_read(&bus->ipend) > 0) {
@@ -2288,8 +2319,9 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
if ((bus->clkstate != CLK_PENDING)
&& bus->idletime == BRCMF_IDLE_IMMEDIATE) {
bus->activity = false;
+ brcmf_dbg(SDIO, "idle state\n");
sdio_claim_host(bus->sdiodev->func[1]);
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+ brcmf_sdbrcm_bus_sleep(bus, true, false);
sdio_release_host(bus->sdiodev->func[1]);
}
}
@@ -2362,69 +2394,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
return ret;
}
-static int
-brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
- uint size)
-{
- int bcmerror = 0;
- u32 sdaddr;
- uint dsize;
-
- /* Determine initial transfer parameters */
- sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
- if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
- dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
- else
- dsize = size;
-
- sdio_claim_host(bus->sdiodev->func[1]);
-
- /* Set the backplane window to include the start address */
- bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address);
- if (bcmerror) {
- brcmf_err("window change failed\n");
- goto xfer_done;
- }
-
- /* Do the transfer(s) */
- while (size) {
- brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
- write ? "write" : "read", dsize,
- sdaddr, address & SBSDIO_SBWINDOW_MASK);
- bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write,
- sdaddr, data, dsize);
- if (bcmerror) {
- brcmf_err("membytes transfer failed\n");
- break;
- }
-
- /* Adjust for next transfer (if any) */
- size -= dsize;
- if (size) {
- data += dsize;
- address += dsize;
- bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev,
- address);
- if (bcmerror) {
- brcmf_err("window change failed\n");
- break;
- }
- sdaddr = 0;
- dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
- }
- }
-
-xfer_done:
- /* Return the window to backplane enumeration space for core access */
- if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, bus->sdiodev->sbwad))
- brcmf_err("FAILED to set window back to 0x%x\n",
- bus->sdiodev->sbwad);
-
- sdio_release_host(bus->sdiodev->func[1]);
-
- return bcmerror;
-}
-
#ifdef DEBUG
#define CONSOLE_LINE_MAX 192
@@ -2441,8 +2410,8 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus)
/* Read console log struct */
addr = bus->console_addr + offsetof(struct rte_console, log_le);
- rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&c->log_le,
- sizeof(c->log_le));
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, (u8 *)&c->log_le,
+ sizeof(c->log_le));
if (rv < 0)
return rv;
@@ -2467,7 +2436,7 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus)
/* Read the console buffer */
addr = le32_to_cpu(c->log_le.buf);
- rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize);
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, c->buf, c->bufsize);
if (rv < 0)
return rv;
@@ -2592,7 +2561,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
/* Make sure backplane clock is on */
sdio_claim_host(bus->sdiodev->func[1]);
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ brcmf_sdbrcm_bus_sleep(bus, false, false);
sdio_release_host(bus->sdiodev->func[1]);
/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
@@ -2650,6 +2619,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
bus->activity = false;
sdio_claim_host(bus->sdiodev->func[1]);
+ brcmf_dbg(INFO, "idle\n");
brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
sdio_release_host(bus->sdiodev->func[1]);
} else {
@@ -2679,16 +2649,15 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
struct sdpcm_shared_le sh_le;
__le32 addr_le;
- shaddr = bus->ramsize - 4;
+ shaddr = bus->ci->rambase + bus->ramsize - 4;
/*
* Read last word in socram to determine
* address of sdpcm_shared structure
*/
sdio_claim_host(bus->sdiodev->func[1]);
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
- rv = brcmf_sdbrcm_membytes(bus, false, shaddr,
- (u8 *)&addr_le, 4);
+ brcmf_sdbrcm_bus_sleep(bus, false, false);
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4);
sdio_release_host(bus->sdiodev->func[1]);
if (rv < 0)
return rv;
@@ -2708,8 +2677,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
}
/* Read hndrte_shared structure */
- rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le,
- sizeof(struct sdpcm_shared_le));
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le,
+ sizeof(struct sdpcm_shared_le));
if (rv < 0)
return rv;
@@ -2745,22 +2714,22 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
/* 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));
+ rv = brcmf_sdio_ramrw(bus->sdiodev, 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));
+ rv = brcmf_sdio_ramrw(bus->sdiodev, 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));
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr,
+ (u8 *)&sh_val, sizeof(u32));
if (rv < 0)
return rv;
console_index = le32_to_cpu(sh_val);
@@ -2774,8 +2743,8 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
/* obtain the console data from device */
conbuf[console_size] = '\0';
- rv = brcmf_sdbrcm_membytes(bus, false, console_ptr, (u8 *)conbuf,
- console_size);
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, console_ptr, (u8 *)conbuf,
+ console_size);
if (rv < 0)
goto done;
@@ -2812,8 +2781,8 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
return 0;
}
- error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
- sizeof(struct brcmf_trap_info));
+ error = brcmf_sdio_ramrw(bus->sdiodev, false, sh->trap_addr, (u8 *)&tr,
+ sizeof(struct brcmf_trap_info));
if (error < 0)
return error;
@@ -2856,14 +2825,14 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
sdio_claim_host(bus->sdiodev->func[1]);
if (sh->assert_file_addr != 0) {
- error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr,
- (u8 *)file, 80);
+ error = brcmf_sdio_ramrw(bus->sdiodev, 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);
+ error = brcmf_sdio_ramrw(bus->sdiodev, false,
+ sh->assert_exp_addr, (u8 *)expr, 80);
if (error < 0)
return error;
}
@@ -3021,84 +2990,8 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
return rxlen ? (int)rxlen : -ETIMEDOUT;
}
-static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus)
-{
- int bcmerror = 0;
- u32 varaddr;
- u32 varsizew;
- __le32 varsizew_le;
-#ifdef DEBUG
- char *nvram_ularray;
-#endif /* DEBUG */
-
- /* Even if there are no vars are to be written, we still
- need to set the ramsize. */
- varaddr = (bus->ramsize - 4) - bus->varsz;
-
- if (bus->vars) {
- /* Write the vars list */
- 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",
- bus->varsz);
- nvram_ularray = kmalloc(bus->varsz, GFP_ATOMIC);
- if (!nvram_ularray)
- return -ENOMEM;
-
- /* Upload image to verify downloaded contents. */
- memset(nvram_ularray, 0xaa, bus->varsz);
-
- /* Read the vars list to temp buffer for comparison */
- bcmerror = brcmf_sdbrcm_membytes(bus, false, varaddr,
- nvram_ularray, bus->varsz);
- if (bcmerror) {
- brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n",
- bcmerror, bus->varsz, varaddr);
- }
- /* Compare the org NVRAM with the one read from RAM */
- if (memcmp(bus->vars, nvram_ularray, bus->varsz))
- brcmf_err("Downloaded NVRAM image is corrupted\n");
- else
- brcmf_err("Download/Upload/Compare of NVRAM ok\n");
-
- kfree(nvram_ularray);
-#endif /* DEBUG */
- }
-
- /* 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, bus->varsz);
-
- /*
- * Determine the length token:
- * Varsize, converted to words, in lower 16-bits, checksum
- * in upper 16-bits.
- */
- if (bcmerror) {
- varsizew = 0;
- varsizew_le = cpu_to_le32(0);
- } else {
- 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",
- bus->varsz, varsizew);
-
- /* Write the length token to the last word */
- bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->ramsize - 4),
- (u8 *)&varsizew_le, 4);
-
- return bcmerror;
-}
-
-static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
+static bool brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
{
- int bcmerror = 0;
struct chip_info *ci = bus->ci;
/* To enter download state, disable ARM and reset SOCRAM.
@@ -3107,41 +3000,19 @@ static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
if (enter) {
bus->alp_only = true;
- ci->coredisable(bus->sdiodev, ci, BCMA_CORE_ARM_CM3);
-
- ci->resetcore(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM);
-
- /* Clear the top bit of memory */
- if (bus->ramsize) {
- u32 zeros = 0;
- brcmf_sdbrcm_membytes(bus, true, bus->ramsize - 4,
- (u8 *)&zeros, 4);
- }
+ brcmf_sdio_chip_enter_download(bus->sdiodev, ci);
} else {
- if (!ci->iscoreup(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
- brcmf_err("SOCRAM core is down after reset?\n");
- bcmerror = -EBADE;
- goto fail;
- }
-
- bcmerror = brcmf_sdbrcm_write_vars(bus);
- if (bcmerror) {
- brcmf_err("no vars written to RAM\n");
- bcmerror = 0;
- }
-
- w_sdreg32(bus, 0xFFFFFFFF,
- offsetof(struct sdpcmd_regs, intstatus));
-
- ci->resetcore(bus->sdiodev, ci, BCMA_CORE_ARM_CM3);
+ if (!brcmf_sdio_chip_exit_download(bus->sdiodev, ci, bus->vars,
+ bus->varsz))
+ return false;
/* Allow HT Clock now that the ARM is running. */
bus->alp_only = false;
bus->sdiodev->bus_if->state = BRCMF_BUS_LOAD;
}
-fail:
- return bcmerror;
+
+ return true;
}
static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_sdio *bus)
@@ -3156,10 +3027,11 @@ static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_sdio *bus)
static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
{
- int offset = 0;
+ int offset;
uint len;
u8 *memblock = NULL, *memptr;
int ret;
+ u8 idx;
brcmf_dbg(INFO, "Enter\n");
@@ -3180,10 +3052,15 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
memptr += (BRCMF_SDALIGN -
((u32)(unsigned long)memblock % BRCMF_SDALIGN));
+ offset = bus->ci->rambase;
+
/* Download image */
- while ((len =
- brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus))) {
- ret = brcmf_sdbrcm_membytes(bus, true, offset, memptr, len);
+ len = brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus);
+ idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_ARM_CR4);
+ if (BRCMF_MAX_CORENUM != idx)
+ memcpy(&bus->ci->rst_vec, memptr, sizeof(bus->ci->rst_vec));
+ while (len) {
+ ret = brcmf_sdio_ramrw(bus->sdiodev, true, offset, memptr, len);
if (ret) {
brcmf_err("error %d on writing %d membytes at 0x%08x\n",
ret, MEMBLOCK, offset);
@@ -3191,6 +3068,7 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
}
offset += MEMBLOCK;
+ len = brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus);
}
err:
@@ -3298,7 +3176,7 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
int bcmerror = -1;
/* Keep arm in reset */
- if (brcmf_sdbrcm_download_state(bus, true)) {
+ if (!brcmf_sdbrcm_download_state(bus, true)) {
brcmf_err("error placing ARM core in reset\n");
goto err;
}
@@ -3314,7 +3192,7 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
}
/* Take arm out of reset */
- if (brcmf_sdbrcm_download_state(bus, false)) {
+ if (!brcmf_sdbrcm_download_state(bus, false)) {
brcmf_err("error getting out of ARM core reset\n");
goto err;
}
@@ -3325,6 +3203,103 @@ err:
return bcmerror;
}
+static bool brcmf_sdbrcm_sr_capable(struct brcmf_sdio *bus)
+{
+ u32 addr, reg;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* old chips with PMU version less than 17 don't support save restore */
+ if (bus->ci->pmurev < 17)
+ return false;
+
+ /* read PMU chipcontrol register 3*/
+ addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_addr);
+ brcmf_sdio_regwl(bus->sdiodev, addr, 3, NULL);
+ addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_data);
+ reg = brcmf_sdio_regrl(bus->sdiodev, addr, NULL);
+
+ return (bool)reg;
+}
+
+static void brcmf_sdbrcm_sr_init(struct brcmf_sdio *bus)
+{
+ int err = 0;
+ u8 val;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL,
+ &err);
+ if (err) {
+ brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n");
+ return;
+ }
+
+ val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL,
+ val, &err);
+ if (err) {
+ brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n");
+ return;
+ }
+
+ /* Add CMD14 Support */
+ brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP,
+ (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
+ SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT),
+ &err);
+ if (err) {
+ brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n");
+ return;
+ }
+
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ SBSDIO_FORCE_HT, &err);
+ if (err) {
+ brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n");
+ return;
+ }
+
+ /* set flag */
+ bus->sr_enabled = true;
+ brcmf_dbg(INFO, "SR enabled\n");
+}
+
+/* enable KSO bit */
+static int brcmf_sdbrcm_kso_init(struct brcmf_sdio *bus)
+{
+ u8 val;
+ int err = 0;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* KSO bit added in SDIO core rev 12 */
+ if (bus->ci->c_inf[1].rev < 12)
+ return 0;
+
+ val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+ &err);
+ if (err) {
+ brcmf_err("error reading SBSDIO_FUNC1_SLEEPCSR\n");
+ return err;
+ }
+
+ if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
+ val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN <<
+ SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+ val, &err);
+ if (err) {
+ brcmf_err("error writing SBSDIO_FUNC1_SLEEPCSR\n");
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+
static bool
brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
{
@@ -3423,8 +3398,13 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
ret = -ENODEV;
}
- /* Restore previous clock setting */
- brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
+ if (brcmf_sdbrcm_sr_capable(bus)) {
+ brcmf_sdbrcm_sr_init(bus);
+ } else {
+ /* Restore previous clock setting */
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ saveclk, &err);
+ }
if (ret == 0) {
ret = brcmf_sdio_intr_register(bus->sdiodev);
@@ -3485,7 +3465,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
brcmf_dbg(TIMER, "Enter\n");
/* Poll period: check device if appropriate. */
- if (bus->poll && (++bus->polltick >= bus->pollrate)) {
+ if (!bus->sr_enabled &&
+ bus->poll && (++bus->polltick >= bus->pollrate)) {
u32 intstatus = 0;
/* Reset poll tick */
@@ -3536,7 +3517,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
bus->console.count -= bus->console_interval;
sdio_claim_host(bus->sdiodev->func[1]);
/* Make sure backplane clock is on */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ brcmf_sdbrcm_bus_sleep(bus, false, false);
if (brcmf_sdbrcm_readconsole(bus) < 0)
/* stop on error */
bus->console_interval = 0;
@@ -3553,8 +3534,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
bus->activity = false;
brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
} else {
+ brcmf_dbg(SDIO, "idle\n");
sdio_claim_host(bus->sdiodev->func[1]);
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+ brcmf_sdbrcm_bus_sleep(bus, true, false);
sdio_release_host(bus->sdiodev->func[1]);
}
}
@@ -3565,6 +3547,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
static bool brcmf_sdbrcm_chipmatch(u16 chipid)
{
+ if (chipid == BCM43143_CHIP_ID)
+ return true;
if (chipid == BCM43241_CHIP_ID)
return true;
if (chipid == BCM4329_CHIP_ID)
@@ -3573,6 +3557,8 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid)
return true;
if (chipid == BCM4334_CHIP_ID)
return true;
+ if (chipid == BCM4335_CHIP_ID)
+ return true;
return false;
}
@@ -3650,7 +3636,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
int err = 0;
int reg_addr;
u32 reg_val;
- u8 idx;
+ u32 drivestrength;
bus->alp_only = true;
@@ -3686,8 +3672,16 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
goto fail;
}
- brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci,
- SDIO_DRIVE_STRENGTH);
+ if (brcmf_sdbrcm_kso_init(bus)) {
+ brcmf_err("error enabling KSO\n");
+ goto fail;
+ }
+
+ if ((bus->sdiodev->pdata) && (bus->sdiodev->pdata->drive_strength))
+ drivestrength = bus->sdiodev->pdata->drive_strength;
+ else
+ drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH;
+ brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength);
/* Get info on the SOCRAM cores... */
bus->ramsize = bus->ci->ramsize;
@@ -3696,12 +3690,37 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
goto fail;
}
- /* Set core control so an SDIO reset does a backplane reset */
- idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
- reg_addr = bus->ci->c_inf[idx].base +
- offsetof(struct sdpcmd_regs, corecontrol);
- reg_val = brcmf_sdio_regrl(bus->sdiodev, reg_addr, NULL);
- brcmf_sdio_regwl(bus->sdiodev, reg_addr, reg_val | CC_BPRESEN, NULL);
+ /* Set card control so an SDIO card reset does a WLAN backplane reset */
+ reg_val = brcmf_sdio_regrb(bus->sdiodev,
+ SDIO_CCCR_BRCM_CARDCTRL, &err);
+ if (err)
+ goto fail;
+
+ reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET;
+
+ brcmf_sdio_regwb(bus->sdiodev,
+ SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err);
+ if (err)
+ goto fail;
+
+ /* set PMUControl so a backplane reset does PMU state reload */
+ reg_addr = CORE_CC_REG(bus->ci->c_inf[0].base,
+ pmucontrol);
+ reg_val = brcmf_sdio_regrl(bus->sdiodev,
+ reg_addr,
+ &err);
+ if (err)
+ goto fail;
+
+ reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT);
+
+ brcmf_sdio_regwl(bus->sdiodev,
+ reg_addr,
+ reg_val,
+ &err);
+ if (err)
+ goto fail;
+
sdio_release_host(bus->sdiodev->func[1]);
@@ -3755,6 +3774,10 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
bus->use_rxchain = false;
bus->sd_rxchain = false;
+ /* SR state */
+ bus->sleeping = false;
+ bus->sr_enabled = false;
+
return true;
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index b3c608ee37cf..5352dc1fdf3c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -21,6 +21,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/err.h>
+#include <linux/jiffies.h>
#include <uapi/linux/nl80211.h>
#include <net/cfg80211.h>
@@ -31,8 +32,11 @@
#include "dhd_dbg.h"
#include "dhd_bus.h"
#include "fwil.h"
+#include "fwil_types.h"
#include "fweh.h"
#include "fwsignal.h"
+#include "p2p.h"
+#include "wl_cfg80211.h"
/**
* DOC: Firmware Signalling
@@ -144,6 +148,9 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
#define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST 0x01
#define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED 0x02
+#define BRCMF_FWS_RET_OK_NOSCHEDULE 0
+#define BRCMF_FWS_RET_OK_SCHEDULE 1
+
/**
* enum brcmf_fws_skb_state - indicates processing state of skb.
*
@@ -265,6 +272,9 @@ struct brcmf_skbuff_cb {
brcmu_maskget32(txs, BRCMF_FWS_TXSTAT_ ## field ## _MASK, \
BRCMF_FWS_TXSTAT_ ## field ## _SHIFT)
+/* How long to defer borrowing in jiffies */
+#define BRCMF_FWS_BORROW_DEFER_PERIOD (HZ / 10)
+
/**
* enum brcmf_fws_fifo - fifo indices used by dongle firmware.
*
@@ -419,9 +429,11 @@ struct brcmf_fws_info {
struct work_struct fws_dequeue_work;
u32 fifo_enqpkt[BRCMF_FWS_FIFO_COUNT];
int fifo_credit[BRCMF_FWS_FIFO_COUNT];
+ int credits_borrowed[BRCMF_FWS_FIFO_AC_VO + 1];
int deq_node_pos[BRCMF_FWS_FIFO_COUNT];
u32 fifo_credit_map;
u32 fifo_delay_map;
+ unsigned long borrow_defer_timestamp;
};
/*
@@ -678,28 +690,28 @@ brcmf_fws_mac_descriptor_lookup(struct brcmf_fws_info *fws, u8 *ea)
}
static struct brcmf_fws_mac_descriptor*
-brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, int ifidx, u8 *da)
+brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, struct brcmf_if *ifp,
+ u8 *da)
{
struct brcmf_fws_mac_descriptor *entry = &fws->desc.other;
- struct brcmf_if *ifp;
bool multicast;
+ enum nl80211_iftype iftype;
- brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx);
+ brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx);
multicast = is_multicast_ether_addr(da);
- ifp = fws->drvr->iflist[ifidx ? ifidx + 1 : 0];
- if (WARN_ON(!ifp))
- goto done;
+ iftype = brcmf_cfg80211_get_iftype(ifp);
/* Multicast destination and P2P clients get the interface entry.
* STA gets the interface entry if there is no exact match. For
* example, TDLS destinations have their own entry.
*/
entry = NULL;
- if (multicast && ifp->fws_desc)
+ if ((multicast || iftype == NL80211_IFTYPE_STATION ||
+ iftype == NL80211_IFTYPE_P2P_CLIENT) && ifp->fws_desc)
entry = ifp->fws_desc;
- if (entry != NULL && multicast)
+ if (entry != NULL && iftype != NL80211_IFTYPE_STATION)
goto done;
entry = brcmf_fws_mac_descriptor_lookup(fws, da);
@@ -711,26 +723,29 @@ done:
return entry;
}
-static bool brcmf_fws_mac_desc_ready(struct brcmf_fws_mac_descriptor *entry,
- int fifo)
+static bool brcmf_fws_mac_desc_closed(struct brcmf_fws_info *fws,
+ struct brcmf_fws_mac_descriptor *entry,
+ int fifo)
{
- bool ready;
+ struct brcmf_fws_mac_descriptor *if_entry;
+ bool closed;
- /*
- * destination entry is ready when firmware says it is OPEN
- * and there are no packets enqueued for it.
+ /* for unique destination entries the related interface
+ * may be closed.
*/
- ready = entry->state == BRCMF_FWS_STATE_OPEN &&
- !entry->suppressed &&
- brcmu_pktq_mlen(&entry->psq, 3 << (fifo * 2)) == 0;
-
- /*
- * Or when the destination entry is CLOSED, but firmware has
- * specifically requested packets for this entry.
+ if (entry->mac_handle) {
+ if_entry = &fws->desc.iface[entry->interface_id];
+ if (if_entry->state == BRCMF_FWS_STATE_CLOSE)
+ return true;
+ }
+ /* an entry is closed when the state is closed and
+ * the firmware did not request anything.
*/
- ready = ready || (entry->state == BRCMF_FWS_STATE_CLOSE &&
- (entry->requested_credit + entry->requested_packet));
- return ready;
+ closed = entry->state == BRCMF_FWS_STATE_CLOSE &&
+ !entry->requested_credit && !entry->requested_packet;
+
+ /* Or firmware does not allow traffic for given fifo */
+ return closed || !(entry->ac_bitmap & BIT(fifo));
}
static void brcmf_fws_mac_desc_cleanup(struct brcmf_fws_info *fws,
@@ -825,11 +840,12 @@ brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq,
{
struct brcmf_if *ifp = fws->drvr->iflist[if_id];
- brcmf_dbg(TRACE,
- "enter: bssidx=%d, ifidx=%d\n", ifp->bssidx, ifp->ifidx);
if (WARN_ON(!ifp))
return;
+ brcmf_dbg(TRACE,
+ "enter: bssidx=%d, ifidx=%d\n", ifp->bssidx, ifp->ifidx);
+
if ((ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) &&
pq->len <= BRCMF_FWS_FLOWCONTROL_LOWATER)
brcmf_txflowblock_if(ifp,
@@ -861,9 +877,10 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
entry = &fws->desc.nodes[mac_handle & 0x1F];
if (type == BRCMF_FWS_TYPE_MACDESC_DEL) {
brcmf_dbg(TRACE, "deleting mac %pM idx %d\n", addr, ifidx);
- if (entry->occupied)
+ if (entry->occupied) {
+ brcmf_fws_mac_desc_cleanup(fws, entry, -1);
brcmf_fws_clear_mac_descriptor(entry);
- else
+ } else
fws->stats.mac_update_failed++;
return 0;
}
@@ -914,12 +931,13 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
entry->requested_credit = 0;
if (type == BRCMF_FWS_TYPE_MAC_OPEN) {
entry->state = BRCMF_FWS_STATE_OPEN;
+ return BRCMF_FWS_RET_OK_SCHEDULE;
} else {
entry->state = BRCMF_FWS_STATE_CLOSE;
for (i = BRCMF_FWS_FIFO_AC_BE; i < NL80211_NUM_ACS; i++)
brcmf_fws_tim_update(fws, entry, i);
}
- return 0;
+ return BRCMF_FWS_RET_OK_NOSCHEDULE;
}
static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
@@ -946,10 +964,10 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
switch (type) {
case BRCMF_FWS_TYPE_INTERFACE_OPEN:
entry->state = BRCMF_FWS_STATE_OPEN;
- return 0;
+ return BRCMF_FWS_RET_OK_SCHEDULE;
case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
entry->state = BRCMF_FWS_STATE_CLOSE;
- return 0;
+ return BRCMF_FWS_RET_OK_NOSCHEDULE;
default:
ret = -EINVAL;
break;
@@ -979,15 +997,40 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
entry->requested_packet = data[0];
entry->ac_bitmap = data[2];
- return 0;
+ return BRCMF_FWS_RET_OK_SCHEDULE;
}
static void brcmf_fws_return_credits(struct brcmf_fws_info *fws,
u8 fifo, u8 credits)
{
+ int lender_ac;
+ int *borrowed;
+ int *fifo_credit;
+
if (!credits)
return;
+ if ((fifo == BRCMF_FWS_FIFO_AC_BE) &&
+ (fws->credits_borrowed[0])) {
+ for (lender_ac = BRCMF_FWS_FIFO_AC_VO; lender_ac >= 0;
+ lender_ac--) {
+ borrowed = &fws->credits_borrowed[lender_ac];
+ if (*borrowed) {
+ fws->fifo_credit_map |= (1 << lender_ac);
+ fifo_credit = &fws->fifo_credit[lender_ac];
+ if (*borrowed >= credits) {
+ *borrowed -= credits;
+ *fifo_credit += credits;
+ return;
+ } else {
+ credits -= *borrowed;
+ *fifo_credit += *borrowed;
+ *borrowed = 0;
+ }
+ }
+ }
+ }
+
fws->fifo_credit_map |= 1 << fifo;
fws->fifo_credit[fifo] += credits;
}
@@ -1074,7 +1117,7 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
int num_nodes;
int node_pos;
int prec_out;
- int pmsk = 3;
+ int pmsk;
int i;
table = (struct brcmf_fws_mac_descriptor *)&fws->desc;
@@ -1083,11 +1126,14 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
for (i = 0; i < num_nodes; i++) {
entry = &table[(node_pos + i) % num_nodes];
- if (!entry->occupied)
+ if (!entry->occupied ||
+ brcmf_fws_mac_desc_closed(fws, entry, fifo))
continue;
if (entry->suppressed)
pmsk = 2;
+ else
+ pmsk = 3;
p = brcmu_pktq_mdeq(&entry->psq, pmsk << (fifo * 2), &prec_out);
if (p == NULL) {
if (entry->suppressed) {
@@ -1250,7 +1296,7 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) {
brcmf_dbg(INFO, "ignored\n");
- return 0;
+ return BRCMF_FWS_RET_OK_NOSCHEDULE;
}
brcmf_dbg(TRACE, "enter: data %pM\n", data);
@@ -1259,8 +1305,7 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
brcmf_dbg(INFO, "map: credit %x delay %x\n", fws->fifo_credit_map,
fws->fifo_delay_map);
- brcmf_fws_schedule_deq(fws);
- return 0;
+ return BRCMF_FWS_RET_OK_SCHEDULE;
}
static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
@@ -1344,6 +1389,8 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
u8 type;
u8 len;
u8 *data;
+ s32 status;
+ s32 err;
brcmf_dbg(TRACE, "enter: ifidx %d, skblen %u, sig %d\n",
ifidx, skb->len, signal_len);
@@ -1363,6 +1410,7 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
data_len = signal_len;
signal_data = skb->data;
+ status = BRCMF_FWS_RET_OK_NOSCHEDULE;
while (data_len > 0) {
/* extract tlv info */
type = signal_data[0];
@@ -1388,6 +1436,7 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
if (len != brcmf_fws_get_tlv_len(fws, type))
break;
+ err = BRCMF_FWS_RET_OK_NOSCHEDULE;
switch (type) {
case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
case BRCMF_FWS_TYPE_COMP_TXSTATUS:
@@ -1398,21 +1447,22 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
break;
case BRCMF_FWS_TYPE_MAC_OPEN:
case BRCMF_FWS_TYPE_MAC_CLOSE:
- brcmf_fws_macdesc_state_indicate(fws, type, data);
+ err = brcmf_fws_macdesc_state_indicate(fws, type, data);
break;
case BRCMF_FWS_TYPE_INTERFACE_OPEN:
case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
- brcmf_fws_interface_state_indicate(fws, type, data);
+ err = brcmf_fws_interface_state_indicate(fws, type,
+ data);
break;
case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT:
case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET:
- brcmf_fws_request_indicate(fws, type, data);
+ err = brcmf_fws_request_indicate(fws, type, data);
break;
case BRCMF_FWS_TYPE_TXSTATUS:
brcmf_fws_txstatus_indicate(fws, data);
break;
case BRCMF_FWS_TYPE_FIFO_CREDITBACK:
- brcmf_fws_fifocreditback_indicate(fws, data);
+ err = brcmf_fws_fifocreditback_indicate(fws, data);
break;
case BRCMF_FWS_TYPE_RSSI:
brcmf_fws_rssi_indicate(fws, *data);
@@ -1426,7 +1476,8 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
fws->stats.tlv_invalid_type++;
break;
}
-
+ if (err == BRCMF_FWS_RET_OK_SCHEDULE)
+ status = BRCMF_FWS_RET_OK_SCHEDULE;
signal_data += len + 2;
data_len -= len + 2;
}
@@ -1434,6 +1485,9 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
if (data_len != 0)
fws->stats.tlv_parse_failed++;
+ if (status == BRCMF_FWS_RET_OK_SCHEDULE)
+ brcmf_fws_schedule_deq(fws);
+
/* signalling processing result does
* not affect the actual ethernet packet.
*/
@@ -1553,7 +1607,7 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
return rc;
}
-static int
+static void
brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb)
{
/*
@@ -1595,7 +1649,6 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb)
/* free the hanger slot */
brcmf_fws_hanger_poppkt(&fws->hanger, hslot,
&pktout, true);
- brcmf_txfinalize(fws->drvr, skb, false);
rc = -EINVAL;
goto fail;
}
@@ -1629,11 +1682,31 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb)
fail:
- if (rc)
+ if (rc) {
+ brcmf_txfinalize(fws->drvr, skb, false);
fws->stats.rollback_failed++;
- else
+ } else
fws->stats.rollback_success++;
- return rc;
+}
+
+static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws)
+{
+ int lender_ac;
+
+ if (time_after(fws->borrow_defer_timestamp, jiffies))
+ return -ENAVAIL;
+
+ for (lender_ac = 0; lender_ac <= BRCMF_FWS_FIFO_AC_VO; lender_ac++) {
+ if (fws->fifo_credit[lender_ac]) {
+ fws->credits_borrowed[lender_ac]++;
+ fws->fifo_credit[lender_ac]--;
+ if (fws->fifo_credit[lender_ac] == 0)
+ fws->fifo_credit_map &= ~(1 << lender_ac);
+ brcmf_dbg(TRACE, "borrow credit from: %d\n", lender_ac);
+ return 0;
+ }
+ }
+ return -ENAVAIL;
}
static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo,
@@ -1669,8 +1742,17 @@ static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo,
return 0;
}
+ if (fifo != BRCMF_FWS_FIFO_AC_BE)
+ fws->borrow_defer_timestamp = jiffies +
+ BRCMF_FWS_BORROW_DEFER_PERIOD;
+
if (!(*credit)) {
- brcmf_dbg(TRACE, "exit: credits depleted\n");
+ /* Try to borrow a credit from other queue */
+ if (fifo == BRCMF_FWS_FIFO_AC_BE &&
+ brcmf_fws_borrow_credit(fws) == 0)
+ return 0;
+
+ brcmf_dbg(TRACE, "exit: ac=%d, credits depleted\n", fifo);
return -ENAVAIL;
}
(*credit)--;
@@ -1712,17 +1794,17 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
return rc;
rollback:
- rc = brcmf_fws_rollback_toq(fws, skb);
+ brcmf_fws_rollback_toq(fws, skb);
return rc;
}
int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
{
struct brcmf_pub *drvr = ifp->drvr;
+ struct brcmf_fws_info *fws = drvr->fws;
struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
struct ethhdr *eh = (struct ethhdr *)(skb->data);
ulong flags;
- u8 ifidx = ifp->ifidx;
int fifo = BRCMF_FWS_FIFO_BCMC;
bool multicast = is_multicast_ether_addr(eh->h_dest);
@@ -1734,9 +1816,9 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
if (ntohs(eh->h_proto) == ETH_P_PAE)
atomic_inc(&ifp->pend_8021x_cnt);
- if (!brcmf_fws_fc_active(drvr->fws)) {
+ if (!brcmf_fws_fc_active(fws)) {
/* If the protocol uses a data header, apply it */
- brcmf_proto_hdrpush(drvr, ifidx, 0, skb);
+ brcmf_proto_hdrpush(drvr, ifp->ifidx, 0, skb);
/* Use bus module to send data frame */
return brcmf_bus_txdata(drvr->bus_if, skb);
@@ -1744,9 +1826,9 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
/* set control buffer information */
skcb->if_flags = 0;
- skcb->mac = brcmf_fws_find_mac_desc(drvr->fws, ifidx, eh->h_dest);
+ skcb->mac = brcmf_fws_find_mac_desc(fws, ifp, eh->h_dest);
skcb->state = BRCMF_FWS_SKBSTATE_NEW;
- brcmf_skb_if_flags_set_field(skb, INDEX, ifidx);
+ brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx);
if (!multicast)
fifo = brcmf_fws_prio2fifo[skb->priority];
brcmf_skb_if_flags_set_field(skb, FIFO, fifo);
@@ -1755,14 +1837,18 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
multicast, fifo);
brcmf_fws_lock(drvr, flags);
- if (!brcmf_fws_mac_desc_ready(skcb->mac, fifo) ||
+ if (skcb->mac->suppressed ||
+ brcmf_fws_mac_desc_closed(fws, skcb->mac, fifo) ||
+ brcmu_pktq_mlen(&skcb->mac->psq, 3 << (fifo * 2)) ||
(!multicast &&
- brcmf_fws_consume_credit(drvr->fws, fifo, skb) < 0)) {
+ brcmf_fws_consume_credit(fws, fifo, skb) < 0)) {
/* enqueue the packet in delayQ */
drvr->fws->fifo_delay_map |= 1 << fifo;
- brcmf_fws_enq(drvr->fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
+ brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
} else {
- brcmf_fws_commit_skb(drvr->fws, fifo, skb);
+ if (brcmf_fws_commit_skb(fws, fifo, skb))
+ if (!multicast)
+ brcmf_skb_pick_up_credit(fws, fifo, skb);
}
brcmf_fws_unlock(drvr, flags);
return 0;
@@ -1799,14 +1885,17 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp)
void brcmf_fws_del_interface(struct brcmf_if *ifp)
{
struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
+ ulong flags;
brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx);
if (!entry)
return;
+ brcmf_fws_lock(ifp->drvr, flags);
ifp->fws_desc = NULL;
brcmf_fws_clear_mac_descriptor(entry);
brcmf_fws_cleanup(ifp->drvr->fws, ifp->ifidx);
+ brcmf_fws_unlock(ifp->drvr, flags);
}
static void brcmf_fws_dequeue_worker(struct work_struct *worker)
@@ -1826,14 +1915,29 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
fws->fifo_credit[fifo]);
for (credit = 0; credit < fws->fifo_credit[fifo]; /* nop */) {
skb = brcmf_fws_deq(fws, fifo);
- if (!skb)
+ if (!skb || brcmf_fws_commit_skb(fws, fifo, skb))
break;
- if (!brcmf_fws_commit_skb(fws, fifo, skb) &&
- brcmf_skbcb(skb)->if_flags &
+ if (brcmf_skbcb(skb)->if_flags &
BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)
credit++;
}
- fws->fifo_credit[fifo] -= credit;
+ if ((fifo == BRCMF_FWS_FIFO_AC_BE) &&
+ (credit == fws->fifo_credit[fifo])) {
+ fws->fifo_credit[fifo] -= credit;
+ while (brcmf_fws_borrow_credit(fws) == 0) {
+ skb = brcmf_fws_deq(fws, fifo);
+ if (!skb) {
+ brcmf_fws_return_credits(fws, fifo, 1);
+ break;
+ }
+ if (brcmf_fws_commit_skb(fws, fifo, skb)) {
+ brcmf_fws_return_credits(fws, fifo, 1);
+ break;
+ }
+ }
+ } else {
+ fws->fifo_credit[fifo] -= credit;
+ }
}
brcmf_fws_unlock(fws->drvr, flags);
}
@@ -1872,16 +1976,20 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS |
BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE;
- rc = brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv);
+ rc = brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP,
+ brcmf_fws_notify_credit_map);
if (rc < 0) {
- brcmf_err("failed to set bdcv2 tlv signaling\n");
+ brcmf_err("register credit map handler failed\n");
goto fail;
}
- if (brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP,
- brcmf_fws_notify_credit_map)) {
- brcmf_err("register credit map handler failed\n");
- goto fail;
+ /* setting the iovar may fail if feature is unsupported
+ * so leave the rc as is so driver initialization can
+ * continue.
+ */
+ if (brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv)) {
+ brcmf_err("failed to set bdcv2 tlv signaling\n");
+ goto fail_event;
}
brcmf_fws_hanger_init(&drvr->fws->hanger);
@@ -1897,9 +2005,9 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
drvr->fw_signals ? "enabled" : "disabled", tlv);
return 0;
+fail_event:
+ brcmf_fweh_unregister(drvr, BRCMF_E_FIFO_CREDIT_MAP);
fail:
- /* disable flow control entirely */
- drvr->fw_signals = false;
brcmf_fws_deinit(drvr);
return rc;
}
@@ -1912,6 +2020,14 @@ void brcmf_fws_deinit(struct brcmf_pub *drvr)
if (!fws)
return;
+ /* disable firmware signalling entirely
+ * to avoid using the workqueue.
+ */
+ drvr->fw_signals = false;
+
+ if (drvr->fws->fws_wq)
+ destroy_workqueue(drvr->fws->fws_wq);
+
/* cleanup */
brcmf_fws_lock(drvr, flags);
brcmf_fws_cleanup(fws, -1);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
index 94ff045df2b3..2b90da0d85f3 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
@@ -424,29 +424,6 @@ static void brcmf_p2p_print_actframe(bool tx, void *frame, u32 frame_len)
/**
- * brcmf_p2p_chnr_to_chspec() - convert channel number to chanspec.
- *
- * @channel: channel number
- */
-static u16 brcmf_p2p_chnr_to_chspec(u16 channel)
-{
- u16 chanspec;
-
- chanspec = channel & WL_CHANSPEC_CHAN_MASK;
-
- if (channel <= CH_MAX_2G_CHANNEL)
- chanspec |= WL_CHANSPEC_BAND_2G;
- else
- chanspec |= WL_CHANSPEC_BAND_5G;
-
- chanspec |= WL_CHANSPEC_BW_20;
- chanspec |= WL_CHANSPEC_CTL_SB_NONE;
-
- return chanspec;
-}
-
-
-/**
* brcmf_p2p_set_firmware() - prepare firmware for peer-to-peer operation.
*
* @ifp: ifp to use for iovars (primary).
@@ -837,7 +814,8 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
IEEE80211_CHAN_PASSIVE_SCAN))
continue;
- chanspecs[i] = channel_to_chanspec(chan);
+ chanspecs[i] = channel_to_chanspec(&p2p->cfg->d11inf,
+ chan);
brcmf_dbg(INFO, "%d: chan=%d, channel spec=%x\n",
num_nodfs, chan->hw_value, chanspecs[i]);
num_nodfs++;
@@ -945,8 +923,8 @@ static s32
brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration)
{
struct brcmf_cfg80211_vif *vif;
+ struct brcmu_chan ch;
s32 err = 0;
- u16 chanspec;
vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
if (!vif) {
@@ -961,9 +939,11 @@ brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration)
goto exit;
}
- chanspec = brcmf_p2p_chnr_to_chspec(channel);
+ ch.chnum = channel;
+ ch.bw = BRCMU_CHAN_BW_20;
+ p2p->cfg->d11inf.encchspec(&ch);
err = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_LISTEN,
- chanspec, (u16)duration);
+ ch.chspec, (u16)duration);
if (!err) {
set_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status);
p2p->remain_on_channel_cookie++;
@@ -1075,6 +1055,7 @@ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel)
u32 channel_cnt;
u16 *default_chan_list;
u32 i;
+ struct brcmu_chan ch;
brcmf_dbg(TRACE, "Enter\n");
@@ -1089,15 +1070,23 @@ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel)
err = -ENOMEM;
goto exit;
}
+ ch.bw = BRCMU_CHAN_BW_20;
if (channel) {
+ ch.chnum = channel;
+ p2p->cfg->d11inf.encchspec(&ch);
/* insert same channel to the chan_list */
for (i = 0; i < channel_cnt; i++)
- default_chan_list[i] =
- brcmf_p2p_chnr_to_chspec(channel);
+ default_chan_list[i] = ch.chspec;
} else {
- default_chan_list[0] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_1);
- default_chan_list[1] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_2);
- default_chan_list[2] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_3);
+ ch.chnum = SOCIAL_CHAN_1;
+ p2p->cfg->d11inf.encchspec(&ch);
+ default_chan_list[0] = ch.chspec;
+ ch.chnum = SOCIAL_CHAN_2;
+ p2p->cfg->d11inf.encchspec(&ch);
+ default_chan_list[1] = ch.chspec;
+ ch.chnum = SOCIAL_CHAN_3;
+ p2p->cfg->d11inf.encchspec(&ch);
+ default_chan_list[2] = ch.chspec;
}
err = brcmf_p2p_escan(p2p, channel_cnt, default_chan_list,
WL_P2P_DISC_ST_SEARCH, WL_ESCAN_ACTION_START,
@@ -1227,6 +1216,7 @@ bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg,
{
struct brcmf_p2p_info *p2p = &cfg->p2p;
struct afx_hdl *afx_hdl = &p2p->afx_hdl;
+ struct brcmu_chan ch;
u8 *ie;
s32 err;
u8 p2p_dev_addr[ETH_ALEN];
@@ -1252,8 +1242,12 @@ bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg,
p2p_dev_addr, sizeof(p2p_dev_addr));
if ((err >= 0) &&
(!memcmp(p2p_dev_addr, afx_hdl->tx_dst_addr, ETH_ALEN))) {
- afx_hdl->peer_chan = bi->ctl_ch ? bi->ctl_ch :
- CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
+ if (!bi->ctl_ch) {
+ ch.chspec = le16_to_cpu(bi->chanspec);
+ cfg->d11inf.decchspec(&ch);
+ bi->ctl_ch = ch.chnum;
+ }
+ afx_hdl->peer_chan = bi->ctl_ch;
brcmf_dbg(TRACE, "ACTION FRAME SCAN : Peer %pM found, channel : %d\n",
afx_hdl->tx_dst_addr, afx_hdl->peer_chan);
complete(&afx_hdl->act_frm_scan);
@@ -1360,12 +1354,14 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
u8 *frame = (u8 *)(rxframe + 1);
struct brcmf_p2p_pub_act_frame *act_frm;
struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm;
- u16 chanspec = be16_to_cpu(rxframe->chanspec);
+ struct brcmu_chan ch;
struct ieee80211_mgmt *mgmt_frame;
s32 freq;
u16 mgmt_type;
u8 action;
+ ch.chspec = be16_to_cpu(rxframe->chanspec);
+ cfg->d11inf.decchspec(&ch);
/* Check if wpa_supplicant has registered for this frame */
brcmf_dbg(INFO, "ifp->vif->mgmt_rx_reg %04x\n", ifp->vif->mgmt_rx_reg);
mgmt_type = (IEEE80211_STYPE_ACTION & IEEE80211_FCTL_STYPE) >> 4;
@@ -1384,7 +1380,7 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
&p2p->status) &&
(memcmp(afx_hdl->tx_dst_addr, e->addr,
ETH_ALEN) == 0)) {
- afx_hdl->peer_chan = CHSPEC_CHANNEL(chanspec);
+ afx_hdl->peer_chan = ch.chnum;
brcmf_dbg(INFO, "GON request: Peer found, channel=%d\n",
afx_hdl->peer_chan);
complete(&afx_hdl->act_frm_scan);
@@ -1427,8 +1423,8 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
memcpy(&mgmt_frame->u, frame, mgmt_frame_len);
mgmt_frame_len += offsetof(struct ieee80211_mgmt, u);
- freq = ieee80211_channel_to_frequency(CHSPEC_CHANNEL(chanspec),
- CHSPEC_IS2G(chanspec) ?
+ freq = ieee80211_channel_to_frequency(ch.chnum,
+ ch.band == BRCMU_CHAN_BAND_2G ?
IEEE80211_BAND_2GHZ :
IEEE80211_BAND_5GHZ);
@@ -1854,6 +1850,7 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
struct brcmf_cfg80211_vif *vif = ifp->vif;
struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
u16 chanspec = be16_to_cpu(rxframe->chanspec);
+ struct brcmu_chan ch;
u8 *mgmt_frame;
u32 mgmt_frame_len;
s32 freq;
@@ -1862,9 +1859,12 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
brcmf_dbg(INFO, "Enter: event %d reason %d\n", e->event_code,
e->reason);
+ ch.chspec = be16_to_cpu(rxframe->chanspec);
+ cfg->d11inf.decchspec(&ch);
+
if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status) &&
(memcmp(afx_hdl->tx_dst_addr, e->addr, ETH_ALEN) == 0)) {
- afx_hdl->peer_chan = CHSPEC_CHANNEL(chanspec);
+ afx_hdl->peer_chan = ch.chnum;
brcmf_dbg(INFO, "PROBE REQUEST: Peer found, channel=%d\n",
afx_hdl->peer_chan);
complete(&afx_hdl->act_frm_scan);
@@ -1889,8 +1889,8 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
mgmt_frame = (u8 *)(rxframe + 1);
mgmt_frame_len = e->datalen - sizeof(*rxframe);
- freq = ieee80211_channel_to_frequency(CHSPEC_CHANNEL(chanspec),
- CHSPEC_IS2G(chanspec) ?
+ freq = ieee80211_channel_to_frequency(ch.chnum,
+ ch.band == BRCMU_CHAN_BAND_2G ?
IEEE80211_BAND_2GHZ :
IEEE80211_BAND_5GHZ);
@@ -2014,21 +2014,19 @@ static void brcmf_p2p_get_current_chanspec(struct brcmf_p2p_info *p2p,
{
struct brcmf_if *ifp;
struct brcmf_fil_chan_info_le ci;
+ struct brcmu_chan ch;
s32 err;
ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
- *chanspec = 11 & WL_CHANSPEC_CHAN_MASK;
+ ch.chnum = 11;
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CHANNEL, &ci, sizeof(ci));
- if (!err) {
- *chanspec = le32_to_cpu(ci.hw_channel) & WL_CHANSPEC_CHAN_MASK;
- if (*chanspec < CH_MAX_2G_CHANNEL)
- *chanspec |= WL_CHANSPEC_BAND_2G;
- else
- *chanspec |= WL_CHANSPEC_BAND_5G;
- }
- *chanspec |= WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE;
+ if (!err)
+ ch.chnum = le32_to_cpu(ci.hw_channel);
+ ch.bw = BRCMU_CHAN_BW_20;
+ p2p->cfg->d11inf.encchspec(&ch);
+ *chanspec = ch.chspec;
}
/**
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
index 14be2d5530ce..ca72177388b9 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
@@ -40,6 +40,15 @@
#define BCM4329_CORE_ARM_BASE 0x18002000
#define BCM4329_RAMSIZE 0x48000
+/* bcm43143 */
+/* SDIO device core */
+#define BCM43143_CORE_BUS_BASE 0x18002000
+/* internal memory core */
+#define BCM43143_CORE_SOCRAM_BASE 0x18004000
+/* ARM Cortex M3 core, ID 0x82a */
+#define BCM43143_CORE_ARM_BASE 0x18003000
+#define BCM43143_RAMSIZE 0x70000
+
#define SBCOREREV(sbidh) \
((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
((sbidh) & SSB_IDHIGH_RCLO))
@@ -52,6 +61,9 @@
#define CIB_REV_MASK 0xff000000
#define CIB_REV_SHIFT 24
+/* ARM CR4 core specific control flag bits */
+#define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020
+
#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
/* SDIO Pad drive strength to select value mappings */
struct sdiod_drive_str {
@@ -70,6 +82,14 @@ static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
{0, 0x1}
};
+/* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */
+static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
+ {16, 0x7},
+ {12, 0x5},
+ {8, 0x3},
+ {4, 0x1}
+};
+
u8
brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid)
{
@@ -149,7 +169,7 @@ brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
static void
brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid)
+ struct chip_info *ci, u16 coreid, u32 core_bits)
{
u32 regdata, base;
u8 idx;
@@ -235,7 +255,7 @@ brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
static void
brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid)
+ struct chip_info *ci, u16 coreid, u32 core_bits)
{
u8 idx;
u32 regdata;
@@ -249,19 +269,36 @@ brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
if ((regdata & BCMA_RESET_CTL_RESET) != 0)
return;
- brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, 0, NULL);
- regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
+ /* ensure no pending backplane operation
+ * 300uc should be sufficient for backplane ops to be finish
+ * extra 10ms is taken into account for firmware load stage
+ * after 10300us carry on disabling the core anyway
+ */
+ SPINWAIT(brcmf_sdio_regrl(sdiodev,
+ ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
+ NULL), 10300);
+ regdata = brcmf_sdio_regrl(sdiodev,
+ ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
NULL);
- udelay(10);
+ if (regdata)
+ brcmf_err("disabling core 0x%x with reset status %x\n",
+ coreid, regdata);
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
BCMA_RESET_CTL_RESET, NULL);
udelay(1);
+
+ brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
+ core_bits, NULL);
+ regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
+ NULL);
+ usleep_range(10, 20);
+
}
static void
brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid)
+ struct chip_info *ci, u16 coreid, u32 core_bits)
{
u32 regdata;
u8 idx;
@@ -272,7 +309,7 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
* Must do the disable sequence first to work for
* arbitrary current core state.
*/
- brcmf_sdio_sb_coredisable(sdiodev, ci, coreid);
+ brcmf_sdio_sb_coredisable(sdiodev, ci, coreid, 0);
/*
* Now do the initialization sequence.
@@ -325,7 +362,7 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
static void
brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid)
+ struct chip_info *ci, u16 coreid, u32 core_bits)
{
u8 idx;
u32 regdata;
@@ -333,31 +370,69 @@ brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
/* must disable first to work for arbitrary current core state */
- brcmf_sdio_ai_coredisable(sdiodev, ci, coreid);
+ brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, core_bits);
/* now do initialization sequence */
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
- BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
+ core_bits | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
NULL);
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
0, NULL);
+ regdata = brcmf_sdio_regrl(sdiodev,
+ ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
+ NULL);
udelay(1);
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
- BCMA_IOCTL_CLK, NULL);
+ core_bits | BCMA_IOCTL_CLK, NULL);
regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
NULL);
udelay(1);
}
+#ifdef DEBUG
+/* safety check for chipinfo */
+static int brcmf_sdio_chip_cichk(struct chip_info *ci)
+{
+ u8 core_idx;
+
+ /* check RAM core presence for ARM CM3 core */
+ core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
+ if (BRCMF_MAX_CORENUM != core_idx) {
+ core_idx = brcmf_sdio_chip_getinfidx(ci,
+ BCMA_CORE_INTERNAL_MEM);
+ if (BRCMF_MAX_CORENUM == core_idx) {
+ brcmf_err("RAM core not provided with ARM CM3 core\n");
+ return -ENODEV;
+ }
+ }
+
+ /* check RAM base for ARM CR4 core */
+ core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4);
+ if (BRCMF_MAX_CORENUM != core_idx) {
+ if (ci->rambase == 0) {
+ brcmf_err("RAM base not provided with ARM CR4 core\n");
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+#else /* DEBUG */
+static inline int brcmf_sdio_chip_cichk(struct chip_info *ci)
+{
+ return 0;
+}
+#endif
+
static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u32 regs)
{
u32 regdata;
+ int ret;
- /*
- * Get CC core rev
+ /* Get CC core rev
* Chipid is assume to be at offset 0 from regs arg
* For different chiptypes or old sdio hosts w/o chipcommon,
* other ways of recognition should be added here.
@@ -375,6 +450,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
/* Address of cores for new chips should be added here */
switch (ci->chip) {
+ case BCM43143_CHIP_ID:
+ ci->c_inf[0].wrapbase = ci->c_inf[0].base + 0x00100000;
+ ci->c_inf[0].cib = 0x2b000000;
+ ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
+ ci->c_inf[1].base = BCM43143_CORE_BUS_BASE;
+ ci->c_inf[1].wrapbase = ci->c_inf[1].base + 0x00100000;
+ ci->c_inf[1].cib = 0x18000000;
+ ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
+ ci->c_inf[2].base = BCM43143_CORE_SOCRAM_BASE;
+ ci->c_inf[2].wrapbase = ci->c_inf[2].base + 0x00100000;
+ ci->c_inf[2].cib = 0x14000000;
+ ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
+ ci->c_inf[3].base = BCM43143_CORE_ARM_BASE;
+ ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
+ ci->c_inf[3].cib = 0x07000000;
+ ci->ramsize = BCM43143_RAMSIZE;
+ break;
case BCM43241_CHIP_ID:
ci->c_inf[0].wrapbase = 0x18100000;
ci->c_inf[0].cib = 0x2a084411;
@@ -435,11 +527,29 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
ci->c_inf[3].cib = 0x07004211;
ci->ramsize = 0x80000;
break;
+ case BCM4335_CHIP_ID:
+ ci->c_inf[0].wrapbase = 0x18100000;
+ ci->c_inf[0].cib = 0x2b084411;
+ ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
+ ci->c_inf[1].base = 0x18005000;
+ ci->c_inf[1].wrapbase = 0x18105000;
+ ci->c_inf[1].cib = 0x0f004211;
+ ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
+ ci->c_inf[2].base = 0x18002000;
+ ci->c_inf[2].wrapbase = 0x18102000;
+ ci->c_inf[2].cib = 0x01084411;
+ ci->ramsize = 0xc0000;
+ ci->rambase = 0x180000;
+ break;
default:
brcmf_err("chipid 0x%x is not supported\n", ci->chip);
return -ENODEV;
}
+ ret = brcmf_sdio_chip_cichk(ci);
+ if (ret)
+ return ret;
+
switch (ci->socitype) {
case SOCI_SB:
ci->iscoreup = brcmf_sdio_sb_iscoreup;
@@ -539,7 +649,7 @@ brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
* Make sure any on-chip ARM is off (in case strapping is wrong),
* or downloaded code was already running.
*/
- ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3);
+ ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
}
int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
@@ -600,21 +710,37 @@ void
brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u32 drivestrength)
{
- struct sdiod_drive_str *str_tab = NULL;
- u32 str_mask = 0;
- u32 str_shift = 0;
+ const struct sdiod_drive_str *str_tab = NULL;
+ u32 str_mask;
+ u32 str_shift;
char chn[8];
u32 base = ci->c_inf[0].base;
+ u32 i;
+ u32 drivestrength_sel = 0;
+ u32 cc_data_temp;
+ u32 addr;
if (!(ci->c_inf[0].caps & CC_CAP_PMU))
return;
switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
- str_tab = (struct sdiod_drive_str *)&sdiod_drvstr_tab1_1v8;
+ str_tab = sdiod_drvstr_tab1_1v8;
str_mask = 0x00003800;
str_shift = 11;
break;
+ case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
+ /* note: 43143 does not support tristate */
+ i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
+ if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) {
+ str_tab = sdiod_drvstr_tab2_3v3;
+ str_mask = 0x00000007;
+ str_shift = 0;
+ } else
+ brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
+ brcmf_sdio_chip_name(ci->chip, chn, 8),
+ drivestrength);
+ break;
default:
brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
brcmf_sdio_chip_name(ci->chip, chn, 8),
@@ -623,30 +749,207 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
}
if (str_tab != NULL) {
- u32 drivestrength_sel = 0;
- u32 cc_data_temp;
- int i;
-
for (i = 0; str_tab[i].strength != 0; i++) {
if (drivestrength >= str_tab[i].strength) {
drivestrength_sel = str_tab[i].sel;
break;
}
}
-
- brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr),
- 1, NULL);
- cc_data_temp =
- brcmf_sdio_regrl(sdiodev,
- CORE_CC_REG(base, chipcontrol_addr),
- NULL);
+ addr = CORE_CC_REG(base, chipcontrol_addr);
+ brcmf_sdio_regwl(sdiodev, addr, 1, NULL);
+ cc_data_temp = brcmf_sdio_regrl(sdiodev, addr, NULL);
cc_data_temp &= ~str_mask;
drivestrength_sel <<= str_shift;
cc_data_temp |= drivestrength_sel;
- brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr),
- cc_data_temp, NULL);
+ brcmf_sdio_regwl(sdiodev, addr, cc_data_temp, NULL);
- brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
- drivestrength, cc_data_temp);
+ brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
+ str_tab[i].strength, drivestrength, cc_data_temp);
}
}
+
+#ifdef DEBUG
+static bool
+brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr,
+ char *nvram_dat, uint nvram_sz)
+{
+ char *nvram_ularray;
+ int err;
+ bool ret = true;
+
+ /* read back and verify */
+ brcmf_dbg(INFO, "Compare NVRAM dl & ul; size=%d\n", nvram_sz);
+ nvram_ularray = kmalloc(nvram_sz, GFP_KERNEL);
+ /* do not proceed while no memory but */
+ if (!nvram_ularray)
+ return true;
+
+ /* Upload image to verify downloaded contents. */
+ memset(nvram_ularray, 0xaa, nvram_sz);
+
+ /* Read the vars list to temp buffer for comparison */
+ err = brcmf_sdio_ramrw(sdiodev, false, nvram_addr, nvram_ularray,
+ nvram_sz);
+ if (err) {
+ brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n",
+ err, nvram_sz, nvram_addr);
+ } else if (memcmp(nvram_dat, nvram_ularray, nvram_sz)) {
+ brcmf_err("Downloaded NVRAM image is corrupted\n");
+ ret = false;
+ }
+ kfree(nvram_ularray);
+
+ return ret;
+}
+#else /* DEBUG */
+static inline bool
+brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr,
+ char *nvram_dat, uint nvram_sz)
+{
+ return true;
+}
+#endif /* DEBUG */
+
+static bool brcmf_sdio_chip_writenvram(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci,
+ char *nvram_dat, uint nvram_sz)
+{
+ int err;
+ u32 nvram_addr;
+ u32 token;
+ __le32 token_le;
+
+ nvram_addr = (ci->ramsize - 4) - nvram_sz + ci->rambase;
+
+ /* Write the vars list */
+ err = brcmf_sdio_ramrw(sdiodev, true, nvram_addr, nvram_dat, nvram_sz);
+ if (err) {
+ brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n",
+ err, nvram_sz, nvram_addr);
+ return false;
+ }
+
+ if (!brcmf_sdio_chip_verifynvram(sdiodev, nvram_addr,
+ nvram_dat, nvram_sz))
+ return false;
+
+ /* generate token:
+ * nvram size, converted to words, in lower 16-bits, checksum
+ * in upper 16-bits.
+ */
+ token = nvram_sz / 4;
+ token = (~token << 16) | (token & 0x0000FFFF);
+ token_le = cpu_to_le32(token);
+
+ brcmf_dbg(INFO, "RAM size: %d\n", ci->ramsize);
+ brcmf_dbg(INFO, "nvram is placed at %d, size %d, token=0x%08x\n",
+ nvram_addr, nvram_sz, token);
+
+ /* Write the length token to the last word */
+ if (brcmf_sdio_ramrw(sdiodev, true, (ci->ramsize - 4 + ci->rambase),
+ (u8 *)&token_le, 4))
+ return false;
+
+ return true;
+}
+
+static void
+brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci)
+{
+ u32 zeros = 0;
+
+ ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
+ ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0);
+
+ /* clear length token */
+ brcmf_sdio_ramrw(sdiodev, true, ci->ramsize - 4, (u8 *)&zeros, 4);
+}
+
+static bool
+brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
+ char *nvram_dat, uint nvram_sz)
+{
+ u8 core_idx;
+ u32 reg_addr;
+
+ if (!ci->iscoreup(sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
+ brcmf_err("SOCRAM core is down after reset?\n");
+ return false;
+ }
+
+ if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz))
+ return false;
+
+ /* clear all interrupts */
+ core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
+ reg_addr = ci->c_inf[core_idx].base;
+ reg_addr += offsetof(struct sdpcmd_regs, intstatus);
+ brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
+
+ ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
+
+ return true;
+}
+
+static inline void
+brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci)
+{
+ ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4,
+ ARMCR4_BCMA_IOCTL_CPUHALT);
+}
+
+static bool
+brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
+ char *nvram_dat, uint nvram_sz)
+{
+ u8 core_idx;
+ u32 reg_addr;
+
+ if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz))
+ return false;
+
+ /* clear all interrupts */
+ core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
+ reg_addr = ci->c_inf[core_idx].base;
+ reg_addr += offsetof(struct sdpcmd_regs, intstatus);
+ brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
+
+ /* Write reset vector to address 0 */
+ brcmf_sdio_ramrw(sdiodev, true, 0, (void *)&ci->rst_vec,
+ sizeof(ci->rst_vec));
+
+ /* restore ARM */
+ ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, 0);
+
+ return true;
+}
+
+void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci)
+{
+ u8 arm_core_idx;
+
+ arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
+ if (BRCMF_MAX_CORENUM != arm_core_idx) {
+ brcmf_sdio_chip_cm3_enterdl(sdiodev, ci);
+ return;
+ }
+
+ brcmf_sdio_chip_cr4_enterdl(sdiodev, ci);
+}
+
+bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci, char *nvram_dat,
+ uint nvram_sz)
+{
+ u8 arm_core_idx;
+
+ arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
+ if (BRCMF_MAX_CORENUM != arm_core_idx)
+ return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci, nvram_dat,
+ nvram_sz);
+
+ return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci, nvram_dat, nvram_sz);
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
index ce974d76bd92..83c041f1bf4a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
@@ -73,15 +73,17 @@ struct chip_info {
u32 pmurev;
u32 pmucaps;
u32 ramsize;
+ u32 rambase;
+ u32 rst_vec; /* reset vertor for ARM CR4 core */
bool (*iscoreup)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
u16 coreid);
u32 (*corerev)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
u16 coreid);
void (*coredisable)(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid);
+ struct chip_info *ci, u16 coreid, u32 core_bits);
void (*resetcore)(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid);
+ struct chip_info *ci, u16 coreid, u32 core_bits);
};
struct sbconfig {
@@ -124,6 +126,95 @@ struct sbconfig {
u32 sbidhigh; /* identification */
};
+/* sdio core registers */
+struct sdpcmd_regs {
+ u32 corecontrol; /* 0x00, rev8 */
+ u32 corestatus; /* rev8 */
+ u32 PAD[1];
+ u32 biststatus; /* rev8 */
+
+ /* PCMCIA access */
+ u16 pcmciamesportaladdr; /* 0x010, rev8 */
+ u16 PAD[1];
+ u16 pcmciamesportalmask; /* rev8 */
+ u16 PAD[1];
+ u16 pcmciawrframebc; /* rev8 */
+ u16 PAD[1];
+ u16 pcmciaunderflowtimer; /* rev8 */
+ u16 PAD[1];
+
+ /* interrupt */
+ u32 intstatus; /* 0x020, rev8 */
+ u32 hostintmask; /* rev8 */
+ u32 intmask; /* rev8 */
+ u32 sbintstatus; /* rev8 */
+ u32 sbintmask; /* rev8 */
+ u32 funcintmask; /* rev4 */
+ u32 PAD[2];
+ u32 tosbmailbox; /* 0x040, rev8 */
+ u32 tohostmailbox; /* rev8 */
+ u32 tosbmailboxdata; /* rev8 */
+ u32 tohostmailboxdata; /* rev8 */
+
+ /* synchronized access to registers in SDIO clock domain */
+ u32 sdioaccess; /* 0x050, rev8 */
+ u32 PAD[3];
+
+ /* PCMCIA frame control */
+ u8 pcmciaframectrl; /* 0x060, rev8 */
+ u8 PAD[3];
+ u8 pcmciawatermark; /* rev8 */
+ u8 PAD[155];
+
+ /* interrupt batching control */
+ u32 intrcvlazy; /* 0x100, rev8 */
+ u32 PAD[3];
+
+ /* counters */
+ u32 cmd52rd; /* 0x110, rev8 */
+ u32 cmd52wr; /* rev8 */
+ u32 cmd53rd; /* rev8 */
+ u32 cmd53wr; /* rev8 */
+ u32 abort; /* rev8 */
+ u32 datacrcerror; /* rev8 */
+ u32 rdoutofsync; /* rev8 */
+ u32 wroutofsync; /* rev8 */
+ u32 writebusy; /* rev8 */
+ u32 readwait; /* rev8 */
+ u32 readterm; /* rev8 */
+ u32 writeterm; /* rev8 */
+ u32 PAD[40];
+ u32 clockctlstatus; /* rev8 */
+ u32 PAD[7];
+
+ u32 PAD[128]; /* DMA engines */
+
+ /* SDIO/PCMCIA CIS region */
+ char cis[512]; /* 0x400-0x5ff, rev6 */
+
+ /* PCMCIA function control registers */
+ char pcmciafcr[256]; /* 0x600-6ff, rev6 */
+ u16 PAD[55];
+
+ /* PCMCIA backplane access */
+ u16 backplanecsr; /* 0x76E, rev6 */
+ u16 backplaneaddr0; /* rev6 */
+ u16 backplaneaddr1; /* rev6 */
+ u16 backplaneaddr2; /* rev6 */
+ u16 backplaneaddr3; /* rev6 */
+ u16 backplanedata0; /* rev6 */
+ u16 backplanedata1; /* rev6 */
+ u16 backplanedata2; /* rev6 */
+ u16 backplanedata3; /* rev6 */
+ u16 PAD[31];
+
+ /* sprom "size" & "blank" info */
+ u16 spromstatus; /* 0x7BE, rev2 */
+ u32 PAD[464];
+
+ u16 PAD[0x80];
+};
+
extern int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
struct chip_info **ci_ptr, u32 regs);
extern void brcmf_sdio_chip_detach(struct chip_info **ci_ptr);
@@ -131,6 +222,10 @@ extern void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci,
u32 drivestrength);
extern u8 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid);
-
+extern void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci);
+extern bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci, char *nvram_dat,
+ uint nvram_sz);
#endif /* _BRCMFMAC_SDIO_CHIP_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 0d30afd8c672..7c1b6332747e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -48,7 +48,13 @@
#define SBSDIO_NUM_FUNCTION 3
/* function 0 vendor specific CCCR registers */
-#define SDIO_CCCR_BRCM_SEPINT 0xf2
+#define SDIO_CCCR_BRCM_CARDCAP 0xf0
+#define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02
+#define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04
+#define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08
+#define SDIO_CCCR_BRCM_CARDCTRL 0xf1
+#define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET 0x02
+#define SDIO_CCCR_BRCM_SEPINT 0xf2
#define SDIO_SEPINT_MASK 0x01
#define SDIO_SEPINT_OE 0x02
@@ -97,9 +103,23 @@
#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B
/* Read Frame Byte Count High */
#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C
+/* MesBusyCtl (rev 11) */
+#define SBSDIO_FUNC1_MESBUSYCTRL 0x1001D
+/* Sdio Core Rev 12 */
+#define SBSDIO_FUNC1_WAKEUPCTRL 0x1001E
+#define SBSDIO_FUNC1_WCTRL_ALPWAIT_MASK 0x1
+#define SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT 0
+#define SBSDIO_FUNC1_WCTRL_HTWAIT_MASK 0x2
+#define SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT 1
+#define SBSDIO_FUNC1_SLEEPCSR 0x1001F
+#define SBSDIO_FUNC1_SLEEPCSR_KSO_MASK 0x1
+#define SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT 0
+#define SBSDIO_FUNC1_SLEEPCSR_KSO_EN 1
+#define SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK 0x2
+#define SBSDIO_FUNC1_SLEEPCSR_DEVON_SHIFT 1
#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */
-#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */
+#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001F /* f1 misc register end */
/* function 1 OCP space */
@@ -154,13 +174,11 @@ struct brcmf_sdio_dev {
wait_queue_head_t request_buffer_wait;
struct device *dev;
struct brcmf_bus *bus_if;
-#ifdef CONFIG_BRCMFMAC_SDIO_OOB
- unsigned int irq; /* oob interrupt number */
- unsigned long irq_flags; /* board specific oob flags */
+ struct brcmfmac_sdio_platform_data *pdata;
+ bool oob_irq_requested;
bool irq_en; /* irq enable flags */
spinlock_t irq_en_lock;
bool irq_wake; /* irq wake enable flags */
-#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
};
/* Register/deregister interrupt handler. */
@@ -224,6 +242,8 @@ brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
*/
extern int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw,
u32 addr, u8 *buf, uint nbytes);
+extern int brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write,
+ u32 address, u8 *data, uint size);
/* Issue an abort to the specified function */
extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index e4f1f3c9575a..6d758f285352 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -29,6 +29,7 @@
#include "tracepoint.h"
#include "fwil_types.h"
#include "p2p.h"
+#include "btcoex.h"
#include "wl_cfg80211.h"
#include "fwil.h"
@@ -334,22 +335,16 @@ static u8 brcmf_mw_to_qdbm(u16 mw)
return qdbm;
}
-u16 channel_to_chanspec(struct ieee80211_channel *ch)
+u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
+ struct ieee80211_channel *ch)
{
- u16 chanspec;
-
- chanspec = ieee80211_frequency_to_channel(ch->center_freq);
- chanspec &= WL_CHANSPEC_CHAN_MASK;
-
- if (ch->band == IEEE80211_BAND_2GHZ)
- chanspec |= WL_CHANSPEC_BAND_2G;
- else
- chanspec |= WL_CHANSPEC_BAND_5G;
+ struct brcmu_chan ch_inf;
- chanspec |= WL_CHANSPEC_BW_20;
- chanspec |= WL_CHANSPEC_CTL_SB_NONE;
+ ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq);
+ ch_inf.bw = BRCMU_CHAN_BW_20;
+ d11inf->encchspec(&ch_inf);
- return chanspec;
+ return ch_inf.chspec;
}
/* Traverse a string of 1-byte tag/1-byte length/variable-length value
@@ -680,7 +675,8 @@ done:
return err;
}
-static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
+static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
+ struct brcmf_scan_params_le *params_le,
struct cfg80211_scan_request *request)
{
u32 n_ssids;
@@ -712,7 +708,8 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
n_channels);
if (n_channels > 0) {
for (i = 0; i < n_channels; i++) {
- chanspec = channel_to_chanspec(request->channels[i]);
+ chanspec = channel_to_chanspec(&cfg->d11inf,
+ request->channels[i]);
brcmf_dbg(SCAN, "Chan : %d, Channel spec: %x\n",
request->channels[i]->hw_value, chanspec);
params_le->channel_list[i] = cpu_to_le16(chanspec);
@@ -784,7 +781,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
goto exit;
}
BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
- brcmf_escan_prep(&params->params_le, request);
+ brcmf_escan_prep(cfg, &params->params_le, request);
params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
params->action = cpu_to_le16(action);
params->sync_id = cpu_to_le16(0x1234);
@@ -860,6 +857,11 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
cfg->scan_status);
return -EAGAIN;
}
+ if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {
+ brcmf_err("Scanning suppressed: status (%lu)\n",
+ cfg->scan_status);
+ return -EAGAIN;
+ }
if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) {
brcmf_err("Connecting: status (%lu)\n", ifp->vif->sme_state);
return -EAGAIN;
@@ -1050,6 +1052,7 @@ static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
static void brcmf_link_down(struct brcmf_cfg80211_vif *vif)
{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy);
s32 err = 0;
brcmf_dbg(TRACE, "Enter\n");
@@ -1063,6 +1066,8 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif)
clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state);
}
clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);
+ clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
+ brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0);
brcmf_dbg(TRACE, "Exit\n");
}
@@ -1182,7 +1187,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
params->chandef.chan->center_freq);
if (params->channel_fixed) {
/* adding chanspec */
- chanspec = channel_to_chanspec(params->chandef.chan);
+ chanspec = channel_to_chanspec(&cfg->d11inf,
+ params->chandef.chan);
join_params.params_le.chanspec_list[0] =
cpu_to_le16(chanspec);
join_params.params_le.chanspec_num = cpu_to_le32(1);
@@ -1572,7 +1578,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
if (chan) {
cfg->channel =
ieee80211_frequency_to_channel(chan->center_freq);
- chanspec = channel_to_chanspec(chan);
+ chanspec = channel_to_chanspec(&cfg->d11inf, chan);
brcmf_dbg(CONN, "channel=%d, center_req=%d, chanspec=0x%04x\n",
cfg->channel, chan->center_freq, chanspec);
} else {
@@ -2231,6 +2237,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
struct ieee80211_channel *notify_channel;
struct cfg80211_bss *bss;
struct ieee80211_supported_band *band;
+ struct brcmu_chan ch;
s32 err = 0;
u16 channel;
u32 freq;
@@ -2245,8 +2252,12 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
return 0;
}
- channel = bi->ctl_ch ? bi->ctl_ch :
- CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
+ if (!bi->ctl_ch) {
+ ch.chspec = le16_to_cpu(bi->chanspec);
+ cfg->d11inf.decchspec(&ch);
+ bi->ctl_ch = ch.chnum;
+ }
+ channel = bi->ctl_ch;
if (channel <= CH_MAX_2G_CHANNEL)
band = wiphy->bands[IEEE80211_BAND_2GHZ];
@@ -2321,9 +2332,9 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
struct brcmf_bss_info_le *bi = NULL;
struct ieee80211_supported_band *band;
struct cfg80211_bss *bss;
+ struct brcmu_chan ch;
u8 *buf = NULL;
s32 err = 0;
- u16 channel;
u32 freq;
u16 notify_capability;
u16 notify_interval;
@@ -2350,15 +2361,15 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
bi = (struct brcmf_bss_info_le *)(buf + 4);
- channel = bi->ctl_ch ? bi->ctl_ch :
- CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
+ ch.chspec = le16_to_cpu(bi->chanspec);
+ cfg->d11inf.decchspec(&ch);
- if (channel <= CH_MAX_2G_CHANNEL)
+ if (ch.band == BRCMU_CHAN_BAND_2G)
band = wiphy->bands[IEEE80211_BAND_2GHZ];
else
band = wiphy->bands[IEEE80211_BAND_5GHZ];
- freq = ieee80211_channel_to_frequency(channel, band->band);
+ freq = ieee80211_channel_to_frequency(ch.chnum, band->band);
notify_channel = ieee80211_get_channel(wiphy, freq);
notify_capability = le16_to_cpu(bi->capability);
@@ -2367,7 +2378,7 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
notify_ielen = le32_to_cpu(bi->ie_length);
notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
- brcmf_dbg(CONN, "channel: %d(%d)\n", channel, freq);
+ brcmf_dbg(CONN, "channel: %d(%d)\n", ch.chnum, freq);
brcmf_dbg(CONN, "capability: %X\n", notify_capability);
brcmf_dbg(CONN, "beacon interval: %d\n", notify_interval);
brcmf_dbg(CONN, "signal: %d\n", notify_signal);
@@ -2490,12 +2501,19 @@ static void brcmf_escan_timeout(unsigned long data)
}
static s32
-brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss,
+brcmf_compare_update_same_bss(struct brcmf_cfg80211_info *cfg,
+ struct brcmf_bss_info_le *bss,
struct brcmf_bss_info_le *bss_info_le)
{
+ struct brcmu_chan ch_bss, ch_bss_info_le;
+
+ ch_bss.chspec = le16_to_cpu(bss->chanspec);
+ cfg->d11inf.decchspec(&ch_bss);
+ ch_bss_info_le.chspec = le16_to_cpu(bss_info_le->chanspec);
+ cfg->d11inf.decchspec(&ch_bss_info_le);
+
if (!memcmp(&bss_info_le->BSSID, &bss->BSSID, ETH_ALEN) &&
- (CHSPEC_BAND(le16_to_cpu(bss_info_le->chanspec)) ==
- CHSPEC_BAND(le16_to_cpu(bss->chanspec))) &&
+ ch_bss.band == ch_bss_info_le.band &&
bss_info_le->SSID_len == bss->SSID_len &&
!memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) {
if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) ==
@@ -2593,7 +2611,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
bss = bss ? (struct brcmf_bss_info_le *)
((unsigned char *)bss +
le32_to_cpu(bss->length)) : list->bss_info_le;
- if (brcmf_compare_update_same_bss(bss, bss_info_le))
+ if (brcmf_compare_update_same_bss(cfg, bss,
+ bss_info_le))
goto exit;
}
memcpy(&(cfg->escan_info.escan_buf[list->buflen]),
@@ -3007,6 +3026,11 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
return -EAGAIN;
}
+ if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {
+ brcmf_err("Scanning suppressed: status (%lu)\n",
+ cfg->scan_status);
+ return -EAGAIN;
+ }
if (!request->n_ssids || !request->n_match_sets) {
brcmf_err("Invalid sched scan req!! n_ssids:%d\n",
@@ -3993,6 +4017,39 @@ exit:
return err;
}
+static int brcmf_cfg80211_crit_proto_start(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ enum nl80211_crit_proto_id proto,
+ u16 duration)
+{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_cfg80211_vif *vif;
+
+ vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+
+ /* only DHCP support for now */
+ if (proto != NL80211_CRIT_PROTO_DHCP)
+ return -EINVAL;
+
+ /* suppress and abort scanning */
+ set_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
+ brcmf_abort_scanning(cfg);
+
+ return brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_DISABLED, duration);
+}
+
+static void brcmf_cfg80211_crit_proto_stop(struct wiphy *wiphy,
+ struct wireless_dev *wdev)
+{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_cfg80211_vif *vif;
+
+ vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+
+ brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0);
+ clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
+}
+
static struct cfg80211_ops wl_cfg80211_ops = {
.add_virtual_intf = brcmf_cfg80211_add_iface,
.del_virtual_intf = brcmf_cfg80211_del_iface,
@@ -4029,6 +4086,8 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel,
.start_p2p_device = brcmf_p2p_start_device,
.stop_p2p_device = brcmf_p2p_stop_device,
+ .crit_proto_start = brcmf_cfg80211_crit_proto_start,
+ .crit_proto_stop = brcmf_cfg80211_crit_proto_stop,
#ifdef CONFIG_NL80211_TESTMODE
.testmode_cmd = brcmf_cfg80211_testmode
#endif
@@ -4337,9 +4396,9 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
struct ieee80211_channel *notify_channel = NULL;
struct ieee80211_supported_band *band;
struct brcmf_bss_info_le *bi;
+ struct brcmu_chan ch;
u32 freq;
s32 err = 0;
- u32 target_channel;
u8 *buf;
brcmf_dbg(TRACE, "Enter\n");
@@ -4363,15 +4422,15 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
goto done;
bi = (struct brcmf_bss_info_le *)(buf + 4);
- target_channel = bi->ctl_ch ? bi->ctl_ch :
- CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
+ ch.chspec = le16_to_cpu(bi->chanspec);
+ cfg->d11inf.decchspec(&ch);
- if (target_channel <= CH_MAX_2G_CHANNEL)
+ if (ch.band == BRCMU_CHAN_BAND_2G)
band = wiphy->bands[IEEE80211_BAND_2GHZ];
else
band = wiphy->bands[IEEE80211_BAND_5GHZ];
- freq = ieee80211_channel_to_frequency(target_channel, band->band);
+ freq = ieee80211_channel_to_frequency(ch.chnum, band->band);
notify_channel = ieee80211_get_channel(wiphy, freq);
done:
@@ -4725,6 +4784,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
struct brcmf_cfg80211_vif *vif;
struct brcmf_if *ifp;
s32 err = 0;
+ s32 io_type;
if (!ndev) {
brcmf_err("ndev is invalid\n");
@@ -4765,6 +4825,21 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
brcmf_err("P2P initilisation failed (%d)\n", err);
goto cfg80211_p2p_attach_out;
}
+ err = brcmf_btcoex_attach(cfg);
+ if (err) {
+ brcmf_err("BT-coex initialisation failed (%d)\n", err);
+ brcmf_p2p_detach(&cfg->p2p);
+ goto cfg80211_p2p_attach_out;
+ }
+
+ err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION,
+ &io_type);
+ if (err) {
+ brcmf_err("Failed to get D11 version (%d)\n", err);
+ goto cfg80211_p2p_attach_out;
+ }
+ cfg->d11inf.io_type = (u8)io_type;
+ brcmu_d11_attach(&cfg->d11inf);
return cfg;
@@ -4783,6 +4858,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
struct brcmf_cfg80211_vif *tmp;
wl_deinit_priv(cfg);
+ brcmf_btcoex_detach(cfg);
list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
brcmf_free_vif(vif);
}
@@ -4885,11 +4961,11 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
struct ieee80211_channel *band_chan_arr;
struct brcmf_chanspec_list *list;
+ struct brcmu_chan ch;
s32 err;
u8 *pbuf;
u32 i, j;
u32 total;
- u16 chanspec;
enum ieee80211_band band;
u32 channel;
u32 *n_cnt;
@@ -4918,42 +4994,30 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
total = le32_to_cpu(list->count);
for (i = 0; i < total; i++) {
- chanspec = (u16)le32_to_cpu(list->element[i]);
- channel = CHSPEC_CHANNEL(chanspec);
+ ch.chspec = (u16)le32_to_cpu(list->element[i]);
+ cfg->d11inf.decchspec(&ch);
- if (CHSPEC_IS40(chanspec)) {
- if (CHSPEC_SB_UPPER(chanspec))
- channel += CH_10MHZ_APART;
- else
- channel -= CH_10MHZ_APART;
- } else if (CHSPEC_IS80(chanspec)) {
- brcmf_dbg(INFO, "HT80 center channel : %d\n",
- channel);
- continue;
- }
- if (CHSPEC_IS2G(chanspec) && (channel >= CH_MIN_2G_CHANNEL) &&
- (channel <= CH_MAX_2G_CHANNEL)) {
+ if (ch.band == BRCMU_CHAN_BAND_2G) {
band_chan_arr = __wl_2ghz_channels;
array_size = ARRAY_SIZE(__wl_2ghz_channels);
n_cnt = &__wl_band_2ghz.n_channels;
band = IEEE80211_BAND_2GHZ;
ht40_allowed = (bw_cap == WLC_N_BW_40ALL);
- } else if (CHSPEC_IS5G(chanspec) &&
- channel >= CH_MIN_5G_CHANNEL) {
+ } else if (ch.band == BRCMU_CHAN_BAND_5G) {
band_chan_arr = __wl_5ghz_a_channels;
array_size = ARRAY_SIZE(__wl_5ghz_a_channels);
n_cnt = &__wl_band_5ghz_a.n_channels;
band = IEEE80211_BAND_5GHZ;
ht40_allowed = !(bw_cap == WLC_N_BW_20ALL);
} else {
- brcmf_err("Invalid channel Sepc. 0x%x.\n", chanspec);
+ brcmf_err("Invalid channel Sepc. 0x%x.\n", ch.chspec);
continue;
}
- if (!ht40_allowed && CHSPEC_IS40(chanspec))
+ if (!ht40_allowed && ch.bw == BRCMU_CHAN_BW_40)
continue;
update = false;
for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
- if (band_chan_arr[j].hw_value == channel) {
+ if (band_chan_arr[j].hw_value == ch.chnum) {
update = true;
break;
}
@@ -4964,16 +5028,16 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
index = *n_cnt;
if (index < array_size) {
band_chan_arr[index].center_freq =
- ieee80211_channel_to_frequency(channel, band);
- band_chan_arr[index].hw_value = channel;
+ ieee80211_channel_to_frequency(ch.chnum, band);
+ band_chan_arr[index].hw_value = ch.chnum;
- if (CHSPEC_IS40(chanspec) && ht40_allowed) {
+ if (ch.bw == BRCMU_CHAN_BW_40 && ht40_allowed) {
/* assuming the order is HT20, HT40 Upper,
* HT40 lower from chanspecs
*/
ht40_flag = band_chan_arr[index].flags &
IEEE80211_CHAN_NO_HT40;
- if (CHSPEC_SB_UPPER(chanspec)) {
+ if (ch.sb == BRCMU_CHAN_SB_U) {
if (ht40_flag == IEEE80211_CHAN_NO_HT40)
band_chan_arr[index].flags &=
~IEEE80211_CHAN_NO_HT40;
@@ -4993,11 +5057,9 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
} else {
band_chan_arr[index].flags =
IEEE80211_CHAN_NO_HT40;
- if (band == IEEE80211_BAND_2GHZ)
- channel |= WL_CHANSPEC_BAND_2G;
- else
- channel |= WL_CHANSPEC_BAND_5G;
- channel |= WL_CHANSPEC_BW_20;
+ ch.bw = BRCMU_CHAN_BW_20;
+ cfg->d11inf.encchspec(&ch);
+ channel = ch.chspec;
err = brcmf_fil_bsscfg_int_get(ifp,
"per_chan_info",
&channel);
@@ -5226,6 +5288,13 @@ s32 brcmf_cfg80211_down(struct net_device *ndev)
return err;
}
+enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp)
+{
+ struct wireless_dev *wdev = &ifp->vif->wdev;
+
+ return wdev->iftype;
+}
+
u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state)
{
struct brcmf_cfg80211_vif *vif;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
index 2907437ef438..a71cff84cdcf 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
@@ -17,6 +17,9 @@
#ifndef _wl_cfg80211_h_
#define _wl_cfg80211_h_
+/* for brcmu_d11inf */
+#include <brcmu_d11.h>
+
#define WL_NUM_SCAN_MAX 10
#define WL_NUM_PMKIDS_MAX MAXPMKID
#define WL_TLV_INFO_MAX 1024
@@ -74,14 +77,16 @@
/**
- * enum brcmf_scan_status - dongle scan status
+ * enum brcmf_scan_status - scan engine status
*
* @BRCMF_SCAN_STATUS_BUSY: scanning in progress on dongle.
* @BRCMF_SCAN_STATUS_ABORT: scan being aborted on dongle.
+ * @BRCMF_SCAN_STATUS_SUPPRESS: scanning is suppressed in driver.
*/
enum brcmf_scan_status {
BRCMF_SCAN_STATUS_BUSY,
BRCMF_SCAN_STATUS_ABORT,
+ BRCMF_SCAN_STATUS_SUPPRESS,
};
/**
@@ -346,6 +351,7 @@ struct brcmf_cfg80211_vif_event {
* @wiphy: wiphy object for cfg80211 interface.
* @conf: dongle configuration.
* @p2p: peer-to-peer specific information.
+ * @btcoex: Bluetooth coexistence information.
* @scan_request: cfg80211 scan request object.
* @usr_sync: mainly for dongle up/down synchronization.
* @bss_list: bss_list holding scanned ap information.
@@ -379,6 +385,7 @@ struct brcmf_cfg80211_info {
struct wiphy *wiphy;
struct brcmf_cfg80211_conf *conf;
struct brcmf_p2p_info p2p;
+ struct brcmf_btcoex_info *btcoex;
struct cfg80211_scan_request *scan_request;
struct mutex usr_sync;
struct brcmf_scan_results *bss_list;
@@ -408,6 +415,7 @@ struct brcmf_cfg80211_info {
u8 vif_cnt;
struct brcmf_cfg80211_vif_event vif_event;
struct completion vif_disabled;
+ struct brcmu_d11inf d11inf;
};
/**
@@ -474,6 +482,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
s32 brcmf_cfg80211_up(struct net_device *ndev);
s32 brcmf_cfg80211_down(struct net_device *ndev);
+enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp);
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
enum nl80211_iftype type,
@@ -484,7 +493,8 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
const u8 *vndr_ie_buf, u32 vndr_ie_len);
s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif);
struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key);
-u16 channel_to_chanspec(struct ieee80211_channel *ch);
+u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
+ struct ieee80211_channel *ch);
u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state);
void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
struct brcmf_cfg80211_vif *vif);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
index cba19d839b77..32464acccd90 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
@@ -21,7 +21,7 @@ ccflags-y := \
-Idrivers/net/wireless/brcm80211/brcmsmac/phy \
-Idrivers/net/wireless/brcm80211/include
-BRCMSMAC_OFILES := \
+brcmsmac-y := \
mac80211_if.o \
ucode_loader.o \
ampdu.o \
@@ -43,11 +43,6 @@ BRCMSMAC_OFILES := \
brcms_trace_events.o \
debug.o
-ifdef CONFIG_BCMA_DRIVER_GPIO
-BRCMSMAC_OFILES += led.o
-endif
+brcmsmac-$(CONFIG_BCMA_DRIVER_GPIO) += led.o
-MODULEPFX := brcmsmac
-
-obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o
-$(MODULEPFX)-objs = $(BRCMSMAC_OFILES)
+obj-$(CONFIG_BRCMSMAC) += brcmsmac.o
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index 10ee314c4229..cc87926f5055 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -379,7 +379,7 @@ 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;
+ struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
struct txpwr_limits txpwr;
brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);
@@ -404,7 +404,7 @@ 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;
+ struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
uint i;
uint chan;
int maxpwr;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index c837be242cba..2346821667e6 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -556,10 +556,10 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
new_int);
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
- if (conf->channel_type == NL80211_CHAN_HT20 ||
- conf->channel_type == NL80211_CHAN_NO_HT)
+ if (conf->chandef.width == NL80211_CHAN_WIDTH_20 ||
+ conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
err = brcms_c_set_channel(wl->wlc,
- conf->channel->hw_value);
+ conf->chandef.chan->hw_value);
else
err = -ENOTSUPP;
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 59d438409dfb..28e7aeedd184 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -5135,7 +5135,7 @@ int brcms_c_up(struct brcms_c_info *wlc)
wlc->pub->up = true;
if (wlc->bandinit_pending) {
- ch = wlc->pub->ieee_hw->conf.channel;
+ ch = wlc->pub->ieee_hw->conf.chandef.chan;
brcms_c_suspend_mac_and_wait(wlc);
brcms_c_set_chanspec(wlc, ch20mhz_chspec(ch->hw_value));
wlc->bandinit_pending = false;
@@ -7919,7 +7919,7 @@ 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;
+ struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
u16 chanspec;
brcms_dbg_info(core, "wl%d\n", wlc->pub->unit);
diff --git a/drivers/net/wireless/brcm80211/brcmutil/Makefile b/drivers/net/wireless/brcm80211/brcmutil/Makefile
index 6281c416289e..8a928184016a 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmutil/Makefile
@@ -19,10 +19,5 @@ ccflags-y := \
-Idrivers/net/wireless/brcm80211/brcmutil \
-Idrivers/net/wireless/brcm80211/include
-BRCMUTIL_OFILES := \
- utils.o
-
-MODULEPFX := brcmutil
-
-obj-$(CONFIG_BRCMUTIL) += $(MODULEPFX).o
-$(MODULEPFX)-objs = $(BRCMUTIL_OFILES)
+obj-$(CONFIG_BRCMUTIL) += brcmutil.o
+brcmutil-objs = utils.o d11.o
diff --git a/drivers/net/wireless/brcm80211/brcmutil/d11.c b/drivers/net/wireless/brcm80211/brcmutil/d11.c
new file mode 100644
index 000000000000..30e54e2c6c9b
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmutil/d11.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2013 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.
+ */
+/*********************channel spec common functions*********************/
+
+#include <linux/module.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include <brcmu_d11.h>
+
+static void brcmu_d11n_encchspec(struct brcmu_chan *ch)
+{
+ ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK;
+
+ switch (ch->bw) {
+ case BRCMU_CHAN_BW_20:
+ ch->chspec |= BRCMU_CHSPEC_D11N_BW_20 | BRCMU_CHSPEC_D11N_SB_N;
+ break;
+ case BRCMU_CHAN_BW_40:
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+ if (ch->chnum <= CH_MAX_2G_CHANNEL)
+ ch->chspec |= BRCMU_CHSPEC_D11N_BND_2G;
+ else
+ ch->chspec |= BRCMU_CHSPEC_D11N_BND_5G;
+}
+
+static void brcmu_d11ac_encchspec(struct brcmu_chan *ch)
+{
+ ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK;
+
+ switch (ch->bw) {
+ case BRCMU_CHAN_BW_20:
+ ch->chspec |= BRCMU_CHSPEC_D11AC_BW_20;
+ break;
+ case BRCMU_CHAN_BW_40:
+ case BRCMU_CHAN_BW_80:
+ case BRCMU_CHAN_BW_80P80:
+ case BRCMU_CHAN_BW_160:
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+ if (ch->chnum <= CH_MAX_2G_CHANNEL)
+ ch->chspec |= BRCMU_CHSPEC_D11AC_BND_2G;
+ else
+ ch->chspec |= BRCMU_CHSPEC_D11AC_BND_5G;
+}
+
+static void brcmu_d11n_decchspec(struct brcmu_chan *ch)
+{
+ u16 val;
+
+ ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK);
+
+ switch (ch->chspec & BRCMU_CHSPEC_D11N_BW_MASK) {
+ case BRCMU_CHSPEC_D11N_BW_20:
+ ch->bw = BRCMU_CHAN_BW_20;
+ break;
+ case BRCMU_CHSPEC_D11N_BW_40:
+ ch->bw = BRCMU_CHAN_BW_40;
+ val = ch->chspec & BRCMU_CHSPEC_D11N_SB_MASK;
+ if (val == BRCMU_CHSPEC_D11N_SB_L) {
+ ch->sb = BRCMU_CHAN_SB_L;
+ ch->chnum -= CH_10MHZ_APART;
+ } else {
+ ch->sb = BRCMU_CHAN_SB_U;
+ ch->chnum += CH_10MHZ_APART;
+ }
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+ switch (ch->chspec & BRCMU_CHSPEC_D11N_BND_MASK) {
+ case BRCMU_CHSPEC_D11N_BND_5G:
+ ch->band = BRCMU_CHAN_BAND_5G;
+ break;
+ case BRCMU_CHSPEC_D11N_BND_2G:
+ ch->band = BRCMU_CHAN_BAND_2G;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+}
+
+static void brcmu_d11ac_decchspec(struct brcmu_chan *ch)
+{
+ u16 val;
+
+ ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK);
+
+ switch (ch->chspec & BRCMU_CHSPEC_D11AC_BW_MASK) {
+ case BRCMU_CHSPEC_D11AC_BW_20:
+ ch->bw = BRCMU_CHAN_BW_20;
+ break;
+ case BRCMU_CHSPEC_D11AC_BW_40:
+ ch->bw = BRCMU_CHAN_BW_40;
+ val = ch->chspec & BRCMU_CHSPEC_D11AC_SB_MASK;
+ if (val == BRCMU_CHSPEC_D11AC_SB_L) {
+ ch->sb = BRCMU_CHAN_SB_L;
+ ch->chnum -= CH_10MHZ_APART;
+ } else if (val == BRCMU_CHSPEC_D11AC_SB_U) {
+ ch->sb = BRCMU_CHAN_SB_U;
+ ch->chnum += CH_10MHZ_APART;
+ } else {
+ WARN_ON_ONCE(1);
+ }
+ break;
+ case BRCMU_CHSPEC_D11AC_BW_80:
+ ch->bw = BRCMU_CHAN_BW_80;
+ break;
+ case BRCMU_CHSPEC_D11AC_BW_8080:
+ case BRCMU_CHSPEC_D11AC_BW_160:
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+ switch (ch->chspec & BRCMU_CHSPEC_D11AC_BND_MASK) {
+ case BRCMU_CHSPEC_D11AC_BND_5G:
+ ch->band = BRCMU_CHAN_BAND_5G;
+ break;
+ case BRCMU_CHSPEC_D11AC_BND_2G:
+ ch->band = BRCMU_CHAN_BAND_2G;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+}
+
+void brcmu_d11_attach(struct brcmu_d11inf *d11inf)
+{
+ if (d11inf->io_type == BRCMU_D11N_IOTYPE) {
+ d11inf->encchspec = brcmu_d11n_encchspec;
+ d11inf->decchspec = brcmu_d11n_decchspec;
+ } else {
+ d11inf->encchspec = brcmu_d11ac_encchspec;
+ d11inf->decchspec = brcmu_d11ac_decchspec;
+ }
+}
+EXPORT_SYMBOL(brcmu_d11_attach);
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c
index bf5e50fc21ba..0f7e1c7b6f58 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/utils.c
+++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c
@@ -45,17 +45,9 @@ void brcmu_pkt_buf_free_skb(struct sk_buff *skb)
{
if (!skb)
return;
+
WARN_ON(skb->next);
- if (skb->destructor)
- /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if
- * destructor exists
- */
- dev_kfree_skb_any(skb);
- else
- /* can free immediately (even in_irq()) if destructor
- * does not exist
- */
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
}
EXPORT_SYMBOL(brcmu_pkt_buf_free_skb);
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
index e8682855b73a..c1fe245bb07e 100644
--- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
@@ -29,6 +29,7 @@
/* Chipcommon Core Chip IDs */
#define BCM4313_CHIP_ID 0x4313
+#define BCM43143_CHIP_ID 43143
#define BCM43224_CHIP_ID 43224
#define BCM43225_CHIP_ID 43225
#define BCM43235_CHIP_ID 43235
@@ -39,5 +40,6 @@
#define BCM4330_CHIP_ID 0x4330
#define BCM4331_CHIP_ID 0x4331
#define BCM4334_CHIP_ID 0x4334
+#define BCM4335_CHIP_ID 0x4335
#endif /* _BRCM_HW_IDS_H_ */
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_d11.h b/drivers/net/wireless/brcm80211/include/brcmu_d11.h
new file mode 100644
index 000000000000..92623f02b1c0
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/include/brcmu_d11.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2010 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.
+ */
+
+#ifndef _BRCMU_D11_H_
+#define _BRCMU_D11_H_
+
+/* d11 io type */
+#define BRCMU_D11N_IOTYPE 1
+#define BRCMU_D11AC_IOTYPE 2
+
+/* A chanspec (channel specification) holds the channel number, band,
+ * bandwidth and control sideband
+ */
+
+/* chanspec binary format */
+
+#define BRCMU_CHSPEC_INVALID 255
+/* bit 0~7 channel number
+ * for 80+80 channels: bit 0~3 low channel id, bit 4~7 high channel id
+ */
+#define BRCMU_CHSPEC_CH_MASK 0x00ff
+#define BRCMU_CHSPEC_CH_SHIFT 0
+#define BRCMU_CHSPEC_CHL_MASK 0x000f
+#define BRCMU_CHSPEC_CHL_SHIFT 0
+#define BRCMU_CHSPEC_CHH_MASK 0x00f0
+#define BRCMU_CHSPEC_CHH_SHIFT 4
+
+/* bit 8~16 for dot 11n IO types
+ * bit 8~9 sideband
+ * bit 10~11 bandwidth
+ * bit 12~13 spectral band
+ * bit 14~15 not used
+ */
+#define BRCMU_CHSPEC_D11N_SB_MASK 0x0300
+#define BRCMU_CHSPEC_D11N_SB_SHIFT 8
+#define BRCMU_CHSPEC_D11N_SB_L 0x0100 /* control lower */
+#define BRCMU_CHSPEC_D11N_SB_U 0x0200 /* control upper */
+#define BRCMU_CHSPEC_D11N_SB_N 0x0300 /* none */
+#define BRCMU_CHSPEC_D11N_BW_MASK 0x0c00
+#define BRCMU_CHSPEC_D11N_BW_SHIFT 10
+#define BRCMU_CHSPEC_D11N_BW_10 0x0400
+#define BRCMU_CHSPEC_D11N_BW_20 0x0800
+#define BRCMU_CHSPEC_D11N_BW_40 0x0c00
+#define BRCMU_CHSPEC_D11N_BND_MASK 0x3000
+#define BRCMU_CHSPEC_D11N_BND_SHIFT 12
+#define BRCMU_CHSPEC_D11N_BND_5G 0x1000
+#define BRCMU_CHSPEC_D11N_BND_2G 0x2000
+
+/* bit 8~16 for dot 11ac IO types
+ * bit 8~10 sideband
+ * bit 11~13 bandwidth
+ * bit 14~15 spectral band
+ */
+#define BRCMU_CHSPEC_D11AC_SB_MASK 0x0700
+#define BRCMU_CHSPEC_D11AC_SB_SHIFT 8
+#define BRCMU_CHSPEC_D11AC_SB_LLL 0x0000
+#define BRCMU_CHSPEC_D11AC_SB_LLU 0x0100
+#define BRCMU_CHSPEC_D11AC_SB_LUL 0x0200
+#define BRCMU_CHSPEC_D11AC_SB_LUU 0x0300
+#define BRCMU_CHSPEC_D11AC_SB_ULL 0x0400
+#define BRCMU_CHSPEC_D11AC_SB_ULU 0x0500
+#define BRCMU_CHSPEC_D11AC_SB_UUL 0x0600
+#define BRCMU_CHSPEC_D11AC_SB_UUU 0x0700
+#define BRCMU_CHSPEC_D11AC_SB_LL BRCMU_CHSPEC_D11AC_SB_LLL
+#define BRCMU_CHSPEC_D11AC_SB_LU BRCMU_CHSPEC_D11AC_SB_LLU
+#define BRCMU_CHSPEC_D11AC_SB_UL BRCMU_CHSPEC_D11AC_SB_LUL
+#define BRCMU_CHSPEC_D11AC_SB_UU BRCMU_CHSPEC_D11AC_SB_LUU
+#define BRCMU_CHSPEC_D11AC_SB_L BRCMU_CHSPEC_D11AC_SB_LLL
+#define BRCMU_CHSPEC_D11AC_SB_U BRCMU_CHSPEC_D11AC_SB_LLU
+#define BRCMU_CHSPEC_D11AC_BW_MASK 0x3800
+#define BRCMU_CHSPEC_D11AC_BW_SHIFT 11
+#define BRCMU_CHSPEC_D11AC_BW_5 0x0000
+#define BRCMU_CHSPEC_D11AC_BW_10 0x0800
+#define BRCMU_CHSPEC_D11AC_BW_20 0x1000
+#define BRCMU_CHSPEC_D11AC_BW_40 0x1800
+#define BRCMU_CHSPEC_D11AC_BW_80 0x2000
+#define BRCMU_CHSPEC_D11AC_BW_160 0x2800
+#define BRCMU_CHSPEC_D11AC_BW_8080 0x3000
+#define BRCMU_CHSPEC_D11AC_BND_MASK 0xc000
+#define BRCMU_CHSPEC_D11AC_BND_SHIFT 14
+#define BRCMU_CHSPEC_D11AC_BND_2G 0x0000
+#define BRCMU_CHSPEC_D11AC_BND_3G 0x4000
+#define BRCMU_CHSPEC_D11AC_BND_4G 0x8000
+#define BRCMU_CHSPEC_D11AC_BND_5G 0xc000
+
+#define BRCMU_CHAN_BAND_2G 0
+#define BRCMU_CHAN_BAND_5G 1
+
+enum brcmu_chan_bw {
+ BRCMU_CHAN_BW_20,
+ BRCMU_CHAN_BW_40,
+ BRCMU_CHAN_BW_80,
+ BRCMU_CHAN_BW_80P80,
+ BRCMU_CHAN_BW_160,
+};
+
+enum brcmu_chan_sb {
+ BRCMU_CHAN_SB_NONE = 0,
+ BRCMU_CHAN_SB_L,
+ BRCMU_CHAN_SB_U,
+ BRCMU_CHAN_SB_LL,
+ BRCMU_CHAN_SB_LU,
+ BRCMU_CHAN_SB_UL,
+ BRCMU_CHAN_SB_UU,
+ BRCMU_CHAN_SB_LLL,
+ BRCMU_CHAN_SB_LLU,
+ BRCMU_CHAN_SB_LUL,
+ BRCMU_CHAN_SB_LUU,
+ BRCMU_CHAN_SB_ULL,
+ BRCMU_CHAN_SB_ULU,
+ BRCMU_CHAN_SB_UUL,
+ BRCMU_CHAN_SB_UUU,
+};
+
+struct brcmu_chan {
+ u16 chspec;
+ u8 chnum;
+ u8 band;
+ enum brcmu_chan_bw bw;
+ enum brcmu_chan_sb sb;
+};
+
+struct brcmu_d11inf {
+ u8 io_type;
+
+ void (*encchspec)(struct brcmu_chan *ch);
+ void (*decchspec)(struct brcmu_chan *ch);
+};
+
+extern void brcmu_d11_attach(struct brcmu_d11inf *d11inf);
+
+#endif /* _BRCMU_CHANNELS_H_ */
diff --git a/drivers/net/wireless/brcm80211/include/chipcommon.h b/drivers/net/wireless/brcm80211/include/chipcommon.h
index f96834a7c055..d242333b7559 100644
--- a/drivers/net/wireless/brcm80211/include/chipcommon.h
+++ b/drivers/net/wireless/brcm80211/include/chipcommon.h
@@ -205,7 +205,7 @@ struct chipcregs {
u32 res_req_timer_sel;
u32 res_req_timer;
u32 res_req_mask;
- u32 PAD;
+ u32 pmucapabilities_ext; /* 0x64c, pmurev >=15 */
u32 chipcontrol_addr; /* 0x650 */
u32 chipcontrol_data; /* 0x654 */
u32 regcontrol_addr;
@@ -214,7 +214,11 @@ struct chipcregs {
u32 pllcontrol_data;
u32 pmustrapopt; /* 0x668, corerev >= 28 */
u32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */
- u32 PAD[100];
+ u32 retention_ctl; /* 0x670, pmurev >= 15 */
+ u32 PAD[3];
+ u32 retention_grpidx; /* 0x680 */
+ u32 retention_grpctl; /* 0x684 */
+ u32 PAD[94];
u16 sromotp[768];
};
@@ -276,6 +280,12 @@ struct chipcregs {
#define PCAP5_VC_SHIFT 22
#define PCAP5_CC_MASK 0xf8000000
#define PCAP5_CC_SHIFT 27
+/* pmucapabilites_ext PMU rev >= 15 */
+#define PCAPEXT_SR_SUPPORTED_MASK (1 << 1)
+/* retention_ctl PMU rev >= 15 */
+#define PMU_RCTL_MACPHY_DISABLE_MASK (1 << 26)
+#define PMU_RCTL_LOGIC_DISABLE_MASK (1 << 27)
+
/*
* Maximum delay for the PMU state transition in us.
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index cb066f62879d..15920aaa5dd6 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -4167,17 +4167,11 @@ static ssize_t show_debug_level(struct device_driver *d, char *buf)
static ssize_t store_debug_level(struct device_driver *d,
const char *buf, size_t count)
{
- char *p = (char *)buf;
u32 val;
+ int ret;
- if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
- p++;
- if (p[0] == 'x' || p[0] == 'X')
- p++;
- val = simple_strtoul(p, &p, 16);
- } else
- val = simple_strtoul(p, &p, 10);
- if (p == buf)
+ ret = kstrtou32(buf, 0, &val);
+ if (ret)
IPW_DEBUG_INFO(": %s is not in hex or decimal form.\n", buf);
else
ipw2100_debug_level = val;
@@ -4238,27 +4232,15 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr,
{
struct ipw2100_priv *priv = dev_get_drvdata(d);
struct net_device *dev = priv->net_dev;
- char buffer[] = "00000000";
- unsigned long len =
- (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1;
unsigned long val;
- char *p = buffer;
+ int ret;
(void)dev; /* kill unused-var warning for debug-only code */
IPW_DEBUG_INFO("enter\n");
- strncpy(buffer, buf, len);
- buffer[len] = 0;
-
- if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
- p++;
- if (p[0] == 'x' || p[0] == 'X')
- p++;
- val = simple_strtoul(p, &p, 16);
- } else
- val = simple_strtoul(p, &p, 10);
- if (p == buffer) {
+ ret = kstrtoul(buf, 0, &val);
+ if (ret) {
IPW_DEBUG_INFO("%s: user supplied invalid value.\n", dev->name);
} else {
priv->ieee->scan_age = val;
@@ -4266,7 +4248,7 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr,
}
IPW_DEBUG_INFO("exit\n");
- return len;
+ return strnlen(buf, count);
}
static DEVICE_ATTR(scan_age, S_IWUSR | S_IRUGO, show_scan_age, store_scan_age);
diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c
index d4fd29ad90dc..c9f197d9ca1e 100644
--- a/drivers/net/wireless/iwlegacy/3945-rs.c
+++ b/drivers/net/wireless/iwlegacy/3945-rs.c
@@ -347,7 +347,7 @@ il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id)
psta = (struct il3945_sta_priv *)sta->drv_priv;
rs_sta = &psta->rs_sta;
- sband = hw->wiphy->bands[conf->channel->band];
+ sband = hw->wiphy->bands[conf->chandef.chan->band];
rs_sta->il = il;
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index 6affa7e8f017..b8f82e688c72 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -6057,7 +6057,7 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw,
struct il_priv *il = hw->priv;
const struct il_channel_info *ch_info;
struct ieee80211_conf *conf = &hw->conf;
- struct ieee80211_channel *channel = ch_switch->channel;
+ struct ieee80211_channel *channel = ch_switch->chandef.chan;
struct il_ht_config *ht_conf = &il->current_ht_config;
u16 ch;
@@ -6094,23 +6094,21 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw,
il->current_ht_config.smps = conf->smps_mode;
/* Configure HT40 channels */
- il->ht.enabled = conf_is_ht(conf);
- if (il->ht.enabled) {
- if (conf_is_ht40_minus(conf)) {
- il->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_BELOW;
- il->ht.is_40mhz = true;
- } else if (conf_is_ht40_plus(conf)) {
- il->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
- il->ht.is_40mhz = true;
- } else {
- il->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_NONE;
- il->ht.is_40mhz = false;
- }
- } else
+ switch (cfg80211_get_chandef_type(&ch_switch->chandef)) {
+ case NL80211_CHAN_NO_HT:
+ case NL80211_CHAN_HT20:
il->ht.is_40mhz = false;
+ il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ break;
+ case NL80211_CHAN_HT40MINUS:
+ il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ il->ht.is_40mhz = true;
+ break;
+ case NL80211_CHAN_HT40PLUS:
+ il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ il->ht.is_40mhz = true;
+ break;
+ }
if ((le16_to_cpu(il->staging.channel) != ch))
il->staging.flags = 0;
diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c
index 6c7493c2d698..1fc0b227e120 100644
--- a/drivers/net/wireless/iwlegacy/4965-rs.c
+++ b/drivers/net/wireless/iwlegacy/4965-rs.c
@@ -2300,7 +2300,7 @@ il4965_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id)
sta_priv = (struct il_station_priv *)sta->drv_priv;
lq_sta = &sta_priv->lq_sta;
- sband = hw->wiphy->bands[conf->channel->band];
+ sband = hw->wiphy->bands[conf->chandef.chan->band];
lq_sta->lq.sta_id = sta_id;
diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c
index 91eb2d07fdb8..777a578294bd 100644
--- a/drivers/net/wireless/iwlegacy/4965.c
+++ b/drivers/net/wireless/iwlegacy/4965.c
@@ -1493,7 +1493,7 @@ il4965_hw_channel_switch(struct il_priv *il,
cmd.band = band;
cmd.expect_beacon = 0;
- ch = ch_switch->channel->hw_value;
+ ch = ch_switch->chandef.chan->hw_value;
cmd.channel = cpu_to_le16(ch);
cmd.rxon_flags = il->staging.flags;
cmd.rxon_filter_flags = il->staging.filter_flags;
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index 3613b3a81ad2..592d0aa634a8 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -4971,7 +4971,7 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed)
struct il_priv *il = hw->priv;
const struct il_channel_info *ch_info;
struct ieee80211_conf *conf = &hw->conf;
- struct ieee80211_channel *channel = conf->channel;
+ struct ieee80211_channel *channel = conf->chandef.chan;
struct il_ht_config *ht_conf = &il->current_ht_config;
unsigned long flags = 0;
int ret = 0;
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h
index 019d433900ef..e575b9b0cda8 100644
--- a/drivers/net/wireless/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/iwlwifi/dvm/agn.h
@@ -73,6 +73,8 @@
/* AUX (TX during scan dwell) queue */
#define IWL_AUX_QUEUE 10
+#define IWL_INVALID_STATION 255
+
/* device operations */
extern struct iwl_lib_ops iwl1000_lib;
extern struct iwl_lib_ops iwl2000_lib;
@@ -176,7 +178,7 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr);
/* lib */
int iwlagn_send_tx_power(struct iwl_priv *priv);
void iwlagn_temperature(struct iwl_priv *priv);
-int iwlagn_txfifo_flush(struct iwl_priv *priv);
+int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk);
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv);
int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
int iwl_send_statistics_request(struct iwl_priv *priv,
@@ -210,6 +212,8 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid, u8 buf_size);
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid);
+int iwlagn_tx_agg_flush(struct iwl_priv *priv, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, u16 tid);
int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c
index 15cca2ef9294..c48907c8ab43 100644
--- a/drivers/net/wireless/iwlwifi/dvm/devices.c
+++ b/drivers/net/wireless/iwlwifi/dvm/devices.c
@@ -379,7 +379,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
};
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
- ch = ch_switch->channel->hw_value;
+ ch = ch_switch->chandef.chan->hw_value;
IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
ctx->active.channel, ch);
cmd.channel = cpu_to_le16(ch);
@@ -414,7 +414,8 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
}
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
cmd.switch_time);
- cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
+ cmd.expect_beacon =
+ ch_switch->chandef.chan->flags & IEEE80211_CHAN_RADAR;
return iwl_dvm_send_cmd(priv, &hcmd);
}
@@ -540,7 +541,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
hcmd.data[0] = cmd;
cmd->band = priv->band == IEEE80211_BAND_2GHZ;
- ch = ch_switch->channel->hw_value;
+ ch = ch_switch->chandef.chan->hw_value;
IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
ctx->active.channel, ch);
cmd->channel = cpu_to_le16(ch);
@@ -575,7 +576,8 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
}
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
cmd->switch_time);
- cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
+ cmd->expect_beacon =
+ ch_switch->chandef.chan->flags & IEEE80211_CHAN_RADAR;
err = iwl_dvm_send_cmd(priv, &hcmd);
kfree(cmd);
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c
index 87c006c9c573..54f553380aa8 100644
--- a/drivers/net/wireless/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/lib.c
@@ -136,7 +136,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
* 1. acquire mutex before calling
* 2. make sure rf is on and not in exit state
*/
-int iwlagn_txfifo_flush(struct iwl_priv *priv)
+int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk)
{
struct iwl_txfifo_flush_cmd flush_cmd;
struct iwl_host_cmd cmd = {
@@ -162,6 +162,9 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv)
if (priv->nvm_data->sku_cap_11n_enable)
flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK;
+ if (scd_q_msk)
+ flush_cmd.queue_control = cpu_to_le32(scd_q_msk);
+
IWL_DEBUG_INFO(priv, "queue control: 0x%x\n",
flush_cmd.queue_control);
flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL);
@@ -173,7 +176,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv)
{
mutex_lock(&priv->mutex);
ieee80211_stop_queues(priv->hw);
- if (iwlagn_txfifo_flush(priv)) {
+ if (iwlagn_txfifo_flush(priv, 0)) {
IWL_ERR(priv, "flush request fail\n");
goto done;
}
@@ -1084,7 +1087,14 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan)
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwlagn_wowlan_kek_kck_material_cmd kek_kck_cmd;
struct iwlagn_wowlan_tkip_params_cmd tkip_cmd = {};
- struct iwlagn_d3_config_cmd d3_cfg_cmd = {};
+ struct iwlagn_d3_config_cmd d3_cfg_cmd = {
+ /*
+ * Program the minimum sleep time to 10 seconds, as many
+ * platforms have issues processing a wakeup signal while
+ * still being in the process of suspending.
+ */
+ .min_sleep_time = cpu_to_le32(10 * 1000 * 1000),
+ };
struct wowlan_key_data key_data = {
.ctx = ctx,
.bssid = ctx->active.bssid_addr,
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index a7294fa4d7e5..cab23af0be9e 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -777,9 +777,12 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
IWL_DEBUG_HT(priv, "start Tx\n");
ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
break;
- case IEEE80211_AMPDU_TX_STOP_CONT:
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+ IWL_DEBUG_HT(priv, "Flush Tx\n");
+ ret = iwlagn_tx_agg_flush(priv, vif, sta, tid);
+ break;
+ case IEEE80211_AMPDU_TX_STOP_CONT:
IWL_DEBUG_HT(priv, "stop Tx\n");
ret = iwlagn_tx_agg_stop(priv, vif, sta, tid);
if ((ret == 0) && (priv->agg_tids_count > 0)) {
@@ -967,7 +970,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct ieee80211_conf *conf = &hw->conf;
- struct ieee80211_channel *channel = ch_switch->channel;
+ struct ieee80211_channel *channel = ch_switch->chandef.chan;
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
/*
* MULTI-FIXME
@@ -1005,11 +1008,21 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
priv->current_ht_config.smps = conf->smps_mode;
/* Configure HT40 channels */
- ctx->ht.enabled = conf_is_ht(conf);
- if (ctx->ht.enabled)
- iwlagn_config_ht40(conf, ctx);
- else
+ switch (cfg80211_get_chandef_type(&ch_switch->chandef)) {
+ case NL80211_CHAN_NO_HT:
+ case NL80211_CHAN_HT20:
ctx->ht.is_40mhz = false;
+ ctx->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ break;
+ case NL80211_CHAN_HT40MINUS:
+ ctx->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ ctx->ht.is_40mhz = true;
+ break;
+ case NL80211_CHAN_HT40PLUS:
+ ctx->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ ctx->ht.is_40mhz = true;
+ break;
+ }
if ((le16_to_cpu(ctx->staging.channel) != ch))
ctx->staging.flags = 0;
@@ -1122,7 +1135,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
*/
if (drop) {
IWL_DEBUG_MAC80211(priv, "send flush command\n");
- if (iwlagn_txfifo_flush(priv)) {
+ if (iwlagn_txfifo_flush(priv, 0)) {
IWL_ERR(priv, "flush request fail\n");
goto done;
}
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c
index abe304267261..907bd6e50aad 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rs.c
@@ -2831,7 +2831,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
sta_priv = (struct iwl_station_priv *) sta->drv_priv;
lq_sta = &sta_priv->lq_sta;
- sband = hw->wiphy->bands[conf->channel->band];
+ sband = hw->wiphy->bands[conf->chandef.chan->band];
lq_sta->lq.sta_id = sta_id;
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c
index a82b6b39d4ff..707446fa00bd 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rxon.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c
@@ -78,8 +78,9 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv,
ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
#endif
- ctx->staging.channel = cpu_to_le16(priv->hw->conf.channel->hw_value);
- priv->band = priv->hw->conf.channel->band;
+ ctx->staging.channel =
+ cpu_to_le16(priv->hw->conf.chandef.chan->hw_value);
+ priv->band = priv->hw->conf.chandef.chan->band;
iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif);
@@ -951,7 +952,7 @@ static void iwl_calc_basic_rates(struct iwl_priv *priv,
unsigned long basic = ctx->vif->bss_conf.basic_rates;
int i;
- sband = priv->hw->wiphy->bands[priv->hw->conf.channel->band];
+ sband = priv->hw->wiphy->bands[priv->hw->conf.chandef.chan->band];
for_each_set_bit(i, &basic, BITS_PER_LONG) {
int hw = sband->bitrates[i].hw_value;
@@ -1159,7 +1160,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
}
void iwlagn_config_ht40(struct ieee80211_conf *conf,
- struct iwl_rxon_context *ctx)
+ struct iwl_rxon_context *ctx)
{
if (conf_is_ht40_minus(conf)) {
ctx->ht.extension_chan_offset =
@@ -1181,7 +1182,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_rxon_context *ctx;
struct ieee80211_conf *conf = &hw->conf;
- struct ieee80211_channel *channel = conf->channel;
+ struct ieee80211_channel *channel = conf->chandef.chan;
int ret = 0;
IWL_DEBUG_MAC80211(priv, "enter: changed %#x\n", changed);
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index 70b7f68c4958..a900aaf47790 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -674,6 +674,51 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
return ret;
}
+int iwlagn_tx_agg_flush(struct iwl_priv *priv, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, u16 tid)
+{
+ struct iwl_tid_data *tid_data;
+ enum iwl_agg_state agg_state;
+ int sta_id, txq_id;
+ sta_id = iwl_sta_id(sta);
+
+ /*
+ * First set the agg state to OFF to avoid calling
+ * ieee80211_stop_tx_ba_cb in iwlagn_check_ratid_empty.
+ */
+ spin_lock_bh(&priv->sta_lock);
+
+ tid_data = &priv->tid_data[sta_id][tid];
+ txq_id = tid_data->agg.txq_id;
+ agg_state = tid_data->agg.state;
+ IWL_DEBUG_TX_QUEUES(priv, "Flush AGG: sta %d tid %d q %d state %d\n",
+ sta_id, tid, txq_id, tid_data->agg.state);
+
+ tid_data->agg.state = IWL_AGG_OFF;
+
+ spin_unlock_bh(&priv->sta_lock);
+
+ if (iwlagn_txfifo_flush(priv, BIT(txq_id)))
+ IWL_ERR(priv, "Couldn't flush the AGG queue\n");
+
+ if (test_bit(txq_id, priv->agg_q_alloc)) {
+ /*
+ * If the transport didn't know that we wanted to start
+ * agreggation, don't tell it that we want to stop them.
+ * This can happen when we don't get the addBA response on
+ * time, or we hadn't time to drain the AC queues.
+ */
+ if (agg_state == IWL_AGG_ON)
+ iwl_trans_txq_disable(priv->trans, txq_id);
+ else
+ IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n",
+ agg_state);
+ iwlagn_dealloc_agg_txq(priv, txq_id);
+ }
+
+ return 0;
+}
+
int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid, u8 buf_size)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 498300577ac0..39aad9893e0b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -912,8 +912,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
}
}
- IWL_INFO(drv, "loaded firmware version %s", drv->fw.fw_version);
-
/*
* In mvm uCode there is no difference between data and instructions
* sections.
@@ -970,6 +968,9 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
else
op = &iwlwifi_opmode_table[DVM_OP_MODE];
+ IWL_INFO(drv, "loaded firmware version %s op_mode %s\n",
+ drv->fw.fw_version, op->name);
+
/* add this device to the list of devices using this op_mode */
list_add_tail(&drv->list, &op->drv);
@@ -997,8 +998,13 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
* else from proceeding if the module fails to load
* or hangs loading.
*/
- if (load_module)
- request_module("%s", op->name);
+ if (load_module) {
+ err = request_module("%s", op->name);
+ if (err)
+ IWL_ERR(drv,
+ "failed to load module %s (error %d), is dynamic loading enabled?\n",
+ op->name, err);
+ }
return;
try_again:
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 7f9c254292a8..7a13790b5bfe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -305,7 +305,6 @@ static inline void iwl_free_rxb(struct iwl_rx_cmd_buffer *r)
* currently supports
*/
#define IWL_MAX_HW_QUEUES 32
-#define IWL_INVALID_STATION 255
#define IWL_MAX_TID_COUNT 8
#define IWL_FRAME_LIMIT 64
@@ -682,7 +681,7 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue,
static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue,
int fifo)
{
- iwl_trans_txq_enable(trans, queue, fifo, IWL_INVALID_STATION,
+ iwl_trans_txq_enable(trans, queue, fifo, -1,
IWL_MAX_TID_COUNT, IWL_FRAME_LIMIT, 0);
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
index 1700232aa166..810bfa5f6de0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
@@ -61,6 +61,8 @@
*
*****************************************************************************/
+#include <net/mac80211.h>
+
#include "fw-api-bt-coex.h"
#include "iwl-modparams.h"
#include "mvm.h"
@@ -96,6 +98,20 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
#undef EVENT_PRIO_ANT
+/* BT Antenna Coupling Threshold (dB) */
+#define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35)
+#define IWL_BT_LOAD_FORCE_SISO_THRESHOLD (3)
+
+#define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD (-62)
+#define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65)
+#define BT_REDUCED_TX_POWER_BIT BIT(7)
+
+static inline bool is_loose_coex(void)
+{
+ return iwlwifi_mod_params.ant_coupling >
+ IWL_BT_ANTENNA_COUPLING_THRESHOLD;
+}
+
int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
{
return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC,
@@ -186,11 +202,6 @@ static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = {
cpu_to_le32(0x00000000),
};
-/* BT Antenna Coupling Threshold (dB) */
-#define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35)
-#define IWL_BT_LOAD_FORCE_SISO_THRESHOLD (3)
-
-
int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
{
struct iwl_bt_coex_cmd cmd = {
@@ -203,8 +214,7 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
cmd.flags = iwlwifi_mod_params.bt_coex_active ?
BT_COEX_NW : BT_COEX_DISABLE;
- cmd.flags |= iwlwifi_mod_params.bt_ch_announce ? BT_CH_PRIMARY_EN : 0;
- cmd.flags |= BT_SYNC_2_BT_DISABLE;
+ cmd.flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE;
cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE |
BT_VALID_BT_PRIO_BOOST |
@@ -215,7 +225,7 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
BT_VALID_REDUCED_TX_POWER |
BT_VALID_LUT);
- if (iwlwifi_mod_params.ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD)
+ if (is_loose_coex())
memcpy(&cmd.decision_lut, iwl_loose_lookup,
sizeof(iwl_tight_lookup));
else
@@ -228,6 +238,8 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
cmd.kill_cts_msk =
cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
+ memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
+
/* go to CALIB state in internal BT-Coex state machine */
ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN,
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
@@ -243,19 +255,101 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
sizeof(cmd), &cmd);
}
-struct iwl_bt_notif_iterator_data {
- struct iwl_mvm *mvm;
+static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
+ bool reduced_tx_power)
+{
+ enum iwl_bt_kill_msk bt_kill_msk;
+ struct iwl_bt_coex_cmd cmd = {};
+ struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (reduced_tx_power) {
+ /* Reduced Tx power has precedence on the type of the profile */
+ bt_kill_msk = BT_KILL_MSK_REDUCED_TXPOW;
+ } else {
+ /* Low latency BT profile is active: give higher prio to BT */
+ if (BT_MBOX_MSG(notif, 3, SCO_STATE) ||
+ BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
+ BT_MBOX_MSG(notif, 3, SNIFF_STATE))
+ bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
+ else
+ bt_kill_msk = BT_KILL_MSK_DEFAULT;
+ }
+
+ IWL_DEBUG_COEX(mvm,
+ "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n",
+ bt_kill_msk,
+ BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
+ BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
+ BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
+
+ /* Don't send HCMD if there is no update */
+ if (bt_kill_msk == mvm->bt_kill_msk)
+ return 0;
+
+ mvm->bt_kill_msk = bt_kill_msk;
+ cmd.kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
+ cmd.kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
+ cmd.valid_bit_msk = cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS);
+
+ IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk);
+ return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC,
+ sizeof(cmd), &cmd);
+}
+
+static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
+ bool enable)
+{
+ struct iwl_bt_coex_cmd cmd = {
+ .valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER),
+ .bt_reduced_tx_power = sta_id,
+ };
+ struct ieee80211_sta *sta;
+ struct iwl_mvm_sta *mvmsta;
+
+ /* This can happen if the station has been removed right now */
+ if (sta_id == IWL_MVM_STATION_COUNT)
+ return 0;
+
+ sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
+ lockdep_is_held(&mvm->mutex));
+ mvmsta = (void *)sta->drv_priv;
+
+ /* nothing to do */
+ if (mvmsta->bt_reduced_txpower == enable)
+ return 0;
+
+ if (enable)
+ cmd.bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
+
+ IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
+ enable ? "en" : "dis", sta_id);
+
+ mvmsta->bt_reduced_txpower = enable;
+
+ /* Send ASYNC since this can be sent from an atomic context */
+ return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_ASYNC,
+ sizeof(cmd), &cmd);
+}
+
+struct iwl_bt_iterator_data {
struct iwl_bt_coex_profile_notif *notif;
+ struct iwl_mvm *mvm;
+ u32 num_bss_ifaces;
+ bool reduced_tx_power;
};
static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_bt_notif_iterator_data *data = _data;
+ struct iwl_bt_iterator_data *data = _data;
+ struct iwl_mvm *mvm = data->mvm;
struct ieee80211_chanctx_conf *chanctx_conf;
enum ieee80211_smps_mode smps_mode;
enum ieee80211_band band;
+ int ave_rssi;
if (vif->type != NL80211_IFTYPE_STATION)
return;
@@ -268,11 +362,13 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
band = -1;
rcu_read_unlock();
- if (band != IEEE80211_BAND_2GHZ)
- return;
-
smps_mode = IEEE80211_SMPS_AUTOMATIC;
+ if (band != IEEE80211_BAND_2GHZ) {
+ ieee80211_request_smps(vif, smps_mode);
+ return;
+ }
+
if (data->notif->bt_status)
smps_mode = IEEE80211_SMPS_DYNAMIC;
@@ -285,20 +381,88 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
data->notif->bt_traffic_load, smps_mode);
ieee80211_request_smps(vif, smps_mode);
+
+ /* don't reduce the Tx power if in loose scheme */
+ if (is_loose_coex())
+ return;
+
+ data->num_bss_ifaces++;
+
+ /* reduced Txpower only if there are open BT connections, so ...*/
+ if (!BT_MBOX_MSG(data->notif, 3, OPEN_CON_2)) {
+ /* ... cancel reduced Tx power ... */
+ if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
+ IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
+ data->reduced_tx_power = false;
+
+ /* ... and there is no need to get reports on RSSI any more. */
+ ieee80211_disable_rssi_reports(vif);
+ return;
+ }
+
+ ave_rssi = ieee80211_ave_rssi(vif);
+
+ /* if the RSSI isn't valid, fake it is very low */
+ if (!ave_rssi)
+ ave_rssi = -100;
+ if (ave_rssi > BT_ENABLE_REDUCED_TXPOWER_THRESHOLD) {
+ if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
+ IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
+
+ /*
+ * bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the
+ * BSS / P2P clients have rssi above threshold.
+ * We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before
+ * the iteration, if one interface's rssi isn't good enough,
+ * bt_kill_msk will be set to default values.
+ */
+ } else if (ave_rssi < BT_DISABLE_REDUCED_TXPOWER_THRESHOLD) {
+ if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
+ IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
+
+ /*
+ * One interface hasn't rssi above threshold, bt_kill_msk must
+ * be set to default values.
+ */
+ data->reduced_tx_power = false;
+ }
+
+ /* Begin to monitor the RSSI: it may influence the reduced Tx power */
+ ieee80211_enable_rssi_reports(vif, BT_DISABLE_REDUCED_TXPOWER_THRESHOLD,
+ BT_ENABLE_REDUCED_TXPOWER_THRESHOLD);
+}
+
+static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
+{
+ struct iwl_bt_iterator_data data = {
+ .mvm = mvm,
+ .notif = &mvm->last_bt_notif,
+ .reduced_tx_power = true,
+ };
+
+ ieee80211_iterate_active_interfaces_atomic(
+ mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_bt_notif_iterator, &data);
+
+ /*
+ * If there are no BSS / P2P client interfaces, reduced Tx Power is
+ * irrelevant since it is based on the RSSI coming from the beacon.
+ * Use BT_KILL_MSK_DEFAULT in that case.
+ */
+ data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
+
+ if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
+ IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
}
+/* upon association, the fw will send in BT Coex notification */
int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *dev_cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data;
- struct iwl_bt_notif_iterator_data data = {
- .mvm = mvm,
- .notif = notif,
- };
- struct iwl_bt_coex_cmd cmd = {};
- enum iwl_bt_kill_msk bt_kill_msk;
+
IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
IWL_DEBUG_COEX(mvm, "\tBT %salive\n", notif->bt_status ? "" : "not ");
@@ -311,38 +475,115 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
/* remember this notification for future use: rssi fluctuations */
memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif));
- ieee80211_iterate_active_interfaces_atomic(
- mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_bt_notif_iterator, &data);
+ iwl_mvm_bt_coex_notif_handle(mvm);
+
+ /*
+ * This is an async handler for a notification, returning anything other
+ * than 0 doesn't make sense even if HCMD failed.
+ */
+ return 0;
+}
+
+static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
+ struct iwl_bt_iterator_data *data = _data;
+ struct iwl_mvm *mvm = data->mvm;
+
+ struct ieee80211_sta *sta;
+ struct iwl_mvm_sta *mvmsta;
+
+ if (vif->type != NL80211_IFTYPE_STATION ||
+ mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
+ return;
+
+ sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
+ lockdep_is_held(&mvm->mutex));
+ mvmsta = (void *)sta->drv_priv;
+
+ /*
+ * This interface doesn't support reduced Tx power (because of low
+ * RSSI probably), then set bt_kill_msk to default values.
+ */
+ if (!mvmsta->bt_reduced_txpower)
+ data->reduced_tx_power = false;
+ /* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */
+}
+
+void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ enum ieee80211_rssi_event rssi_event)
+{
+ struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
+ struct iwl_bt_iterator_data data = {
+ .mvm = mvm,
+ .reduced_tx_power = true,
+ };
+ int ret;
+
+ mutex_lock(&mvm->mutex);
+
+ /* Rssi update while not associated ?! */
+ if (WARN_ON_ONCE(mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT))
+ goto out_unlock;
- /* Low latency BT profile is active: give higher prio to BT */
- if (BT_MBOX_MSG(notif, 3, SCO_STATE) ||
- BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
- BT_MBOX_MSG(notif, 3, SNIFF_STATE))
- bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
+ /* No open connection - reports should be disabled */
+ if (!BT_MBOX_MSG(&mvm->last_bt_notif, 3, OPEN_CON_2))
+ goto out_unlock;
+
+ IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid,
+ rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW");
+
+ /*
+ * Check if rssi is good enough for reduced Tx power, but not in loose
+ * scheme.
+ */
+ if (rssi_event == RSSI_EVENT_LOW || is_loose_coex())
+ ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
+ false);
else
- bt_kill_msk = BT_KILL_MSK_DEFAULT;
+ ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true);
- /* Don't send HCMD if there is no update */
- if (bt_kill_msk == mvm->bt_kill_msk)
- return 0;
+ if (ret)
+ IWL_ERR(mvm, "couldn't send BT_CONFIG HCMD upon RSSI event\n");
- IWL_DEBUG_COEX(mvm,
- "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n",
- bt_kill_msk,
- BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
- BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
- BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
+ ieee80211_iterate_active_interfaces_atomic(
+ mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_bt_rssi_iterator, &data);
- mvm->bt_kill_msk = bt_kill_msk;
- cmd.kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
- cmd.kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
+ /*
+ * If there are no BSS / P2P client interfaces, reduced Tx Power is
+ * irrelevant since it is based on the RSSI coming from the beacon.
+ * Use BT_KILL_MSK_DEFAULT in that case.
+ */
+ data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
- cmd.valid_bit_msk = cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS);
+ if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
+ IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
- if (iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, sizeof(cmd), &cmd))
- IWL_ERR(mvm, "Failed to sent BT Coex CMD\n");
+ out_unlock:
+ mutex_unlock(&mvm->mutex);
+}
- /* This handler is ASYNC */
- return 0;
+void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ enum ieee80211_band band;
+
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(vif->chanctx_conf);
+ if (chanctx_conf && chanctx_conf->def.chan)
+ band = chanctx_conf->def.chan->band;
+ else
+ band = -1;
+ rcu_read_unlock();
+
+ /* if we are in 2GHz we will get a notification from the fw */
+ if (band == IEEE80211_BAND_2GHZ)
+ return;
+
+ /* else, we can remove all the constraints */
+ memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
+
+ iwl_mvm_bt_coex_notif_handle(mvm);
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index bf087abe39f3..16bbdcc8627a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -769,7 +769,14 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
struct iwl_wowlan_tkip_params_cmd tkip_cmd = {};
- struct iwl_d3_manager_config d3_cfg_cmd = {};
+ struct iwl_d3_manager_config d3_cfg_cmd = {
+ /*
+ * Program the minimum sleep time to 10 seconds, as many
+ * platforms have issues processing a wakeup signal while
+ * still being in the process of suspending.
+ */
+ .min_sleep_time = cpu_to_le32(10 * 1000 * 1000),
+ };
struct wowlan_key_data key_data = {
.use_rsc_tsc = false,
.tkip = &tkip_cmd,
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index b080b4ba5458..2053dccefcd6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -300,6 +300,67 @@ static ssize_t iwl_dbgfs_power_down_d3_allow_write(struct file *file,
return count;
}
+static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_vif *vif = file->private_data;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm *mvm = mvmvif->dbgfs_data;
+ u8 ap_sta_id;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ char buf[512];
+ int bufsz = sizeof(buf);
+ int pos = 0;
+ int i;
+
+ mutex_lock(&mvm->mutex);
+
+ ap_sta_id = mvmvif->ap_sta_id;
+
+ pos += scnprintf(buf+pos, bufsz-pos, "mac id/color: %d / %d\n",
+ mvmvif->id, mvmvif->color);
+ pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n",
+ vif->bss_conf.bssid);
+ pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n");
+ for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++) {
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
+ i, mvmvif->queue_params[i].txop,
+ mvmvif->queue_params[i].cw_min,
+ mvmvif->queue_params[i].cw_max,
+ mvmvif->queue_params[i].aifs,
+ mvmvif->queue_params[i].uapsd);
+ }
+
+ if (vif->type == NL80211_IFTYPE_STATION &&
+ ap_sta_id != IWL_MVM_STATION_COUNT) {
+ struct ieee80211_sta *sta;
+ struct iwl_mvm_sta *mvm_sta;
+
+ sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id],
+ lockdep_is_held(&mvm->mutex));
+ mvm_sta = (void *)sta->drv_priv;
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "ap_sta_id %d - reduced Tx power %d\n",
+ ap_sta_id, mvm_sta->bt_reduced_txpower);
+ }
+
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(vif->chanctx_conf);
+ if (chanctx_conf) {
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "idle rx chains %d, active rx chains: %d\n",
+ chanctx_conf->rx_chains_static,
+ chanctx_conf->rx_chains_dynamic);
+ }
+ rcu_read_unlock();
+
+ mutex_unlock(&mvm->mutex);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
#define BT_MBOX_MSG(_notif, _num, _field) \
((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
>> BT_MBOX##_num##_##_field##_POS)
@@ -464,6 +525,9 @@ MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow);
MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart);
+/* Interface specific debugfs entries */
+MVM_DEBUGFS_READ_FILE_OPS(mac_params);
+
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
{
char buf[100];
@@ -494,3 +558,58 @@ err:
IWL_ERR(mvm, "Can't create the mvm debugfs directory\n");
return -ENOMEM;
}
+
+void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+ struct dentry *dbgfs_dir = vif->debugfs_dir;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ char buf[100];
+
+ if (!dbgfs_dir)
+ return;
+
+ mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
+ mvmvif->dbgfs_data = mvm;
+
+ if (!mvmvif->dbgfs_dir) {
+ IWL_ERR(mvm, "Failed to create debugfs directory under %s\n",
+ dbgfs_dir->d_name.name);
+ return;
+ }
+
+ MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir,
+ S_IRUSR);
+
+ /*
+ * Create symlink for convenience pointing to interface specific
+ * debugfs entries for the driver. For example, under
+ * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
+ * find
+ * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
+ */
+ snprintf(buf, 100, "../../../%s/%s/%s/%s",
+ dbgfs_dir->d_parent->d_parent->d_name.name,
+ dbgfs_dir->d_parent->d_name.name,
+ dbgfs_dir->d_name.name,
+ mvmvif->dbgfs_dir->d_name.name);
+
+ mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name,
+ mvm->debugfs_dir, buf);
+ if (!mvmvif->dbgfs_slink)
+ IWL_ERR(mvm, "Can't create debugfs symbolic link under %s\n",
+ dbgfs_dir->d_name.name);
+ return;
+err:
+ IWL_ERR(mvm, "Can't create debugfs entity\n");
+}
+
+void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ debugfs_remove(mvmvif->dbgfs_slink);
+ mvmvif->dbgfs_slink = NULL;
+
+ debugfs_remove_recursive(mvmvif->dbgfs_dir);
+ mvmvif->dbgfs_dir = NULL;
+}
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index 127051891e9b..81fe45f46be7 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -68,73 +68,53 @@
/**
* enum iwl_scan_flags - masks for power table command flags
+ * @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
+ * receiver and transmitter. '0' - does not allow.
* @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management,
* '1' Driver enables PM (use rest of parameters)
- * @POWER_FLAGS_SLEEP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM,
+ * @POWER_FLAGS_SKIP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM,
* '1' PM could sleep over DTIM till listen Interval.
- * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
- * @POWER_FLAGS_SNOOZE_ENA_MSK: Enable snoozing only if uAPSD is enabled and all
- * access categories are both delivery and trigger enabled.
- * @POWER_FLAGS_BT_SCO_ENA: Enable BT SCO coex only if uAPSD and
- * PBW Snoozing enabled
* @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask
+ * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
*/
enum iwl_power_flags {
- POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(0),
- POWER_FLAGS_SLEEP_OVER_DTIM_MSK = BIT(1),
- POWER_FLAGS_LPRX_ENA_MSK = BIT(2),
- POWER_FLAGS_SNOOZE_ENA_MSK = BIT(3),
- POWER_FLAGS_BT_SCO_ENA = BIT(4),
- POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(5)
+ POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
+ POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(1),
+ POWER_FLAGS_SKIP_OVER_DTIM_MSK = BIT(2),
+ POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(9),
+ POWER_FLAGS_LPRX_ENA_MSK = BIT(11),
};
+#define IWL_POWER_VEC_SIZE 5
+
/**
* struct iwl_powertable_cmd - Power Table Command
* POWER_TABLE_CMD = 0x77 (command, has simple generic response)
*
- * @id_and_color: MAC contex identifier
- * @action: Action on context - no action, add new,
- * modify existent, remove
* @flags: Power table command flags from POWER_FLAGS_*
* @keep_alive_seconds: Keep alive period in seconds. Default - 25 sec.
- * Minimum allowed:- 3 * DTIM
+ * Minimum allowed:- 3 * DTIM. Keep alive period must be
+ * set regardless of power scheme or current power state.
+ * FW use this value also when PM is disabled.
* @rx_data_timeout: Minimum time (usec) from last Rx packet for AM to
* PSM transition - legacy PM
* @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to
* PSM transition - legacy PM
- * @rx_data_timeout_uapsd: Minimum time (usec) from last Rx packet for AM to
- * PSM transition - uAPSD
- * @tx_data_timeout_uapsd: Minimum time (usec) from last Tx packet for AM to
- * PSM transition - uAPSD
+ * @sleep_interval: not in use
+ * @keep_alive_beacons: not in use
* @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.
* Default: 80dbm
- * @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set
- * @snooze_interval: TBD
- * @snooze_window: TBD
- * @snooze_step: TBD
- * @qndp_tid: TBD
- * @uapsd_ac_flags: TBD
- * @uapsd_max_sp: TBD
*/
struct iwl_powertable_cmd {
- /* COMMON_INDEX_HDR_API_S_VER_1 */
- __le32 id_and_color;
- __le32 action;
+ /* PM_POWER_TABLE_CMD_API_S_VER_5 */
__le16 flags;
- u8 reserved;
- __le16 keep_alive_seconds;
+ u8 keep_alive_seconds;
+ u8 debug_flags;
__le32 rx_data_timeout;
__le32 tx_data_timeout;
- __le32 rx_data_timeout_uapsd;
- __le32 tx_data_timeout_uapsd;
- u8 lprx_rssi_threshold;
- u8 num_skip_dtim;
- __le16 snooze_interval;
- __le16 snooze_window;
- u8 snooze_step;
- u8 qndp_tid;
- u8 uapsd_ac_flags;
- u8 uapsd_max_sp;
+ __le32 sleep_interval[IWL_POWER_VEC_SIZE];
+ __le32 keep_alive_beacons;
+ __le32 lprx_rssi_threshold;
} __packed;
#endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 1073f2682221..191dcae8ba47 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -480,15 +480,34 @@ enum {
TE_DEP_TSF = 2,
TE_EVENT_SOCIOPATHIC = 4,
}; /* MAC_EVENT_DEPENDENCY_POLICY_API_E_VER_2 */
-
-/* When to send Time Event notifications and to whom (internal = FW) */
+/*
+ * Supported Time event notifications configuration.
+ * A notification (both event and fragment) includes a status indicating weather
+ * the FW was able to schedule the event or not. For fragment start/end
+ * notification the status is always success. There is no start/end fragment
+ * notification for monolithic events.
+ *
+ * @TE_NOTIF_NONE: no notifications
+ * @TE_NOTIF_HOST_EVENT_START: request/receive notification on event start
+ * @TE_NOTIF_HOST_EVENT_END:request/receive notification on event end
+ * @TE_NOTIF_INTERNAL_EVENT_START: internal FW use
+ * @TE_NOTIF_INTERNAL_EVENT_END: internal FW use.
+ * @TE_NOTIF_HOST_FRAG_START: request/receive notification on frag start
+ * @TE_NOTIF_HOST_FRAG_END:request/receive notification on frag end
+ * @TE_NOTIF_INTERNAL_FRAG_START: internal FW use.
+ * @TE_NOTIF_INTERNAL_FRAG_END: internal FW use.
+ */
enum {
TE_NOTIF_NONE = 0,
- TE_NOTIF_HOST_START = 0x1,
- TE_NOTIF_HOST_END = 0x2,
- TE_NOTIF_INTERNAL_START = 0x4,
- TE_NOTIF_INTERNAL_END = 0x8
-}; /* MAC_EVENT_ACTION_API_E_VER_1 */
+ TE_NOTIF_HOST_EVENT_START = 0x1,
+ TE_NOTIF_HOST_EVENT_END = 0x2,
+ TE_NOTIF_INTERNAL_EVENT_START = 0x4,
+ TE_NOTIF_INTERNAL_EVENT_END = 0x8,
+ TE_NOTIF_HOST_FRAG_START = 0x10,
+ TE_NOTIF_HOST_FRAG_END = 0x20,
+ TE_NOTIF_INTERNAL_FRAG_START = 0x40,
+ TE_NOTIF_INTERNAL_FRAG_END = 0x80
+}; /* MAC_EVENT_ACTION_API_E_VER_2 */
/*
* @TE_FRAG_NONE: fragmentation of the time event is NOT allowed.
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 86e312a4f629..e6eca4d66f6c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -669,6 +669,7 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm *mvm,
u32 action)
{
struct iwl_mac_ctx_cmd cmd = {};
+ struct ieee80211_p2p_noa_attr *noa = &vif->bss_conf.p2p_noa_attr;
WARN_ON(vif->type != NL80211_IFTYPE_STATION || !vif->p2p);
@@ -678,7 +679,8 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm *mvm,
/* Fill the data specific for station mode */
iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta);
- cmd.p2p_sta.ctwin = cpu_to_le32(vif->bss_conf.p2p_ctwindow);
+ cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow &
+ IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
}
@@ -919,6 +921,7 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
u32 action)
{
struct iwl_mac_ctx_cmd cmd = {};
+ struct ieee80211_p2p_noa_attr *noa = &vif->bss_conf.p2p_noa_attr;
WARN_ON(vif->type != NL80211_IFTYPE_AP || !vif->p2p);
@@ -929,8 +932,11 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap,
action == FW_CTXT_ACTION_ADD);
- cmd.go.ctwin = cpu_to_le32(vif->bss_conf.p2p_ctwindow);
- cmd.go.opp_ps_enabled = cpu_to_le32(!!vif->bss_conf.p2p_oppps);
+ cmd.go.ctwin = cpu_to_le32(noa->oppps_ctwindow &
+ IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
+ cmd.go.opp_ps_enabled =
+ cpu_to_le32(!!(noa->oppps_ctwindow &
+ IEEE80211_P2P_OPPPS_ENABLE_BIT));
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 3d193f8c33b6..fe031608fd91 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -502,11 +502,15 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
/*
* TODO: remove this temporary code.
* Currently MVM FW supports power management only on single MAC.
- * Iterate and disable PM on all active interfaces.
+ * If new interface added, disable PM on existing interface.
+ * P2P device is a special case, since it is handled by FW similary to
+ * scan. If P2P deviced is added, PM remains enabled on existing
+ * interface.
* Note: the method below does not count the new interface being added
* at this moment.
*/
- mvm->vif_count++;
+ if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
+ mvm->vif_count++;
if (mvm->vif_count > 1) {
IWL_DEBUG_MAC80211(mvm,
"Disable power on existing interfaces\n");
@@ -562,6 +566,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
mvm->p2p_device_vif = vif;
}
+ iwl_mvm_vif_dbgfs_register(mvm, vif);
goto out_unlock;
out_unbind:
@@ -575,10 +580,11 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
/*
* TODO: remove this temporary code.
* Currently MVM FW supports power management only on single MAC.
- * Check if only one additional interface remains after rereasing
+ * Check if only one additional interface remains after releasing
* current one. Update power mode on the remaining interface.
*/
- mvm->vif_count--;
+ if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
+ mvm->vif_count--;
IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n",
mvm->vif_count);
if (mvm->vif_count == 1) {
@@ -640,6 +646,8 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex);
+ iwl_mvm_vif_dbgfs_clean(mvm, vif);
+
/*
* For AP/GO interface, the tear down of the resources allocated to the
* interface is be handled as part of the stop_ap flow.
@@ -663,7 +671,7 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
* Check if only one additional interface remains after removing
* current one. Update power mode on the remaining interface.
*/
- if (mvm->vif_count)
+ if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE)
mvm->vif_count--;
IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n",
mvm->vif_count);
@@ -713,6 +721,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
IWL_ERR(mvm, "failed to update quotas\n");
return;
}
+ iwl_mvm_bt_coex_vif_assoc(mvm, vif);
} else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
/* remove AP station now that the MAC is unassoc */
ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id);
@@ -931,7 +940,7 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
*/
break;
case STA_NOTIFY_AWAKE:
- if (WARN_ON(mvmsta->sta_id == IWL_INVALID_STATION))
+ if (WARN_ON(mvmsta->sta_id == IWL_MVM_STATION_COUNT))
break;
iwl_mvm_sta_modify_ps_wake(mvm, sta);
break;
@@ -1326,6 +1335,15 @@ static int iwl_mvm_set_tim(struct ieee80211_hw *hw,
return iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm_sta->vif);
}
+static void iwl_mvm_mac_rssi_callback(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum ieee80211_rssi_event rssi_event)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+ iwl_mvm_bt_rssi_event(mvm, vif, rssi_event);
+}
+
struct ieee80211_ops iwl_mvm_hw_ops = {
.tx = iwl_mvm_mac_tx,
.ampdu_action = iwl_mvm_mac_ampdu_action,
@@ -1349,6 +1367,7 @@ struct ieee80211_ops iwl_mvm_hw_ops = {
.update_tkip_key = iwl_mvm_mac_update_tkip_key,
.remain_on_channel = iwl_mvm_roc,
.cancel_remain_on_channel = iwl_mvm_cancel_roc,
+ .rssi_callback = iwl_mvm_mac_rssi_callback,
.add_chanctx = iwl_mvm_add_chanctx,
.remove_chanctx = iwl_mvm_remove_chanctx,
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 53d58968e30a..8269bc562951 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -212,6 +212,7 @@ struct iwl_mvm_vif {
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct dentry *dbgfs_dir;
+ struct dentry *dbgfs_slink;
void *dbgfs_data;
#endif
};
@@ -321,6 +322,13 @@ struct iwl_mvm {
* can hold 16 keys at most. Reflect this fact.
*/
unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)];
+
+ /*
+ * This counter of created interfaces is referenced only in conjunction
+ * with FW limitation related to power management. Currently PM is
+ * supported only on a single interface.
+ * IMPORTANT: this variable counts all interfaces except P2P device.
+ */
u8 vif_count;
struct led_classdev led;
@@ -471,16 +479,22 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm);
/* MVM debugfs */
#ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir);
-int iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct dentry *dbgfs_dir);
-void iwl_power_get_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct iwl_powertable_cmd *cmd);
+void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
#else
static inline int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm,
struct dentry *dbgfs_dir)
{
return 0;
}
+static inline void
+iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+}
+static inline void
+iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+}
#endif /* CONFIG_IWLWIFI_DEBUGFS */
/* rate scaling */
@@ -490,6 +504,8 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
/* power managment */
int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct iwl_powertable_cmd *cmd);
int iwl_mvm_leds_init(struct iwl_mvm *mvm);
void iwl_mvm_leds_exit(struct iwl_mvm *mvm);
@@ -513,5 +529,8 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm);
int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
+void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ enum ieee80211_rssi_event rssi_event);
+void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
#endif /* __IWL_MVM_H__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index efb9a6f3faac..9395ab2a1af2 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -75,23 +75,49 @@
#define POWER_KEEP_ALIVE_PERIOD_SEC 25
-static void iwl_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct iwl_powertable_cmd *cmd)
+static void iwl_mvm_power_log(struct iwl_mvm *mvm,
+ struct iwl_powertable_cmd *cmd)
+{
+ IWL_DEBUG_POWER(mvm,
+ "Sending power table command for power level %d, flags = 0x%X\n",
+ iwlmvm_mod_params.power_scheme,
+ le16_to_cpu(cmd->flags));
+ IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", cmd->keep_alive_seconds);
+
+ if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
+ IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
+ le32_to_cpu(cmd->rx_data_timeout));
+ IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
+ le32_to_cpu(cmd->tx_data_timeout));
+ IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
+ cmd->lprx_rssi_threshold);
+ }
+}
+
+void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct iwl_powertable_cmd *cmd)
{
struct ieee80211_hw *hw = mvm->hw;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_channel *chan;
int dtimper, dtimper_msec;
int keep_alive;
bool radar_detect = false;
- cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
- mvmvif->color));
- cmd->action = cpu_to_le32(FW_CTXT_ACTION_MODIFY);
+ /*
+ * Regardless of power management state the driver must set
+ * keep alive period. FW will use it for sending keep alive NDPs
+ * immediately after association.
+ */
+ cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC;
+
+ if ((iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) ||
+ !iwlwifi_mod_params.power_save)
+ return;
+
+ cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
- if ((!vif->bss_conf.ps) ||
- (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM))
+ if (!vif->bss_conf.ps)
return;
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
@@ -110,26 +136,23 @@ static void iwl_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
/* Check skip over DTIM conditions */
if (!radar_detect && (dtimper <= 10) &&
- (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP)) {
- cmd->flags |= cpu_to_le16(POWER_FLAGS_SLEEP_OVER_DTIM_MSK);
- cmd->num_skip_dtim = 2;
- }
+ (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP))
+ cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
/* Check that keep alive period is at least 3 * DTIM */
dtimper_msec = dtimper * vif->bss_conf.beacon_int;
keep_alive = max_t(int, 3 * dtimper_msec,
- MSEC_PER_SEC * POWER_KEEP_ALIVE_PERIOD_SEC);
+ MSEC_PER_SEC * cmd->keep_alive_seconds);
keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
-
- cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
+ cmd->keep_alive_seconds = keep_alive;
if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP) {
/* TODO: Also for D3 (device sleep / WoWLAN) */
- cmd->rx_data_timeout = cpu_to_le32(10);
- cmd->tx_data_timeout = cpu_to_le32(10);
+ cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
+ cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
} else {
- cmd->rx_data_timeout = cpu_to_le32(50);
- cmd->tx_data_timeout = cpu_to_le32(50);
+ cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
+ cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
}
}
@@ -137,36 +160,11 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_powertable_cmd cmd = {};
- if (!iwlwifi_mod_params.power_save) {
- IWL_DEBUG_POWER(mvm, "Power management is not allowed\n");
- return 0;
- }
-
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
return 0;
- iwl_power_build_cmd(mvm, vif, &cmd);
-
- IWL_DEBUG_POWER(mvm,
- "Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n",
- cmd.id_and_color, iwlmvm_mod_params.power_scheme,
- le16_to_cpu(cmd.flags));
-
- if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
- IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n",
- le16_to_cpu(cmd.keep_alive_seconds));
- IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
- le32_to_cpu(cmd.rx_data_timeout));
- IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
- le32_to_cpu(cmd.tx_data_timeout));
- IWL_DEBUG_POWER(mvm, "Rx timeout (uAPSD) = %u usec\n",
- le32_to_cpu(cmd.rx_data_timeout_uapsd));
- IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
- le32_to_cpu(cmd.tx_data_timeout_uapsd));
- IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
- cmd.lprx_rssi_threshold);
- IWL_DEBUG_POWER(mvm, "DTIMs to skip = %u\n", cmd.num_skip_dtim);
- }
+ iwl_mvm_power_build_cmd(mvm, vif, &cmd);
+ iwl_mvm_power_log(mvm, &cmd);
return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
sizeof(cmd), &cmd);
@@ -175,33 +173,16 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_powertable_cmd cmd = {};
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- if (!iwlwifi_mod_params.power_save) {
- IWL_DEBUG_POWER(mvm, "Power management is not allowed\n");
- return 0;
- }
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
return 0;
- cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
- mvmvif->color));
- cmd.action = cpu_to_le32(FW_CTXT_ACTION_MODIFY);
+ if ((iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) &&
+ iwlwifi_mod_params.power_save)
+ cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
- IWL_DEBUG_POWER(mvm,
- "Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n",
- cmd.id_and_color, iwlmvm_mod_params.power_scheme,
- le16_to_cpu(cmd.flags));
+ iwl_mvm_power_log(mvm, &cmd);
return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC,
sizeof(cmd), &cmd);
}
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-void iwl_power_get_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct iwl_powertable_cmd *cmd)
-{
- iwl_power_build_cmd(mvm, vif, cmd);
-}
-#endif /* CONFIG_IWLWIFI_DEBUGFS */
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index a01a6612677e..55334d542e26 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -793,7 +793,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
if (num_of_ant(tbl->ant_type) > 1)
tbl->ant_type =
- first_antenna(mvm->nvm_data->valid_tx_ant);
+ first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
tbl->is_ht40 = 0;
tbl->is_SGI = 0;
@@ -1235,7 +1235,7 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm,
return -1;
/* Need both Tx chains/antennas to support MIMO */
- if (num_of_ant(mvm->nvm_data->valid_tx_ant) < 2)
+ if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) < 2)
return -1;
IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO2\n");
@@ -1287,7 +1287,7 @@ static int rs_switch_to_mimo3(struct iwl_mvm *mvm,
return -1;
/* Need both Tx chains/antennas to support MIMO */
- if (num_of_ant(mvm->nvm_data->valid_tx_ant) < 3)
+ if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) < 3)
return -1;
IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO3\n");
@@ -1381,7 +1381,7 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm,
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action;
- u8 valid_tx_ant = mvm->nvm_data->valid_tx_ant;
+ u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
u8 tx_chains_num = num_of_ant(valid_tx_ant);
int ret;
u8 update_search_tbl_counter = 0;
@@ -1514,7 +1514,7 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm,
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action;
- u8 valid_tx_ant = mvm->nvm_data->valid_tx_ant;
+ u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
u8 tx_chains_num = num_of_ant(valid_tx_ant);
u8 update_search_tbl_counter = 0;
int ret;
@@ -1649,7 +1649,7 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm,
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action;
- u8 valid_tx_ant = mvm->nvm_data->valid_tx_ant;
+ u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
u8 tx_chains_num = num_of_ant(valid_tx_ant);
u8 update_search_tbl_counter = 0;
int ret;
@@ -1786,7 +1786,7 @@ static int rs_move_mimo3_to_other(struct iwl_mvm *mvm,
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action;
- u8 valid_tx_ant = mvm->nvm_data->valid_tx_ant;
+ u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
u8 tx_chains_num = num_of_ant(valid_tx_ant);
int ret;
u8 update_search_tbl_counter = 0;
@@ -2449,7 +2449,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
i = lq_sta->last_txrate_idx;
- valid_tx_ant = mvm->nvm_data->valid_tx_ant;
+ valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
if (!lq_sta->search_better_tbl)
active_tbl = lq_sta->active_tbl;
@@ -2639,15 +2639,15 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
/* These values will be overridden later */
lq_sta->lq.single_stream_ant_msk =
- first_antenna(mvm->nvm_data->valid_tx_ant);
+ first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
lq_sta->lq.dual_stream_ant_msk =
- mvm->nvm_data->valid_tx_ant &
- ~first_antenna(mvm->nvm_data->valid_tx_ant);
+ iwl_fw_valid_tx_ant(mvm->fw) &
+ ~first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
if (!lq_sta->lq.dual_stream_ant_msk) {
lq_sta->lq.dual_stream_ant_msk = ANT_AB;
- } else if (num_of_ant(mvm->nvm_data->valid_tx_ant) == 2) {
+ } else if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) == 2) {
lq_sta->lq.dual_stream_ant_msk =
- mvm->nvm_data->valid_tx_ant;
+ iwl_fw_valid_tx_ant(mvm->fw);
}
/* as default allow aggregation for all tids */
@@ -2708,7 +2708,7 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm,
index++;
repeat_rate--;
if (mvm)
- valid_tx_ant = mvm->nvm_data->valid_tx_ant;
+ valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
/* Fill rest of rate table */
while (index < LINK_QUAL_MAX_RETRY_NUM) {
@@ -2813,7 +2813,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
u8 ant_sel_tx;
mvm = lq_sta->drv;
- valid_tx_ant = mvm->nvm_data->valid_tx_ant;
+ valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
if (lq_sta->dbg_fixed_rate) {
ant_sel_tx =
((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK)
@@ -2884,9 +2884,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
desc += sprintf(buff+desc, "fixed rate 0x%X\n",
lq_sta->dbg_fixed_rate);
desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
- (mvm->nvm_data->valid_tx_ant & ANT_A) ? "ANT_A," : "",
- (mvm->nvm_data->valid_tx_ant & ANT_B) ? "ANT_B," : "",
- (mvm->nvm_data->valid_tx_ant & ANT_C) ? "ANT_C" : "");
+ (iwl_fw_valid_tx_ant(mvm->fw) & ANT_A) ? "ANT_A," : "",
+ (iwl_fw_valid_tx_ant(mvm->fw) & ANT_B) ? "ANT_B," : "",
+ (iwl_fw_valid_tx_ant(mvm->fw) & ANT_C) ? "ANT_C" : "");
desc += sprintf(buff+desc, "lq type %s\n",
(is_legacy(tbl->lq_type)) ? "legacy" : "HT");
if (is_Ht(tbl->lq_type)) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 4d872d69577f..0fd96e4da461 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -945,7 +945,7 @@ static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT)
return mvmvif->ap_sta_id;
- return IWL_INVALID_STATION;
+ return IWL_MVM_STATION_COUNT;
}
static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
@@ -1093,7 +1093,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
/* Get the station id from the mvm local station table */
sta_id = iwl_mvm_get_key_sta_id(vif, sta);
- if (sta_id == IWL_INVALID_STATION) {
+ if (sta_id == IWL_MVM_STATION_COUNT) {
IWL_ERR(mvm, "Failed to find station id\n");
return -EINVAL;
}
@@ -1188,7 +1188,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
return -ENOENT;
}
- if (sta_id == IWL_INVALID_STATION) {
+ if (sta_id == IWL_MVM_STATION_COUNT) {
IWL_DEBUG_WEP(mvm, "station non-existent, early return.\n");
return 0;
}
@@ -1254,7 +1254,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvm_sta;
u8 sta_id = iwl_mvm_get_key_sta_id(vif, sta);
- if (WARN_ON_ONCE(sta_id == IWL_INVALID_STATION))
+ if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT))
return;
rcu_read_lock();
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h
index b0352df981e4..12abd2d71835 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.h
@@ -271,6 +271,7 @@ struct iwl_mvm_tid_data {
* @tid_disable_agg: bitmap: if bit(tid) is set, the fw won't send ampdus for
* tid.
* @max_agg_bufsize: the maximal size of the AGG buffer for this station
+ * @bt_reduced_txpower: is reduced tx power enabled for this station
* @lock: lock to protect the whole struct. Since %tid_data is access from Tx
* and from Tx response flow, it needs a spinlock.
* @pending_frames: number of frames for this STA on the shared Tx queues.
@@ -287,6 +288,7 @@ struct iwl_mvm_sta {
u32 mac_id_n_color;
u16 tid_disable_agg;
u8 max_agg_bufsize;
+ bool bt_reduced_txpower;
spinlock_t lock;
atomic_t pending_frames;
struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT];
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index 4dc934bed055..ad9bbca99213 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -166,7 +166,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
WARN_ONCE(!le32_to_cpu(notif->status),
"Failed to schedule time event\n");
- if (le32_to_cpu(notif->action) == TE_NOTIF_HOST_END) {
+ if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_END) {
IWL_DEBUG_TE(mvm,
"TE ended - current time %lu, estimated end %lu\n",
jiffies, te_data->end_jiffies);
@@ -189,7 +189,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
}
iwl_mvm_te_clear_data(mvm, te_data);
- } else if (le32_to_cpu(notif->action) == TE_NOTIF_HOST_START) {
+ } else if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_START) {
te_data->running = true;
te_data->end_jiffies = jiffies +
TU_TO_JIFFIES(te_data->duration);
@@ -368,7 +368,8 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
time_cmd.interval_reciprocal = cpu_to_le32(iwl_mvm_reciprocal(1));
time_cmd.duration = cpu_to_le32(duration);
time_cmd.repeat = cpu_to_le32(1);
- time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_START | TE_NOTIF_HOST_END);
+ time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_EVENT_START |
+ TE_NOTIF_HOST_EVENT_END);
iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
}
@@ -485,7 +486,8 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2));
time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration));
time_cmd.repeat = cpu_to_le32(1);
- time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_START | TE_NOTIF_HOST_END);
+ time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_EVENT_START |
+ TE_NOTIF_HOST_EVENT_END);
return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 0acc0bff43c7..479074303bd7 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -205,7 +205,7 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx);
mvm->mgmt_last_antenna_idx =
- iwl_mvm_next_antenna(mvm, mvm->nvm_data->valid_tx_ant,
+ iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw),
mvm->mgmt_last_antenna_idx);
rate_flags = BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS;
@@ -365,7 +365,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
if (WARN_ON_ONCE(!mvmsta))
return -1;
- if (WARN_ON_ONCE(mvmsta->sta_id == IWL_INVALID_STATION))
+ if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT))
return -1;
dev_cmd = iwl_mvm_set_tx_params(mvm, skb, sta, mvmsta->sta_id);
@@ -641,10 +641,12 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
}
IWL_DEBUG_TX_REPLY(mvm,
- "TXQ %d status %s (0x%08x)\n\t\t\t\tinitial_rate 0x%x "
- "retries %d, idx=%d ssn=%d next_reclaimed=0x%x seq_ctl=0x%x\n",
- txq_id, iwl_mvm_get_tx_fail_reason(status),
- status, le32_to_cpu(tx_resp->initial_rate),
+ "TXQ %d status %s (0x%08x)\n",
+ txq_id, iwl_mvm_get_tx_fail_reason(status), status);
+
+ IWL_DEBUG_TX_REPLY(mvm,
+ "\t\t\t\tinitial_rate 0x%x retries %d, idx=%d ssn=%d next_reclaimed=0x%x seq_ctl=0x%x\n",
+ le32_to_cpu(tx_resp->initial_rate),
tx_resp->failure_frame, SEQ_TO_INDEX(sequence),
ssn, next_reclaimed, seq_ctl);
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index e308ad93aa9e..0cc8d8c0d393 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -462,7 +462,7 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
.data = { lq, },
};
- if (WARN_ON(lq->sta_id == IWL_INVALID_STATION))
+ if (WARN_ON(lq->sta_id == IWL_MVM_STATION_COUNT))
return -EINVAL;
if (WARN_ON(init && (cmd.flags & CMD_ASYNC)))
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index 46ca91f77c9c..0016bb24b3d7 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -241,6 +241,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
{IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
{IWL_PCI_DEVICE(0x088E, 0x4860, iwl6035_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x088F, 0x5260, iwl6035_2agn_cfg)},
/* 105 Series */
{IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)},
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 68466ca80770..c5e30294c5ac 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -1061,7 +1061,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id));
/* If this queue is mapped to a certain station: it is an AGG queue */
- if (sta_id != IWL_INVALID_STATION) {
+ if (sta_id >= 0) {
u16 ra_tid = BUILD_RAxTID(sta_id, tid);
/* Map receiver-address / traffic-ID to this queue */
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index 7001856241e6..088de9d25c39 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -412,9 +412,9 @@ static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed)
struct ieee80211_conf *conf = &hw->conf;
lbtf_deb_enter(LBTF_DEB_MACOPS);
- if (conf->channel->center_freq != priv->cur_freq) {
- priv->cur_freq = conf->channel->center_freq;
- lbtf_set_channel(priv, conf->channel->hw_value);
+ if (conf->chandef.chan->center_freq != priv->cur_freq) {
+ priv->cur_freq = conf->chandef.chan->center_freq;
+ lbtf_set_channel(priv, conf->chandef.chan->hw_value);
}
lbtf_deb_leave(LBTF_DEB_MACOPS);
return 0;
@@ -537,7 +537,7 @@ static int lbtf_op_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = priv->noise;
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 0064d38276bf..b878a32e7a98 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -25,6 +25,7 @@
#include <linux/if_arp.h>
#include <linux/rtnetlink.h>
#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/ktime.h>
@@ -52,6 +53,10 @@ static bool paged_rx = false;
module_param(paged_rx, bool, 0644);
MODULE_PARM_DESC(paged_rx, "Use paged SKBs for RX instead of linear ones");
+static bool rctbl = false;
+module_param(rctbl, bool, 0444);
+MODULE_PARM_DESC(rctbl, "Handle rate control table");
+
/**
* enum hwsim_regtest - the type of regulatory tests we offer
*
@@ -717,9 +722,17 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
rx_status.flag |= RX_FLAG_MACTIME_START;
rx_status.freq = chan->center_freq;
rx_status.band = chan->band;
- rx_status.rate_idx = info->control.rates[0].idx;
- if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
- rx_status.flag |= RX_FLAG_HT;
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) {
+ rx_status.rate_idx =
+ ieee80211_rate_get_vht_mcs(&info->control.rates[0]);
+ rx_status.vht_nss =
+ ieee80211_rate_get_vht_nss(&info->control.rates[0]);
+ rx_status.flag |= RX_FLAG_VHT;
+ } else {
+ rx_status.rate_idx = info->control.rates[0].idx;
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
+ rx_status.flag |= RX_FLAG_HT;
+ }
if (info->control.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
rx_status.flag |= RX_FLAG_40MHZ;
if (info->control.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
@@ -886,8 +899,12 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
if (control->sta)
hwsim_check_sta_magic(control->sta);
- txi->rate_driver_data[0] = channel;
+ if (rctbl)
+ ieee80211_get_tx_rates(txi->control.vif, control->sta, skb,
+ txi->control.rates,
+ ARRAY_SIZE(txi->control.rates));
+ txi->rate_driver_data[0] = channel;
mac80211_hwsim_monitor_rx(hw, skb, channel);
/* wmediumd mode check */
@@ -989,6 +1006,13 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
{
u32 _pid = ACCESS_ONCE(wmediumd_portid);
+ if (rctbl) {
+ struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb);
+ ieee80211_get_tx_rates(txi->control.vif, NULL, skb,
+ txi->control.rates,
+ ARRAY_SIZE(txi->control.rates));
+ }
+
mac80211_hwsim_monitor_rx(hw, skb, chan);
if (_pid)
@@ -1019,6 +1043,11 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
if (skb == NULL)
return;
info = IEEE80211_SKB_CB(skb);
+ if (rctbl)
+ ieee80211_get_tx_rates(vif, NULL, skb,
+ info->control.rates,
+ ARRAY_SIZE(info->control.rates));
+
txrate = ieee80211_get_tx_rate(hw, info);
mgmt = (struct ieee80211_mgmt *) skb->data;
@@ -1062,11 +1091,13 @@ out:
return HRTIMER_NORESTART;
}
-static const char *hwsim_chantypes[] = {
- [NL80211_CHAN_NO_HT] = "noht",
- [NL80211_CHAN_HT20] = "ht20",
- [NL80211_CHAN_HT40MINUS] = "ht40-",
- [NL80211_CHAN_HT40PLUS] = "ht40+",
+static const char * const hwsim_chanwidths[] = {
+ [NL80211_CHAN_WIDTH_20_NOHT] = "noht",
+ [NL80211_CHAN_WIDTH_20] = "ht20",
+ [NL80211_CHAN_WIDTH_40] = "ht40",
+ [NL80211_CHAN_WIDTH_80] = "vht80",
+ [NL80211_CHAN_WIDTH_80P80] = "vht80p80",
+ [NL80211_CHAN_WIDTH_160] = "vht160",
};
static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
@@ -1080,18 +1111,28 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
[IEEE80211_SMPS_DYNAMIC] = "dynamic",
};
- wiphy_debug(hw->wiphy,
- "%s (freq=%d/%s idle=%d ps=%d smps=%s)\n",
- __func__,
- conf->channel ? conf->channel->center_freq : 0,
- hwsim_chantypes[conf->channel_type],
- !!(conf->flags & IEEE80211_CONF_IDLE),
- !!(conf->flags & IEEE80211_CONF_PS),
- smps_modes[conf->smps_mode]);
+ if (conf->chandef.chan)
+ wiphy_debug(hw->wiphy,
+ "%s (freq=%d(%d - %d)/%s idle=%d ps=%d smps=%s)\n",
+ __func__,
+ conf->chandef.chan->center_freq,
+ conf->chandef.center_freq1,
+ conf->chandef.center_freq2,
+ hwsim_chanwidths[conf->chandef.width],
+ !!(conf->flags & IEEE80211_CONF_IDLE),
+ !!(conf->flags & IEEE80211_CONF_PS),
+ smps_modes[conf->smps_mode]);
+ else
+ wiphy_debug(hw->wiphy,
+ "%s (freq=0 idle=%d ps=%d smps=%s)\n",
+ __func__,
+ !!(conf->flags & IEEE80211_CONF_IDLE),
+ !!(conf->flags & IEEE80211_CONF_PS),
+ smps_modes[conf->smps_mode]);
data->idle = !!(conf->flags & IEEE80211_CONF_IDLE);
- data->channel = conf->channel;
+ data->channel = conf->chandef.chan;
WARN_ON(data->channel && channels > 1);
@@ -1277,7 +1318,7 @@ static int mac80211_hwsim_get_survey(
return -ENOENT;
/* Current channel */
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
/*
* Magically conjured noise level --- this is only ok for simulated hardware.
@@ -1675,6 +1716,7 @@ static void mac80211_hwsim_free(void)
debugfs_remove(data->debugfs_ps);
debugfs_remove(data->debugfs);
ieee80211_unregister_hw(data->hw);
+ device_release_driver(data->dev);
device_unregister(data->dev);
ieee80211_free_hw(data->hw);
}
@@ -1683,7 +1725,9 @@ static void mac80211_hwsim_free(void)
static struct device_driver mac80211_hwsim_driver = {
- .name = "mac80211_hwsim"
+ .name = "mac80211_hwsim",
+ .bus = &platform_bus_type,
+ .owner = THIS_MODULE,
};
static const struct net_device_ops hwsim_netdev_ops = {
@@ -2175,9 +2219,15 @@ static int __init init_mac80211_hwsim(void)
spin_lock_init(&hwsim_radio_lock);
INIT_LIST_HEAD(&hwsim_radios);
+ err = driver_register(&mac80211_hwsim_driver);
+ if (err)
+ return err;
+
hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim");
- if (IS_ERR(hwsim_class))
- return PTR_ERR(hwsim_class);
+ if (IS_ERR(hwsim_class)) {
+ err = PTR_ERR(hwsim_class);
+ goto failed_unregister_driver;
+ }
memset(addr, 0, ETH_ALEN);
addr[0] = 0x02;
@@ -2199,12 +2249,20 @@ static int __init init_mac80211_hwsim(void)
"hwsim%d", i);
if (IS_ERR(data->dev)) {
printk(KERN_DEBUG
- "mac80211_hwsim: device_create "
- "failed (%ld)\n", PTR_ERR(data->dev));
+ "mac80211_hwsim: device_create failed (%ld)\n",
+ PTR_ERR(data->dev));
err = -ENOMEM;
goto failed_drvdata;
}
data->dev->driver = &mac80211_hwsim_driver;
+ err = device_bind_driver(data->dev);
+ if (err != 0) {
+ printk(KERN_DEBUG
+ "mac80211_hwsim: device_bind_driver failed (%d)\n",
+ err);
+ goto failed_hw;
+ }
+
skb_queue_head_init(&data->pending);
SET_IEEE80211_DEV(hw, data->dev);
@@ -2247,6 +2305,8 @@ static int __init init_mac80211_hwsim(void)
IEEE80211_HW_AMPDU_AGGREGATION |
IEEE80211_HW_WANT_MONITOR_VIF |
IEEE80211_HW_QUEUE_CONTROL;
+ if (rctbl)
+ hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE;
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
@@ -2298,9 +2358,6 @@ static int __init init_mac80211_hwsim(void)
hw->wiphy->bands[band] = sband;
- if (channels == 1)
- continue;
-
sband->vht_cap.vht_supported = true;
sband->vht_cap.cap =
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
@@ -2506,6 +2563,8 @@ failed_drvdata:
ieee80211_free_hw(hw);
failed:
mac80211_hwsim_free();
+failed_unregister_driver:
+ driver_unregister(&mac80211_hwsim_driver);
return err;
}
module_init(init_mac80211_hwsim);
@@ -2518,5 +2577,6 @@ static void __exit exit_mac80211_hwsim(void)
mac80211_hwsim_free();
unregister_netdev(hwsim_mon);
+ driver_unregister(&mac80211_hwsim_driver);
}
module_exit(exit_mac80211_hwsim);
diff --git a/drivers/net/wireless/mwifiex/11ac.c b/drivers/net/wireless/mwifiex/11ac.c
index 966a78f8e21a..5e0eec4d71c7 100644
--- a/drivers/net/wireless/mwifiex/11ac.c
+++ b/drivers/net/wireless/mwifiex/11ac.c
@@ -200,7 +200,7 @@ int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
/* VHT Operation IE */
if (bss_desc->bcn_vht_oper) {
- if (priv->bss_mode == HostCmd_BSS_MODE_IBSS) {
+ if (priv->bss_mode == NL80211_IFTYPE_STATION) {
vht_op = (struct mwifiex_ie_types_vht_oper *)*buffer;
memset(vht_op, 0, sizeof(*vht_op));
vht_op->header.type =
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index af8fe6352eed..a78e0651409c 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -296,19 +296,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
break;
}
if (ret != -EBUSY) {
- spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
- if (mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) {
- priv->wmm.packets_out[ptrindex]++;
- priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr = pra_list;
- }
- /* Now bss_prio_cur pointer points to next node */
- adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur =
- list_first_entry(
- &adapter->bss_prio_tbl[priv->bss_priority]
- .bss_prio_cur->list,
- struct mwifiex_bss_prio_node, list);
- spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
- ra_list_flags);
+ mwifiex_rotate_priolists(priv, pra_list, ptrindex);
}
return 0;
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index 5e796f847088..ada809f576fe 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -447,7 +447,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
del_timer(&tbl->timer_context.timer);
mod_timer(&tbl->timer_context.timer,
- jiffies + (MIN_FLUSH_TIMER_MS * win_size * HZ) / 1000);
+ jiffies + msecs_to_jiffies(MIN_FLUSH_TIMER_MS * win_size));
/*
* If seq_num is less then starting win then ignore and drop the
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 47012947a447..a0cb0770d319 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1666,17 +1666,13 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_connect_params *sme)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
- int ret = 0;
-
- if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
- wiphy_err(wiphy, "received infra assoc request "
- "when station is in ibss mode\n");
- goto done;
- }
+ int ret;
- if (priv->bss_mode == NL80211_IFTYPE_AP) {
- wiphy_err(wiphy, "skip association request for AP interface\n");
- goto done;
+ if (priv->bss_mode != NL80211_IFTYPE_STATION) {
+ wiphy_err(wiphy,
+ "%s: reject infra assoc request in non-STA mode\n",
+ dev->name);
+ return -EINVAL;
}
wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n",
@@ -1684,7 +1680,6 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,
priv->bss_mode, sme->channel, sme, 0);
-done:
if (!ret) {
cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0,
NULL, 0, WLAN_STATUS_SUCCESS,
@@ -2136,10 +2131,9 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
/* At start-up, wpa_supplicant tries to change the interface
* to NL80211_IFTYPE_STATION if it is not managed mode.
- * So, we initialize it to STA mode.
*/
- wdev->iftype = NL80211_IFTYPE_STATION;
- priv->bss_mode = NL80211_IFTYPE_STATION;
+ wdev->iftype = NL80211_IFTYPE_P2P_CLIENT;
+ priv->bss_mode = NL80211_IFTYPE_P2P_CLIENT;
/* Setting bss_type to P2P tells firmware that this interface
* is receiving P2P peers found during find phase and doing
@@ -2153,6 +2147,9 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->bss_started = 0;
priv->bss_num = 0;
+ if (mwifiex_cfg80211_init_p2p_client(priv))
+ return ERR_PTR(-EFAULT);
+
break;
default:
wiphy_err(wiphy, "type not supported\n");
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index da469c336aa1..74db0d24a579 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -250,7 +250,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
/* Setup the timer after transmit command */
mod_timer(&adapter->cmd_timer,
- jiffies + (MWIFIEX_TIMER_10S * HZ) / 1000);
+ jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
return 0;
}
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 42d7f0adf9bd..9f44fda19db9 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -44,8 +44,6 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
bss_prio->priv = priv;
INIT_LIST_HEAD(&bss_prio->list);
- if (!tbl[priv->bss_priority].bss_prio_cur)
- tbl[priv->bss_priority].bss_prio_cur = bss_prio;
spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags);
list_add_tail(&bss_prio->list, &tbl[priv->bss_priority].bss_prio_head);
@@ -525,7 +523,6 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
for (i = 0; i < adapter->priv_num; ++i) {
INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head);
- adapter->bss_prio_tbl[i].bss_prio_cur = NULL;
spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock);
}
@@ -625,42 +622,36 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv)
{
int i;
struct mwifiex_adapter *adapter = priv->adapter;
- struct mwifiex_bss_prio_node *bssprio_node, *tmp_node, **cur;
+ struct mwifiex_bss_prio_node *bssprio_node, *tmp_node;
struct list_head *head;
spinlock_t *lock; /* bss priority lock */
unsigned long flags;
for (i = 0; i < adapter->priv_num; ++i) {
head = &adapter->bss_prio_tbl[i].bss_prio_head;
- cur = &adapter->bss_prio_tbl[i].bss_prio_cur;
lock = &adapter->bss_prio_tbl[i].bss_prio_lock;
dev_dbg(adapter->dev, "info: delete BSS priority table,"
" bss_type = %d, bss_num = %d, i = %d,"
- " head = %p, cur = %p\n",
- priv->bss_type, priv->bss_num, i, head, *cur);
- if (*cur) {
+ " head = %p\n",
+ priv->bss_type, priv->bss_num, i, head);
+
+ {
spin_lock_irqsave(lock, flags);
if (list_empty(head)) {
spin_unlock_irqrestore(lock, flags);
continue;
}
- bssprio_node = list_first_entry(head,
- struct mwifiex_bss_prio_node, list);
- spin_unlock_irqrestore(lock, flags);
-
list_for_each_entry_safe(bssprio_node, tmp_node, head,
list) {
if (bssprio_node->priv == priv) {
dev_dbg(adapter->dev, "info: Delete "
"node %p, next = %p\n",
bssprio_node, tmp_node);
- spin_lock_irqsave(lock, flags);
list_del(&bssprio_node->list);
- spin_unlock_irqrestore(lock, flags);
kfree(bssprio_node);
}
}
- *cur = (struct mwifiex_bss_prio_node *)head;
+ spin_unlock_irqrestore(lock, flags);
}
}
}
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index b7484efc9443..4ef67fca06d3 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -213,7 +213,6 @@ struct mwifiex_ra_list_tbl {
struct mwifiex_tid_tbl {
struct list_head ra_list;
- struct mwifiex_ra_list_tbl *ra_list_curr;
};
#define WMM_HIGHEST_PRIORITY 7
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 856959b64bc7..80f282c0bd4d 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -572,7 +572,7 @@ static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter)
if (card->rx_buf_list[i]) {
skb = card->rx_buf_list[i];
pci_unmap_single(card->dev, desc2->paddr,
- skb->len, PCI_DMA_TODEVICE);
+ skb->len, PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(skb);
}
memset(desc2, 0, sizeof(*desc2));
@@ -581,7 +581,7 @@ static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter)
if (card->rx_buf_list[i]) {
skb = card->rx_buf_list[i];
pci_unmap_single(card->dev, desc->paddr,
- skb->len, PCI_DMA_TODEVICE);
+ skb->len, PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(skb);
}
memset(desc, 0, sizeof(*desc));
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index e7f6deaf715e..9cf5d8f07df8 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1500,43 +1500,22 @@ static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
if (ret)
goto done;
- /* Update current bss descriptor parameters */
spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
- priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL;
- priv->curr_bss_params.bss_descriptor.wpa_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL;
- priv->curr_bss_params.bss_descriptor.rsn_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL;
- priv->curr_bss_params.bss_descriptor.wapi_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL;
- priv->curr_bss_params.bss_descriptor.ht_cap_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_ht_oper = NULL;
- priv->curr_bss_params.bss_descriptor.ht_info_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 = NULL;
- priv->curr_bss_params.bss_descriptor.bss_co_2040_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL;
- priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0;
- priv->curr_bss_params.bss_descriptor.beacon_buf = NULL;
- priv->curr_bss_params.bss_descriptor.beacon_buf_size = 0;
- priv->curr_bss_params.bss_descriptor.bcn_vht_cap = NULL;
- priv->curr_bss_params.bss_descriptor.vht_cap_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_vht_oper = NULL;
- priv->curr_bss_params.bss_descriptor.vht_info_offset = 0;
- priv->curr_bss_params.bss_descriptor.oper_mode = NULL;
- priv->curr_bss_params.bss_descriptor.oper_mode_offset = 0;
-
- /* Disable 11ac by default. Enable it only where there
- * exist VHT_CAP IE in AP beacon
- */
- priv->curr_bss_params.bss_descriptor.disable_11ac = true;
-
/* Make a copy of current BSSID descriptor */
memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
sizeof(priv->curr_bss_params.bss_descriptor));
+
+ /* The contents of beacon_ie will be copied to its own buffer
+ * in mwifiex_save_curr_bcn()
+ */
mwifiex_save_curr_bcn(priv);
spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
done:
+ /* beacon_ie buffer was allocated in function
+ * mwifiex_fill_new_bss_desc(). Free it now.
+ */
+ kfree(bss_desc->beacon_buf);
kfree(bss_desc);
return 0;
}
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index e6c9b2ae22ed..311d0b26b81c 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -140,12 +140,13 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
/*
* This function fills bss descriptor structure using provided
* information.
+ * beacon_ie buffer is allocated in this function. It is caller's
+ * responsibility to free the memory.
*/
int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
struct cfg80211_bss *bss,
struct mwifiex_bssdescriptor *bss_desc)
{
- int ret;
u8 *beacon_ie;
size_t beacon_ie_len;
struct mwifiex_bss_priv *bss_priv = (void *)bss->priv;
@@ -165,6 +166,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
memcpy(bss_desc->mac_address, bss->bssid, ETH_ALEN);
bss_desc->rssi = bss->signal;
+ /* The caller of this function will free beacon_ie */
bss_desc->beacon_buf = beacon_ie;
bss_desc->beacon_buf_size = beacon_ie_len;
bss_desc->beacon_period = bss->beacon_interval;
@@ -182,10 +184,12 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
else
bss_desc->bss_mode = NL80211_IFTYPE_STATION;
- ret = mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc);
+ /* Disable 11ac by default. Enable it only where there
+ * exist VHT_CAP IE in AP beacon
+ */
+ bss_desc->disable_11ac = true;
- kfree(beacon_ie);
- return ret;
+ return mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc);
}
static int mwifiex_process_country_ie(struct mwifiex_private *priv,
@@ -349,6 +353,11 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
}
done:
+ /* beacon_ie buffer was allocated in function
+ * mwifiex_fill_new_bss_desc(). Free it now.
+ */
+ if (bss_desc)
+ kfree(bss_desc->beacon_buf);
kfree(bss_desc);
return ret;
}
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 2cc81ba590e3..4be3d33ceae8 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -191,9 +191,6 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
}
list_add_tail(&ra_list->list,
&priv->wmm.tid_tbl_ptr[i].ra_list);
-
- if (!priv->wmm.tid_tbl_ptr[i].ra_list_curr)
- priv->wmm.tid_tbl_ptr[i].ra_list_curr = ra_list;
}
}
@@ -424,7 +421,6 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter)
priv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i];
priv->aggr_prio_tbl[i].ampdu_ap = tos_to_tid_inv[i];
priv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i];
- priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL;
}
priv->aggr_prio_tbl[6].amsdu
@@ -530,8 +526,6 @@ static void mwifiex_wmm_delete_all_ralist(struct mwifiex_private *priv)
}
INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[i].ra_list);
-
- priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL;
}
}
@@ -883,38 +877,26 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
struct mwifiex_private **priv, int *tid)
{
struct mwifiex_private *priv_tmp;
- struct mwifiex_ra_list_tbl *ptr, *head;
- struct mwifiex_bss_prio_node *bssprio_node, *bssprio_head;
+ struct mwifiex_ra_list_tbl *ptr;
struct mwifiex_tid_tbl *tid_ptr;
atomic_t *hqp;
unsigned long flags_bss, flags_ra;
int i, j;
+ /* check the BSS with highest priority first */
for (j = adapter->priv_num - 1; j >= 0; --j) {
spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock,
flags_bss);
- if (list_empty(&adapter->bss_prio_tbl[j].bss_prio_head))
- goto skip_prio_tbl;
-
- if (adapter->bss_prio_tbl[j].bss_prio_cur ==
- (struct mwifiex_bss_prio_node *)
- &adapter->bss_prio_tbl[j].bss_prio_head) {
- adapter->bss_prio_tbl[j].bss_prio_cur =
- list_first_entry(&adapter->bss_prio_tbl[j]
- .bss_prio_head,
- struct mwifiex_bss_prio_node,
- list);
- }
-
- bssprio_node = adapter->bss_prio_tbl[j].bss_prio_cur;
- bssprio_head = bssprio_node;
+ /* iterate over BSS with the equal priority */
+ list_for_each_entry(adapter->bss_prio_tbl[j].bss_prio_cur,
+ &adapter->bss_prio_tbl[j].bss_prio_head,
+ list) {
- do {
- priv_tmp = bssprio_node->priv;
+ priv_tmp = adapter->bss_prio_tbl[j].bss_prio_cur->priv;
if (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0)
- goto skip_bss;
+ continue;
/* iterate over the WMM queues of the BSS */
hqp = &priv_tmp->wmm.highest_queued_prio;
@@ -926,73 +908,21 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
tid_ptr = &(priv_tmp)->wmm.
tid_tbl_ptr[tos_to_tid[i]];
- /* For non-STA ra_list_curr may be NULL */
- if (!tid_ptr->ra_list_curr)
- goto skip_wmm_queue;
-
- if (list_empty(&tid_ptr->ra_list))
- goto skip_wmm_queue;
-
- /*
- * Always choose the next ra we transmitted
- * last time, this way we pick the ra's in
- * round robin fashion.
- */
- ptr = list_first_entry(
- &tid_ptr->ra_list_curr->list,
- struct mwifiex_ra_list_tbl,
- list);
-
- head = ptr;
- if (ptr == (struct mwifiex_ra_list_tbl *)
- &tid_ptr->ra_list) {
- /* Get next ra */
- ptr = list_first_entry(&ptr->list,
- struct mwifiex_ra_list_tbl, list);
- head = ptr;
- }
+ /* iterate over receiver addresses */
+ list_for_each_entry(ptr, &tid_ptr->ra_list,
+ list) {
- do {
if (!skb_queue_empty(&ptr->skb_head))
/* holds both locks */
goto found;
+ }
- /* Get next ra */
- ptr = list_first_entry(&ptr->list,
- struct mwifiex_ra_list_tbl,
- list);
- if (ptr ==
- (struct mwifiex_ra_list_tbl *)
- &tid_ptr->ra_list)
- ptr = list_first_entry(
- &ptr->list,
- struct mwifiex_ra_list_tbl,
- list);
- } while (ptr != head);
-
-skip_wmm_queue:
spin_unlock_irqrestore(&priv_tmp->wmm.
ra_list_spinlock,
flags_ra);
}
+ }
-skip_bss:
- /* Get next bss priority node */
- bssprio_node = list_first_entry(&bssprio_node->list,
- struct mwifiex_bss_prio_node,
- list);
-
- if (bssprio_node ==
- (struct mwifiex_bss_prio_node *)
- &adapter->bss_prio_tbl[j].bss_prio_head)
- /* Get next bss priority node */
- bssprio_node = list_first_entry(
- &bssprio_node->list,
- struct mwifiex_bss_prio_node,
- list);
- } while (bssprio_node != bssprio_head);
-
-skip_prio_tbl:
spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock,
flags_bss);
}
@@ -1013,6 +943,42 @@ found:
return ptr;
}
+/* This functions rotates ra and bss lists so packets are picked round robin.
+ *
+ * After a packet is successfully transmitted, rotate the ra list, so the ra
+ * next to the one transmitted, will come first in the list. This way we pick
+ * the ra' in a round robin fashion. Same applies to bss nodes of equal
+ * priority.
+ *
+ * Function also increments wmm.packets_out counter.
+ */
+void mwifiex_rotate_priolists(struct mwifiex_private *priv,
+ struct mwifiex_ra_list_tbl *ra,
+ int tid)
+{
+ struct mwifiex_adapter *adapter = priv->adapter;
+ struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl;
+ struct mwifiex_tid_tbl *tid_ptr = &priv->wmm.tid_tbl_ptr[tid];
+ unsigned long flags;
+
+ spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags);
+ /*
+ * dirty trick: we remove 'head' temporarily and reinsert it after
+ * curr bss node. imagine list to stay fixed while head is moved
+ */
+ list_move(&tbl[priv->bss_priority].bss_prio_head,
+ &tbl[priv->bss_priority].bss_prio_cur->list);
+ spin_unlock_irqrestore(&tbl[priv->bss_priority].bss_prio_lock, flags);
+
+ spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+ if (mwifiex_is_ralist_valid(priv, ra, tid)) {
+ priv->wmm.packets_out[tid]++;
+ /* same as above */
+ list_move(&tid_ptr->ra_list, &ra->list);
+ }
+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+}
+
/*
* This function checks if 11n aggregation is possible.
*/
@@ -1099,20 +1065,8 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
ra_list_flags);
} else {
- spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
- if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
- priv->wmm.packets_out[ptr_index]++;
- priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr;
- }
- adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur =
- list_first_entry(
- &adapter->bss_prio_tbl[priv->bss_priority]
- .bss_prio_cur->list,
- struct mwifiex_bss_prio_node,
- list);
+ mwifiex_rotate_priolists(priv, ptr, ptr_index);
atomic_dec(&priv->wmm.tx_pkts_queued);
- spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
- ra_list_flags);
}
}
@@ -1216,20 +1170,8 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
break;
}
if (ret != -EBUSY) {
- spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
- if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
- priv->wmm.packets_out[ptr_index]++;
- priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr;
- }
- adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur =
- list_first_entry(
- &adapter->bss_prio_tbl[priv->bss_priority]
- .bss_prio_cur->list,
- struct mwifiex_bss_prio_node,
- list);
+ mwifiex_rotate_priolists(priv, ptr, ptr_index);
atomic_dec(&priv->wmm.tx_pkts_queued);
- spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
- ra_list_flags);
}
}
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h
index b92f39d8963b..644d6e0c51cc 100644
--- a/drivers/net/wireless/mwifiex/wmm.h
+++ b/drivers/net/wireless/mwifiex/wmm.h
@@ -85,6 +85,9 @@ mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead)
void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
struct sk_buff *skb);
void mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra);
+void mwifiex_rotate_priolists(struct mwifiex_private *priv,
+ struct mwifiex_ra_list_tbl *ra,
+ int tid);
int mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter);
void mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter);
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 956c1084ebf1..6820fce4016b 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -193,10 +193,10 @@ struct mwl8k_priv {
struct rxd_ops *rxd_ops;
struct ieee80211_supported_band band_24;
struct ieee80211_channel channels_24[14];
- struct ieee80211_rate rates_24[14];
+ struct ieee80211_rate rates_24[13];
struct ieee80211_supported_band band_50;
struct ieee80211_channel channels_50[4];
- struct ieee80211_rate rates_50[9];
+ struct ieee80211_rate rates_50[8];
u32 ap_macids_supported;
u32 sta_macids_supported;
@@ -366,7 +366,6 @@ static const struct ieee80211_rate mwl8k_rates_24[] = {
{ .bitrate = 360, .hw_value = 72, },
{ .bitrate = 480, .hw_value = 96, },
{ .bitrate = 540, .hw_value = 108, },
- { .bitrate = 720, .hw_value = 144, },
};
static const struct ieee80211_channel mwl8k_channels_50[] = {
@@ -385,7 +384,6 @@ static const struct ieee80211_rate mwl8k_rates_50[] = {
{ .bitrate = 360, .hw_value = 72, },
{ .bitrate = 480, .hw_value = 96, },
{ .bitrate = 540, .hw_value = 108, },
- { .bitrate = 720, .hw_value = 144, },
};
/* Set or get info from Firmware */
@@ -2852,7 +2850,9 @@ static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw,
struct ieee80211_conf *conf,
unsigned short pwr)
{
- struct ieee80211_channel *channel = conf->channel;
+ struct ieee80211_channel *channel = conf->chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&conf->chandef);
struct mwl8k_cmd_tx_power *cmd;
int rc;
int i;
@@ -2872,14 +2872,14 @@ static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw,
cmd->channel = cpu_to_le16(channel->hw_value);
- if (conf->channel_type == NL80211_CHAN_NO_HT ||
- conf->channel_type == NL80211_CHAN_HT20) {
+ if (channel_type == NL80211_CHAN_NO_HT ||
+ channel_type == NL80211_CHAN_HT20) {
cmd->bw = cpu_to_le16(0x2);
} else {
cmd->bw = cpu_to_le16(0x4);
- if (conf->channel_type == NL80211_CHAN_HT40MINUS)
+ if (channel_type == NL80211_CHAN_HT40MINUS)
cmd->sub_ch = cpu_to_le16(0x3);
- else if (conf->channel_type == NL80211_CHAN_HT40PLUS)
+ else if (channel_type == NL80211_CHAN_HT40PLUS)
cmd->sub_ch = cpu_to_le16(0x1);
}
@@ -3023,7 +3023,9 @@ struct mwl8k_cmd_set_rf_channel {
static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw,
struct ieee80211_conf *conf)
{
- struct ieee80211_channel *channel = conf->channel;
+ struct ieee80211_channel *channel = conf->chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&conf->chandef);
struct mwl8k_cmd_set_rf_channel *cmd;
int rc;
@@ -3041,12 +3043,12 @@ static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw,
else if (channel->band == IEEE80211_BAND_5GHZ)
cmd->channel_flags |= cpu_to_le32(0x00000004);
- if (conf->channel_type == NL80211_CHAN_NO_HT ||
- conf->channel_type == NL80211_CHAN_HT20)
+ if (channel_type == NL80211_CHAN_NO_HT ||
+ channel_type == NL80211_CHAN_HT20)
cmd->channel_flags |= cpu_to_le32(0x00000080);
- else if (conf->channel_type == NL80211_CHAN_HT40MINUS)
+ else if (channel_type == NL80211_CHAN_HT40MINUS)
cmd->channel_flags |= cpu_to_le32(0x000001900);
- else if (conf->channel_type == NL80211_CHAN_HT40PLUS)
+ else if (channel_type == NL80211_CHAN_HT40PLUS)
cmd->channel_flags |= cpu_to_le32(0x000000900);
rc = mwl8k_post_cmd(hw, &cmd->header);
@@ -3079,11 +3081,11 @@ static void legacy_rate_mask_to_array(u8 *rates, u32 mask)
int j;
/*
- * Clear nonstandard rates 4 and 13.
+ * Clear nonstandard rate 4.
*/
mask &= 0x1fef;
- for (i = 0, j = 0; i < 14; i++) {
+ for (i = 0, j = 0; i < 13; i++) {
if (mask & (1 << i))
rates[j++] = mwl8k_rates_24[i].hw_value;
}
@@ -3965,7 +3967,7 @@ static int mwl8k_cmd_set_new_stn_add(struct ieee80211_hw *hw,
memcpy(cmd->mac_addr, sta->addr, ETH_ALEN);
cmd->stn_id = cpu_to_le16(sta->aid);
cmd->action = cpu_to_le16(MWL8K_STA_ACTION_ADD);
- if (hw->conf.channel->band == IEEE80211_BAND_2GHZ)
+ if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ)
rates = sta->supp_rates[IEEE80211_BAND_2GHZ];
else
rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5;
@@ -4400,7 +4402,7 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw,
p->ht_caps = cpu_to_le16(sta->ht_cap.cap);
p->extended_ht_caps = (sta->ht_cap.ampdu_factor & 3) |
((sta->ht_cap.ampdu_density & 7) << 2);
- if (hw->conf.channel->band == IEEE80211_BAND_2GHZ)
+ if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ)
rates = sta->supp_rates[IEEE80211_BAND_2GHZ];
else
rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5;
@@ -4881,7 +4883,7 @@ mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
goto out;
}
- if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
+ if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) {
ap_legacy_rates = ap->supp_rates[IEEE80211_BAND_2GHZ];
} else {
ap_legacy_rates =
@@ -4913,7 +4915,7 @@ mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (idx)
idx--;
- if (hw->conf.channel->band == IEEE80211_BAND_2GHZ)
+ if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ)
rate = mwl8k_rates_24[idx].hw_value;
else
rate = mwl8k_rates_50[idx].hw_value;
@@ -4986,7 +4988,7 @@ mwl8k_bss_info_changed_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (idx)
idx--;
- if (hw->conf.channel->band == IEEE80211_BAND_2GHZ)
+ if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ)
rate = mwl8k_rates_24[idx].hw_value;
else
rate = mwl8k_rates_50[idx].hw_value;
@@ -5259,7 +5261,7 @@ static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = priv->noise;
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c
index 9ba85106eec0..b3879fbf5368 100644
--- a/drivers/net/wireless/p54/fwio.c
+++ b/drivers/net/wireless/p54/fwio.c
@@ -402,7 +402,7 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
struct p54_rssi_db_entry *rssi_data;
unsigned int i;
void *entry;
- __le16 freq = cpu_to_le16(priv->hw->conf.channel->center_freq);
+ __le16 freq = cpu_to_le16(priv->hw->conf.chandef.chan->center_freq);
skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) +
2 + sizeof(*iq_autocal) + sizeof(*body) +
@@ -532,7 +532,7 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
err:
wiphy_err(priv->hw->wiphy, "frequency change to channel %d failed.\n",
ieee80211_frequency_to_channel(
- priv->hw->conf.channel->center_freq));
+ priv->hw->conf.chandef.chan->center_freq));
dev_kfree_skb_any(skb);
return -EINVAL;
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index ee654a691f38..067e6f2fd050 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -340,7 +340,7 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed)
* TODO: Use the LM_SCAN_TRAP to determine the current
* operating channel.
*/
- priv->curchan = priv->hw->conf.channel;
+ priv->curchan = priv->hw->conf.chandef.chan;
p54_reset_stats(priv);
WARN_ON(p54_fetch_statistics(priv));
}
@@ -480,7 +480,7 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev,
p54_set_edcf(priv);
}
if (changed & BSS_CHANGED_BASIC_RATES) {
- if (dev->conf.channel->band == IEEE80211_BAND_5GHZ)
+ if (dev->conf.chandef.chan->band == IEEE80211_BAND_5GHZ)
priv->basic_rate_mask = (info->basic_rates << 4);
else
priv->basic_rate_mask = info->basic_rates;
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index 12f0a34477f2..f95de0d16216 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -354,13 +354,13 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb)
rx_status->signal = p54_rssi_to_dbm(priv, hdr->rssi);
if (hdr->rate & 0x10)
rx_status->flag |= RX_FLAG_SHORTPRE;
- if (priv->hw->conf.channel->band == IEEE80211_BAND_5GHZ)
+ if (priv->hw->conf.chandef.chan->band == IEEE80211_BAND_5GHZ)
rx_status->rate_idx = (rate < 4) ? 0 : rate - 4;
else
rx_status->rate_idx = rate;
rx_status->freq = freq;
- rx_status->band = priv->hw->conf.channel->band;
+ rx_status->band = priv->hw->conf.chandef.chan->band;
rx_status->antenna = hdr->antenna;
tsf32 = le32_to_cpu(hdr->tsf32);
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index dcfb54e0c516..f7143733d7e9 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -41,7 +41,7 @@
/*
* Register access.
* All access to the CSR registers will go through the methods
- * rt2x00pci_register_read and rt2x00pci_register_write.
+ * rt2x00mmio_register_read and rt2x00mmio_register_write.
* BBP and RF register require indirect register access,
* and use the CSR registers BBPCSR and RFCSR to achieve this.
* These indirect registers work with busy bits,
@@ -52,9 +52,9 @@
* and we will print an error.
*/
#define WAIT_FOR_BBP(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
+ rt2x00mmio_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
#define WAIT_FOR_RF(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
+ rt2x00mmio_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
@@ -74,7 +74,7 @@ static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 1);
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
}
mutex_unlock(&rt2x00dev->csr_mutex);
@@ -101,7 +101,7 @@ static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 0);
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
WAIT_FOR_BBP(rt2x00dev, &reg);
}
@@ -129,7 +129,7 @@ static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, RFCSR_IF_SELECT, 0);
rt2x00_set_field32(&reg, RFCSR_BUSY, 1);
- rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RFCSR, reg);
rt2x00_rf_write(rt2x00dev, word, value);
}
@@ -141,7 +141,7 @@ static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR21, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN);
eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT);
@@ -163,15 +163,15 @@ static void rt2400pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
rt2x00_set_field32(&reg, CSR21_EEPROM_CHIP_SELECT,
!!eeprom->reg_chip_select);
- rt2x00pci_register_write(rt2x00dev, CSR21, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR21, reg);
}
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
static const struct rt2x00debug rt2400pci_rt2x00debug = {
.owner = THIS_MODULE,
.csr = {
- .read = rt2x00pci_register_read,
- .write = rt2x00pci_register_write,
+ .read = rt2x00mmio_register_read,
+ .write = rt2x00mmio_register_write,
.flags = RT2X00DEBUGFS_OFFSET,
.word_base = CSR_REG_BASE,
.word_size = sizeof(u32),
@@ -205,7 +205,7 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
return rt2x00_get_field32(reg, GPIOCSR_VAL0);
}
@@ -218,14 +218,14 @@ static void rt2400pci_brightness_set(struct led_classdev *led_cdev,
unsigned int enabled = brightness != LED_OFF;
u32 reg;
- rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
+ rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
else if (led->type == LED_TYPE_ACTIVITY)
rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, enabled);
- rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
+ rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
}
static int rt2400pci_blink_set(struct led_classdev *led_cdev,
@@ -236,10 +236,10 @@ static int rt2400pci_blink_set(struct led_classdev *led_cdev,
container_of(led_cdev, struct rt2x00_led, led_dev);
u32 reg;
- rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
+ rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
- rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
+ rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
return 0;
}
@@ -269,7 +269,7 @@ static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,
* Note that the version error will always be dropped
* since there is no filter for it at this time.
*/
- rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
@@ -282,7 +282,7 @@ static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,
!(filter_flags & FIF_PROMISC_IN_BSS) &&
!rt2x00dev->intf_ap_count);
rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
}
static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
@@ -298,25 +298,26 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
* Enable beacon config
*/
bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
- rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, BCNCSR1, &reg);
rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
- rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg);
/*
* Enable synchronisation.
*/
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
}
if (flags & CONFIG_UPDATE_MAC)
- rt2x00pci_register_multiwrite(rt2x00dev, CSR3,
- conf->mac, sizeof(conf->mac));
+ rt2x00mmio_register_multiwrite(rt2x00dev, CSR3,
+ conf->mac, sizeof(conf->mac));
if (flags & CONFIG_UPDATE_BSSID)
- rt2x00pci_register_multiwrite(rt2x00dev, CSR5,
- conf->bssid, sizeof(conf->bssid));
+ rt2x00mmio_register_multiwrite(rt2x00dev, CSR5,
+ conf->bssid,
+ sizeof(conf->bssid));
}
static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
@@ -332,68 +333,68 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
preamble_mask = erp->short_preamble << 3;
- rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR1, &reg);
rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x1ff);
rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0x13a);
rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR2, &reg);
rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 10));
- rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR3, &reg);
rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 20));
- rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR4, &reg);
rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 55));
- rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR5, &reg);
rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 110));
- rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR5, reg);
}
if (changed & BSS_CHANGED_BASIC_RATES)
- rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
if (changed & BSS_CHANGED_ERP_SLOT) {
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
- rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR18, &reg);
rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
- rt2x00pci_register_write(rt2x00dev, CSR18, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR18, reg);
- rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR19, &reg);
rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
- rt2x00pci_register_write(rt2x00dev, CSR19, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR19, reg);
}
if (changed & BSS_CHANGED_BEACON_INT) {
- rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR12, &reg);
rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
erp->beacon_int * 16);
rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
erp->beacon_int * 16);
- rt2x00pci_register_write(rt2x00dev, CSR12, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR12, reg);
}
}
@@ -497,7 +498,7 @@ static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
/*
* Clear false CRC during channel switch.
*/
- rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1);
+ rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1);
}
static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower)
@@ -510,12 +511,12 @@ static void rt2400pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
libconf->conf->long_frame_max_tx_count);
rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
libconf->conf->short_frame_max_tx_count);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
}
static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
@@ -527,7 +528,7 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
u32 reg;
if (state == STATE_SLEEP) {
- rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
(rt2x00dev->beacon_int - 20) * 16);
rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
@@ -535,14 +536,14 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
/* We must first disable autowake before it can be enabled */
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
- rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
- rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
} else {
- rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
- rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
}
rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
@@ -568,10 +569,10 @@ static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
rt2x00_set_field32(&reg, CSR11_CWMIN, cw_min);
rt2x00_set_field32(&reg, CSR11_CWMAX, cw_max);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
}
/*
@@ -586,7 +587,7 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
/*
* Update FCS error count from register.
*/
- rt2x00pci_register_read(rt2x00dev, CNT0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
/*
@@ -641,16 +642,16 @@ static void rt2400pci_start_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
rt2x00_set_field32(&reg, CSR14_TBCN, 1);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
break;
default:
break;
@@ -664,19 +665,19 @@ static void rt2400pci_kick_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_AC_VO:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_AC_VI:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_ATIM:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
default:
break;
@@ -692,21 +693,21 @@ static void rt2400pci_stop_queue(struct data_queue *queue)
case QID_AC_VO:
case QID_AC_VI:
case QID_ATIM:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(&reg, CSR14_TBCN, 0);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
/*
* Wait for possibly running tbtt tasklets.
@@ -723,7 +724,7 @@ static void rt2400pci_stop_queue(struct data_queue *queue)
*/
static bool rt2400pci_get_entry_state(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
u32 word;
if (entry->queue->qid == QID_RX) {
@@ -740,7 +741,7 @@ static bool rt2400pci_get_entry_state(struct queue_entry *entry)
static void rt2400pci_clear_entry(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
u32 word;
@@ -766,53 +767,53 @@ static void rt2400pci_clear_entry(struct queue_entry *entry)
static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
{
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
u32 reg;
/*
* Initialize registers.
*/
- rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR2, &reg);
rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
- rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg);
entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR3, &reg);
rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg);
entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR5, &reg);
rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg);
entry_priv = rt2x00dev->atim->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR4, &reg);
rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg);
entry_priv = rt2x00dev->bcn->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR6, &reg);
rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg);
- rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR1, &reg);
rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
- rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg);
entry_priv = rt2x00dev->rx->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR2, &reg);
rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg);
return 0;
}
@@ -821,23 +822,23 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002);
- rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002);
- rt2x00pci_register_write(rt2x00dev, PSCSR2, 0x00023f20);
- rt2x00pci_register_write(rt2x00dev, PSCSR3, 0x00000002);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR0, 0x00020002);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR1, 0x00000002);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00023f20);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002);
- rt2x00pci_register_read(rt2x00dev, TIMECSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TIMECSR, &reg);
rt2x00_set_field32(&reg, TIMECSR_US_COUNT, 33);
rt2x00_set_field32(&reg, TIMECSR_US_64_COUNT, 63);
rt2x00_set_field32(&reg, TIMECSR_BEACON_EXPECT, 0);
- rt2x00pci_register_write(rt2x00dev, TIMECSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg);
- rt2x00pci_register_read(rt2x00dev, CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR9, &reg);
rt2x00_set_field32(&reg, CSR9_MAX_FRAME_UNIT,
(rt2x00dev->rx->data_size / 128));
- rt2x00pci_register_write(rt2x00dev, CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR9, reg);
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
rt2x00_set_field32(&reg, CSR14_TBCN, 0);
@@ -846,63 +847,63 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00_set_field32(&reg, CSR14_CFP_COUNT_PRELOAD, 0);
rt2x00_set_field32(&reg, CSR14_TBCM_PRELOAD, 0);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
- rt2x00pci_register_write(rt2x00dev, CNT3, 0x3f080000);
+ rt2x00mmio_register_write(rt2x00dev, CNT3, 0x3f080000);
- rt2x00pci_register_read(rt2x00dev, ARCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR0, &reg);
rt2x00_set_field32(&reg, ARCSR0_AR_BBP_DATA0, 133);
rt2x00_set_field32(&reg, ARCSR0_AR_BBP_ID0, 134);
rt2x00_set_field32(&reg, ARCSR0_AR_BBP_DATA1, 136);
rt2x00_set_field32(&reg, ARCSR0_AR_BBP_ID1, 135);
- rt2x00pci_register_write(rt2x00dev, ARCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR0, reg);
- rt2x00pci_register_read(rt2x00dev, RXCSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR3, &reg);
rt2x00_set_field32(&reg, RXCSR3_BBP_ID0, 3); /* Tx power.*/
rt2x00_set_field32(&reg, RXCSR3_BBP_ID0_VALID, 1);
rt2x00_set_field32(&reg, RXCSR3_BBP_ID1, 32); /* Signal */
rt2x00_set_field32(&reg, RXCSR3_BBP_ID1_VALID, 1);
rt2x00_set_field32(&reg, RXCSR3_BBP_ID2, 36); /* Rssi */
rt2x00_set_field32(&reg, RXCSR3_BBP_ID2_VALID, 1);
- rt2x00pci_register_write(rt2x00dev, RXCSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR3, reg);
- rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
return -EBUSY;
- rt2x00pci_register_write(rt2x00dev, MACCSR0, 0x00217223);
- rt2x00pci_register_write(rt2x00dev, MACCSR1, 0x00235518);
+ rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00217223);
+ rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518);
- rt2x00pci_register_read(rt2x00dev, MACCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MACCSR2, &reg);
rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
- rt2x00pci_register_write(rt2x00dev, MACCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg);
- rt2x00pci_register_read(rt2x00dev, RALINKCSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RALINKCSR, &reg);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA0, 17);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID0, 154);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA1, 0);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID1, 154);
- rt2x00pci_register_write(rt2x00dev, RALINKCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RALINKCSR, reg);
- rt2x00pci_register_read(rt2x00dev, CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 1);
rt2x00_set_field32(&reg, CSR1_BBP_RESET, 0);
rt2x00_set_field32(&reg, CSR1_HOST_READY, 0);
- rt2x00pci_register_write(rt2x00dev, CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
- rt2x00pci_register_read(rt2x00dev, CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 0);
rt2x00_set_field32(&reg, CSR1_HOST_READY, 1);
- rt2x00pci_register_write(rt2x00dev, CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
/*
* We must clear the FCS and FIFO error count.
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
*/
- rt2x00pci_register_read(rt2x00dev, CNT0, &reg);
- rt2x00pci_register_read(rt2x00dev, CNT4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CNT4, &reg);
return 0;
}
@@ -919,7 +920,7 @@ static int rt2400pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
+ rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
return -EACCES;
}
@@ -976,8 +977,8 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
* should clear the register to assure a clean state.
*/
if (state == STATE_RADIO_IRQ_ON) {
- rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
- rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
}
/*
@@ -986,13 +987,13 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, mask);
rt2x00_set_field32(&reg, CSR8_RXDONE, mask);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
@@ -1025,7 +1026,7 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Disable power
*/
- rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0);
}
static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
@@ -1039,12 +1040,12 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
put_to_sleep = (state != STATE_AWAKE);
- rt2x00pci_register_read(rt2x00dev, PWRCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg);
rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, state);
rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, state);
rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, put_to_sleep);
- rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
/*
* Device is not guaranteed to be in the requested state yet.
@@ -1052,12 +1053,12 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
* device has entered the correct state.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, PWRCSR1, &reg2);
+ rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg2);
bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);
rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);
if (bbp_state == state && rf_state == state)
return 0;
- rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
msleep(10);
}
@@ -1092,8 +1093,8 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
}
if (unlikely(retval))
- ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
- state, retval);
+ rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+ state, retval);
return retval;
}
@@ -1105,7 +1106,7 @@ static void rt2400pci_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
__le32 *txd = entry_priv->desc;
u32 word;
@@ -1182,12 +1183,12 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
if (rt2x00queue_map_txskb(entry)) {
- ERROR(rt2x00dev, "Fail to map beacon, aborting\n");
+ rt2x00_err(rt2x00dev, "Fail to map beacon, aborting\n");
goto out;
}
/*
@@ -1208,7 +1209,7 @@ out:
* Enable beaconing again.
*/
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
}
/*
@@ -1218,7 +1219,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
u32 word0;
u32 word2;
u32 word3;
@@ -1276,7 +1277,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
const enum data_queue_qid queue_idx)
{
struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
struct queue_entry *entry;
struct txdone_entry_desc txdesc;
u32 word;
@@ -1322,9 +1323,9 @@ static inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
rt2x00_set_field32(&reg, irq_field, 0);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
@@ -1347,11 +1348,11 @@ static void rt2400pci_txstatus_tasklet(unsigned long data)
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
@@ -1368,7 +1369,7 @@ static void rt2400pci_tbtt_tasklet(unsigned long data)
static void rt2400pci_rxdone_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- if (rt2x00pci_rxdone(rt2x00dev))
+ if (rt2x00mmio_rxdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->rxdone_tasklet);
else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
@@ -1383,8 +1384,8 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
* Get the interrupt sources & saved to local variable.
* Write register value back to clear pending interrupts.
*/
- rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
- rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
if (!reg)
return IRQ_NONE;
@@ -1421,9 +1422,9 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
*/
spin_lock(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
reg |= mask;
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock(&rt2x00dev->irqmask_lock);
@@ -1442,7 +1443,7 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
u16 word;
u8 *mac;
- rt2x00pci_register_read(rt2x00dev, CSR21, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
eeprom.data = rt2x00dev;
eeprom.register_read = rt2400pci_eepromregister_read;
@@ -1463,12 +1464,12 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
eth_random_addr(mac);
- EEPROM(rt2x00dev, "MAC: %pM\n", mac);
+ rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
- ERROR(rt2x00dev, "Invalid EEPROM data detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid EEPROM data detected\n");
return -EINVAL;
}
@@ -1490,12 +1491,12 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Identify RF chipset.
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
- rt2x00pci_register_read(rt2x00dev, CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR0, &reg);
rt2x00_set_chip(rt2x00dev, RT2460, value,
rt2x00_get_field32(reg, CSR0_REVISION));
if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) {
- ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
return -ENODEV;
}
@@ -1635,9 +1636,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
- rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
- rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg);
/*
* Initialize hw specifications.
@@ -1697,9 +1698,9 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw,
u64 tsf;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR17, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR17, &reg);
tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32;
- rt2x00pci_register_read(rt2x00dev, CSR16, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR16, &reg);
tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER);
return tsf;
@@ -1710,7 +1711,7 @@ static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)
struct rt2x00_dev *rt2x00dev = hw->priv;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR15, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR15, &reg);
return rt2x00_get_field32(reg, CSR15_BEACON_SENT);
}
@@ -1743,8 +1744,8 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.tbtt_tasklet = rt2400pci_tbtt_tasklet,
.rxdone_tasklet = rt2400pci_rxdone_tasklet,
.probe_hw = rt2400pci_probe_hw,
- .initialize = rt2x00pci_initialize,
- .uninitialize = rt2x00pci_uninitialize,
+ .initialize = rt2x00mmio_initialize,
+ .uninitialize = rt2x00mmio_uninitialize,
.get_entry_state = rt2400pci_get_entry_state,
.clear_entry = rt2400pci_clear_entry,
.set_device_state = rt2400pci_set_device_state,
@@ -1755,7 +1756,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.start_queue = rt2400pci_start_queue,
.kick_queue = rt2400pci_kick_queue,
.stop_queue = rt2400pci_stop_queue,
- .flush_queue = rt2x00pci_flush_queue,
+ .flush_queue = rt2x00mmio_flush_queue,
.write_tx_desc = rt2400pci_write_tx_desc,
.write_beacon = rt2400pci_write_beacon,
.fill_rxdone = rt2400pci_fill_rxdone,
@@ -1770,28 +1771,28 @@ static const struct data_queue_desc rt2400pci_queue_rx = {
.entry_num = 24,
.data_size = DATA_FRAME_SIZE,
.desc_size = RXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2400pci_queue_tx = {
.entry_num = 24,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2400pci_queue_bcn = {
.entry_num = 1,
.data_size = MGMT_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2400pci_queue_atim = {
.entry_num = 8,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct rt2x00_ops rt2400pci_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index e1d2dc9ed28a..77e45b223d15 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -41,7 +41,7 @@
/*
* Register access.
* All access to the CSR registers will go through the methods
- * rt2x00pci_register_read and rt2x00pci_register_write.
+ * rt2x00mmio_register_read and rt2x00mmio_register_write.
* BBP and RF register require indirect register access,
* and use the CSR registers BBPCSR and RFCSR to achieve this.
* These indirect registers work with busy bits,
@@ -52,9 +52,9 @@
* and we will print an error.
*/
#define WAIT_FOR_BBP(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
+ rt2x00mmio_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
#define WAIT_FOR_RF(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
+ rt2x00mmio_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
@@ -74,7 +74,7 @@ static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 1);
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
}
mutex_unlock(&rt2x00dev->csr_mutex);
@@ -101,7 +101,7 @@ static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 0);
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
WAIT_FOR_BBP(rt2x00dev, &reg);
}
@@ -129,7 +129,7 @@ static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, RFCSR_IF_SELECT, 0);
rt2x00_set_field32(&reg, RFCSR_BUSY, 1);
- rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RFCSR, reg);
rt2x00_rf_write(rt2x00dev, word, value);
}
@@ -141,7 +141,7 @@ static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR21, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN);
eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT);
@@ -163,15 +163,15 @@ static void rt2500pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
rt2x00_set_field32(&reg, CSR21_EEPROM_CHIP_SELECT,
!!eeprom->reg_chip_select);
- rt2x00pci_register_write(rt2x00dev, CSR21, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR21, reg);
}
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
static const struct rt2x00debug rt2500pci_rt2x00debug = {
.owner = THIS_MODULE,
.csr = {
- .read = rt2x00pci_register_read,
- .write = rt2x00pci_register_write,
+ .read = rt2x00mmio_register_read,
+ .write = rt2x00mmio_register_write,
.flags = RT2X00DEBUGFS_OFFSET,
.word_base = CSR_REG_BASE,
.word_size = sizeof(u32),
@@ -205,7 +205,7 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
return rt2x00_get_field32(reg, GPIOCSR_VAL0);
}
@@ -218,14 +218,14 @@ static void rt2500pci_brightness_set(struct led_classdev *led_cdev,
unsigned int enabled = brightness != LED_OFF;
u32 reg;
- rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
+ rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
else if (led->type == LED_TYPE_ACTIVITY)
rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, enabled);
- rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
+ rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
}
static int rt2500pci_blink_set(struct led_classdev *led_cdev,
@@ -236,10 +236,10 @@ static int rt2500pci_blink_set(struct led_classdev *led_cdev,
container_of(led_cdev, struct rt2x00_led, led_dev);
u32 reg;
- rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
+ rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
- rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
+ rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
return 0;
}
@@ -270,7 +270,7 @@ static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev,
* and broadcast frames will always be accepted since
* there is no filter for it at this time.
*/
- rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
@@ -286,7 +286,7 @@ static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, RXCSR0_DROP_MCAST,
!(filter_flags & FIF_ALLMULTI));
rt2x00_set_field32(&reg, RXCSR0_DROP_BCAST, 0);
- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
}
static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
@@ -303,25 +303,25 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
* Enable beacon config
*/
bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
- rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, BCNCSR1, &reg);
rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
rt2x00_set_field32(&reg, BCNCSR1_BEACON_CWMIN, queue->cw_min);
- rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg);
/*
* Enable synchronisation.
*/
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
}
if (flags & CONFIG_UPDATE_MAC)
- rt2x00pci_register_multiwrite(rt2x00dev, CSR3,
+ rt2x00mmio_register_multiwrite(rt2x00dev, CSR3,
conf->mac, sizeof(conf->mac));
if (flags & CONFIG_UPDATE_BSSID)
- rt2x00pci_register_multiwrite(rt2x00dev, CSR5,
+ rt2x00mmio_register_multiwrite(rt2x00dev, CSR5,
conf->bssid, sizeof(conf->bssid));
}
@@ -338,68 +338,68 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
preamble_mask = erp->short_preamble << 3;
- rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR1, &reg);
rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x162);
rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0xa2);
rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR2, &reg);
rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 10));
- rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR3, &reg);
rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 20));
- rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR4, &reg);
rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 55));
- rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR5, &reg);
rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 110));
- rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR5, reg);
}
if (changed & BSS_CHANGED_BASIC_RATES)
- rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
if (changed & BSS_CHANGED_ERP_SLOT) {
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
- rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR18, &reg);
rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
- rt2x00pci_register_write(rt2x00dev, CSR18, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR18, reg);
- rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR19, &reg);
rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
- rt2x00pci_register_write(rt2x00dev, CSR19, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR19, reg);
}
if (changed & BSS_CHANGED_BEACON_INT) {
- rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR12, &reg);
rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
erp->beacon_int * 16);
rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
erp->beacon_int * 16);
- rt2x00pci_register_write(rt2x00dev, CSR12, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR12, reg);
}
}
@@ -418,7 +418,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
ant->tx == ANTENNA_SW_DIVERSITY);
- rt2x00pci_register_read(rt2x00dev, BBPCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, BBPCSR1, &reg);
rt2500pci_bbp_read(rt2x00dev, 14, &r14);
rt2500pci_bbp_read(rt2x00dev, 2, &r2);
@@ -470,7 +470,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, BBPCSR1_OFDM_FLIP, 0);
}
- rt2x00pci_register_write(rt2x00dev, BBPCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, BBPCSR1, reg);
rt2500pci_bbp_write(rt2x00dev, 14, r14);
rt2500pci_bbp_write(rt2x00dev, 2, r2);
}
@@ -541,7 +541,7 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
/*
* Clear false CRC during channel switch.
*/
- rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1);
+ rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1);
}
static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev,
@@ -559,12 +559,12 @@ static void rt2500pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
libconf->conf->long_frame_max_tx_count);
rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
libconf->conf->short_frame_max_tx_count);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
}
static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
@@ -576,7 +576,7 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
u32 reg;
if (state == STATE_SLEEP) {
- rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
(rt2x00dev->beacon_int - 20) * 16);
rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
@@ -584,14 +584,14 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
/* We must first disable autowake before it can be enabled */
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
- rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
- rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
} else {
- rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
- rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
}
rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
@@ -625,13 +625,13 @@ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev,
/*
* Update FCS error count from register.
*/
- rt2x00pci_register_read(rt2x00dev, CNT0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
- rt2x00pci_register_read(rt2x00dev, CNT3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CNT3, &reg);
qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA);
}
@@ -731,16 +731,16 @@ static void rt2500pci_start_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
rt2x00_set_field32(&reg, CSR14_TBCN, 1);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
break;
default:
break;
@@ -754,19 +754,19 @@ static void rt2500pci_kick_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_AC_VO:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_AC_VI:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_ATIM:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
default:
break;
@@ -782,21 +782,21 @@ static void rt2500pci_stop_queue(struct data_queue *queue)
case QID_AC_VO:
case QID_AC_VI:
case QID_ATIM:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(&reg, CSR14_TBCN, 0);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
/*
* Wait for possibly running tbtt tasklets.
@@ -813,7 +813,7 @@ static void rt2500pci_stop_queue(struct data_queue *queue)
*/
static bool rt2500pci_get_entry_state(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
u32 word;
if (entry->queue->qid == QID_RX) {
@@ -830,7 +830,7 @@ static bool rt2500pci_get_entry_state(struct queue_entry *entry)
static void rt2500pci_clear_entry(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
u32 word;
@@ -852,53 +852,53 @@ static void rt2500pci_clear_entry(struct queue_entry *entry)
static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
{
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
u32 reg;
/*
* Initialize registers.
*/
- rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR2, &reg);
rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
- rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg);
entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR3, &reg);
rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg);
entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR5, &reg);
rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg);
entry_priv = rt2x00dev->atim->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR4, &reg);
rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg);
entry_priv = rt2x00dev->bcn->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR6, &reg);
rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg);
- rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR1, &reg);
rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
- rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg);
entry_priv = rt2x00dev->rx->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR2, &reg);
rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg);
return 0;
}
@@ -907,30 +907,30 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002);
- rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002);
- rt2x00pci_register_write(rt2x00dev, PSCSR2, 0x00020002);
- rt2x00pci_register_write(rt2x00dev, PSCSR3, 0x00000002);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR0, 0x00020002);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR1, 0x00000002);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00020002);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002);
- rt2x00pci_register_read(rt2x00dev, TIMECSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TIMECSR, &reg);
rt2x00_set_field32(&reg, TIMECSR_US_COUNT, 33);
rt2x00_set_field32(&reg, TIMECSR_US_64_COUNT, 63);
rt2x00_set_field32(&reg, TIMECSR_BEACON_EXPECT, 0);
- rt2x00pci_register_write(rt2x00dev, TIMECSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg);
- rt2x00pci_register_read(rt2x00dev, CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR9, &reg);
rt2x00_set_field32(&reg, CSR9_MAX_FRAME_UNIT,
rt2x00dev->rx->data_size / 128);
- rt2x00pci_register_write(rt2x00dev, CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR9, reg);
/*
* Always use CWmin and CWmax set in descriptor.
*/
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
rt2x00_set_field32(&reg, CSR11_CW_SELECT, 0);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
rt2x00_set_field32(&reg, CSR14_TBCN, 0);
@@ -939,11 +939,11 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00_set_field32(&reg, CSR14_CFP_COUNT_PRELOAD, 0);
rt2x00_set_field32(&reg, CSR14_TBCM_PRELOAD, 0);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
- rt2x00pci_register_write(rt2x00dev, CNT3, 0);
+ rt2x00mmio_register_write(rt2x00dev, CNT3, 0);
- rt2x00pci_register_read(rt2x00dev, TXCSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR8, &reg);
rt2x00_set_field32(&reg, TXCSR8_BBP_ID0, 10);
rt2x00_set_field32(&reg, TXCSR8_BBP_ID0_VALID, 1);
rt2x00_set_field32(&reg, TXCSR8_BBP_ID1, 11);
@@ -952,30 +952,30 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, TXCSR8_BBP_ID2_VALID, 1);
rt2x00_set_field32(&reg, TXCSR8_BBP_ID3, 12);
rt2x00_set_field32(&reg, TXCSR8_BBP_ID3_VALID, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR8, reg);
- rt2x00pci_register_read(rt2x00dev, ARTCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARTCSR0, &reg);
rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_1MBS, 112);
rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_2MBS, 56);
rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_5_5MBS, 20);
rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_11MBS, 10);
- rt2x00pci_register_write(rt2x00dev, ARTCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARTCSR0, reg);
- rt2x00pci_register_read(rt2x00dev, ARTCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARTCSR1, &reg);
rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_6MBS, 45);
rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_9MBS, 37);
rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_12MBS, 33);
rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_18MBS, 29);
- rt2x00pci_register_write(rt2x00dev, ARTCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARTCSR1, reg);
- rt2x00pci_register_read(rt2x00dev, ARTCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARTCSR2, &reg);
rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_24MBS, 29);
rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_36MBS, 25);
rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_48MBS, 25);
rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_54MBS, 25);
- rt2x00pci_register_write(rt2x00dev, ARTCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARTCSR2, reg);
- rt2x00pci_register_read(rt2x00dev, RXCSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR3, &reg);
rt2x00_set_field32(&reg, RXCSR3_BBP_ID0, 47); /* CCK Signal */
rt2x00_set_field32(&reg, RXCSR3_BBP_ID0_VALID, 1);
rt2x00_set_field32(&reg, RXCSR3_BBP_ID1, 51); /* Rssi */
@@ -984,9 +984,9 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, RXCSR3_BBP_ID2_VALID, 1);
rt2x00_set_field32(&reg, RXCSR3_BBP_ID3, 51); /* RSSI */
rt2x00_set_field32(&reg, RXCSR3_BBP_ID3_VALID, 1);
- rt2x00pci_register_write(rt2x00dev, RXCSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR3, reg);
- rt2x00pci_register_read(rt2x00dev, PCICSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, PCICSR, &reg);
rt2x00_set_field32(&reg, PCICSR_BIG_ENDIAN, 0);
rt2x00_set_field32(&reg, PCICSR_RX_TRESHOLD, 0);
rt2x00_set_field32(&reg, PCICSR_TX_TRESHOLD, 3);
@@ -994,54 +994,54 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, PCICSR_ENABLE_CLK, 1);
rt2x00_set_field32(&reg, PCICSR_READ_MULTIPLE, 1);
rt2x00_set_field32(&reg, PCICSR_WRITE_INVALID, 1);
- rt2x00pci_register_write(rt2x00dev, PCICSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, PCICSR, reg);
- rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
- rt2x00pci_register_write(rt2x00dev, GPIOCSR, 0x0000ff00);
- rt2x00pci_register_write(rt2x00dev, TESTCSR, 0x000000f0);
+ rt2x00mmio_register_write(rt2x00dev, GPIOCSR, 0x0000ff00);
+ rt2x00mmio_register_write(rt2x00dev, TESTCSR, 0x000000f0);
if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
return -EBUSY;
- rt2x00pci_register_write(rt2x00dev, MACCSR0, 0x00213223);
- rt2x00pci_register_write(rt2x00dev, MACCSR1, 0x00235518);
+ rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00213223);
+ rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518);
- rt2x00pci_register_read(rt2x00dev, MACCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MACCSR2, &reg);
rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
- rt2x00pci_register_write(rt2x00dev, MACCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg);
- rt2x00pci_register_read(rt2x00dev, RALINKCSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RALINKCSR, &reg);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA0, 17);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID0, 26);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_VALID0, 1);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA1, 0);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID1, 26);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_VALID1, 1);
- rt2x00pci_register_write(rt2x00dev, RALINKCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RALINKCSR, reg);
- rt2x00pci_register_write(rt2x00dev, BBPCSR1, 0x82188200);
+ rt2x00mmio_register_write(rt2x00dev, BBPCSR1, 0x82188200);
- rt2x00pci_register_write(rt2x00dev, TXACKCSR0, 0x00000020);
+ rt2x00mmio_register_write(rt2x00dev, TXACKCSR0, 0x00000020);
- rt2x00pci_register_read(rt2x00dev, CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 1);
rt2x00_set_field32(&reg, CSR1_BBP_RESET, 0);
rt2x00_set_field32(&reg, CSR1_HOST_READY, 0);
- rt2x00pci_register_write(rt2x00dev, CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
- rt2x00pci_register_read(rt2x00dev, CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 0);
rt2x00_set_field32(&reg, CSR1_HOST_READY, 1);
- rt2x00pci_register_write(rt2x00dev, CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
/*
* We must clear the FCS and FIFO error count.
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
*/
- rt2x00pci_register_read(rt2x00dev, CNT0, &reg);
- rt2x00pci_register_read(rt2x00dev, CNT4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CNT4, &reg);
return 0;
}
@@ -1058,7 +1058,7 @@ static int rt2500pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
+ rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
return -EACCES;
}
@@ -1131,8 +1131,8 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
* should clear the register to assure a clean state.
*/
if (state == STATE_RADIO_IRQ_ON) {
- rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
- rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
}
/*
@@ -1141,13 +1141,13 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, mask);
rt2x00_set_field32(&reg, CSR8_RXDONE, mask);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
@@ -1179,7 +1179,7 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Disable power
*/
- rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0);
}
static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
@@ -1193,12 +1193,12 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
put_to_sleep = (state != STATE_AWAKE);
- rt2x00pci_register_read(rt2x00dev, PWRCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg);
rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, state);
rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, state);
rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, put_to_sleep);
- rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
/*
* Device is not guaranteed to be in the requested state yet.
@@ -1206,12 +1206,12 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
* device has entered the correct state.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, PWRCSR1, &reg2);
+ rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg2);
bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);
rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);
if (bbp_state == state && rf_state == state)
return 0;
- rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
msleep(10);
}
@@ -1246,8 +1246,8 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
}
if (unlikely(retval))
- ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
- state, retval);
+ rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+ state, retval);
return retval;
}
@@ -1259,7 +1259,7 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
__le32 *txd = entry_priv->desc;
u32 word;
@@ -1335,12 +1335,12 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
if (rt2x00queue_map_txskb(entry)) {
- ERROR(rt2x00dev, "Fail to map beacon, aborting\n");
+ rt2x00_err(rt2x00dev, "Fail to map beacon, aborting\n");
goto out;
}
@@ -1358,7 +1358,7 @@ out:
* Enable beaconing again.
*/
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
}
/*
@@ -1367,7 +1367,7 @@ out:
static void rt2500pci_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
u32 word0;
u32 word2;
@@ -1405,7 +1405,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
const enum data_queue_qid queue_idx)
{
struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
struct queue_entry *entry;
struct txdone_entry_desc txdesc;
u32 word;
@@ -1451,9 +1451,9 @@ static inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
rt2x00_set_field32(&reg, irq_field, 0);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
@@ -1476,11 +1476,11 @@ static void rt2500pci_txstatus_tasklet(unsigned long data)
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
@@ -1497,7 +1497,7 @@ static void rt2500pci_tbtt_tasklet(unsigned long data)
static void rt2500pci_rxdone_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- if (rt2x00pci_rxdone(rt2x00dev))
+ if (rt2x00mmio_rxdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->rxdone_tasklet);
else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
@@ -1512,8 +1512,8 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
* Get the interrupt sources & saved to local variable.
* Write register value back to clear pending interrupts.
*/
- rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
- rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
if (!reg)
return IRQ_NONE;
@@ -1550,9 +1550,9 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
*/
spin_lock(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
reg |= mask;
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock(&rt2x00dev->irqmask_lock);
@@ -1569,7 +1569,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
u16 word;
u8 *mac;
- rt2x00pci_register_read(rt2x00dev, CSR21, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
eeprom.data = rt2x00dev;
eeprom.register_read = rt2500pci_eepromregister_read;
@@ -1590,7 +1590,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
eth_random_addr(mac);
- EEPROM(rt2x00dev, "MAC: %pM\n", mac);
+ rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -1606,7 +1606,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522);
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
- EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
@@ -1615,7 +1615,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
- EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
@@ -1623,7 +1623,8 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
DEFAULT_RSSI_OFFSET);
rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word);
- EEPROM(rt2x00dev, "Calibrate offset: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Calibrate offset: 0x%04x\n",
+ word);
}
return 0;
@@ -1644,7 +1645,7 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Identify RF chipset.
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
- rt2x00pci_register_read(rt2x00dev, CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR0, &reg);
rt2x00_set_chip(rt2x00dev, RT2560, value,
rt2x00_get_field32(reg, CSR0_REVISION));
@@ -1654,7 +1655,7 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
!rt2x00_rf(rt2x00dev, RF2525) &&
!rt2x00_rf(rt2x00dev, RF2525E) &&
!rt2x00_rf(rt2x00dev, RF5222)) {
- ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
return -ENODEV;
}
@@ -1950,9 +1951,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
- rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
- rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg);
/*
* Initialize hw specifications.
@@ -1986,9 +1987,9 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw,
u64 tsf;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR17, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR17, &reg);
tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32;
- rt2x00pci_register_read(rt2x00dev, CSR16, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR16, &reg);
tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER);
return tsf;
@@ -1999,7 +2000,7 @@ static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)
struct rt2x00_dev *rt2x00dev = hw->priv;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR15, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR15, &reg);
return rt2x00_get_field32(reg, CSR15_BEACON_SENT);
}
@@ -2032,8 +2033,8 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.tbtt_tasklet = rt2500pci_tbtt_tasklet,
.rxdone_tasklet = rt2500pci_rxdone_tasklet,
.probe_hw = rt2500pci_probe_hw,
- .initialize = rt2x00pci_initialize,
- .uninitialize = rt2x00pci_uninitialize,
+ .initialize = rt2x00mmio_initialize,
+ .uninitialize = rt2x00mmio_uninitialize,
.get_entry_state = rt2500pci_get_entry_state,
.clear_entry = rt2500pci_clear_entry,
.set_device_state = rt2500pci_set_device_state,
@@ -2044,7 +2045,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.start_queue = rt2500pci_start_queue,
.kick_queue = rt2500pci_kick_queue,
.stop_queue = rt2500pci_stop_queue,
- .flush_queue = rt2x00pci_flush_queue,
+ .flush_queue = rt2x00mmio_flush_queue,
.write_tx_desc = rt2500pci_write_tx_desc,
.write_beacon = rt2500pci_write_beacon,
.fill_rxdone = rt2500pci_fill_rxdone,
@@ -2059,28 +2060,28 @@ static const struct data_queue_desc rt2500pci_queue_rx = {
.entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = RXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2500pci_queue_tx = {
.entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2500pci_queue_bcn = {
.entry_num = 1,
.data_size = MGMT_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2500pci_queue_atim = {
.entry_num = 8,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct rt2x00_ops rt2500pci_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 6b2e1e431dd2..a7f7b365eff4 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -134,8 +134,8 @@ static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "Indirect register access failed: "
- "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
+ rt2x00_err(rt2x00dev, "Indirect register access failed: offset=0x%.08x, value=0x%.08x\n",
+ offset, *reg);
*reg = ~0;
return 0;
@@ -916,7 +916,7 @@ static int rt2500usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
+ rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
return -EACCES;
}
@@ -1069,8 +1069,8 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
}
if (unlikely(retval))
- ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
- state, retval);
+ rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+ state, retval);
return retval;
}
@@ -1353,7 +1353,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
eth_random_addr(mac);
- EEPROM(rt2x00dev, "MAC: %pM\n", mac);
+ rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -1369,7 +1369,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522);
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
- EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
@@ -1378,7 +1378,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
- EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
@@ -1386,14 +1386,15 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
DEFAULT_RSSI_OFFSET);
rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word);
- EEPROM(rt2x00dev, "Calibrate offset: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Calibrate offset: 0x%04x\n",
+ word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE, &word);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_BBPTUNE_THRESHOLD, 45);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE, word);
- EEPROM(rt2x00dev, "BBPtune: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "BBPtune: 0x%04x\n", word);
}
/*
@@ -1408,7 +1409,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
- EEPROM(rt2x00dev, "BBPtune vgc: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "BBPtune vgc: 0x%04x\n", word);
} else {
rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
@@ -1419,7 +1420,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_LOW, 0x48);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word);
- EEPROM(rt2x00dev, "BBPtune r17: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r17: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word);
@@ -1427,7 +1428,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_LOW, 0x40);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_HIGH, 0x80);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R24, word);
- EEPROM(rt2x00dev, "BBPtune r24: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r24: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &word);
@@ -1435,7 +1436,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_LOW, 0x40);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_HIGH, 0x50);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R25, word);
- EEPROM(rt2x00dev, "BBPtune r25: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r25: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &word);
@@ -1443,7 +1444,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_LOW, 0x60);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_HIGH, 0x6d);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R61, word);
- EEPROM(rt2x00dev, "BBPtune r61: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r61: 0x%04x\n", word);
}
return 0;
@@ -1468,7 +1469,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
if (((reg & 0xfff0) != 0) || ((reg & 0x0000000f) == 0)) {
- ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid RT chipset detected\n");
return -ENODEV;
}
@@ -1478,7 +1479,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
!rt2x00_rf(rt2x00dev, RF2525) &&
!rt2x00_rf(rt2x00dev, RF2525E) &&
!rt2x00_rf(rt2x00dev, RF5222)) {
- ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
return -ENODEV;
}
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 7deac4d2459f..b52d70c75e1a 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -80,7 +80,7 @@ static inline bool rt2800_is_305x_soc(struct rt2x00_dev *rt2x00dev)
rt2x00_rf(rt2x00dev, RF3022))
return true;
- WARNING(rt2x00dev, "Unknown RF chipset on rt305x\n");
+ rt2x00_warn(rt2x00dev, "Unknown RF chipset on rt305x\n");
return false;
}
@@ -328,7 +328,7 @@ int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev)
msleep(1);
}
- ERROR(rt2x00dev, "Unstable hardware.\n");
+ rt2x00_err(rt2x00dev, "Unstable hardware\n");
return -EBUSY;
}
EXPORT_SYMBOL_GPL(rt2800_wait_csr_ready);
@@ -351,7 +351,7 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
msleep(10);
}
- ERROR(rt2x00dev, "WPDMA TX/RX busy [0x%08x].\n", reg);
+ rt2x00_err(rt2x00dev, "WPDMA TX/RX busy [0x%08x]\n", reg);
return -EACCES;
}
EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready);
@@ -512,7 +512,7 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
}
if (i == REGISTER_BUSY_COUNT) {
- ERROR(rt2x00dev, "PBF system register not ready.\n");
+ rt2x00_err(rt2x00dev, "PBF system register not ready\n");
return -EBUSY;
}
@@ -542,6 +542,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
{
__le32 *txwi = rt2800_drv_get_txwi(entry);
u32 word;
+ int i;
/*
* Initialize TX Info descriptor
@@ -584,14 +585,16 @@ void rt2800_write_tx_data(struct queue_entry *entry,
rt2x00_desc_write(txwi, 1, word);
/*
- * Always write 0 to IV/EIV fields, hardware will insert the IV
- * from the IVEIV register when TXD_W3_WIV is set to 0.
+ * Always write 0 to IV/EIV fields (word 2 and 3), hardware will insert
+ * the IV from the IVEIV register when TXD_W3_WIV is set to 0.
* When TXD_W3_WIV is set to 1 it will use the IV data
* from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which
* crypto entry in the registers should be used to encrypt the frame.
+ *
+ * Nulify all remaining words as well, we don't know how to program them.
*/
- _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */);
- _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */);
+ for (i = 2; i < entry->queue->winfo_size / sizeof(__le32); i++)
+ _rt2x00_desc_write(txwi, i, 0);
}
EXPORT_SYMBOL_GPL(rt2800_write_tx_data);
@@ -676,6 +679,10 @@ void rt2800_process_rxwi(struct queue_entry *entry,
* Convert descriptor AGC value to RSSI value.
*/
rxdesc->rssi = rt2800_agc_to_rssi(entry->queue->rt2x00dev, word);
+ /*
+ * Remove RXWI descriptor from start of the buffer.
+ */
+ skb_pull(entry->skb, entry->queue->winfo_size);
}
EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
@@ -766,6 +773,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
unsigned int beacon_base;
unsigned int padding_len;
u32 orig_reg, reg;
+ const int txwi_desc_size = entry->queue->winfo_size;
/*
* Disable beaconing while we are reloading the beacon data,
@@ -779,14 +787,14 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
/*
* Add space for the TXWI in front of the skb.
*/
- memset(skb_push(entry->skb, TXWI_DESC_SIZE), 0, TXWI_DESC_SIZE);
+ memset(skb_push(entry->skb, txwi_desc_size), 0, txwi_desc_size);
/*
* Register descriptor details in skb frame descriptor.
*/
skbdesc->flags |= SKBDESC_DESC_IN_SKB;
skbdesc->desc = entry->skb->data;
- skbdesc->desc_len = TXWI_DESC_SIZE;
+ skbdesc->desc_len = txwi_desc_size;
/*
* Add the TXWI for the beacon to the skb.
@@ -803,7 +811,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
*/
padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
if (padding_len && skb_pad(entry->skb, padding_len)) {
- ERROR(rt2x00dev, "Failure padding beacon, aborting\n");
+ rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n");
/* skb freed by skb_pad() on failure */
entry->skb = NULL;
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
@@ -832,13 +840,14 @@ static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
unsigned int beacon_base)
{
int i;
+ const int txwi_desc_size = rt2x00dev->ops->bcn->winfo_size;
/*
* For the Beacon base registers we only need to clear
* the whole TXWI which (when set to 0) will invalidate
* the entire beacon.
*/
- for (i = 0; i < TXWI_DESC_SIZE; i += sizeof(__le32))
+ for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
rt2800_register_write(rt2x00dev, beacon_base + i, 0);
}
@@ -3147,7 +3156,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev)
{
- rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.channel,
+ rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.chandef.chan,
rt2x00dev->tx_power);
}
EXPORT_SYMBOL_GPL(rt2800_gain_calibration);
@@ -3282,11 +3291,11 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev,
if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {
rt2800_config_channel(rt2x00dev, libconf->conf,
&libconf->rf, &libconf->channel);
- rt2800_config_txpower(rt2x00dev, libconf->conf->channel,
+ rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan,
libconf->conf->power_level);
}
if (flags & IEEE80211_CONF_CHANGE_POWER)
- rt2800_config_txpower(rt2x00dev, libconf->conf->channel,
+ rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan,
libconf->conf->power_level);
if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
rt2800_config_retry_limit(rt2x00dev, libconf);
@@ -3860,7 +3869,7 @@ static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n");
+ rt2x00_err(rt2x00dev, "BBP/RF register access failed, aborting\n");
return -EACCES;
}
@@ -3884,7 +3893,7 @@ static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
+ rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
return -EACCES;
}
@@ -3924,7 +3933,7 @@ static void rt2800_init_bbp_5592_glrt(struct rt2x00_dev *rt2x00dev)
}
};
-static void rt2800_init_bbb_early(struct rt2x00_dev *rt2x00dev)
+static void rt2800_init_bbp_early(struct rt2x00_dev *rt2x00dev)
{
rt2800_bbp_write(rt2x00dev, 65, 0x2C);
rt2800_bbp_write(rt2x00dev, 66, 0x38);
@@ -3950,7 +3959,7 @@ static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev)
u16 eeprom;
u8 value;
- rt2800_init_bbb_early(rt2x00dev);
+ rt2800_init_bbp_early(rt2x00dev);
rt2800_bbp_read(rt2x00dev, 105, &value);
rt2x00_set_field8(&value, BBP105_MLD,
@@ -4332,8 +4341,17 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
return 0;
}
-static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,
- bool bw40, u8 rfcsr24, u8 filter_target)
+static void rt2800_led_open_drain_enable(struct rt2x00_dev *rt2x00dev)
+{
+ u32 reg;
+
+ rt2800_register_read(rt2x00dev, OPT_14_CSR, &reg);
+ rt2x00_set_field32(&reg, OPT_14_CSR_BIT0, 1);
+ rt2800_register_write(rt2x00dev, OPT_14_CSR, reg);
+}
+
+static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, bool bw40,
+ u8 filter_target)
{
unsigned int i;
u8 bbp;
@@ -4341,6 +4359,7 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,
u8 passband;
u8 stopband;
u8 overtuned = 0;
+ u8 rfcsr24 = (bw40) ? 0x27 : 0x07;
rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);
@@ -4396,8 +4415,169 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,
return rfcsr24;
}
+static void rt2800_rf_init_calibration(struct rt2x00_dev *rt2x00dev,
+ const unsigned int rf_reg)
+{
+ u8 rfcsr;
+
+ rt2800_rfcsr_read(rt2x00dev, rf_reg, &rfcsr);
+ rt2x00_set_field8(&rfcsr, FIELD8(0x80), 1);
+ rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr);
+ msleep(1);
+ rt2x00_set_field8(&rfcsr, FIELD8(0x80), 0);
+ rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr);
+}
+
+static void rt2800_rx_filter_calibration(struct rt2x00_dev *rt2x00dev)
+{
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+ u8 filter_tgt_bw20;
+ u8 filter_tgt_bw40;
+ u8 rfcsr, bbp;
+
+ /*
+ * TODO: sync filter_tgt values with vendor driver
+ */
+ if (rt2x00_rt(rt2x00dev, RT3070)) {
+ filter_tgt_bw20 = 0x16;
+ filter_tgt_bw40 = 0x19;
+ } else {
+ filter_tgt_bw20 = 0x13;
+ filter_tgt_bw40 = 0x15;
+ }
+
+ drv_data->calibration_bw20 =
+ rt2800_init_rx_filter(rt2x00dev, false, filter_tgt_bw20);
+ drv_data->calibration_bw40 =
+ rt2800_init_rx_filter(rt2x00dev, true, filter_tgt_bw40);
+
+ /*
+ * Save BBP 25 & 26 values for later use in channel switching (for 3052)
+ */
+ rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25);
+ rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26);
+
+ /*
+ * Set back to initial state
+ */
+ rt2800_bbp_write(rt2x00dev, 24, 0);
+
+ rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
+ rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
+
+ /*
+ * Set BBP back to BW20
+ */
+ rt2800_bbp_read(rt2x00dev, 4, &bbp);
+ rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
+ rt2800_bbp_write(rt2x00dev, 4, bbp);
+}
+
+static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
+{
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+ u8 min_gain, rfcsr, bbp;
+ u16 eeprom;
+
+ rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+
+ rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);
+ if (rt2x00_rt(rt2x00dev, RT3070) ||
+ rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
+ rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
+ rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
+ if (!test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))
+ rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
+ }
+
+ min_gain = rt2x00_rt(rt2x00dev, RT3070) ? 1 : 2;
+ if (drv_data->txmixer_gain_24g >= min_gain) {
+ rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN,
+ drv_data->txmixer_gain_24g);
+ }
+
+ rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+
+ if (rt2x00_rt(rt2x00dev, RT3090)) {
+ /* Turn off unused DAC1 and ADC1 to reduce power consumption */
+ rt2800_bbp_read(rt2x00dev, 138, &bbp);
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
+ rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0);
+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
+ rt2x00_set_field8(&bbp, BBP138_TX_DAC1, 1);
+ rt2800_bbp_write(rt2x00dev, 138, bbp);
+ }
+
+ if (rt2x00_rt(rt2x00dev, RT3070)) {
+ rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr);
+ if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F))
+ rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3);
+ else
+ rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR27_R2, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR27_R3, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR27_R4, 0);
+ rt2800_rfcsr_write(rt2x00dev, 27, rfcsr);
+ } else if (rt2x00_rt(rt2x00dev, RT3071) ||
+ rt2x00_rt(rt2x00dev, RT3090) ||
+ rt2x00_rt(rt2x00dev, RT3390)) {
+ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
+ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 15, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR15_TX_LO2_EN, 0);
+ rt2800_rfcsr_write(rt2x00dev, 15, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR20_RX_LO1_EN, 0);
+ rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR21_RX_LO2_EN, 0);
+ rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
+ }
+}
+
+static void rt2800_normal_mode_setup_5xxx(struct rt2x00_dev *rt2x00dev)
+{
+ u8 reg;
+ u16 eeprom;
+
+ /* Turn off unused DAC1 and ADC1 to reduce power consumption */
+ rt2800_bbp_read(rt2x00dev, 138, &reg);
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
+ rt2x00_set_field8(&reg, BBP138_RX_ADC1, 0);
+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
+ rt2x00_set_field8(&reg, BBP138_TX_DAC1, 1);
+ rt2800_bbp_write(rt2x00dev, 138, reg);
+
+ rt2800_rfcsr_read(rt2x00dev, 38, &reg);
+ rt2x00_set_field8(&reg, RFCSR38_RX_LO1_EN, 0);
+ rt2800_rfcsr_write(rt2x00dev, 38, reg);
+
+ rt2800_rfcsr_read(rt2x00dev, 39, &reg);
+ rt2x00_set_field8(&reg, RFCSR39_RX_LO2_EN, 0);
+ rt2800_rfcsr_write(rt2x00dev, 39, reg);
+
+ rt2800_bbp4_mac_if_ctrl(rt2x00dev);
+
+ rt2800_rfcsr_read(rt2x00dev, 30, &reg);
+ rt2x00_set_field8(&reg, RFCSR30_RX_VCM, 2);
+ rt2800_rfcsr_write(rt2x00dev, 30, reg);
+}
+
static void rt2800_init_rfcsr_305x_soc(struct rt2x00_dev *rt2x00dev)
{
+ rt2800_rf_init_calibration(rt2x00dev, 30);
+
rt2800_rfcsr_write(rt2x00dev, 0, 0x50);
rt2800_rfcsr_write(rt2x00dev, 1, 0x01);
rt2800_rfcsr_write(rt2x00dev, 2, 0xf7);
@@ -4434,6 +4614,13 @@ static void rt2800_init_rfcsr_305x_soc(struct rt2x00_dev *rt2x00dev)
static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev)
{
+ u8 rfcsr;
+ u16 eeprom;
+ u32 reg;
+
+ /* XXX vendor driver do this only for 3070 */
+ rt2800_rf_init_calibration(rt2x00dev, 30);
+
rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
@@ -4453,10 +4640,54 @@ static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);
+
+ if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
+ rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+ rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+ rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+ } else if (rt2x00_rt(rt2x00dev, RT3071) ||
+ rt2x00_rt(rt2x00dev, RT3090)) {
+ rt2800_rfcsr_write(rt2x00dev, 31, 0x14);
+
+ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
+ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+ rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+ if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
+ rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
+ rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+ else
+ rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
+ }
+ rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+
+ rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+ rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
+ rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+ }
+
+ rt2800_rx_filter_calibration(rt2x00dev);
+
+ if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) ||
+ rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
+ rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E))
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
+
+ rt2800_led_open_drain_enable(rt2x00dev);
+ rt2800_normal_mode_setup_3xxx(rt2x00dev);
}
static void rt2800_init_rfcsr_3290(struct rt2x00_dev *rt2x00dev)
{
+ u8 rfcsr;
+
+ rt2800_rf_init_calibration(rt2x00dev, 2);
+
rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
@@ -4503,10 +4734,19 @@ static void rt2800_init_rfcsr_3290(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 59, 0x09);
rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
+
+ rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR29_RSSI_GAIN, 3);
+ rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
+
+ rt2800_led_open_drain_enable(rt2x00dev);
+ rt2800_normal_mode_setup_3xxx(rt2x00dev);
}
static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)
{
+ rt2800_rf_init_calibration(rt2x00dev, 30);
+
rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);
rt2800_rfcsr_write(rt2x00dev, 1, 0x23);
rt2800_rfcsr_write(rt2x00dev, 2, 0x50);
@@ -4570,10 +4810,18 @@ static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
+
+ rt2800_rx_filter_calibration(rt2x00dev);
+ rt2800_led_open_drain_enable(rt2x00dev);
+ rt2800_normal_mode_setup_3xxx(rt2x00dev);
}
static void rt2800_init_rfcsr_3390(struct rt2x00_dev *rt2x00dev)
{
+ u32 reg;
+
+ rt2800_rf_init_calibration(rt2x00dev, 30);
+
rt2800_rfcsr_write(rt2x00dev, 0, 0xa0);
rt2800_rfcsr_write(rt2x00dev, 1, 0xe1);
rt2800_rfcsr_write(rt2x00dev, 2, 0xf1);
@@ -4606,10 +4854,27 @@ static void rt2800_init_rfcsr_3390(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 29, 0x8f);
rt2800_rfcsr_write(rt2x00dev, 30, 0x20);
rt2800_rfcsr_write(rt2x00dev, 31, 0x0f);
+
+ rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+ rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
+ rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+
+ rt2800_rx_filter_calibration(rt2x00dev);
+
+ if (rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E))
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
+
+ rt2800_led_open_drain_enable(rt2x00dev);
+ rt2800_normal_mode_setup_3xxx(rt2x00dev);
}
static void rt2800_init_rfcsr_3572(struct rt2x00_dev *rt2x00dev)
{
+ u8 rfcsr;
+ u32 reg;
+
+ rt2800_rf_init_calibration(rt2x00dev, 30);
+
rt2800_rfcsr_write(rt2x00dev, 0, 0x70);
rt2800_rfcsr_write(rt2x00dev, 1, 0x81);
rt2800_rfcsr_write(rt2x00dev, 2, 0xf1);
@@ -4641,10 +4906,30 @@ static void rt2800_init_rfcsr_3572(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
rt2800_rfcsr_write(rt2x00dev, 30, 0x09);
rt2800_rfcsr_write(rt2x00dev, 31, 0x10);
+
+ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
+ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+ rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+ rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+ rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+ msleep(1);
+ rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
+ rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+ rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+
+ rt2800_rx_filter_calibration(rt2x00dev);
+ rt2800_led_open_drain_enable(rt2x00dev);
+ rt2800_normal_mode_setup_3xxx(rt2x00dev);
}
static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
{
+ rt2800_rf_init_calibration(rt2x00dev, 2);
+
rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
rt2800_rfcsr_write(rt2x00dev, 3, 0x88);
@@ -4725,10 +5010,16 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 61, 0xdd);
rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
+
+ rt2800_normal_mode_setup_5xxx(rt2x00dev);
+
+ rt2800_led_open_drain_enable(rt2x00dev);
}
static void rt2800_init_rfcsr_5392(struct rt2x00_dev *rt2x00dev)
{
+ rt2800_rf_init_calibration(rt2x00dev, 2);
+
rt2800_rfcsr_write(rt2x00dev, 1, 0x17);
rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
rt2800_rfcsr_write(rt2x00dev, 3, 0x88);
@@ -4788,12 +5079,15 @@ static void rt2800_init_rfcsr_5392(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
+
+ rt2800_normal_mode_setup_5xxx(rt2x00dev);
+
+ rt2800_led_open_drain_enable(rt2x00dev);
}
static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev)
{
- u8 reg;
- u16 eeprom;
+ rt2800_rf_init_calibration(rt2x00dev, 30);
rt2800_rfcsr_write(rt2x00dev, 1, 0x3F);
rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
@@ -4823,83 +5117,23 @@ static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev)
rt2800_adjust_freq_offset(rt2x00dev);
- rt2800_bbp_read(rt2x00dev, 138, &reg);
-
- /* Turn off unused DAC1 and ADC1 to reduce power consumption */
- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
- if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
- rt2x00_set_field8(&reg, BBP138_RX_ADC1, 0);
- if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
- rt2x00_set_field8(&reg, BBP138_TX_DAC1, 1);
-
- rt2800_bbp_write(rt2x00dev, 138, reg);
-
/* Enable DC filter */
if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C))
rt2800_bbp_write(rt2x00dev, 103, 0xc0);
- rt2800_rfcsr_read(rt2x00dev, 38, &reg);
- rt2x00_set_field8(&reg, RFCSR38_RX_LO1_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 38, reg);
-
- rt2800_rfcsr_read(rt2x00dev, 39, &reg);
- rt2x00_set_field8(&reg, RFCSR39_RX_LO2_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 39, reg);
+ rt2800_normal_mode_setup_5xxx(rt2x00dev);
- rt2800_bbp4_mac_if_ctrl(rt2x00dev);
+ if (rt2x00_rt_rev_lt(rt2x00dev, RT5592, REV_RT5592C))
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
- rt2800_rfcsr_read(rt2x00dev, 30, &reg);
- rt2x00_set_field8(&reg, RFCSR30_RX_VCM, 2);
- rt2800_rfcsr_write(rt2x00dev, 30, reg);
+ rt2800_led_open_drain_enable(rt2x00dev);
}
-static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
+static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
{
- struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
- u8 rfcsr;
- u8 bbp;
- u32 reg;
- u16 eeprom;
-
- if (!rt2x00_rt(rt2x00dev, RT3070) &&
- !rt2x00_rt(rt2x00dev, RT3071) &&
- !rt2x00_rt(rt2x00dev, RT3090) &&
- !rt2x00_rt(rt2x00dev, RT3290) &&
- !rt2x00_rt(rt2x00dev, RT3352) &&
- !rt2x00_rt(rt2x00dev, RT3390) &&
- !rt2x00_rt(rt2x00dev, RT3572) &&
- !rt2x00_rt(rt2x00dev, RT5390) &&
- !rt2x00_rt(rt2x00dev, RT5392) &&
- !rt2x00_rt(rt2x00dev, RT5392) &&
- !rt2x00_rt(rt2x00dev, RT5592) &&
- !rt2800_is_305x_soc(rt2x00dev))
- return 0;
-
- /*
- * Init RF calibration.
- */
-
- 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);
- msleep(1);
- rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
- } else {
- rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
- rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
- msleep(1);
- rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
- rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
- }
-
if (rt2800_is_305x_soc(rt2x00dev)) {
rt2800_init_rfcsr_305x_soc(rt2x00dev);
- return 0;
+ return;
}
switch (rt2x00dev->chip.rt) {
@@ -4928,202 +5162,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
break;
case RT5592:
rt2800_init_rfcsr_5592(rt2x00dev);
- return 0;
- }
-
- if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
- rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
- rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
- rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
- rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
- } else if (rt2x00_rt(rt2x00dev, RT3071) ||
- rt2x00_rt(rt2x00dev, RT3090)) {
- rt2800_rfcsr_write(rt2x00dev, 31, 0x14);
-
- rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
- rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
-
- rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
- rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
- if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
- rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
- if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
- rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
- else
- rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
- }
- rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
-
- rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
- rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
- rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
- } else if (rt2x00_rt(rt2x00dev, RT3390)) {
- rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
- rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
- rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
- } else if (rt2x00_rt(rt2x00dev, RT3572)) {
- rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
- rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
-
- rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
- rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
- rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
- rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
- msleep(1);
- rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
- rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
- rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
- rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
- }
-
- /*
- * Set RX Filter calibration for 20MHz and 40MHz
- */
- if (rt2x00_rt(rt2x00dev, RT3070)) {
- drv_data->calibration_bw20 =
- rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16);
- drv_data->calibration_bw40 =
- rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19);
- } else if (rt2x00_rt(rt2x00dev, RT3071) ||
- rt2x00_rt(rt2x00dev, RT3090) ||
- rt2x00_rt(rt2x00dev, RT3352) ||
- rt2x00_rt(rt2x00dev, RT3390) ||
- rt2x00_rt(rt2x00dev, RT3572)) {
- drv_data->calibration_bw20 =
- rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13);
- drv_data->calibration_bw40 =
- rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x15);
- }
-
- /*
- * Save BBP 25 & 26 values for later use in channel switching
- */
- rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25);
- rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26);
-
- if (!rt2x00_rt(rt2x00dev, RT5390) &&
- !rt2x00_rt(rt2x00dev, RT5392)) {
- /*
- * Set back to initial state
- */
- rt2800_bbp_write(rt2x00dev, 24, 0);
-
- rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
- rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
-
- /*
- * Set BBP back to BW20
- */
- rt2800_bbp_read(rt2x00dev, 4, &bbp);
- rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
- rt2800_bbp_write(rt2x00dev, 4, bbp);
- }
-
- if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) ||
- rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
- rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
- rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E) ||
- rt2x00_rt_rev_lt(rt2x00dev, RT5592, REV_RT5592C))
- rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
-
- rt2800_register_read(rt2x00dev, OPT_14_CSR, &reg);
- rt2x00_set_field32(&reg, OPT_14_CSR_BIT0, 1);
- rt2800_register_write(rt2x00dev, OPT_14_CSR, reg);
-
- if (!rt2x00_rt(rt2x00dev, RT5390) &&
- !rt2x00_rt(rt2x00dev, RT5392)) {
- rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);
- if (rt2x00_rt(rt2x00dev, RT3070) ||
- rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
- rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
- rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
- if (!test_bit(CAPABILITY_EXTERNAL_LNA_BG,
- &rt2x00dev->cap_flags))
- rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
- }
- rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN,
- drv_data->txmixer_gain_24g);
- rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
- }
-
- if (rt2x00_rt(rt2x00dev, RT3090) ||
- rt2x00_rt(rt2x00dev, RT5592)) {
- rt2800_bbp_read(rt2x00dev, 138, &bbp);
-
- /* Turn off unused DAC1 and ADC1 to reduce power consumption */
- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
- if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
- rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0);
- if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
- rt2x00_set_field8(&bbp, BBP138_TX_DAC1, 1);
-
- rt2800_bbp_write(rt2x00dev, 138, bbp);
- }
-
- if (rt2x00_rt(rt2x00dev, RT3071) ||
- rt2x00_rt(rt2x00dev, RT3090) ||
- rt2x00_rt(rt2x00dev, RT3390)) {
- rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
- rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
- rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
- rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
- rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
- rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
-
- rt2800_rfcsr_read(rt2x00dev, 15, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR15_TX_LO2_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 15, rfcsr);
-
- rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR20_RX_LO1_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
-
- rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR21_RX_LO2_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
- }
-
- if (rt2x00_rt(rt2x00dev, RT3070)) {
- rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr);
- if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F))
- rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3);
- else
- rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0);
- rt2x00_set_field8(&rfcsr, RFCSR27_R2, 0);
- rt2x00_set_field8(&rfcsr, RFCSR27_R3, 0);
- rt2x00_set_field8(&rfcsr, RFCSR27_R4, 0);
- 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) ||
- rt2x00_rt(rt2x00dev, RT5592)) {
- rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 38, rfcsr);
-
- rt2800_rfcsr_read(rt2x00dev, 39, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR39_RX_LO2_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
-
- rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
- rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+ break;
}
-
- return 0;
}
int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
@@ -5149,10 +5189,11 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
}
msleep(1);
- if (unlikely(rt2800_init_bbp(rt2x00dev) ||
- rt2800_init_rfcsr(rt2x00dev)))
+ if (unlikely(rt2800_init_bbp(rt2x00dev)))
return -EIO;
+ rt2800_init_rfcsr(rt2x00dev);
+
if (rt2x00_is_usb(rt2x00dev) &&
(rt2x00_rt(rt2x00dev, RT3070) ||
rt2x00_rt(rt2x00dev, RT3071) ||
@@ -5312,7 +5353,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
eth_random_addr(mac);
- EEPROM(rt2x00dev, "MAC: %pM\n", mac);
+ rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word);
@@ -5321,7 +5362,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1);
rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
- EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
} else if (rt2x00_rt(rt2x00dev, RT2860) ||
rt2x00_rt(rt2x00dev, RT2872)) {
/*
@@ -5350,14 +5391,14 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BT_COEXIST, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_DAC_TEST, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word);
- EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
if ((word & 0x00ff) == 0x00ff) {
rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
- EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
}
if ((word & 0xff00) == 0xff00) {
rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,
@@ -5367,7 +5408,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8);
- EEPROM(rt2x00dev, "Led Mode: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Led Mode: 0x%04x\n", word);
}
/*
@@ -5473,7 +5514,8 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
case RF5592:
break;
default:
- ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", rf);
+ rt2x00_err(rt2x00dev, "Invalid RF chipset 0x%04x detected\n",
+ rf);
return -ENODEV;
}
@@ -6062,9 +6104,8 @@ static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev)
case RT5592:
break;
default:
- ERROR(rt2x00dev,
- "Invalid RT chipset 0x%04x, rev %04x detected.\n",
- rt, rev);
+ rt2x00_err(rt2x00dev, "Invalid RT chipset 0x%04x, rev %04x detected\n",
+ rt, rev);
return -ENODEV;
}
@@ -6323,7 +6364,8 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
case IEEE80211_AMPDU_TX_OPERATIONAL:
break;
default:
- WARNING((struct rt2x00_dev *)hw->priv, "Unknown AMPDU action\n");
+ rt2x00_warn((struct rt2x00_dev *)hw->priv,
+ "Unknown AMPDU action\n");
}
return ret;
@@ -6340,7 +6382,7 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
rt2800_register_read(rt2x00dev, CH_IDLE_STA, &idle);
rt2800_register_read(rt2x00dev, CH_BUSY_STA, &busy);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 565a80d0e564..6f4a861af336 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -72,7 +72,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
return;
for (i = 0; i < 200; i++) {
- rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
+ rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
(rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
@@ -84,10 +84,10 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
}
if (i == 200)
- ERROR(rt2x00dev, "MCU request failed, no response from hardware\n");
+ rt2x00_err(rt2x00dev, "MCU request failed, no response from hardware\n");
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
}
#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
@@ -116,7 +116,7 @@ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
@@ -138,7 +138,7 @@ static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
rt2x00_set_field32(&reg, E2PROM_CSR_CHIP_SELECT,
!!eeprom->reg_chip_select);
- rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, E2PROM_CSR, reg);
}
static int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
@@ -146,7 +146,7 @@ static int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
struct eeprom_93cx6 eeprom;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
eeprom.data = rt2x00dev;
eeprom.register_read = rt2800pci_eepromregister_read;
@@ -210,20 +210,20 @@ static void rt2800pci_start_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
- rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, &reg);
rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 1);
- rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg);
break;
default:
break;
@@ -241,13 +241,13 @@ static void rt2800pci_kick_queue(struct data_queue *queue)
case QID_AC_BE:
case QID_AC_BK:
entry = rt2x00queue_get_entry(queue, Q_INDEX);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
- entry->entry_idx);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
+ entry->entry_idx);
break;
case QID_MGMT:
entry = rt2x00queue_get_entry(queue, Q_INDEX);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(5),
- entry->entry_idx);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(5),
+ entry->entry_idx);
break;
default:
break;
@@ -261,20 +261,20 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
- rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, &reg);
rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 0);
- rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg);
/*
* Wait for current invocation to finish. The tasklet
@@ -314,19 +314,19 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
*/
reg = 0;
rt2x00_set_field32(&reg, PBF_SYS_CTRL_HOST_RAM_WRITE, 1);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
+ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
/*
* Write firmware to device.
*/
- rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
- data, len);
+ rt2x00mmio_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
+ data, len);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
+ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
+ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
- rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+ rt2x00mmio_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
return 0;
}
@@ -336,7 +336,7 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
*/
static bool rt2800pci_get_entry_state(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
u32 word;
if (entry->queue->qid == QID_RX) {
@@ -352,7 +352,7 @@ static bool rt2800pci_get_entry_state(struct queue_entry *entry)
static void rt2800pci_clear_entry(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
u32 word;
@@ -370,8 +370,8 @@ static void rt2800pci_clear_entry(struct queue_entry *entry)
* Set RX IDX in register to inform hardware that we have
* handled this entry and it is available for reuse again.
*/
- rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX,
- entry->entry_idx);
+ rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX,
+ entry->entry_idx);
} else {
rt2x00_desc_read(entry_priv->desc, 1, &word);
rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1);
@@ -381,60 +381,65 @@ static void rt2800pci_clear_entry(struct queue_entry *entry)
static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
{
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
/*
* Initialize registers.
*/
entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
- rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT0,
- rt2x00dev->tx[0].limit);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX0, 0);
- rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX0, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR0,
+ entry_priv->desc_dma);
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT0,
+ rt2x00dev->tx[0].limit);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX0, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX0, 0);
entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
- rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT1,
- rt2x00dev->tx[1].limit);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX1, 0);
- rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX1, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR1,
+ entry_priv->desc_dma);
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT1,
+ rt2x00dev->tx[1].limit);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX1, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX1, 0);
entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
- rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT2,
- rt2x00dev->tx[2].limit);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX2, 0);
- rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX2, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR2,
+ entry_priv->desc_dma);
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT2,
+ rt2x00dev->tx[2].limit);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX2, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX2, 0);
entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
- rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT3,
- rt2x00dev->tx[3].limit);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0);
- rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX3, 0);
-
- rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR4, 0);
- rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT4, 0);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX4, 0);
- rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX4, 0);
-
- rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR5, 0);
- rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT5, 0);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX5, 0);
- rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX5, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR3,
+ entry_priv->desc_dma);
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT3,
+ rt2x00dev->tx[3].limit);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX3, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX3, 0);
+
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR4, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT4, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX4, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX4, 0);
+
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR5, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT5, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX5, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX5, 0);
entry_priv = rt2x00dev->rx->entries[0].priv_data;
- rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT,
- rt2x00dev->rx[0].limit);
- rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX,
- rt2x00dev->rx[0].limit - 1);
- rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0);
+ rt2x00mmio_register_write(rt2x00dev, RX_BASE_PTR,
+ entry_priv->desc_dma);
+ rt2x00mmio_register_write(rt2x00dev, RX_MAX_CNT,
+ rt2x00dev->rx[0].limit);
+ rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX,
+ rt2x00dev->rx[0].limit - 1);
+ rt2x00mmio_register_write(rt2x00dev, RX_DRX_IDX, 0);
rt2800_disable_wpdma(rt2x00dev);
- rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0);
+ rt2x00mmio_register_write(rt2x00dev, DELAY_INT_CFG, 0);
return 0;
}
@@ -453,8 +458,8 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
* should clear the register to assure a clean state.
*/
if (state == STATE_RADIO_IRQ_ON) {
- rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
- rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
}
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
@@ -466,7 +471,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, 1);
}
- rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
if (state == STATE_RADIO_IRQ_OFF) {
@@ -488,7 +493,7 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
/*
* Reset DMA indexes
*/
- rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
+ rt2x00mmio_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
@@ -496,29 +501,29 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX4, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX5, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
- rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
+ rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
+ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
+ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
if (rt2x00_is_pcie(rt2x00dev) &&
(rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))) {
- rt2x00pci_register_read(rt2x00dev, AUX_CTRL, &reg);
+ rt2x00mmio_register_read(rt2x00dev, AUX_CTRL, &reg);
rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
- rt2x00pci_register_write(rt2x00dev, AUX_CTRL, reg);
+ rt2x00mmio_register_write(rt2x00dev, AUX_CTRL, reg);
}
- rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+ rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
reg = 0;
rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
- rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+ rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
return 0;
}
@@ -538,8 +543,8 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
return retval;
/* After resume MCU_BOOT_SIGNAL will trash these. */
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, 0xff, 0x02);
rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF);
@@ -554,8 +559,8 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
{
if (rt2x00_is_soc(rt2x00dev)) {
rt2800_disable_radio(rt2x00dev);
- rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
- rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
+ rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0);
}
}
@@ -567,10 +572,10 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
0, 0x02);
rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP);
} else if (state == STATE_SLEEP) {
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
- 0xffffffff);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID,
- 0xffffffff);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
+ 0xffffffff);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID,
+ 0xffffffff);
rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP,
0xff, 0x01);
}
@@ -611,8 +616,8 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
}
if (unlikely(retval))
- ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
- state, retval);
+ rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+ state, retval);
return retval;
}
@@ -629,7 +634,7 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
__le32 *txd = entry_priv->desc;
u32 word;
@@ -683,7 +688,7 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry,
static void rt2800pci_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
__le32 *rxd = entry_priv->desc;
u32 word;
@@ -730,11 +735,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
* Process the RXWI structure that is at the start of the buffer.
*/
rt2800_process_rxwi(entry, rxdesc);
-
- /*
- * Remove RXWI descriptor from start of buffer.
- */
- skb_pull(entry->skb, RXWI_DESC_SIZE);
}
/*
@@ -843,8 +843,8 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
* Unknown queue, this shouldn't happen. Just drop
* this tx status.
*/
- WARNING(rt2x00dev, "Got TX status report with "
- "unexpected pid %u, dropping\n", qid);
+ rt2x00_warn(rt2x00dev, "Got TX status report with unexpected pid %u, dropping\n",
+ qid);
break;
}
@@ -854,8 +854,8 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
* The queue is NULL, this shouldn't happen. Stop
* processing here and drop the tx status
*/
- WARNING(rt2x00dev, "Got TX status for an unavailable "
- "queue %u, dropping\n", qid);
+ rt2x00_warn(rt2x00dev, "Got TX status for an unavailable queue %u, dropping\n",
+ qid);
break;
}
@@ -864,8 +864,8 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
* The queue is empty. Stop processing here
* and drop the tx status.
*/
- WARNING(rt2x00dev, "Got TX status for an empty "
- "queue %u, dropping\n", qid);
+ rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
+ qid);
break;
}
@@ -883,9 +883,8 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
Q_INDEX, &status,
rt2800pci_txdone_match_first)) {
- WARNING(rt2x00dev, "No frame found for TX "
- "status on queue %u, dropping\n",
- qid);
+ rt2x00_warn(rt2x00dev, "No frame found for TX status on queue %u, dropping\n",
+ qid);
break;
}
}
@@ -914,9 +913,9 @@ static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
* access needs locking.
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
rt2x00_set_field32(&reg, irq_field, 1);
- rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
@@ -957,15 +956,15 @@ static void rt2800pci_tbtt_tasklet(unsigned long data)
* interval every 64 beacons by 64us to mitigate this effect.
*/
if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) {
- rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
(rt2x00dev->beacon_int * 16) - 1);
- rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
} else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) {
- rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
(rt2x00dev->beacon_int * 16));
- rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
}
drv_data->tbtt_tick++;
drv_data->tbtt_tick %= BCN_TBTT_OFFSET;
@@ -978,7 +977,7 @@ static void rt2800pci_tbtt_tasklet(unsigned long data)
static void rt2800pci_rxdone_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- if (rt2x00pci_rxdone(rt2x00dev))
+ if (rt2x00mmio_rxdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->rxdone_tasklet);
else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
@@ -1016,14 +1015,13 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
* need to lock the kfifo.
*/
for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
- rt2x00pci_register_read(rt2x00dev, TX_STA_FIFO, &status);
+ rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status);
if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
break;
if (!kfifo_put(&rt2x00dev->txstatus_fifo, &status)) {
- WARNING(rt2x00dev, "TX status FIFO overrun,"
- "drop tx status report.\n");
+ rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n");
break;
}
}
@@ -1038,8 +1036,8 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
u32 reg, mask;
/* Read status and ACK all interrupts */
- rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
- rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
if (!reg)
return IRQ_NONE;
@@ -1079,9 +1077,9 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
* the tasklet will reenable the appropriate interrupts.
*/
spin_lock(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
reg &= mask;
- rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock(&rt2x00dev->irqmask_lock);
return IRQ_HANDLED;
@@ -1132,13 +1130,13 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
};
static const struct rt2800_ops rt2800pci_rt2800_ops = {
- .register_read = rt2x00pci_register_read,
- .register_read_lock = rt2x00pci_register_read, /* same for PCI */
- .register_write = rt2x00pci_register_write,
- .register_write_lock = rt2x00pci_register_write, /* same for PCI */
- .register_multiread = rt2x00pci_register_multiread,
- .register_multiwrite = rt2x00pci_register_multiwrite,
- .regbusy_read = rt2x00pci_regbusy_read,
+ .register_read = rt2x00mmio_register_read,
+ .register_read_lock = rt2x00mmio_register_read, /* same for PCI */
+ .register_write = rt2x00mmio_register_write,
+ .register_write_lock = rt2x00mmio_register_write, /* same for PCI */
+ .register_multiread = rt2x00mmio_register_multiread,
+ .register_multiwrite = rt2x00mmio_register_multiwrite,
+ .regbusy_read = rt2x00mmio_regbusy_read,
.read_eeprom = rt2800pci_read_eeprom,
.hwcrypt_disabled = rt2800pci_hwcrypt_disabled,
.drv_write_firmware = rt2800pci_write_firmware,
@@ -1157,8 +1155,8 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.get_firmware_name = rt2800pci_get_firmware_name,
.check_firmware = rt2800_check_firmware,
.load_firmware = rt2800_load_firmware,
- .initialize = rt2x00pci_initialize,
- .uninitialize = rt2x00pci_uninitialize,
+ .initialize = rt2x00mmio_initialize,
+ .uninitialize = rt2x00mmio_uninitialize,
.get_entry_state = rt2800pci_get_entry_state,
.clear_entry = rt2800pci_clear_entry,
.set_device_state = rt2800pci_set_device_state,
@@ -1171,7 +1169,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.start_queue = rt2800pci_start_queue,
.kick_queue = rt2800pci_kick_queue,
.stop_queue = rt2800pci_stop_queue,
- .flush_queue = rt2x00pci_flush_queue,
+ .flush_queue = rt2x00mmio_flush_queue,
.write_tx_desc = rt2800pci_write_tx_desc,
.write_tx_data = rt2800_write_tx_data,
.write_beacon = rt2800_write_beacon,
@@ -1192,21 +1190,24 @@ static const struct data_queue_desc rt2800pci_queue_rx = {
.entry_num = 128,
.data_size = AGGREGATION_SIZE,
.desc_size = RXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .winfo_size = RXWI_DESC_SIZE,
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2800pci_queue_tx = {
.entry_num = 64,
.data_size = AGGREGATION_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .winfo_size = TXWI_DESC_SIZE,
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2800pci_queue_bcn = {
.entry_num = 8,
.data_size = 0, /* No DMA required for beacons */
- .desc_size = TXWI_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .desc_size = TXD_DESC_SIZE,
+ .winfo_size = TXWI_DESC_SIZE,
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct rt2x00_ops rt2800pci_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index f32282009146..ac854d75bd6c 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -128,9 +128,9 @@ static inline bool rt2800usb_entry_txstatus_timeout(struct queue_entry *entry)
tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
if (unlikely(tout))
- WARNING(entry->queue->rt2x00dev,
- "TX status timeout for entry %d in queue %d\n",
- entry->entry_idx, entry->queue->qid);
+ rt2x00_warn(entry->queue->rt2x00dev,
+ "TX status timeout for entry %d in queue %d\n",
+ entry->entry_idx, entry->queue->qid);
return tout;
}
@@ -154,7 +154,8 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
bool valid;
if (urb_status) {
- WARNING(rt2x00dev, "TX status read failed %d\n", urb_status);
+ rt2x00_warn(rt2x00dev, "TX status read failed %d\n",
+ urb_status);
goto stop_reading;
}
@@ -162,7 +163,7 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
valid = rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID);
if (valid) {
if (!kfifo_put(&rt2x00dev->txstatus_fifo, &tx_status))
- WARNING(rt2x00dev, "TX status FIFO overrun\n");
+ rt2x00_warn(rt2x00dev, "TX status FIFO overrun\n");
queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
@@ -269,7 +270,7 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
0, USB_MODE_FIRMWARE,
REGISTER_TIMEOUT_FIRMWARE);
if (status < 0) {
- ERROR(rt2x00dev, "Failed to write Firmware to device.\n");
+ rt2x00_err(rt2x00dev, "Failed to write Firmware to device\n");
return status;
}
@@ -392,8 +393,8 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
}
if (unlikely(retval))
- ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
- state, retval);
+ rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+ state, retval);
return retval;
}
@@ -408,8 +409,7 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) {
- WARNING(rt2x00dev, "TX HW queue 0 timed out,"
- " invoke forced kick\n");
+ rt2x00_warn(rt2x00dev, "TX HW queue 0 timed out, invoke forced kick\n");
rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012);
@@ -424,8 +424,7 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) {
- WARNING(rt2x00dev, "TX HW queue 1 timed out,"
- " invoke forced kick\n");
+ rt2x00_warn(rt2x00dev, "TX HW queue 1 timed out, invoke forced kick\n");
rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
@@ -485,7 +484,7 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry,
*/
skbdesc->flags |= SKBDESC_DESC_IN_SKB;
skbdesc->desc = txi;
- skbdesc->desc_len = entry->queue->desc_size;
+ skbdesc->desc_len = TXINFO_DESC_SIZE + entry->queue->winfo_size;
}
/*
@@ -540,9 +539,9 @@ rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
if (wcid != tx_wcid || ack != tx_ack || (!is_agg && pid != tx_pid)) {
- DEBUG(entry->queue->rt2x00dev,
- "TX status report missed for queue %d entry %d\n",
- entry->queue->qid, entry->entry_idx);
+ rt2x00_dbg(entry->queue->rt2x00dev,
+ "TX status report missed for queue %d entry %d\n",
+ entry->queue->qid, entry->entry_idx);
return TXDONE_UNKNOWN;
}
@@ -566,8 +565,8 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
if (unlikely(rt2x00queue_empty(queue))) {
- WARNING(rt2x00dev, "Got TX status for an empty "
- "queue %u, dropping\n", qid);
+ rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
+ qid);
break;
}
@@ -575,8 +574,8 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))) {
- WARNING(rt2x00dev, "Data pending for entry %u "
- "in queue %u\n", entry->entry_idx, qid);
+ rt2x00_warn(rt2x00dev, "Data pending for entry %u in queue %u\n",
+ entry->entry_idx, qid);
break;
}
@@ -677,8 +676,8 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
*/
if (unlikely(rx_pkt_len == 0 ||
rx_pkt_len > entry->queue->data_size)) {
- ERROR(entry->queue->rt2x00dev,
- "Bad frame size %d, forcing to 0\n", rx_pkt_len);
+ rt2x00_err(entry->queue->rt2x00dev,
+ "Bad frame size %d, forcing to 0\n", rx_pkt_len);
return;
}
@@ -730,11 +729,6 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
* Process the RXWI structure.
*/
rt2800_process_rxwi(entry, rxdesc);
-
- /*
- * Remove RXWI descriptor from start of buffer.
- */
- skb_pull(entry->skb, entry->queue->desc_size - RXINFO_DESC_SIZE);
}
/*
@@ -858,21 +852,24 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
static const struct data_queue_desc rt2800usb_queue_rx = {
.entry_num = 128,
.data_size = AGGREGATION_SIZE,
- .desc_size = RXINFO_DESC_SIZE + RXWI_DESC_SIZE,
+ .desc_size = RXINFO_DESC_SIZE,
+ .winfo_size = RXWI_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
};
static const struct data_queue_desc rt2800usb_queue_tx = {
.entry_num = 16,
.data_size = AGGREGATION_SIZE,
- .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
+ .desc_size = TXINFO_DESC_SIZE,
+ .winfo_size = TXWI_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
};
static const struct data_queue_desc rt2800usb_queue_bcn = {
.entry_num = 8,
.data_size = MGMT_FRAME_SIZE,
- .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
+ .desc_size = TXINFO_DESC_SIZE,
+ .winfo_size = TXWI_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
};
@@ -898,21 +895,24 @@ static const struct rt2x00_ops rt2800usb_ops = {
static const struct data_queue_desc rt2800usb_queue_rx_5592 = {
.entry_num = 128,
.data_size = AGGREGATION_SIZE,
- .desc_size = RXINFO_DESC_SIZE + RXWI_DESC_SIZE_5592,
+ .desc_size = RXINFO_DESC_SIZE,
+ .winfo_size = RXWI_DESC_SIZE_5592,
.priv_size = sizeof(struct queue_entry_priv_usb),
};
static const struct data_queue_desc rt2800usb_queue_tx_5592 = {
.entry_num = 16,
.data_size = AGGREGATION_SIZE,
- .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE_5592,
+ .desc_size = TXINFO_DESC_SIZE,
+ .winfo_size = TXWI_DESC_SIZE_5592,
.priv_size = sizeof(struct queue_entry_priv_usb),
};
static const struct data_queue_desc rt2800usb_queue_bcn_5592 = {
.entry_num = 8,
.data_size = MGMT_FRAME_SIZE,
- .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE_5592,
+ .desc_size = TXINFO_DESC_SIZE,
+ .winfo_size = TXWI_DESC_SIZE_5592,
.priv_size = sizeof(struct queue_entry_priv_usb),
};
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 0d02d16ca166..7510723a8c37 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -54,47 +54,36 @@
#define DRV_VERSION "2.3.0"
#define DRV_PROJECT "http://rt2x00.serialmonkey.com"
-/*
- * Debug definitions.
+/* Debug definitions.
* Debug output has to be enabled during compile time.
*/
-#define DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, __args...) \
- printk(__kernlvl "%s -> %s: %s - " __msg, \
- wiphy_name((__dev)->hw->wiphy), __func__, __lvl, ##__args)
-
-#define DEBUG_PRINTK_PROBE(__kernlvl, __lvl, __msg, __args...) \
- printk(__kernlvl "%s -> %s: %s - " __msg, \
- KBUILD_MODNAME, __func__, __lvl, ##__args)
-
#ifdef CONFIG_RT2X00_DEBUG
-#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \
- DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, ##__args)
-#else
-#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \
- do { } while (0)
+#define DEBUG
#endif /* CONFIG_RT2X00_DEBUG */
-/*
- * Various debug levels.
- * The debug levels PANIC and ERROR both indicate serious problems,
- * for this reason they should never be ignored.
- * The special ERROR_PROBE message is for messages that are generated
- * when the rt2x00_dev is not yet initialized.
+/* Utility printing macros
+ * rt2x00_probe_err is for messages when rt2x00_dev is uninitialized
*/
-#define PANIC(__dev, __msg, __args...) \
- DEBUG_PRINTK_MSG(__dev, KERN_CRIT, "Panic", __msg, ##__args)
-#define ERROR(__dev, __msg, __args...) \
- DEBUG_PRINTK_MSG(__dev, KERN_ERR, "Error", __msg, ##__args)
-#define ERROR_PROBE(__msg, __args...) \
- DEBUG_PRINTK_PROBE(KERN_ERR, "Error", __msg, ##__args)
-#define WARNING(__dev, __msg, __args...) \
- DEBUG_PRINTK_MSG(__dev, KERN_WARNING, "Warning", __msg, ##__args)
-#define INFO(__dev, __msg, __args...) \
- DEBUG_PRINTK_MSG(__dev, KERN_INFO, "Info", __msg, ##__args)
-#define DEBUG(__dev, __msg, __args...) \
- DEBUG_PRINTK(__dev, KERN_DEBUG, "Debug", __msg, ##__args)
-#define EEPROM(__dev, __msg, __args...) \
- DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args)
+#define rt2x00_probe_err(fmt, ...) \
+ printk(KERN_ERR KBUILD_MODNAME ": %s: Error - " fmt, \
+ __func__, ##__VA_ARGS__)
+#define rt2x00_err(dev, fmt, ...) \
+ wiphy_err((dev)->hw->wiphy, "%s: Error - " fmt, \
+ __func__, ##__VA_ARGS__)
+#define rt2x00_warn(dev, fmt, ...) \
+ wiphy_warn((dev)->hw->wiphy, "%s: Warning - " fmt, \
+ __func__, ##__VA_ARGS__)
+#define rt2x00_info(dev, fmt, ...) \
+ wiphy_info((dev)->hw->wiphy, "%s: Info - " fmt, \
+ __func__, ##__VA_ARGS__)
+
+/* Various debug levels */
+#define rt2x00_dbg(dev, fmt, ...) \
+ wiphy_dbg((dev)->hw->wiphy, "%s: Debug - " fmt, \
+ __func__, ##__VA_ARGS__)
+#define rt2x00_eeprom_dbg(dev, fmt, ...) \
+ wiphy_dbg((dev)->hw->wiphy, "%s: EEPROM recovery - " fmt, \
+ __func__, ##__VA_ARGS__)
/*
* Duration calculations
@@ -1101,9 +1090,9 @@ static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev,
rt2x00dev->chip.rf = rf;
rt2x00dev->chip.rev = rev;
- INFO(rt2x00dev,
- "Chipset detected - rt: %04x, rf: %04x, rev: %04x.\n",
- rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev);
+ rt2x00_info(rt2x00dev, "Chipset detected - rt: %04x, rf: %04x, rev: %04x\n",
+ rt2x00dev->chip.rt, rt2x00dev->chip.rf,
+ rt2x00dev->chip.rev);
}
static inline void rt2x00_set_rt(struct rt2x00_dev *rt2x00dev,
@@ -1112,15 +1101,16 @@ static inline void rt2x00_set_rt(struct rt2x00_dev *rt2x00dev,
rt2x00dev->chip.rt = rt;
rt2x00dev->chip.rev = rev;
- INFO(rt2x00dev, "RT chipset %04x, rev %04x detected\n",
- rt2x00dev->chip.rt, rt2x00dev->chip.rev);
+ rt2x00_info(rt2x00dev, "RT chipset %04x, rev %04x detected\n",
+ rt2x00dev->chip.rt, rt2x00dev->chip.rev);
}
static inline void rt2x00_set_rf(struct rt2x00_dev *rt2x00dev, const u16 rf)
{
rt2x00dev->chip.rf = rf;
- INFO(rt2x00dev, "RF chipset %04x detected\n", rt2x00dev->chip.rf);
+ rt2x00_info(rt2x00dev, "RF chipset %04x detected\n",
+ rt2x00dev->chip.rf);
}
static inline bool rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt)
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 49a63e973934..8cb43f8f3efc 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -184,7 +184,7 @@ static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
/*
* Initialize center channel to current channel.
*/
- center_channel = spec->channels[conf->channel->hw_value].channel;
+ center_channel = spec->channels[conf->chandef.chan->hw_value].channel;
/*
* Adjust center channel to HT40+ and HT40- operation.
@@ -199,7 +199,7 @@ static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
return i;
WARN_ON(1);
- return conf->channel->hw_value;
+ return conf->chandef.chan->hw_value;
}
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
@@ -227,7 +227,7 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
hw_value = rt2x00ht_center_channel(rt2x00dev, conf);
} else {
clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
- hw_value = conf->channel->hw_value;
+ hw_value = conf->chandef.chan->hw_value;
}
memcpy(&libconf.rf,
@@ -279,8 +279,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
else
clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
- rt2x00dev->curr_band = conf->channel->band;
- rt2x00dev->curr_freq = conf->channel->center_freq;
+ rt2x00dev->curr_band = conf->chandef.chan->band;
+ rt2x00dev->curr_freq = conf->chandef.chan->center_freq;
rt2x00dev->tx_power = conf->power_level;
rt2x00dev->short_retry = conf->short_frame_max_tx_count;
rt2x00dev->long_retry = conf->long_frame_max_tx_count;
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 3bb8cafbac59..fe7a7f63a9ed 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -174,7 +174,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
do_gettimeofday(&timestamp);
if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
- DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n");
+ rt2x00_dbg(rt2x00dev, "txrx dump queue length exceeded\n");
return;
}
@@ -185,7 +185,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
skbcopy = alloc_skb(sizeof(*dump_hdr) + skbdesc->desc_len + data_len,
GFP_ATOMIC);
if (!skbcopy) {
- DEBUG(rt2x00dev, "Failed to copy skb for dump.\n");
+ rt2x00_dbg(rt2x00dev, "Failed to copy skb for dump\n");
return;
}
@@ -657,7 +657,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
intf = kzalloc(sizeof(struct rt2x00debug_intf), GFP_KERNEL);
if (!intf) {
- ERROR(rt2x00dev, "Failed to allocate debug handler.\n");
+ rt2x00_err(rt2x00dev, "Failed to allocate debug handler\n");
return;
}
@@ -760,7 +760,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
exit:
rt2x00debug_deregister(rt2x00dev);
- ERROR(rt2x00dev, "Failed to register debug handler.\n");
+ rt2x00_err(rt2x00dev, "Failed to register debug handler\n");
}
void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 189744db65e0..90dc14336980 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -171,7 +171,7 @@ static void rt2x00lib_autowakeup(struct work_struct *work)
return;
if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
- ERROR(rt2x00dev, "Device failed to wakeup.\n");
+ rt2x00_err(rt2x00dev, "Device failed to wakeup\n");
clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
}
@@ -673,9 +673,8 @@ static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
break;
}
- WARNING(rt2x00dev, "Frame received with unrecognized signal, "
- "mode=0x%.4x, signal=0x%.4x, type=%d.\n",
- rxdesc->rate_mode, signal, type);
+ rt2x00_warn(rt2x00dev, "Frame received with unrecognized signal, mode=0x%.4x, signal=0x%.4x, type=%d\n",
+ rxdesc->rate_mode, signal, type);
return 0;
}
@@ -720,8 +719,8 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
*/
if (unlikely(rxdesc.size == 0 ||
rxdesc.size > entry->queue->data_size)) {
- ERROR(rt2x00dev, "Wrong frame size %d max %d.\n",
- rxdesc.size, entry->queue->data_size);
+ rt2x00_err(rt2x00dev, "Wrong frame size %d max %d\n",
+ rxdesc.size, entry->queue->data_size);
dev_kfree_skb(entry->skb);
goto renew_skb;
}
@@ -1006,7 +1005,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
exit_free_channels:
kfree(channels);
- ERROR(rt2x00dev, "Allocation ieee80211 modes failed.\n");
+ rt2x00_err(rt2x00dev, "Allocation ieee80211 modes failed\n");
return -ENOMEM;
}
@@ -1337,7 +1336,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
*/
retval = rt2x00dev->ops->lib->probe_hw(rt2x00dev);
if (retval) {
- ERROR(rt2x00dev, "Failed to allocate device.\n");
+ rt2x00_err(rt2x00dev, "Failed to allocate device\n");
goto exit;
}
@@ -1353,7 +1352,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
*/
retval = rt2x00lib_probe_hw(rt2x00dev);
if (retval) {
- ERROR(rt2x00dev, "Failed to initialize hw.\n");
+ rt2x00_err(rt2x00dev, "Failed to initialize hw\n");
goto exit;
}
@@ -1451,7 +1450,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
#ifdef CONFIG_PM
int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)
{
- DEBUG(rt2x00dev, "Going to sleep.\n");
+ rt2x00_dbg(rt2x00dev, "Going to sleep\n");
/*
* Prevent mac80211 from accessing driver while suspended.
@@ -1482,8 +1481,7 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)
* device is as good as disabled.
*/
if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_SLEEP))
- WARNING(rt2x00dev, "Device failed to enter sleep state, "
- "continue suspending.\n");
+ rt2x00_warn(rt2x00dev, "Device failed to enter sleep state, continue suspending\n");
return 0;
}
@@ -1491,7 +1489,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_suspend);
int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
{
- DEBUG(rt2x00dev, "Waking up.\n");
+ rt2x00_dbg(rt2x00dev, "Waking up\n");
/*
* Restore/enable extra components.
diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c
index f316aad30612..1b4254b4272d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00firmware.c
+++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c
@@ -42,28 +42,28 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
*/
fw_name = rt2x00dev->ops->lib->get_firmware_name(rt2x00dev);
if (!fw_name) {
- ERROR(rt2x00dev,
- "Invalid firmware filename.\n"
- "Please file bug report to %s.\n", DRV_PROJECT);
+ rt2x00_err(rt2x00dev,
+ "Invalid firmware filename\n"
+ "Please file bug report to %s\n", DRV_PROJECT);
return -EINVAL;
}
- INFO(rt2x00dev, "Loading firmware file '%s'.\n", fw_name);
+ rt2x00_info(rt2x00dev, "Loading firmware file '%s'\n", fw_name);
retval = request_firmware(&fw, fw_name, device);
if (retval) {
- ERROR(rt2x00dev, "Failed to request Firmware.\n");
+ rt2x00_err(rt2x00dev, "Failed to request Firmware\n");
return retval;
}
if (!fw || !fw->size || !fw->data) {
- ERROR(rt2x00dev, "Failed to read Firmware.\n");
+ rt2x00_err(rt2x00dev, "Failed to read Firmware\n");
release_firmware(fw);
return -ENOENT;
}
- INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n",
- fw->data[fw->size - 4], fw->data[fw->size - 3]);
+ rt2x00_info(rt2x00dev, "Firmware detected - version: %d.%d\n",
+ fw->data[fw->size - 4], fw->data[fw->size - 3]);
snprintf(rt2x00dev->hw->wiphy->fw_version,
sizeof(rt2x00dev->hw->wiphy->fw_version), "%d.%d",
fw->data[fw->size - 4], fw->data[fw->size - 3]);
@@ -73,15 +73,14 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
case FW_OK:
break;
case FW_BAD_CRC:
- ERROR(rt2x00dev, "Firmware checksum error.\n");
+ rt2x00_err(rt2x00dev, "Firmware checksum error\n");
goto exit;
case FW_BAD_LENGTH:
- ERROR(rt2x00dev,
- "Invalid firmware file length (len=%zu)\n", fw->size);
+ rt2x00_err(rt2x00dev, "Invalid firmware file length (len=%zu)\n",
+ fw->size);
goto exit;
case FW_BAD_VERSION:
- ERROR(rt2x00dev,
- "Current firmware does not support detected chipset.\n");
+ rt2x00_err(rt2x00dev, "Current firmware does not support detected chipset\n");
goto exit;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c
index 8679d781a264..997a6c89e66e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00leds.c
+++ b/drivers/net/wireless/rt2x00/rt2x00leds.c
@@ -113,7 +113,7 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
retval = led_classdev_register(device, &led->led_dev);
if (retval) {
- ERROR(rt2x00dev, "Failed to register led handler.\n");
+ rt2x00_err(rt2x00dev, "Failed to register led handler\n");
return retval;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 9161c02d8ff9..f883802f3505 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -46,7 +46,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
skb = dev_alloc_skb(data_length + rt2x00dev->hw->extra_tx_headroom);
if (unlikely(!skb)) {
- WARNING(rt2x00dev, "Failed to create RTS/CTS frame.\n");
+ rt2x00_warn(rt2x00dev, "Failed to create RTS/CTS frame\n");
return -ENOMEM;
}
@@ -93,7 +93,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
retval = rt2x00queue_write_tx_frame(queue, skb, true);
if (retval) {
dev_kfree_skb_any(skb);
- WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n");
+ rt2x00_warn(rt2x00dev, "Failed to send RTS/CTS frame\n");
}
return retval;
@@ -126,9 +126,9 @@ void rt2x00mac_tx(struct ieee80211_hw *hw,
queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
if (unlikely(!queue)) {
- ERROR(rt2x00dev,
- "Attempt to send packet over invalid queue %d.\n"
- "Please file bug report to %s.\n", qid, DRV_PROJECT);
+ rt2x00_err(rt2x00dev,
+ "Attempt to send packet over invalid queue %d\n"
+ "Please file bug report to %s\n", qid, DRV_PROJECT);
goto exit_free_skb;
}
@@ -731,9 +731,10 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw,
queue->aifs = params->aifs;
queue->txop = params->txop;
- DEBUG(rt2x00dev,
- "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d, TXop: %d.\n",
- queue_idx, queue->cw_min, queue->cw_max, queue->aifs, queue->txop);
+ rt2x00_dbg(rt2x00dev,
+ "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d, TXop: %d\n",
+ queue_idx, queue->cw_min, queue->cw_max, queue->aifs,
+ queue->txop);
return 0;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.c b/drivers/net/wireless/rt2x00/rt2x00mmio.c
index d84a680ba0c9..64b06c6abe58 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mmio.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mmio.c
@@ -34,10 +34,10 @@
/*
* Register access.
*/
-int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- const struct rt2x00_field32 field,
- u32 *reg)
+int rt2x00mmio_regbusy_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ const struct rt2x00_field32 field,
+ u32 *reg)
{
unsigned int i;
@@ -45,7 +45,7 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
return 0;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, offset, reg);
+ rt2x00mmio_register_read(rt2x00dev, offset, reg);
if (!rt2x00_get_field32(*reg, field))
return 1;
udelay(REGISTER_BUSY_DELAY);
@@ -57,13 +57,13 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
return 0;
}
-EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);
+EXPORT_SYMBOL_GPL(rt2x00mmio_regbusy_read);
-bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
+bool rt2x00mmio_rxdone(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue = rt2x00dev->rx;
struct queue_entry *entry;
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
struct skb_frame_desc *skbdesc;
int max_rx = 16;
@@ -96,24 +96,24 @@ bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
return !max_rx;
}
-EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
+EXPORT_SYMBOL_GPL(rt2x00mmio_rxdone);
-void rt2x00pci_flush_queue(struct data_queue *queue, bool drop)
+void rt2x00mmio_flush_queue(struct data_queue *queue, bool drop)
{
unsigned int i;
for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++)
msleep(10);
}
-EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue);
+EXPORT_SYMBOL_GPL(rt2x00mmio_flush_queue);
/*
* Device initialization handlers.
*/
-static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
- struct data_queue *queue)
+static int rt2x00mmio_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
+ struct data_queue *queue)
{
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
void *addr;
dma_addr_t dma;
unsigned int i;
@@ -141,10 +141,10 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
return 0;
}
-static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
- struct data_queue *queue)
+static void rt2x00mmio_free_queue_dma(struct rt2x00_dev *rt2x00dev,
+ struct data_queue *queue)
{
- struct queue_entry_priv_pci *entry_priv =
+ struct queue_entry_priv_mmio *entry_priv =
queue->entries[0].priv_data;
if (entry_priv->desc)
@@ -154,7 +154,7 @@ static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
entry_priv->desc = NULL;
}
-int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
+int rt2x00mmio_initialize(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
int status;
@@ -163,7 +163,7 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
* Allocate DMA
*/
queue_for_each(rt2x00dev, queue) {
- status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue);
+ status = rt2x00mmio_alloc_queue_dma(rt2x00dev, queue);
if (status)
goto exit;
}
@@ -175,8 +175,8 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
rt2x00dev->ops->lib->irq_handler,
IRQF_SHARED, rt2x00dev->name, rt2x00dev);
if (status) {
- ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
- rt2x00dev->irq, status);
+ rt2x00_err(rt2x00dev, "IRQ %d allocation failed (error %d)\n",
+ rt2x00dev->irq, status);
goto exit;
}
@@ -184,13 +184,13 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
exit:
queue_for_each(rt2x00dev, queue)
- rt2x00pci_free_queue_dma(rt2x00dev, queue);
+ rt2x00mmio_free_queue_dma(rt2x00dev, queue);
return status;
}
-EXPORT_SYMBOL_GPL(rt2x00pci_initialize);
+EXPORT_SYMBOL_GPL(rt2x00mmio_initialize);
-void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
+void rt2x00mmio_uninitialize(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
@@ -203,9 +203,9 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
* Free DMA
*/
queue_for_each(rt2x00dev, queue)
- rt2x00pci_free_queue_dma(rt2x00dev, queue);
+ rt2x00mmio_free_queue_dma(rt2x00dev, queue);
}
-EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
+EXPORT_SYMBOL_GPL(rt2x00mmio_uninitialize);
/*
* rt2x00mmio module information.
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.h b/drivers/net/wireless/rt2x00/rt2x00mmio.h
index 4ecaf60175bf..cda3dbcf7ead 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mmio.h
+++ b/drivers/net/wireless/rt2x00/rt2x00mmio.h
@@ -31,37 +31,37 @@
/*
* Register access.
*/
-static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- u32 *value)
+static inline void rt2x00mmio_register_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u32 *value)
{
*value = readl(rt2x00dev->csr.base + offset);
}
-static inline void rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- void *value, const u32 length)
+static inline void rt2x00mmio_register_multiread(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ void *value, const u32 length)
{
memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
}
-static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- u32 value)
+static inline void rt2x00mmio_register_write(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u32 value)
{
writel(value, rt2x00dev->csr.base + offset);
}
-static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- const void *value,
- const u32 length)
+static inline void rt2x00mmio_register_multiwrite(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ const void *value,
+ const u32 length)
{
__iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2);
}
/**
- * rt2x00pci_regbusy_read - Read from register with busy check
+ * rt2x00mmio_regbusy_read - Read from register with busy check
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
* @offset: Register offset
* @field: Field to check if register is busy
@@ -73,47 +73,47 @@ static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
* is not read after a certain timeout, this function will return
* FALSE.
*/
-int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- const struct rt2x00_field32 field,
- u32 *reg);
+int rt2x00mmio_regbusy_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ const struct rt2x00_field32 field,
+ u32 *reg);
/**
- * struct queue_entry_priv_pci: Per entry PCI specific information
+ * struct queue_entry_priv_mmio: Per entry PCI specific information
*
* @desc: Pointer to device descriptor
* @desc_dma: DMA pointer to &desc.
* @data: Pointer to device's entry memory.
* @data_dma: DMA pointer to &data.
*/
-struct queue_entry_priv_pci {
+struct queue_entry_priv_mmio {
__le32 *desc;
dma_addr_t desc_dma;
};
/**
- * rt2x00pci_rxdone - Handle RX done events
+ * rt2x00mmio_rxdone - Handle RX done events
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
*
* Returns true if there are still rx frames pending and false if all
* pending rx frames were processed.
*/
-bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
+bool rt2x00mmio_rxdone(struct rt2x00_dev *rt2x00dev);
/**
- * rt2x00pci_flush_queue - Flush data queue
+ * rt2x00mmio_flush_queue - Flush data queue
* @queue: Data queue to stop
* @drop: True to drop all pending frames.
*
* This will wait for a maximum of 100ms, waiting for the queues
* to become empty.
*/
-void rt2x00pci_flush_queue(struct data_queue *queue, bool drop);
+void rt2x00mmio_flush_queue(struct data_queue *queue, bool drop);
/*
* Device initialization handlers.
*/
-int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev);
-void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev);
+int rt2x00mmio_initialize(struct rt2x00_dev *rt2x00dev);
+void rt2x00mmio_uninitialize(struct rt2x00_dev *rt2x00dev);
#endif /* RT2X00MMIO_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index e87865e33113..dc49e525ae5e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -68,7 +68,7 @@ static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev)
return 0;
exit:
- ERROR_PROBE("Failed to allocate registers.\n");
+ rt2x00_probe_err("Failed to allocate registers\n");
rt2x00pci_free_reg(rt2x00dev);
@@ -84,30 +84,30 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
retval = pci_enable_device(pci_dev);
if (retval) {
- ERROR_PROBE("Enable device failed.\n");
+ rt2x00_probe_err("Enable device failed\n");
return retval;
}
retval = pci_request_regions(pci_dev, pci_name(pci_dev));
if (retval) {
- ERROR_PROBE("PCI request regions failed.\n");
+ rt2x00_probe_err("PCI request regions failed\n");
goto exit_disable_device;
}
pci_set_master(pci_dev);
if (pci_set_mwi(pci_dev))
- ERROR_PROBE("MWI not available.\n");
+ rt2x00_probe_err("MWI not available\n");
if (dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) {
- ERROR_PROBE("PCI DMA not supported.\n");
+ rt2x00_probe_err("PCI DMA not supported\n");
retval = -EIO;
goto exit_release_regions;
}
hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
if (!hw) {
- ERROR_PROBE("Failed to allocate hardware.\n");
+ rt2x00_probe_err("Failed to allocate hardware\n");
retval = -ENOMEM;
goto exit_release_regions;
}
@@ -207,7 +207,7 @@ int rt2x00pci_resume(struct pci_dev *pci_dev)
if (pci_set_power_state(pci_dev, PCI_D0) ||
pci_enable_device(pci_dev)) {
- ERROR(rt2x00dev, "Failed to resume device.\n");
+ rt2x00_err(rt2x00dev, "Failed to resume device\n");
return -EIO;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 952a0490eb17..2c12311467a9 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -35,7 +35,8 @@
struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp)
{
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ struct data_queue *queue = entry->queue;
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
struct sk_buff *skb;
struct skb_frame_desc *skbdesc;
unsigned int frame_size;
@@ -46,7 +47,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp)
* The frame size includes descriptor size, because the
* hardware directly receive the frame into the skbuffer.
*/
- frame_size = entry->queue->data_size + entry->queue->desc_size;
+ frame_size = queue->data_size + queue->desc_size + queue->winfo_size;
/*
* The payload should be aligned to a 4-byte boundary,
@@ -531,10 +532,10 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry,
*/
if (unlikely(rt2x00dev->ops->lib->get_entry_state &&
rt2x00dev->ops->lib->get_entry_state(entry))) {
- ERROR(rt2x00dev,
- "Corrupt queue %d, accessing entry which is not ours.\n"
- "Please file bug report to %s.\n",
- entry->queue->qid, DRV_PROJECT);
+ rt2x00_err(rt2x00dev,
+ "Corrupt queue %d, accessing entry which is not ours\n"
+ "Please file bug report to %s\n",
+ entry->queue->qid, DRV_PROJECT);
return -EINVAL;
}
@@ -698,8 +699,8 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
spin_lock(&queue->tx_lock);
if (unlikely(rt2x00queue_full(queue))) {
- ERROR(queue->rt2x00dev,
- "Dropping frame due to full tx queue %d.\n", queue->qid);
+ rt2x00_err(queue->rt2x00dev, "Dropping frame due to full tx queue %d\n",
+ queue->qid);
ret = -ENOBUFS;
goto out;
}
@@ -708,10 +709,10 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
&entry->flags))) {
- ERROR(queue->rt2x00dev,
- "Arrived at non-free entry in the non-full queue %d.\n"
- "Please file bug report to %s.\n",
- queue->qid, DRV_PROJECT);
+ rt2x00_err(queue->rt2x00dev,
+ "Arrived at non-free entry in the non-full queue %d\n"
+ "Please file bug report to %s\n",
+ queue->qid, DRV_PROJECT);
ret = -EINVAL;
goto out;
}
@@ -842,9 +843,9 @@ bool rt2x00queue_for_each_entry(struct data_queue *queue,
unsigned int i;
if (unlikely(start >= Q_INDEX_MAX || end >= Q_INDEX_MAX)) {
- ERROR(queue->rt2x00dev,
- "Entry requested from invalid index range (%d - %d)\n",
- start, end);
+ rt2x00_err(queue->rt2x00dev,
+ "Entry requested from invalid index range (%d - %d)\n",
+ start, end);
return true;
}
@@ -891,8 +892,8 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
unsigned long irqflags;
if (unlikely(index >= Q_INDEX_MAX)) {
- ERROR(queue->rt2x00dev,
- "Entry requested from invalid index type (%d)\n", index);
+ rt2x00_err(queue->rt2x00dev, "Entry requested from invalid index type (%d)\n",
+ index);
return NULL;
}
@@ -912,8 +913,8 @@ void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index)
unsigned long irqflags;
if (unlikely(index >= Q_INDEX_MAX)) {
- ERROR(queue->rt2x00dev,
- "Index change on invalid index type (%d)\n", index);
+ rt2x00_err(queue->rt2x00dev,
+ "Index change on invalid index type (%d)\n", index);
return;
}
@@ -1073,7 +1074,8 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
* The queue flush has failed...
*/
if (unlikely(!rt2x00queue_empty(queue)))
- WARNING(queue->rt2x00dev, "Queue %d failed to flush\n", queue->qid);
+ rt2x00_warn(queue->rt2x00dev, "Queue %d failed to flush\n",
+ queue->qid);
/*
* Restore the queue to the previous status
@@ -1172,6 +1174,7 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue,
queue->threshold = DIV_ROUND_UP(qdesc->entry_num, 10);
queue->data_size = qdesc->data_size;
queue->desc_size = qdesc->desc_size;
+ queue->winfo_size = qdesc->winfo_size;
/*
* Allocate all queue entries.
@@ -1262,7 +1265,7 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
return 0;
exit:
- ERROR(rt2x00dev, "Queue entries allocation failed.\n");
+ rt2x00_err(rt2x00dev, "Queue entries allocation failed\n");
rt2x00queue_uninitialize(rt2x00dev);
@@ -1314,7 +1317,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
queue = kcalloc(rt2x00dev->data_queues, sizeof(*queue), GFP_KERNEL);
if (!queue) {
- ERROR(rt2x00dev, "Queue allocation failed.\n");
+ rt2x00_err(rt2x00dev, "Queue allocation failed\n");
return -ENOMEM;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 3d0137193da0..4a7b34e9261b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -479,7 +479,8 @@ struct data_queue {
unsigned short cw_max;
unsigned short data_size;
- unsigned short desc_size;
+ unsigned char desc_size;
+ unsigned char winfo_size;
unsigned short usb_endpoint;
unsigned short usb_maxpacket;
@@ -499,7 +500,8 @@ struct data_queue {
struct data_queue_desc {
unsigned short entry_num;
unsigned short data_size;
- unsigned short desc_size;
+ unsigned char desc_size;
+ unsigned char winfo_size;
unsigned short priv_size;
};
diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.c b/drivers/net/wireless/rt2x00/rt2x00soc.c
index 2aa5c38022f3..9271a5fce0a8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00soc.c
+++ b/drivers/net/wireless/rt2x00/rt2x00soc.c
@@ -68,7 +68,7 @@ static int rt2x00soc_alloc_reg(struct rt2x00_dev *rt2x00dev)
return 0;
exit:
- ERROR_PROBE("Failed to allocate registers.\n");
+ rt2x00_probe_err("Failed to allocate registers\n");
rt2x00soc_free_reg(rt2x00dev);
return -ENOMEM;
@@ -82,7 +82,7 @@ int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops)
hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
if (!hw) {
- ERROR_PROBE("Failed to allocate hardware.\n");
+ rt2x00_probe_err("Failed to allocate hardware\n");
return -ENOMEM;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 5e50d4ff9d21..88289873c0cf 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -70,9 +70,9 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
}
}
- ERROR(rt2x00dev,
- "Vendor Request 0x%02x failed for offset 0x%04x with error %d.\n",
- request, offset, status);
+ rt2x00_err(rt2x00dev,
+ "Vendor Request 0x%02x failed for offset 0x%04x with error %d\n",
+ request, offset, status);
return status;
}
@@ -91,7 +91,7 @@ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
* Check for Cache availability.
*/
if (unlikely(!rt2x00dev->csr.cache || buffer_length > CSR_CACHE_SIZE)) {
- ERROR(rt2x00dev, "CSR cache not available.\n");
+ rt2x00_err(rt2x00dev, "CSR cache not available\n");
return -ENOMEM;
}
@@ -157,8 +157,8 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "Indirect register access failed: "
- "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
+ rt2x00_err(rt2x00dev, "Indirect register access failed: offset=0x%.08x, value=0x%.08x\n",
+ offset, *reg);
*reg = ~0;
return 0;
@@ -307,7 +307,7 @@ static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void *data)
status = skb_padto(entry->skb, length);
if (unlikely(status)) {
/* TODO: report something more appropriate than IO_FAILED. */
- WARNING(rt2x00dev, "TX SKB padding error, out of memory\n");
+ rt2x00_warn(rt2x00dev, "TX SKB padding error, out of memory\n");
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
rt2x00lib_dmadone(entry);
@@ -520,8 +520,8 @@ EXPORT_SYMBOL_GPL(rt2x00usb_flush_queue);
static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
{
- WARNING(queue->rt2x00dev, "TX queue %d DMA timed out,"
- " invoke forced forced reset\n", queue->qid);
+ rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced forced reset\n",
+ queue->qid);
rt2x00queue_flush_queue(queue, true);
}
@@ -622,7 +622,7 @@ static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev)
* At least 1 endpoint for RX and 1 endpoint for TX must be available.
*/
if (!rt2x00dev->rx->usb_endpoint || !rt2x00dev->tx->usb_endpoint) {
- ERROR(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n");
+ rt2x00_err(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n");
return -EPIPE;
}
@@ -775,7 +775,7 @@ static int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev)
return 0;
exit:
- ERROR_PROBE("Failed to allocate registers.\n");
+ rt2x00_probe_err("Failed to allocate registers\n");
rt2x00usb_free_reg(rt2x00dev);
@@ -795,7 +795,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
if (!hw) {
- ERROR_PROBE("Failed to allocate hardware.\n");
+ rt2x00_probe_err("Failed to allocate hardware\n");
retval = -ENOMEM;
goto exit_put_device;
}
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 9e3c8ff53e3f..0dc8180e251b 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -58,12 +58,12 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
* and we will print an error.
*/
#define WAIT_FOR_BBP(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
+ rt2x00mmio_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
#define WAIT_FOR_RF(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
+ rt2x00mmio_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
#define WAIT_FOR_MCU(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), H2M_MAILBOX_CSR, \
- H2M_MAILBOX_CSR_OWNER, (__reg))
+ rt2x00mmio_regbusy_read((__dev), H2M_MAILBOX_CSR, \
+ H2M_MAILBOX_CSR_OWNER, (__reg))
static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
@@ -83,7 +83,7 @@ static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR3, reg);
}
mutex_unlock(&rt2x00dev->csr_mutex);
@@ -110,7 +110,7 @@ static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR3, reg);
WAIT_FOR_BBP(rt2x00dev, &reg);
}
@@ -138,7 +138,7 @@ static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0);
rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR4, reg);
rt2x00_rf_write(rt2x00dev, word, value);
}
@@ -162,12 +162,12 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_CMD_TOKEN, token);
rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG0, arg0);
rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, HOST_CMD_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, HOST_CMD_CSR, &reg);
rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
rt2x00_set_field32(&reg, HOST_CMD_CSR_INTERRUPT_MCU, 1);
- rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, HOST_CMD_CSR, reg);
}
mutex_unlock(&rt2x00dev->csr_mutex);
@@ -179,7 +179,7 @@ static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
@@ -201,15 +201,15 @@ static void rt61pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
rt2x00_set_field32(&reg, E2PROM_CSR_CHIP_SELECT,
!!eeprom->reg_chip_select);
- rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, E2PROM_CSR, reg);
}
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
static const struct rt2x00debug rt61pci_rt2x00debug = {
.owner = THIS_MODULE,
.csr = {
- .read = rt2x00pci_register_read,
- .write = rt2x00pci_register_write,
+ .read = rt2x00mmio_register_read,
+ .write = rt2x00mmio_register_write,
.flags = RT2X00DEBUGFS_OFFSET,
.word_base = CSR_REG_BASE,
.word_size = sizeof(u32),
@@ -243,7 +243,7 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
return rt2x00_get_field32(reg, MAC_CSR13_VAL5);
}
@@ -294,10 +294,10 @@ static int rt61pci_blink_set(struct led_classdev *led_cdev,
container_of(led_cdev, struct rt2x00_led, led_dev);
u32 reg;
- rt2x00pci_register_read(led->rt2x00dev, MAC_CSR14, &reg);
+ rt2x00mmio_register_read(led->rt2x00dev, MAC_CSR14, &reg);
rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
- rt2x00pci_register_write(led->rt2x00dev, MAC_CSR14, reg);
+ rt2x00mmio_register_write(led->rt2x00dev, MAC_CSR14, reg);
return 0;
}
@@ -339,7 +339,7 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
*/
mask = (0xf << crypto->bssidx);
- rt2x00pci_register_read(rt2x00dev, SEC_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, &reg);
reg &= mask;
if (reg && reg == mask)
@@ -358,8 +358,8 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
sizeof(key_entry.rx_mic));
reg = SHARED_KEY_ENTRY(key->hw_key_idx);
- rt2x00pci_register_multiwrite(rt2x00dev, reg,
- &key_entry, sizeof(key_entry));
+ rt2x00mmio_register_multiwrite(rt2x00dev, reg,
+ &key_entry, sizeof(key_entry));
/*
* The cipher types are stored over 2 registers.
@@ -372,16 +372,16 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
field.bit_offset = (3 * key->hw_key_idx);
field.bit_mask = 0x7 << field.bit_offset;
- rt2x00pci_register_read(rt2x00dev, SEC_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR1, &reg);
rt2x00_set_field32(&reg, field, crypto->cipher);
- rt2x00pci_register_write(rt2x00dev, SEC_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, reg);
} else {
field.bit_offset = (3 * (key->hw_key_idx - 8));
field.bit_mask = 0x7 << field.bit_offset;
- rt2x00pci_register_read(rt2x00dev, SEC_CSR5, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR5, &reg);
rt2x00_set_field32(&reg, field, crypto->cipher);
- rt2x00pci_register_write(rt2x00dev, SEC_CSR5, reg);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, reg);
}
/*
@@ -404,12 +404,12 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
*/
mask = 1 << key->hw_key_idx;
- rt2x00pci_register_read(rt2x00dev, SEC_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, &reg);
if (crypto->cmd == SET_KEY)
reg |= mask;
else if (crypto->cmd == DISABLE_KEY)
reg &= ~mask;
- rt2x00pci_register_write(rt2x00dev, SEC_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR0, reg);
return 0;
}
@@ -433,10 +433,10 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
* When both registers are full, we drop the key.
* Otherwise, we use the first invalid entry.
*/
- rt2x00pci_register_read(rt2x00dev, SEC_CSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, &reg);
if (reg && reg == ~0) {
key->hw_key_idx = 32;
- rt2x00pci_register_read(rt2x00dev, SEC_CSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, &reg);
if (reg && reg == ~0)
return -ENOSPC;
}
@@ -458,21 +458,21 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
addr_entry.cipher = crypto->cipher;
reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
- rt2x00pci_register_multiwrite(rt2x00dev, reg,
- &key_entry, sizeof(key_entry));
+ rt2x00mmio_register_multiwrite(rt2x00dev, reg,
+ &key_entry, sizeof(key_entry));
reg = PAIRWISE_TA_ENTRY(key->hw_key_idx);
- rt2x00pci_register_multiwrite(rt2x00dev, reg,
- &addr_entry, sizeof(addr_entry));
+ rt2x00mmio_register_multiwrite(rt2x00dev, reg,
+ &addr_entry, sizeof(addr_entry));
/*
* Enable pairwise lookup table for given BSS idx.
* Without this, received frames will not be decrypted
* by the hardware.
*/
- rt2x00pci_register_read(rt2x00dev, SEC_CSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR4, &reg);
reg |= (1 << crypto->bssidx);
- rt2x00pci_register_write(rt2x00dev, SEC_CSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR4, reg);
/*
* The driver does not support the IV/EIV generation
@@ -495,21 +495,21 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
if (key->hw_key_idx < 32) {
mask = 1 << key->hw_key_idx;
- rt2x00pci_register_read(rt2x00dev, SEC_CSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, &reg);
if (crypto->cmd == SET_KEY)
reg |= mask;
else if (crypto->cmd == DISABLE_KEY)
reg &= ~mask;
- rt2x00pci_register_write(rt2x00dev, SEC_CSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR2, reg);
} else {
mask = 1 << (key->hw_key_idx - 32);
- rt2x00pci_register_read(rt2x00dev, SEC_CSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, &reg);
if (crypto->cmd == SET_KEY)
reg |= mask;
else if (crypto->cmd == DISABLE_KEY)
reg &= ~mask;
- rt2x00pci_register_write(rt2x00dev, SEC_CSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR3, reg);
}
return 0;
@@ -526,7 +526,7 @@ static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,
* and broadcast frames will always be accepted since
* there is no filter for it at this time.
*/
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
@@ -544,7 +544,7 @@ static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
!(filter_flags & FIF_CONTROL));
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
}
static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
@@ -558,9 +558,9 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
/*
* Enable synchronisation.
*/
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
}
if (flags & CONFIG_UPDATE_MAC) {
@@ -568,8 +568,8 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
conf->mac[1] = cpu_to_le32(reg);
- rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2,
- conf->mac, sizeof(conf->mac));
+ rt2x00mmio_register_multiwrite(rt2x00dev, MAC_CSR2,
+ conf->mac, sizeof(conf->mac));
}
if (flags & CONFIG_UPDATE_BSSID) {
@@ -577,8 +577,9 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
conf->bssid[1] = cpu_to_le32(reg);
- rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4,
- conf->bssid, sizeof(conf->bssid));
+ rt2x00mmio_register_multiwrite(rt2x00dev, MAC_CSR4,
+ conf->bssid,
+ sizeof(conf->bssid));
}
}
@@ -588,40 +589,40 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32);
rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, &reg);
rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
!!erp->short_preamble);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR4, reg);
}
if (changed & BSS_CHANGED_BASIC_RATES)
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR5,
- erp->basic_rates);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR5,
+ erp->basic_rates);
if (changed & BSS_CHANGED_BEACON_INT) {
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
erp->beacon_int * 16);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
}
if (changed & BSS_CHANGED_ERP_SLOT) {
- rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, &reg);
rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR8, &reg);
rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR8, reg);
}
}
@@ -714,7 +715,7 @@ static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
rt2x00_set_field32(&reg, MAC_CSR13_DIR4, 0);
rt2x00_set_field32(&reg, MAC_CSR13_VAL4, p1);
@@ -722,7 +723,7 @@ static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, MAC_CSR13_DIR3, 0);
rt2x00_set_field32(&reg, MAC_CSR13_VAL3, !p2);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, reg);
}
static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev,
@@ -821,14 +822,14 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
rt61pci_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
- rt2x00pci_register_read(rt2x00dev, PHY_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, PHY_CSR0, &reg);
rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR0, reg);
if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325))
rt61pci_config_antenna_5x(rt2x00dev, ant);
@@ -848,7 +849,7 @@ static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
u16 eeprom;
short lna_gain = 0;
- if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
+ if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) {
if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))
lna_gain += 14;
@@ -928,7 +929,7 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, &reg);
rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1);
rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_STEP, 0);
rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0);
@@ -936,7 +937,7 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
libconf->conf->long_frame_max_tx_count);
rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT,
libconf->conf->short_frame_max_tx_count);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR4, reg);
}
static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
@@ -948,7 +949,7 @@ static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
u32 reg;
if (state == STATE_SLEEP) {
- rt2x00pci_register_read(rt2x00dev, MAC_CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, &reg);
rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
rt2x00dev->beacon_int - 10);
rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
@@ -957,27 +958,29 @@ static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
/* We must first disable autowake before it can be enabled */
rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg);
rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg);
- rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000005);
- rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x0000001c);
- rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000060);
+ rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR,
+ 0x00000005);
+ rt2x00mmio_register_write(rt2x00dev, IO_CNTL_CSR, 0x0000001c);
+ rt2x00mmio_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000060);
rt61pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0);
} else {
- rt2x00pci_register_read(rt2x00dev, MAC_CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, &reg);
rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN, 0);
rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0);
rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg);
- rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007);
- rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x00000018);
- rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000020);
+ rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR,
+ 0x00000007);
+ rt2x00mmio_register_write(rt2x00dev, IO_CNTL_CSR, 0x00000018);
+ rt2x00mmio_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000020);
rt61pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0);
}
@@ -1013,13 +1016,13 @@ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,
/*
* Update FCS error count from register.
*/
- rt2x00pci_register_read(rt2x00dev, STA_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, STA_CSR0, &reg);
qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
- rt2x00pci_register_read(rt2x00dev, STA_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, STA_CSR1, &reg);
qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
}
@@ -1138,16 +1141,16 @@ static void rt61pci_start_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
break;
default:
break;
@@ -1161,24 +1164,24 @@ static void rt61pci_kick_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_AC_VO:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_VI:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BE:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BK:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
default:
break;
@@ -1192,36 +1195,36 @@ static void rt61pci_stop_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_AC_VO:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC0, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_VI:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BE:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BK:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
/*
* Wait for possibly running tbtt tasklets.
@@ -1299,14 +1302,14 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
* Wait for stable hardware.
*/
for (i = 0; i < 100; i++) {
- rt2x00pci_register_read(rt2x00dev, MAC_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, &reg);
if (reg)
break;
msleep(1);
}
if (!reg) {
- ERROR(rt2x00dev, "Unstable hardware.\n");
+ rt2x00_err(rt2x00dev, "Unstable hardware\n");
return -EBUSY;
}
@@ -1315,10 +1318,10 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
*/
reg = 0;
rt2x00_set_field32(&reg, MCU_CNTL_CSR_RESET, 1);
- rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
- rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
- rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, 0);
+ rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+ rt2x00mmio_register_write(rt2x00dev, HOST_CMD_CSR, 0);
/*
* Write firmware to device.
@@ -1326,26 +1329,26 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
reg = 0;
rt2x00_set_field32(&reg, MCU_CNTL_CSR_RESET, 1);
rt2x00_set_field32(&reg, MCU_CNTL_CSR_SELECT_BANK, 1);
- rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
- rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
- data, len);
+ rt2x00mmio_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
+ data, len);
rt2x00_set_field32(&reg, MCU_CNTL_CSR_SELECT_BANK, 0);
- rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
rt2x00_set_field32(&reg, MCU_CNTL_CSR_RESET, 0);
- rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
for (i = 0; i < 100; i++) {
- rt2x00pci_register_read(rt2x00dev, MCU_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MCU_CNTL_CSR, &reg);
if (rt2x00_get_field32(reg, MCU_CNTL_CSR_READY))
break;
msleep(1);
}
if (i == 100) {
- ERROR(rt2x00dev, "MCU Control register not ready.\n");
+ rt2x00_err(rt2x00dev, "MCU Control register not ready\n");
return -EBUSY;
}
@@ -1360,16 +1363,16 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
reg = 0;
rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
return 0;
}
@@ -1379,7 +1382,7 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
*/
static bool rt61pci_get_entry_state(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
u32 word;
if (entry->queue->qid == QID_RX) {
@@ -1396,7 +1399,7 @@ static bool rt61pci_get_entry_state(struct queue_entry *entry)
static void rt61pci_clear_entry(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
u32 word;
@@ -1419,13 +1422,13 @@ static void rt61pci_clear_entry(struct queue_entry *entry)
static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
{
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
u32 reg;
/*
* Initialize registers.
*/
- rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR0, &reg);
rt2x00_set_field32(&reg, TX_RING_CSR0_AC0_RING_SIZE,
rt2x00dev->tx[0].limit);
rt2x00_set_field32(&reg, TX_RING_CSR0_AC1_RING_SIZE,
@@ -1434,67 +1437,67 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
rt2x00dev->tx[2].limit);
rt2x00_set_field32(&reg, TX_RING_CSR0_AC3_RING_SIZE,
rt2x00dev->tx[3].limit);
- rt2x00pci_register_write(rt2x00dev, TX_RING_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR0, reg);
- rt2x00pci_register_read(rt2x00dev, TX_RING_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR1, &reg);
rt2x00_set_field32(&reg, TX_RING_CSR1_TXD_SIZE,
rt2x00dev->tx[0].desc_size / 4);
- rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR1, reg);
entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, AC0_BASE_CSR, &reg);
rt2x00_set_field32(&reg, AC0_BASE_CSR_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, AC0_BASE_CSR, reg);
entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, AC1_BASE_CSR, &reg);
rt2x00_set_field32(&reg, AC1_BASE_CSR_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, AC1_BASE_CSR, reg);
entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, AC2_BASE_CSR, &reg);
rt2x00_set_field32(&reg, AC2_BASE_CSR_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, AC2_BASE_CSR, reg);
entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, AC3_BASE_CSR, &reg);
rt2x00_set_field32(&reg, AC3_BASE_CSR_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, AC3_BASE_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RX_RING_CSR, &reg);
rt2x00_set_field32(&reg, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit);
rt2x00_set_field32(&reg, RX_RING_CSR_RXD_SIZE,
rt2x00dev->rx->desc_size / 4);
rt2x00_set_field32(&reg, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4);
- rt2x00pci_register_write(rt2x00dev, RX_RING_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RX_RING_CSR, reg);
entry_priv = rt2x00dev->rx->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RX_BASE_CSR, &reg);
rt2x00_set_field32(&reg, RX_BASE_CSR_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RX_BASE_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_DMA_DST_CSR, &reg);
rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC0, 2);
rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC1, 2);
rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC2, 2);
rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC3, 2);
- rt2x00pci_register_write(rt2x00dev, TX_DMA_DST_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_DMA_DST_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, LOAD_TX_RING_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, LOAD_TX_RING_CSR, &reg);
rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC0, 1);
rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1);
rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1);
rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1);
- rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, RX_CNTL_CSR_LOAD_RXD, 1);
- rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg);
return 0;
}
@@ -1503,13 +1506,13 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_AUTO_TX_SEQ, 1);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
rt2x00_set_field32(&reg, TXRX_CSR0_TX_WITHOUT_WAITING, 0);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR1, &reg);
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID1, 30); /* Rssi */
@@ -1518,12 +1521,12 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID2_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3, 30); /* Rssi */
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3_VALID, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR1, reg);
/*
* CCK TXD BBP registers
*/
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR2, &reg);
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0, 13);
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID1, 12);
@@ -1532,76 +1535,76 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID2_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3, 10);
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3_VALID, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR2, reg);
/*
* OFDM TXD BBP registers
*/
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR3, &reg);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0, 7);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1, 6);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2, 5);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2_VALID, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR3, reg);
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR7, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR7, &reg);
rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_6MBS, 59);
rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_9MBS, 53);
rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_12MBS, 49);
rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_18MBS, 46);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR7, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR7, reg);
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR8, &reg);
rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_24MBS, 44);
rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_36MBS, 42);
rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_48MBS, 42);
rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR8, reg);
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR6, 0x00000fff);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR6, 0x00000fff);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, &reg);
rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x0000071c);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR10, 0x0000071c);
if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
return -EBUSY;
- rt2x00pci_register_write(rt2x00dev, MAC_CSR13, 0x0000e000);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, 0x0000e000);
/*
* Invalidate all Shared Keys (SEC_CSR0),
* and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
*/
- rt2x00pci_register_write(rt2x00dev, SEC_CSR0, 0x00000000);
- rt2x00pci_register_write(rt2x00dev, SEC_CSR1, 0x00000000);
- rt2x00pci_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR0, 0x00000000);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, 0x00000000);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR1, 0x000023b0);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR5, 0x060a100c);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR7, 0x00000a08);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR1, 0x000023b0);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR5, 0x060a100c);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR7, 0x00000a08);
- rt2x00pci_register_write(rt2x00dev, PCI_CFG_CSR, 0x28ca4404);
+ rt2x00mmio_register_write(rt2x00dev, PCI_CFG_CSR, 0x28ca4404);
- rt2x00pci_register_write(rt2x00dev, TEST_MODE_CSR, 0x00000200);
+ rt2x00mmio_register_write(rt2x00dev, TEST_MODE_CSR, 0x00000200);
- rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff);
+ rt2x00mmio_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff);
/*
* Clear all beacons
@@ -1609,36 +1612,36 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
* the first byte since that byte contains the VALID and OWNER
* bits which (when set to 0) will invalidate the entire beacon.
*/
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
+ rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
+ rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
+ rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
+ rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
/*
* We must clear the error counters.
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
*/
- rt2x00pci_register_read(rt2x00dev, STA_CSR0, &reg);
- rt2x00pci_register_read(rt2x00dev, STA_CSR1, &reg);
- rt2x00pci_register_read(rt2x00dev, STA_CSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, STA_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, STA_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, STA_CSR2, &reg);
/*
* Reset MAC and BBP registers.
*/
- rt2x00pci_register_read(rt2x00dev, MAC_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
return 0;
}
@@ -1655,7 +1658,7 @@ static int rt61pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
+ rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
return -EACCES;
}
@@ -1722,11 +1725,11 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
* should clear the register to assure a clean state.
*/
if (state == STATE_RADIO_IRQ_ON) {
- rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
- rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg);
- rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
+ rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg);
+ rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
}
/*
@@ -1735,15 +1738,15 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
- rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_BEACON_DONE, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_ENABLE_MITIGATION, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
- rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_0, mask);
rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_1, mask);
rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_2, mask);
@@ -1753,7 +1756,7 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_6, mask);
rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_7, mask);
rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_TWAKEUP, mask);
- rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
@@ -1783,9 +1786,9 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Enable RX.
*/
- rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, RX_CNTL_CSR_ENABLE_RX_DMA, 1);
- rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg);
return 0;
}
@@ -1795,7 +1798,7 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Disable power
*/
- rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
}
static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
@@ -1806,10 +1809,10 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
put_to_sleep = (state != STATE_AWAKE);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR12, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR12, &reg);
rt2x00_set_field32(&reg, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep);
rt2x00_set_field32(&reg, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR12, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR12, reg);
/*
* Device is not guaranteed to be in the requested state yet.
@@ -1817,11 +1820,11 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
* device has entered the correct state.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, MAC_CSR12, &reg2);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR12, &reg2);
state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);
if (state == !put_to_sleep)
return 0;
- rt2x00pci_register_write(rt2x00dev, MAC_CSR12, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR12, reg);
msleep(10);
}
@@ -1856,8 +1859,8 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
}
if (unlikely(retval))
- ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
- state, retval);
+ rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+ state, retval);
return retval;
}
@@ -1869,7 +1872,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
__le32 *txd = entry_priv->desc;
u32 word;
@@ -1967,7 +1970,7 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
unsigned int beacon_base;
unsigned int padding_len;
u32 orig_reg, reg;
@@ -1976,10 +1979,10 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
orig_reg = reg;
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
/*
* Write the TX descriptor for the beacon.
@@ -1996,19 +1999,19 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
*/
padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
if (padding_len && skb_pad(entry->skb, padding_len)) {
- ERROR(rt2x00dev, "Failure padding beacon, aborting\n");
+ rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n");
/* skb freed by skb_pad() on failure */
entry->skb = NULL;
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
return;
}
beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
- rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
- entry_priv->desc, TXINFO_SIZE);
- rt2x00pci_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE,
- entry->skb->data,
- entry->skb->len + padding_len);
+ rt2x00mmio_register_multiwrite(rt2x00dev, beacon_base,
+ entry_priv->desc, TXINFO_SIZE);
+ rt2x00mmio_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE,
+ entry->skb->data,
+ entry->skb->len + padding_len);
/*
* Enable beaconing again.
@@ -2016,10 +2019,10 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
* For Wi-Fi faily generated beacons between participating
* stations. Set TBTT phase adaptive adjustment step to 8us.
*/
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
/*
* Clean up beacon skb.
@@ -2037,21 +2040,21 @@ static void rt61pci_clear_beacon(struct queue_entry *entry)
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
/*
* Clear beacon.
*/
- rt2x00pci_register_write(rt2x00dev,
- HW_BEACON_OFFSET(entry->entry_idx), 0);
+ rt2x00mmio_register_write(rt2x00dev,
+ HW_BEACON_OFFSET(entry->entry_idx), 0);
/*
* Enable beaconing again.
*/
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
}
/*
@@ -2089,7 +2092,7 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
u32 word0;
u32 word1;
@@ -2155,7 +2158,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
struct data_queue *queue;
struct queue_entry *entry;
struct queue_entry *entry_done;
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
struct txdone_entry_desc txdesc;
u32 word;
u32 reg;
@@ -2173,7 +2176,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
* tx ring size for now.
*/
for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
- rt2x00pci_register_read(rt2x00dev, STA_CSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, STA_CSR4, &reg);
if (!rt2x00_get_field32(reg, STA_CSR4_VALID))
break;
@@ -2207,9 +2210,8 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
/* Catch up.
* Just report any entries we missed as failed.
*/
- WARNING(rt2x00dev,
- "TX status report missed for entry %d\n",
- entry_done->entry_idx);
+ rt2x00_warn(rt2x00dev, "TX status report missed for entry %d\n",
+ entry_done->entry_idx);
rt2x00lib_txdone_noinfo(entry_done, TXDONE_UNKNOWN);
entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
@@ -2260,9 +2262,9 @@ static inline void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
rt2x00_set_field32(&reg, irq_field, 0);
- rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
@@ -2278,9 +2280,9 @@ static void rt61pci_enable_mcu_interrupt(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
rt2x00_set_field32(&reg, irq_field, 0);
- rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
@@ -2304,7 +2306,7 @@ static void rt61pci_tbtt_tasklet(unsigned long data)
static void rt61pci_rxdone_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- if (rt2x00pci_rxdone(rt2x00dev))
+ if (rt2x00mmio_rxdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->rxdone_tasklet);
else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE);
@@ -2314,8 +2316,8 @@ static void rt61pci_autowake_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt61pci_wakeup(rt2x00dev);
- rt2x00pci_register_write(rt2x00dev,
- M2H_CMD_DONE_CSR, 0xffffffff);
+ rt2x00mmio_register_write(rt2x00dev,
+ M2H_CMD_DONE_CSR, 0xffffffff);
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP);
}
@@ -2330,11 +2332,11 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
* Get the interrupt sources & saved to local variable.
* Write register value back to clear pending interrupts.
*/
- rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg_mcu);
- rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu);
+ rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg_mcu);
+ rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu);
- rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
- rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
if (!reg && !reg_mcu)
return IRQ_NONE;
@@ -2371,13 +2373,13 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
*/
spin_lock(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
reg |= mask;
- rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
reg |= mask_mcu;
- rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
spin_unlock(&rt2x00dev->irqmask_lock);
@@ -2395,7 +2397,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
u8 *mac;
s8 value;
- rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
eeprom.data = rt2x00dev;
eeprom.register_read = rt61pci_eepromregister_read;
@@ -2416,7 +2418,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
eth_random_addr(mac);
- EEPROM(rt2x00dev, "MAC: %pM\n", mac);
+ rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -2431,7 +2433,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF5225);
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
- EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
@@ -2444,7 +2446,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
- EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word);
@@ -2452,7 +2454,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_LED_LED_MODE,
LED_MODE_DEFAULT);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED, word);
- EEPROM(rt2x00dev, "Led: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Led: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
@@ -2460,7 +2462,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
- EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
@@ -2468,7 +2470,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
- EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
} else {
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1);
if (value < -10 || value > 10)
@@ -2484,7 +2486,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
- EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
} else {
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
if (value < -10 || value > 10)
@@ -2513,7 +2515,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Identify RF chipset.
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, &reg);
rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
@@ -2521,7 +2523,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
!rt2x00_rf(rt2x00dev, RF5325) &&
!rt2x00_rf(rt2x00dev, RF2527) &&
!rt2x00_rf(rt2x00dev, RF2529)) {
- ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
return -ENODEV;
}
@@ -2838,7 +2840,7 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* Disable power saving.
*/
- rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007);
+ rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007);
/*
* Allocate eeprom data.
@@ -2855,9 +2857,9 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
- rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
rt2x00_set_field32(&reg, MAC_CSR13_DIR5, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, reg);
/*
* Initialize hw specifications.
@@ -2927,25 +2929,25 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw,
field.bit_offset = (queue_idx & 1) * 16;
field.bit_mask = 0xffff << field.bit_offset;
- rt2x00pci_register_read(rt2x00dev, offset, &reg);
+ rt2x00mmio_register_read(rt2x00dev, offset, &reg);
rt2x00_set_field32(&reg, field, queue->txop);
- rt2x00pci_register_write(rt2x00dev, offset, reg);
+ rt2x00mmio_register_write(rt2x00dev, offset, reg);
/* Update WMM registers */
field.bit_offset = queue_idx * 4;
field.bit_mask = 0xf << field.bit_offset;
- rt2x00pci_register_read(rt2x00dev, AIFSN_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, AIFSN_CSR, &reg);
rt2x00_set_field32(&reg, field, queue->aifs);
- rt2x00pci_register_write(rt2x00dev, AIFSN_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, AIFSN_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, CWMIN_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CWMIN_CSR, &reg);
rt2x00_set_field32(&reg, field, queue->cw_min);
- rt2x00pci_register_write(rt2x00dev, CWMIN_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, CWMIN_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, CWMAX_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CWMAX_CSR, &reg);
rt2x00_set_field32(&reg, field, queue->cw_max);
- rt2x00pci_register_write(rt2x00dev, CWMAX_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, CWMAX_CSR, reg);
return 0;
}
@@ -2956,9 +2958,9 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
u64 tsf;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR13, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR13, &reg);
tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32;
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR12, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR12, &reg);
tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER);
return tsf;
@@ -2997,8 +2999,8 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
.get_firmware_name = rt61pci_get_firmware_name,
.check_firmware = rt61pci_check_firmware,
.load_firmware = rt61pci_load_firmware,
- .initialize = rt2x00pci_initialize,
- .uninitialize = rt2x00pci_uninitialize,
+ .initialize = rt2x00mmio_initialize,
+ .uninitialize = rt2x00mmio_uninitialize,
.get_entry_state = rt61pci_get_entry_state,
.clear_entry = rt61pci_clear_entry,
.set_device_state = rt61pci_set_device_state,
@@ -3009,7 +3011,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
.start_queue = rt61pci_start_queue,
.kick_queue = rt61pci_kick_queue,
.stop_queue = rt61pci_stop_queue,
- .flush_queue = rt2x00pci_flush_queue,
+ .flush_queue = rt2x00mmio_flush_queue,
.write_tx_desc = rt61pci_write_tx_desc,
.write_beacon = rt61pci_write_beacon,
.clear_beacon = rt61pci_clear_beacon,
@@ -3027,21 +3029,21 @@ static const struct data_queue_desc rt61pci_queue_rx = {
.entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = RXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt61pci_queue_tx = {
.entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt61pci_queue_bcn = {
.entry_num = 4,
.data_size = 0, /* No DMA required for beacons */
.desc_size = TXINFO_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct rt2x00_ops rt61pci_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 24eec66e9fd2..377e09bb0b81 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -739,7 +739,7 @@ static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
u16 eeprom;
short lna_gain = 0;
- if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
+ if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) {
if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))
lna_gain += 14;
@@ -1122,7 +1122,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev,
}
if (!reg) {
- ERROR(rt2x00dev, "Unstable hardware.\n");
+ rt2x00_err(rt2x00dev, "Unstable hardware\n");
return -EBUSY;
}
@@ -1139,7 +1139,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev,
0, USB_MODE_FIRMWARE,
REGISTER_TIMEOUT_FIRMWARE);
if (status < 0) {
- ERROR(rt2x00dev, "Failed to write Firmware to device.\n");
+ rt2x00_err(rt2x00dev, "Failed to write Firmware to device\n");
return status;
}
@@ -1305,7 +1305,7 @@ static int rt73usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
+ rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
return -EACCES;
}
@@ -1443,8 +1443,8 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
}
if (unlikely(retval))
- ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
- state, retval);
+ rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+ state, retval);
return retval;
}
@@ -1567,7 +1567,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
*/
padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
if (padding_len && skb_pad(entry->skb, padding_len)) {
- ERROR(rt2x00dev, "Failure padding beacon, aborting\n");
+ rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n");
/* skb freed by skb_pad() on failure */
entry->skb = NULL;
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
@@ -1771,7 +1771,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
eth_random_addr(mac);
- EEPROM(rt2x00dev, "MAC: %pM\n", mac);
+ rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -1786,14 +1786,14 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF5226);
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
- EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
- EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word);
@@ -1809,7 +1809,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_LED_LED_MODE,
LED_MODE_DEFAULT);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED, word);
- EEPROM(rt2x00dev, "Led: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Led: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
@@ -1817,7 +1817,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
- EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
@@ -1825,7 +1825,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
- EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
} else {
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1);
if (value < -10 || value > 10)
@@ -1841,7 +1841,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
- EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
} else {
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
if (value < -10 || value > 10)
@@ -1875,7 +1875,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
if (!rt2x00_rt(rt2x00dev, RT2573) || (rt2x00_rev(rt2x00dev) == 0)) {
- ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid RT chipset detected\n");
return -ENODEV;
}
@@ -1883,7 +1883,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
!rt2x00_rf(rt2x00dev, RF2528) &&
!rt2x00_rf(rt2x00dev, RF5225) &&
!rt2x00_rf(rt2x00dev, RF2527)) {
- ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
return -ENODEV;
}
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index 1b3c2843221d..91a04e2b8ece 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -147,8 +147,8 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
signal = priv->rf->calc_rssi(agc, sq);
}
rx_status.signal = signal;
- rx_status.freq = dev->conf.channel->center_freq;
- rx_status.band = dev->conf.channel->band;
+ rx_status.freq = dev->conf.chandef.chan->center_freq;
+ rx_status.band = dev->conf.chandef.chan->band;
rx_status.mactime = le64_to_cpu(entry->tsft);
rx_status.flag |= RX_FLAG_MACTIME_START;
if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
diff --git a/drivers/net/wireless/rtl818x/rtl8180/grf5101.c b/drivers/net/wireless/rtl818x/rtl8180/grf5101.c
index 5ee7589dd546..077ff92cc139 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/grf5101.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/grf5101.c
@@ -82,7 +82,8 @@ static void grf5101_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
- int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ int channel =
+ ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
u32 chan = channel - 1;
diff --git a/drivers/net/wireless/rtl818x/rtl8180/max2820.c b/drivers/net/wireless/rtl818x/rtl8180/max2820.c
index 667b3363d437..4715000c94dd 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/max2820.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/max2820.c
@@ -95,7 +95,7 @@ static void max2820_rf_set_channel(struct ieee80211_hw *dev,
{
struct rtl8180_priv *priv = dev->priv;
int channel = conf ?
- ieee80211_frequency_to_channel(conf->channel->center_freq) : 1;
+ ieee80211_frequency_to_channel(conf->chandef.chan->center_freq) : 1;
unsigned int chan_idx = channel - 1;
u32 txpw = priv->channels[chan_idx].hw_value & 0xFF;
u32 chan = max2820_chan[chan_idx];
diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c
index 7c4574ba9d75..cc2a5412c1f0 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c
@@ -719,7 +719,8 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
- int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ int chan =
+ ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
if (priv->rf->init == rtl8225_rf_init)
rtl8225_rf_set_tx_power(dev, chan);
diff --git a/drivers/net/wireless/rtl818x/rtl8180/sa2400.c b/drivers/net/wireless/rtl818x/rtl8180/sa2400.c
index 44771a6286af..b3ec40f6bd23 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/sa2400.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/sa2400.c
@@ -105,7 +105,8 @@ static void sa2400_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
- int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ int channel =
+ ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
u32 chan = sa2400_chan[channel - 1];
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
index 4574bd213705..f49220e234b0 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c
@@ -379,8 +379,8 @@ static void rtl8187_rx_cb(struct urb *urb)
rate = (flags >> 20) & 0xF;
skb_trim(skb, flags & 0x0FFF);
rx_status.rate_idx = rate;
- rx_status.freq = dev->conf.channel->center_freq;
- rx_status.band = dev->conf.channel->band;
+ rx_status.freq = dev->conf.chandef.chan->center_freq;
+ rx_status.band = dev->conf.chandef.chan->band;
rx_status.flag |= RX_FLAG_MACTIME_START;
if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c
index 908903f721f5..f0bf35fedbaf 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c
@@ -905,7 +905,8 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
struct rtl8187_priv *priv = dev->priv;
- int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ int chan =
+ ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
if (priv->rf->init == rtl8225_rf_init)
rtl8225_rf_set_tx_power(dev, chan);
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index cac1fa912e8c..af59dd5718e1 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -722,7 +722,7 @@ int rtlwifi_rate_mapping(struct ieee80211_hw *hw,
int rate_idx;
if (false == isht) {
- if (IEEE80211_BAND_2GHZ == hw->conf.channel->band) {
+ if (IEEE80211_BAND_2GHZ == hw->conf.chandef.chan->band) {
switch (desc_rate) {
case DESC92_RATE1M:
rate_idx = 0;
@@ -987,8 +987,8 @@ static bool addbareq_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
if (tid_data->agg.rx_agg_state == RTL_RX_AGG_START) {
skb_delba = rtl_make_del_ba(hw, hdr->addr2, hdr->addr3, tid);
if (skb_delba) {
- rx_status.freq = hw->conf.channel->center_freq;
- rx_status.band = hw->conf.channel->band;
+ rx_status.freq = hw->conf.chandef.chan->center_freq;
+ rx_status.band = hw->conf.chandef.chan->band;
rx_status.flag |= RX_FLAG_DECRYPTED;
rx_status.flag |= RX_FLAG_MACTIME_END;
rx_status.rate_idx = 0;
@@ -1593,7 +1593,7 @@ int rtl_send_smps_action(struct ieee80211_hw *hw,
sta_entry->mimo_ps = smps;
info->control.rates[0].idx = 0;
- info->band = hw->conf.channel->band;
+ info->band = hw->conf.chandef.chan->band;
rtlpriv->intf_ops->adapter_tx(hw, sta, skb, &tcb_desc);
}
return 1;
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index 2201b5cee08f..ee84844be008 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -370,7 +370,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
- struct ieee80211_channel *channel = hw->conf.channel;
+ struct ieee80211_channel *channel = hw->conf.chandef.chan;
u8 wide_chan = (u8) channel->hw_value;
if (mac->act_scanning)
@@ -392,7 +392,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
*info for cisco1253 bw20, so we modify
*it here based on UPPER & LOWER
*/
- switch (hw->conf.channel_type) {
+ switch (cfg80211_get_chandef_type(&hw->conf.chandef)) {
case NL80211_CHAN_HT20:
case NL80211_CHAN_NO_HT:
/* SC */
@@ -450,7 +450,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
rtlpriv->cfg->ops->switch_channel(hw);
rtlpriv->cfg->ops->set_channel_access(hw);
rtlpriv->cfg->ops->set_bw_mode(hw,
- hw->conf.channel_type);
+ cfg80211_get_chandef_type(&hw->conf.chandef));
}
mutex_unlock(&rtlpriv->locks.conf_mutex);
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
index bcff49730a4e..b68cae3024fc 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
@@ -1635,7 +1635,7 @@ static void _rtl8188e_read_power_value_fromprom(struct ieee80211_hw *hw,
if (pwr2g->index_cck_base[path][i] == 0xFF)
pwr2g->index_cck_base[path][i] = 0x2D;
}
- for (i = 0; i < MAX_CHNL_GROUP_24G-1; i++) {
+ for (i = 0; i < MAX_CHNL_GROUP_24G; i++) {
pwr2g->index_bw40_base[path][i] = hwinfo[eadr++];
if (pwr2g->index_bw40_base[path][i] == 0xFF)
pwr2g->index_bw40_base[path][i] = 0x2D;
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
index d075237add51..a8871d66d56a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
@@ -421,8 +421,8 @@ bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw,
RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD,
"Get Wakeup Packet!! WakeMatch =%d\n",
status->wake_match);
- rx_status->freq = hw->conf.channel->center_freq;
- rx_status->band = hw->conf.channel->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
if (status->crc)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
index 926e2a34c766..d2d57a27a7c1 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -669,7 +669,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
u8 thermalvalue, delta, delta_lck, delta_iqk;
long ele_a, ele_d, temp_cck, val_x, value32;
long val_y, ele_c = 0;
- u8 ofdm_index[2], ofdm_index_old[2], cck_index_old = 0;
+ u8 ofdm_index[2], ofdm_index_old[2] = {0, 0}, cck_index_old = 0;
s8 cck_index = 0;
int i;
bool is2t = IS_92C_SERIAL(rtlhal->version);
@@ -717,7 +717,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
if (ele_d == (ofdmswing_table[i] &
MASKOFDM_D)) {
-
+ ofdm_index_old[1] = (u8) i;
RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
DBG_LOUD,
"Initial pathB ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
index 65bf5fb97002..6ad23b413eb3 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
@@ -363,8 +363,8 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
stats->is_cck = RX_HAL_IS_CCK_RATE(pdesc);
- rx_status->freq = hw->conf.channel->center_freq;
- rx_status->band = hw->conf.channel->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size
+ stats->rx_bufshift);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
index 710f7904ecdf..763cf1defab5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
@@ -324,8 +324,8 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
&& (GET_RX_DESC_FAGGR(pdesc) == 1));
stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
- rx_status->freq = hw->conf.channel->center_freq;
- rx_status->band = hw->conf.channel->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
if (GET_RX_DESC_CRC32(pdesc))
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (!GET_RX_DESC_SWDEC(pdesc))
@@ -395,8 +395,8 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)
stats.rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(rxdesc);
/* TODO: is center_freq changed when doing scan? */
/* TODO: Shall we add protection or just skip those two step? */
- rx_status->freq = hw->conf.channel->center_freq;
- rx_status->band = hw->conf.channel->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
if (GET_RX_DESC_CRC32(rxdesc))
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (!GET_RX_DESC_SWDEC(rxdesc))
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
index 941080e03c06..b8ec718a0fab 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
@@ -499,8 +499,8 @@ bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
&& (GET_RX_DESC_FAGGR(pdesc) == 1));
stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
- rx_status->freq = hw->conf.channel->center_freq;
- rx_status->band = hw->conf.channel->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
if (GET_RX_DESC_CRC32(pdesc))
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (!GET_RX_DESC_SWDEC(pdesc))
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index 960bc28cc51e..c7095118de6e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -281,8 +281,8 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
if (stats->hwerror)
return false;
- rx_status->freq = hw->conf.channel->center_freq;
- rx_status->band = hw->conf.channel->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
if (stats->crc)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
index 6c64365308d3..c72758d8f4ed 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
@@ -304,8 +304,8 @@ bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw,
status->is_cck = RTL8723E_RX_HAL_IS_CCK_RATE(status->rate);
- rx_status->freq = hw->conf.channel->center_freq;
- rx_status->band = hw->conf.channel->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
if (status->crc)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index bbbf68cf50a7..3291ffa95273 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -572,7 +572,8 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
struct ieee80211_conf *conf = &hw->conf;
int channel, ret = 0;
- channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ channel = ieee80211_frequency_to_channel(
+ conf->chandef.chan->center_freq);
wl1251_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
channel,
@@ -1223,7 +1224,7 @@ static int wl1251_op_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = wl->noise;
diff --git a/drivers/net/wireless/ti/wl12xx/cmd.c b/drivers/net/wireless/ti/wl12xx/cmd.c
index 7dc9f965037d..7485dbae8c4b 100644
--- a/drivers/net/wireless/ti/wl12xx/cmd.c
+++ b/drivers/net/wireless/ti/wl12xx/cmd.c
@@ -301,7 +301,7 @@ int wl12xx_cmd_channel_switch(struct wl1271 *wl,
}
cmd->role_id = wlvif->role_id;
- cmd->channel = ch_switch->channel->hw_value;
+ cmd->channel = ch_switch->chandef.chan->hw_value;
cmd->switch_time = ch_switch->count;
cmd->stop_tx = ch_switch->block_tx;
diff --git a/drivers/net/wireless/ti/wl18xx/cmd.c b/drivers/net/wireless/ti/wl18xx/cmd.c
index 1d1f6cc7a50a..7649c75cd68d 100644
--- a/drivers/net/wireless/ti/wl18xx/cmd.c
+++ b/drivers/net/wireless/ti/wl18xx/cmd.c
@@ -42,11 +42,11 @@ int wl18xx_cmd_channel_switch(struct wl1271 *wl,
}
cmd->role_id = wlvif->role_id;
- cmd->channel = ch_switch->channel->hw_value;
+ cmd->channel = ch_switch->chandef.chan->hw_value;
cmd->switch_time = ch_switch->count;
cmd->stop_tx = ch_switch->block_tx;
- switch (ch_switch->channel->band) {
+ switch (ch_switch->chandef.chan->band) {
case IEEE80211_BAND_2GHZ:
cmd->band = WLCORE_BAND_2_4GHZ;
break;
@@ -55,7 +55,7 @@ int wl18xx_cmd_channel_switch(struct wl1271 *wl,
break;
default:
wl1271_error("invalid channel switch band: %d",
- ch_switch->channel->band);
+ ch_switch->chandef.chan->band);
ret = -EINVAL;
goto out_free;
}
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index d10954c0c181..953111a502ee 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -4502,7 +4502,7 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->filled = 0;
return 0;
}
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 114364b5d466..c6208a7988e4 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -1156,10 +1156,10 @@ static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
struct ieee80211_conf *conf = &hw->conf;
spin_lock_irq(&mac->lock);
- mac->channel = conf->channel->hw_value;
+ mac->channel = conf->chandef.chan->hw_value;
spin_unlock_irq(&mac->lock);
- return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
+ return zd_chip_set_channel(&mac->chip, conf->chandef.chan->hw_value);
}
static void zd_beacon_done(struct zd_mac *mac)
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index e57034971ccc..4775d4e61b88 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -26,6 +26,16 @@ config NFC_WILINK
Say Y here to compile support for Texas Instrument's NFC WiLink driver
into the kernel or say M to compile it as module.
+config NFC_MEI_PHY
+ tristate "MEI bus NFC device support"
+ depends on INTEL_MEI_BUS_NFC && NFC_HCI
+ help
+ This adds support to use an mei bus nfc device. Select this if you
+ will use an HCI NFC driver for an NFC chip connected behind an
+ Intel's Management Engine chip.
+
+ If unsure, say N.
+
source "drivers/nfc/pn544/Kconfig"
source "drivers/nfc/microread/Kconfig"
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index a189ada0926a..aa6bd657ef40 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -6,5 +6,6 @@ obj-$(CONFIG_NFC_PN544) += pn544/
obj-$(CONFIG_NFC_MICROREAD) += microread/
obj-$(CONFIG_NFC_PN533) += pn533.o
obj-$(CONFIG_NFC_WILINK) += nfcwilink.o
+obj-$(CONFIG_NFC_MEI_PHY) += mei_phy.o
ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c
new file mode 100644
index 000000000000..b8f8abc422f0
--- /dev/null
+++ b/drivers/nfc/mei_phy.c
@@ -0,0 +1,164 @@
+/*
+ * MEI Library for mei bus nfc device access
+ *
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/nfc.h>
+
+#include "mei_phy.h"
+
+struct mei_nfc_hdr {
+ u8 cmd;
+ u8 status;
+ u16 req_id;
+ u32 reserved;
+ u16 data_size;
+} __attribute__((packed));
+
+#define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD)
+
+#define MEI_DUMP_SKB_IN(info, skb) \
+do { \
+ pr_debug("%s:\n", info); \
+ print_hex_dump_debug("mei in : ", DUMP_PREFIX_OFFSET, \
+ 16, 1, (skb)->data, (skb)->len, false); \
+} while (0)
+
+#define MEI_DUMP_SKB_OUT(info, skb) \
+do { \
+ pr_debug("%s:\n", info); \
+ print_hex_dump_debug("mei out: ", DUMP_PREFIX_OFFSET, \
+ 16, 1, (skb)->data, (skb)->len, false); \
+} while (0)
+
+int nfc_mei_phy_enable(void *phy_id)
+{
+ int r;
+ struct nfc_mei_phy *phy = phy_id;
+
+ pr_info("%s\n", __func__);
+
+ if (phy->powered == 1)
+ return 0;
+
+ r = mei_cl_enable_device(phy->device);
+ if (r < 0) {
+ pr_err("MEI_PHY: Could not enable device\n");
+ return r;
+ }
+
+ phy->powered = 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nfc_mei_phy_enable);
+
+void nfc_mei_phy_disable(void *phy_id)
+{
+ struct nfc_mei_phy *phy = phy_id;
+
+ pr_info("%s\n", __func__);
+
+ mei_cl_disable_device(phy->device);
+
+ phy->powered = 0;
+}
+EXPORT_SYMBOL_GPL(nfc_mei_phy_disable);
+
+/*
+ * Writing a frame must not return the number of written bytes.
+ * It must return either zero for success, or <0 for error.
+ * In addition, it must not alter the skb
+ */
+static int nfc_mei_phy_write(void *phy_id, struct sk_buff *skb)
+{
+ struct nfc_mei_phy *phy = phy_id;
+ int r;
+
+ MEI_DUMP_SKB_OUT("mei frame sent", skb);
+
+ r = mei_cl_send(phy->device, skb->data, skb->len);
+ if (r > 0)
+ r = 0;
+
+ return r;
+}
+
+void nfc_mei_event_cb(struct mei_cl_device *device, u32 events, void *context)
+{
+ struct nfc_mei_phy *phy = context;
+
+ if (phy->hard_fault != 0)
+ return;
+
+ if (events & BIT(MEI_CL_EVENT_RX)) {
+ struct sk_buff *skb;
+ int reply_size;
+
+ skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL);
+ if (!skb)
+ return;
+
+ reply_size = mei_cl_recv(device, skb->data, MEI_NFC_MAX_READ);
+ if (reply_size < MEI_NFC_HEADER_SIZE) {
+ kfree(skb);
+ return;
+ }
+
+ skb_put(skb, reply_size);
+ skb_pull(skb, MEI_NFC_HEADER_SIZE);
+
+ MEI_DUMP_SKB_IN("mei frame read", skb);
+
+ nfc_hci_recv_frame(phy->hdev, skb);
+ }
+}
+EXPORT_SYMBOL_GPL(nfc_mei_event_cb);
+
+struct nfc_phy_ops mei_phy_ops = {
+ .write = nfc_mei_phy_write,
+ .enable = nfc_mei_phy_enable,
+ .disable = nfc_mei_phy_disable,
+};
+EXPORT_SYMBOL_GPL(mei_phy_ops);
+
+struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *device)
+{
+ struct nfc_mei_phy *phy;
+
+ phy = kzalloc(sizeof(struct nfc_mei_phy), GFP_KERNEL);
+ if (!phy)
+ return NULL;
+
+ phy->device = device;
+ mei_cl_set_drvdata(device, phy);
+
+ return phy;
+}
+EXPORT_SYMBOL_GPL(nfc_mei_phy_alloc);
+
+void nfc_mei_phy_free(struct nfc_mei_phy *phy)
+{
+ kfree(phy);
+}
+EXPORT_SYMBOL_GPL(nfc_mei_phy_free);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("mei bus NFC device interface");
diff --git a/drivers/nfc/mei_phy.h b/drivers/nfc/mei_phy.h
new file mode 100644
index 000000000000..d669900f8278
--- /dev/null
+++ b/drivers/nfc/mei_phy.h
@@ -0,0 +1,30 @@
+#ifndef __LOCAL_MEI_PHY_H_
+#define __LOCAL_MEI_PHY_H_
+
+#include <linux/mei_cl_bus.h>
+#include <net/nfc/hci.h>
+
+#define MEI_NFC_HEADER_SIZE 10
+#define MEI_NFC_MAX_HCI_PAYLOAD 300
+
+struct nfc_mei_phy {
+ struct mei_cl_device *device;
+ struct nfc_hci_dev *hdev;
+
+ int powered;
+
+ int hard_fault; /*
+ * < 0 if hardware error occured
+ * and prevents normal operation.
+ */
+};
+
+extern struct nfc_phy_ops mei_phy_ops;
+
+int nfc_mei_phy_enable(void *phy_id);
+void nfc_mei_phy_disable(void *phy_id);
+void nfc_mei_event_cb(struct mei_cl_device *device, u32 events, void *context);
+struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *device);
+void nfc_mei_phy_free(struct nfc_mei_phy *phy);
+
+#endif /* __LOCAL_MEI_PHY_H_ */
diff --git a/drivers/nfc/microread/Kconfig b/drivers/nfc/microread/Kconfig
index 572305be6e37..951d5542f6bc 100644
--- a/drivers/nfc/microread/Kconfig
+++ b/drivers/nfc/microread/Kconfig
@@ -25,7 +25,7 @@ config NFC_MICROREAD_I2C
config NFC_MICROREAD_MEI
tristate "NFC Microread MEI support"
- depends on NFC_MICROREAD && INTEL_MEI_BUS_NFC
+ depends on NFC_MICROREAD && NFC_MEI_PHY
---help---
This module adds support for the mei interface of adapters using
Inside microread chipsets. Select this if your microread chipset
diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c
index ca33ae193935..1ad044dce7b6 100644
--- a/drivers/nfc/microread/mei.c
+++ b/drivers/nfc/microread/mei.c
@@ -19,151 +19,31 @@
*/
#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/mei_cl_bus.h>
-
+#include <linux/mod_devicetable.h>
#include <linux/nfc.h>
#include <net/nfc/hci.h>
#include <net/nfc/llc.h>
+#include "../mei_phy.h"
#include "microread.h"
#define MICROREAD_DRIVER_NAME "microread"
-struct mei_nfc_hdr {
- u8 cmd;
- u8 status;
- u16 req_id;
- u32 reserved;
- u16 data_size;
-} __attribute__((packed));
-
-#define MEI_NFC_HEADER_SIZE 10
-#define MEI_NFC_MAX_HCI_PAYLOAD 300
-#define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD)
-
-struct microread_mei_phy {
- struct mei_cl_device *device;
- struct nfc_hci_dev *hdev;
-
- int powered;
-
- int hard_fault; /*
- * < 0 if hardware error occured (e.g. i2c err)
- * and prevents normal operation.
- */
-};
-
-#define MEI_DUMP_SKB_IN(info, skb) \
-do { \
- pr_debug("%s:\n", info); \
- print_hex_dump(KERN_DEBUG, "mei in : ", DUMP_PREFIX_OFFSET, \
- 16, 1, (skb)->data, (skb)->len, 0); \
-} while (0)
-
-#define MEI_DUMP_SKB_OUT(info, skb) \
-do { \
- pr_debug("%s:\n", info); \
- print_hex_dump(KERN_DEBUG, "mei out: ", DUMP_PREFIX_OFFSET, \
- 16, 1, (skb)->data, (skb)->len, 0); \
-} while (0)
-
-static int microread_mei_enable(void *phy_id)
-{
- struct microread_mei_phy *phy = phy_id;
-
- pr_info(DRIVER_DESC ": %s\n", __func__);
-
- phy->powered = 1;
-
- return 0;
-}
-
-static void microread_mei_disable(void *phy_id)
-{
- struct microread_mei_phy *phy = phy_id;
-
- pr_info(DRIVER_DESC ": %s\n", __func__);
-
- phy->powered = 0;
-}
-
-/*
- * Writing a frame must not return the number of written bytes.
- * It must return either zero for success, or <0 for error.
- * In addition, it must not alter the skb
- */
-static int microread_mei_write(void *phy_id, struct sk_buff *skb)
-{
- struct microread_mei_phy *phy = phy_id;
- int r;
-
- MEI_DUMP_SKB_OUT("mei frame sent", skb);
-
- r = mei_cl_send(phy->device, skb->data, skb->len);
- if (r > 0)
- r = 0;
-
- return r;
-}
-
-static void microread_event_cb(struct mei_cl_device *device, u32 events,
- void *context)
-{
- struct microread_mei_phy *phy = context;
-
- if (phy->hard_fault != 0)
- return;
-
- if (events & BIT(MEI_CL_EVENT_RX)) {
- struct sk_buff *skb;
- int reply_size;
-
- skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL);
- if (!skb)
- return;
-
- reply_size = mei_cl_recv(device, skb->data, MEI_NFC_MAX_READ);
- if (reply_size < MEI_NFC_HEADER_SIZE) {
- kfree(skb);
- return;
- }
-
- skb_put(skb, reply_size);
- skb_pull(skb, MEI_NFC_HEADER_SIZE);
-
- MEI_DUMP_SKB_IN("mei frame read", skb);
-
- nfc_hci_recv_frame(phy->hdev, skb);
- }
-}
-
-static struct nfc_phy_ops mei_phy_ops = {
- .write = microread_mei_write,
- .enable = microread_mei_enable,
- .disable = microread_mei_disable,
-};
-
static int microread_mei_probe(struct mei_cl_device *device,
const struct mei_cl_device_id *id)
{
- struct microread_mei_phy *phy;
+ struct nfc_mei_phy *phy;
int r;
pr_info("Probing NFC microread\n");
- phy = kzalloc(sizeof(struct microread_mei_phy), GFP_KERNEL);
+ phy = nfc_mei_phy_alloc(device);
if (!phy) {
pr_err("Cannot allocate memory for microread mei phy.\n");
return -ENOMEM;
}
- phy->device = device;
- mei_cl_set_drvdata(device, phy);
-
- r = mei_cl_register_event_cb(device, microread_event_cb, phy);
+ r = mei_cl_register_event_cb(device, nfc_mei_event_cb, phy);
if (r) {
pr_err(MICROREAD_DRIVER_NAME ": event cb registration failed\n");
goto err_out;
@@ -178,23 +58,22 @@ static int microread_mei_probe(struct mei_cl_device *device,
return 0;
err_out:
- kfree(phy);
+ nfc_mei_phy_free(phy);
return r;
}
static int microread_mei_remove(struct mei_cl_device *device)
{
- struct microread_mei_phy *phy = mei_cl_get_drvdata(device);
+ struct nfc_mei_phy *phy = mei_cl_get_drvdata(device);
pr_info("Removing microread\n");
microread_remove(phy->hdev);
- if (phy->powered)
- microread_mei_disable(phy);
+ nfc_mei_phy_disable(phy);
- kfree(phy);
+ nfc_mei_phy_free(phy);
return 0;
}
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index f0f6763d67ae..8f6f2baa930d 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -1,9 +1,6 @@
/*
* Copyright (C) 2011 Instituto Nokia de Tecnologia
- *
- * Authors:
- * Lauro Ramos Venancio <lauro.venancio@openbossa.org>
- * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
+ * Copyright (C) 2012-2013 Tieto Poland
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,7 +27,7 @@
#include <linux/netdevice.h>
#include <net/nfc/nfc.h>
-#define VERSION "0.1"
+#define VERSION "0.2"
#define PN533_VENDOR_ID 0x4CC
#define PN533_PRODUCT_ID 0x2533
@@ -41,8 +38,12 @@
#define SONY_VENDOR_ID 0x054c
#define PASORI_PRODUCT_ID 0x02e1
-#define PN533_DEVICE_STD 0x1
-#define PN533_DEVICE_PASORI 0x2
+#define ACS_VENDOR_ID 0x072f
+#define ACR122U_PRODUCT_ID 0x2200
+
+#define PN533_DEVICE_STD 0x1
+#define PN533_DEVICE_PASORI 0x2
+#define PN533_DEVICE_ACR122U 0x3
#define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\
NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\
@@ -71,6 +72,11 @@ static const struct usb_device_id pn533_table[] = {
.idProduct = PASORI_PRODUCT_ID,
.driver_info = PN533_DEVICE_PASORI,
},
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = ACS_VENDOR_ID,
+ .idProduct = ACR122U_PRODUCT_ID,
+ .driver_info = PN533_DEVICE_ACR122U,
+ },
{ }
};
MODULE_DEVICE_TABLE(usb, pn533_table);
@@ -78,32 +84,47 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
/* How much time we spend listening for initiators */
#define PN533_LISTEN_TIME 2
-/* frame definitions */
-#define PN533_FRAME_HEADER_LEN (sizeof(struct pn533_frame) \
+/* Standard pn533 frame definitions */
+#define PN533_STD_FRAME_HEADER_LEN (sizeof(struct pn533_std_frame) \
+ 2) /* data[0] TFI, data[1] CC */
-#define PN533_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/
+#define PN533_STD_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/
/*
* Max extended frame payload len, excluding TFI and CC
* which are already in PN533_FRAME_HEADER_LEN.
*/
-#define PN533_FRAME_MAX_PAYLOAD_LEN 263
+#define PN533_STD_FRAME_MAX_PAYLOAD_LEN 263
-#define PN533_FRAME_ACK_SIZE 6 /* Preamble (1), SoPC (2), ACK Code (2),
+#define PN533_STD_FRAME_ACK_SIZE 6 /* Preamble (1), SoPC (2), ACK Code (2),
Postamble (1) */
-#define PN533_FRAME_CHECKSUM(f) (f->data[f->datalen])
-#define PN533_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1])
+#define PN533_STD_FRAME_CHECKSUM(f) (f->data[f->datalen])
+#define PN533_STD_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1])
/* start of frame */
-#define PN533_SOF 0x00FF
+#define PN533_STD_FRAME_SOF 0x00FF
+
+/* standard frame identifier: in/out/error */
+#define PN533_STD_FRAME_IDENTIFIER(f) (f->data[0]) /* TFI */
+#define PN533_STD_FRAME_DIR_OUT 0xD4
+#define PN533_STD_FRAME_DIR_IN 0xD5
+
+/* ACS ACR122 pn533 frame definitions */
+#define PN533_ACR122_TX_FRAME_HEADER_LEN (sizeof(struct pn533_acr122_tx_frame) \
+ + 2)
+#define PN533_ACR122_TX_FRAME_TAIL_LEN 0
+#define PN533_ACR122_RX_FRAME_HEADER_LEN (sizeof(struct pn533_acr122_rx_frame) \
+ + 2)
+#define PN533_ACR122_RX_FRAME_TAIL_LEN 2
+#define PN533_ACR122_FRAME_MAX_PAYLOAD_LEN PN533_STD_FRAME_MAX_PAYLOAD_LEN
+
+/* CCID messages types */
+#define PN533_ACR122_PC_TO_RDR_ICCPOWERON 0x62
+#define PN533_ACR122_PC_TO_RDR_ESCAPE 0x6B
-/* frame identifier: in/out/error */
-#define PN533_FRAME_IDENTIFIER(f) (f->data[0])
-#define PN533_DIR_OUT 0xD4
-#define PN533_DIR_IN 0xD5
+#define PN533_ACR122_RDR_TO_PC_ESCAPE 0x83
/* PN533 Commands */
-#define PN533_FRAME_CMD(f) (f->data[1])
+#define PN533_STD_FRAME_CMD(f) (f->data[1])
#define PN533_CMD_GET_FIRMWARE_VERSION 0x02
#define PN533_CMD_RF_CONFIGURATION 0x32
@@ -128,8 +149,6 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
struct pn533;
-typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg, int status);
-
typedef int (*pn533_send_async_complete_t) (struct pn533 *dev, void *arg,
struct sk_buff *resp);
@@ -144,9 +163,13 @@ struct pn533_fw_version {
};
/* PN533_CMD_RF_CONFIGURATION */
-#define PN533_CFGITEM_TIMING 0x02
+#define PN533_CFGITEM_RF_FIELD 0x01
+#define PN533_CFGITEM_TIMING 0x02
#define PN533_CFGITEM_MAX_RETRIES 0x05
-#define PN533_CFGITEM_PASORI 0x82
+#define PN533_CFGITEM_PASORI 0x82
+
+#define PN533_CFGITEM_RF_FIELD_ON 0x1
+#define PN533_CFGITEM_RF_FIELD_OFF 0x0
#define PN533_CONFIG_TIMING_102 0xb
#define PN533_CONFIG_TIMING_204 0xc
@@ -313,10 +336,17 @@ struct pn533_cmd_jump_dep_response {
#define PN533_INIT_TARGET_RESP_ACTIVE 0x1
#define PN533_INIT_TARGET_RESP_DEP 0x4
+enum pn533_protocol_type {
+ PN533_PROTO_REQ_ACK_RESP = 0,
+ PN533_PROTO_REQ_RESP
+};
+
struct pn533 {
struct usb_device *udev;
struct usb_interface *interface;
struct nfc_dev *nfc_dev;
+ u32 device_type;
+ enum pn533_protocol_type protocol_type;
struct urb *out_urb;
struct urb *in_urb;
@@ -329,21 +359,21 @@ struct pn533 {
struct work_struct poll_work;
struct work_struct mi_work;
struct work_struct tg_work;
- struct timer_list listen_timer;
- int wq_in_error;
- int cancel_listen;
- pn533_cmd_complete_t cmd_complete;
- void *cmd_complete_arg;
+ struct list_head cmd_queue;
+ struct pn533_cmd *cmd;
+ u8 cmd_pending;
+ struct mutex cmd_lock; /* protects cmd queue */
+
void *cmd_complete_mi_arg;
- struct mutex cmd_lock;
- u8 cmd;
struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1];
u8 poll_mod_count;
u8 poll_mod_curr;
u32 poll_protocols;
u32 listen_protocols;
+ struct timer_list listen_timer;
+ int cancel_listen;
u8 *gb;
size_t gb_len;
@@ -352,24 +382,21 @@ struct pn533 {
u8 tgt_active_prot;
u8 tgt_mode;
- u32 device_type;
-
- struct list_head cmd_queue;
- u8 cmd_pending;
-
struct pn533_frame_ops *ops;
};
struct pn533_cmd {
struct list_head queue;
- u8 cmd_code;
+ u8 code;
+ int status;
struct sk_buff *req;
struct sk_buff *resp;
int resp_len;
- void *arg;
+ pn533_send_async_complete_t complete_cb;
+ void *complete_cb_context;
};
-struct pn533_frame {
+struct pn533_std_frame {
u8 preamble;
__be16 start_frame;
u8 datalen;
@@ -393,14 +420,124 @@ struct pn533_frame_ops {
u8 (*get_cmd_code)(void *frame);
};
+struct pn533_acr122_ccid_hdr {
+ u8 type;
+ u32 datalen;
+ u8 slot;
+ u8 seq;
+ u8 params[3]; /* 3 msg specific bytes or status, error and 1 specific
+ byte for reposnse msg */
+ u8 data[]; /* payload */
+} __packed;
+
+struct pn533_acr122_apdu_hdr {
+ u8 class;
+ u8 ins;
+ u8 p1;
+ u8 p2;
+} __packed;
+
+struct pn533_acr122_tx_frame {
+ struct pn533_acr122_ccid_hdr ccid;
+ struct pn533_acr122_apdu_hdr apdu;
+ u8 datalen;
+ u8 data[]; /* pn533 frame: TFI ... */
+} __packed;
+
+struct pn533_acr122_rx_frame {
+ struct pn533_acr122_ccid_hdr ccid;
+ u8 data[]; /* pn533 frame : TFI ... */
+} __packed;
+
+static void pn533_acr122_tx_frame_init(void *_frame, u8 cmd_code)
+{
+ struct pn533_acr122_tx_frame *frame = _frame;
+
+ frame->ccid.type = PN533_ACR122_PC_TO_RDR_ESCAPE;
+ frame->ccid.datalen = sizeof(frame->apdu) + 1; /* sizeof(apdu_hdr) +
+ sizeof(datalen) */
+ frame->ccid.slot = 0;
+ frame->ccid.seq = 0;
+ frame->ccid.params[0] = 0;
+ frame->ccid.params[1] = 0;
+ frame->ccid.params[2] = 0;
+
+ frame->data[0] = PN533_STD_FRAME_DIR_OUT;
+ frame->data[1] = cmd_code;
+ frame->datalen = 2; /* data[0] + data[1] */
+
+ frame->apdu.class = 0xFF;
+ frame->apdu.ins = 0;
+ frame->apdu.p1 = 0;
+ frame->apdu.p2 = 0;
+}
+
+static void pn533_acr122_tx_frame_finish(void *_frame)
+{
+ struct pn533_acr122_tx_frame *frame = _frame;
+
+ frame->ccid.datalen += frame->datalen;
+}
+
+static void pn533_acr122_tx_update_payload_len(void *_frame, int len)
+{
+ struct pn533_acr122_tx_frame *frame = _frame;
+
+ frame->datalen += len;
+}
+
+static bool pn533_acr122_is_rx_frame_valid(void *_frame)
+{
+ struct pn533_acr122_rx_frame *frame = _frame;
+
+ if (frame->ccid.type != 0x83)
+ return false;
+
+ if (frame->data[frame->ccid.datalen - 2] == 0x63)
+ return false;
+
+ return true;
+}
+
+static int pn533_acr122_rx_frame_size(void *frame)
+{
+ struct pn533_acr122_rx_frame *f = frame;
+
+ /* f->ccid.datalen already includes tail length */
+ return sizeof(struct pn533_acr122_rx_frame) + f->ccid.datalen;
+}
+
+static u8 pn533_acr122_get_cmd_code(void *frame)
+{
+ struct pn533_acr122_rx_frame *f = frame;
+
+ return PN533_STD_FRAME_CMD(f);
+}
+
+static struct pn533_frame_ops pn533_acr122_frame_ops = {
+ .tx_frame_init = pn533_acr122_tx_frame_init,
+ .tx_frame_finish = pn533_acr122_tx_frame_finish,
+ .tx_update_payload_len = pn533_acr122_tx_update_payload_len,
+ .tx_header_len = PN533_ACR122_TX_FRAME_HEADER_LEN,
+ .tx_tail_len = PN533_ACR122_TX_FRAME_TAIL_LEN,
+
+ .rx_is_frame_valid = pn533_acr122_is_rx_frame_valid,
+ .rx_header_len = PN533_ACR122_RX_FRAME_HEADER_LEN,
+ .rx_tail_len = PN533_ACR122_RX_FRAME_TAIL_LEN,
+ .rx_frame_size = pn533_acr122_rx_frame_size,
+
+ .max_payload_len = PN533_ACR122_FRAME_MAX_PAYLOAD_LEN,
+ .get_cmd_code = pn533_acr122_get_cmd_code,
+};
+
/* The rule: value + checksum = 0 */
-static inline u8 pn533_checksum(u8 value)
+static inline u8 pn533_std_checksum(u8 value)
{
return ~value + 1;
}
/* The rule: sum(data elements) + checksum = 0 */
-static u8 pn533_data_checksum(u8 *data, int datalen)
+static u8 pn533_std_data_checksum(u8 *data, int datalen)
{
u8 sum = 0;
int i;
@@ -408,61 +545,61 @@ static u8 pn533_data_checksum(u8 *data, int datalen)
for (i = 0; i < datalen; i++)
sum += data[i];
- return pn533_checksum(sum);
+ return pn533_std_checksum(sum);
}
-static void pn533_tx_frame_init(void *_frame, u8 cmd_code)
+static void pn533_std_tx_frame_init(void *_frame, u8 cmd_code)
{
- struct pn533_frame *frame = _frame;
+ struct pn533_std_frame *frame = _frame;
frame->preamble = 0;
- frame->start_frame = cpu_to_be16(PN533_SOF);
- PN533_FRAME_IDENTIFIER(frame) = PN533_DIR_OUT;
- PN533_FRAME_CMD(frame) = cmd_code;
+ frame->start_frame = cpu_to_be16(PN533_STD_FRAME_SOF);
+ PN533_STD_FRAME_IDENTIFIER(frame) = PN533_STD_FRAME_DIR_OUT;
+ PN533_STD_FRAME_CMD(frame) = cmd_code;
frame->datalen = 2;
}
-static void pn533_tx_frame_finish(void *_frame)
+static void pn533_std_tx_frame_finish(void *_frame)
{
- struct pn533_frame *frame = _frame;
+ struct pn533_std_frame *frame = _frame;
- frame->datalen_checksum = pn533_checksum(frame->datalen);
+ frame->datalen_checksum = pn533_std_checksum(frame->datalen);
- PN533_FRAME_CHECKSUM(frame) =
- pn533_data_checksum(frame->data, frame->datalen);
+ PN533_STD_FRAME_CHECKSUM(frame) =
+ pn533_std_data_checksum(frame->data, frame->datalen);
- PN533_FRAME_POSTAMBLE(frame) = 0;
+ PN533_STD_FRAME_POSTAMBLE(frame) = 0;
}
-static void pn533_tx_update_payload_len(void *_frame, int len)
+static void pn533_std_tx_update_payload_len(void *_frame, int len)
{
- struct pn533_frame *frame = _frame;
+ struct pn533_std_frame *frame = _frame;
frame->datalen += len;
}
-static bool pn533_rx_frame_is_valid(void *_frame)
+static bool pn533_std_rx_frame_is_valid(void *_frame)
{
u8 checksum;
- struct pn533_frame *frame = _frame;
+ struct pn533_std_frame *frame = _frame;
- if (frame->start_frame != cpu_to_be16(PN533_SOF))
+ if (frame->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF))
return false;
- checksum = pn533_checksum(frame->datalen);
+ checksum = pn533_std_checksum(frame->datalen);
if (checksum != frame->datalen_checksum)
return false;
- checksum = pn533_data_checksum(frame->data, frame->datalen);
- if (checksum != PN533_FRAME_CHECKSUM(frame))
+ checksum = pn533_std_data_checksum(frame->data, frame->datalen);
+ if (checksum != PN533_STD_FRAME_CHECKSUM(frame))
return false;
return true;
}
-static bool pn533_rx_frame_is_ack(struct pn533_frame *frame)
+static bool pn533_std_rx_frame_is_ack(struct pn533_std_frame *frame)
{
- if (frame->start_frame != cpu_to_be16(PN533_SOF))
+ if (frame->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF))
return false;
if (frame->datalen != 0 || frame->datalen_checksum != 0xFF)
@@ -471,57 +608,51 @@ static bool pn533_rx_frame_is_ack(struct pn533_frame *frame)
return true;
}
-static inline int pn533_rx_frame_size(void *frame)
+static inline int pn533_std_rx_frame_size(void *frame)
{
- struct pn533_frame *f = frame;
+ struct pn533_std_frame *f = frame;
- return sizeof(struct pn533_frame) + f->datalen + PN533_FRAME_TAIL_LEN;
+ return sizeof(struct pn533_std_frame) + f->datalen +
+ PN533_STD_FRAME_TAIL_LEN;
}
-static u8 pn533_get_cmd_code(void *frame)
+static u8 pn533_std_get_cmd_code(void *frame)
{
- struct pn533_frame *f = frame;
+ struct pn533_std_frame *f = frame;
- return PN533_FRAME_CMD(f);
+ return PN533_STD_FRAME_CMD(f);
}
static struct pn533_frame_ops pn533_std_frame_ops = {
- .tx_frame_init = pn533_tx_frame_init,
- .tx_frame_finish = pn533_tx_frame_finish,
- .tx_update_payload_len = pn533_tx_update_payload_len,
- .tx_header_len = PN533_FRAME_HEADER_LEN,
- .tx_tail_len = PN533_FRAME_TAIL_LEN,
-
- .rx_is_frame_valid = pn533_rx_frame_is_valid,
- .rx_frame_size = pn533_rx_frame_size,
- .rx_header_len = PN533_FRAME_HEADER_LEN,
- .rx_tail_len = PN533_FRAME_TAIL_LEN,
-
- .max_payload_len = PN533_FRAME_MAX_PAYLOAD_LEN,
- .get_cmd_code = pn533_get_cmd_code,
+ .tx_frame_init = pn533_std_tx_frame_init,
+ .tx_frame_finish = pn533_std_tx_frame_finish,
+ .tx_update_payload_len = pn533_std_tx_update_payload_len,
+ .tx_header_len = PN533_STD_FRAME_HEADER_LEN,
+ .tx_tail_len = PN533_STD_FRAME_TAIL_LEN,
+
+ .rx_is_frame_valid = pn533_std_rx_frame_is_valid,
+ .rx_frame_size = pn533_std_rx_frame_size,
+ .rx_header_len = PN533_STD_FRAME_HEADER_LEN,
+ .rx_tail_len = PN533_STD_FRAME_TAIL_LEN,
+
+ .max_payload_len = PN533_STD_FRAME_MAX_PAYLOAD_LEN,
+ .get_cmd_code = pn533_std_get_cmd_code,
};
static bool pn533_rx_frame_is_cmd_response(struct pn533 *dev, void *frame)
{
- return (dev->ops->get_cmd_code(frame) == PN533_CMD_RESPONSE(dev->cmd));
-}
-
-
-static void pn533_wq_cmd_complete(struct work_struct *work)
-{
- struct pn533 *dev = container_of(work, struct pn533, cmd_complete_work);
- int rc;
-
- rc = dev->cmd_complete(dev, dev->cmd_complete_arg, dev->wq_in_error);
- if (rc != -EINPROGRESS)
- queue_work(dev->wq, &dev->cmd_work);
+ return (dev->ops->get_cmd_code(frame) ==
+ PN533_CMD_RESPONSE(dev->cmd->code));
}
static void pn533_recv_response(struct urb *urb)
{
struct pn533 *dev = urb->context;
+ struct pn533_cmd *cmd = dev->cmd;
u8 *in_frame;
+ cmd->status = urb->status;
+
switch (urb->status) {
case 0:
break; /* success */
@@ -530,37 +661,33 @@ static void pn533_recv_response(struct urb *urb)
nfc_dev_dbg(&dev->interface->dev,
"The urb has been canceled (status %d)",
urb->status);
- dev->wq_in_error = urb->status;
goto sched_wq;
case -ESHUTDOWN:
default:
nfc_dev_err(&dev->interface->dev,
"Urb failure (status %d)", urb->status);
- dev->wq_in_error = urb->status;
goto sched_wq;
}
in_frame = dev->in_urb->transfer_buffer;
nfc_dev_dbg(&dev->interface->dev, "Received a frame.");
- print_hex_dump(KERN_DEBUG, "PN533 RX: ", DUMP_PREFIX_NONE, 16, 1,
- in_frame, dev->ops->rx_frame_size(in_frame), false);
+ print_hex_dump_debug("PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, in_frame,
+ dev->ops->rx_frame_size(in_frame), false);
if (!dev->ops->rx_is_frame_valid(in_frame)) {
nfc_dev_err(&dev->interface->dev, "Received an invalid frame");
- dev->wq_in_error = -EIO;
+ cmd->status = -EIO;
goto sched_wq;
}
if (!pn533_rx_frame_is_cmd_response(dev, in_frame)) {
nfc_dev_err(&dev->interface->dev,
"It it not the response to the last command");
- dev->wq_in_error = -EIO;
+ cmd->status = -EIO;
goto sched_wq;
}
- dev->wq_in_error = 0;
-
sched_wq:
queue_work(dev->wq, &dev->cmd_complete_work);
}
@@ -575,9 +702,12 @@ static int pn533_submit_urb_for_response(struct pn533 *dev, gfp_t flags)
static void pn533_recv_ack(struct urb *urb)
{
struct pn533 *dev = urb->context;
- struct pn533_frame *in_frame;
+ struct pn533_cmd *cmd = dev->cmd;
+ struct pn533_std_frame *in_frame;
int rc;
+ cmd->status = urb->status;
+
switch (urb->status) {
case 0:
break; /* success */
@@ -586,21 +716,19 @@ static void pn533_recv_ack(struct urb *urb)
nfc_dev_dbg(&dev->interface->dev,
"The urb has been stopped (status %d)",
urb->status);
- dev->wq_in_error = urb->status;
goto sched_wq;
case -ESHUTDOWN:
default:
nfc_dev_err(&dev->interface->dev,
"Urb failure (status %d)", urb->status);
- dev->wq_in_error = urb->status;
goto sched_wq;
}
in_frame = dev->in_urb->transfer_buffer;
- if (!pn533_rx_frame_is_ack(in_frame)) {
+ if (!pn533_std_rx_frame_is_ack(in_frame)) {
nfc_dev_err(&dev->interface->dev, "Received an invalid ack");
- dev->wq_in_error = -EIO;
+ cmd->status = -EIO;
goto sched_wq;
}
@@ -608,7 +736,7 @@ static void pn533_recv_ack(struct urb *urb)
if (rc) {
nfc_dev_err(&dev->interface->dev,
"usb_submit_urb failed with result %d", rc);
- dev->wq_in_error = rc;
+ cmd->status = rc;
goto sched_wq;
}
@@ -627,7 +755,7 @@ static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags)
static int pn533_send_ack(struct pn533 *dev, gfp_t flags)
{
- u8 ack[PN533_FRAME_ACK_SIZE] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00};
+ u8 ack[PN533_STD_FRAME_ACK_SIZE] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00};
/* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */
int rc;
@@ -643,32 +771,34 @@ static int pn533_send_ack(struct pn533 *dev, gfp_t flags)
static int __pn533_send_frame_async(struct pn533 *dev,
struct sk_buff *out,
struct sk_buff *in,
- int in_len,
- pn533_cmd_complete_t cmd_complete,
- void *arg)
+ int in_len)
{
int rc;
- dev->cmd = dev->ops->get_cmd_code(out->data);
- dev->cmd_complete = cmd_complete;
- dev->cmd_complete_arg = arg;
-
dev->out_urb->transfer_buffer = out->data;
dev->out_urb->transfer_buffer_length = out->len;
dev->in_urb->transfer_buffer = in->data;
dev->in_urb->transfer_buffer_length = in_len;
- print_hex_dump(KERN_DEBUG, "PN533 TX: ", DUMP_PREFIX_NONE, 16, 1,
- out->data, out->len, false);
+ print_hex_dump_debug("PN533 TX: ", DUMP_PREFIX_NONE, 16, 1,
+ out->data, out->len, false);
rc = usb_submit_urb(dev->out_urb, GFP_KERNEL);
if (rc)
return rc;
- rc = pn533_submit_urb_for_ack(dev, GFP_KERNEL);
- if (rc)
- goto error;
+ if (dev->protocol_type == PN533_PROTO_REQ_RESP) {
+ /* request for response for sent packet directly */
+ rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC);
+ if (rc)
+ goto error;
+ } else if (dev->protocol_type == PN533_PROTO_REQ_ACK_RESP) {
+ /* request for ACK if that's the case */
+ rc = pn533_submit_urb_for_ack(dev, GFP_KERNEL);
+ if (rc)
+ goto error;
+ }
return 0;
@@ -693,39 +823,34 @@ static void pn533_build_cmd_frame(struct pn533 *dev, u8 cmd_code,
ops->tx_frame_finish(skb->data);
}
-struct pn533_send_async_complete_arg {
- pn533_send_async_complete_t complete_cb;
- void *complete_cb_context;
- struct sk_buff *resp;
- struct sk_buff *req;
-};
-
-static int pn533_send_async_complete(struct pn533 *dev, void *_arg, int status)
+static int pn533_send_async_complete(struct pn533 *dev)
{
- struct pn533_send_async_complete_arg *arg = _arg;
+ struct pn533_cmd *cmd = dev->cmd;
+ int status = cmd->status;
- struct sk_buff *req = arg->req;
- struct sk_buff *resp = arg->resp;
+ struct sk_buff *req = cmd->req;
+ struct sk_buff *resp = cmd->resp;
int rc;
dev_kfree_skb(req);
if (status < 0) {
- arg->complete_cb(dev, arg->complete_cb_context,
- ERR_PTR(status));
+ rc = cmd->complete_cb(dev, cmd->complete_cb_context,
+ ERR_PTR(status));
dev_kfree_skb(resp);
- kfree(arg);
- return status;
+ goto done;
}
skb_put(resp, dev->ops->rx_frame_size(resp->data));
skb_pull(resp, dev->ops->rx_header_len);
skb_trim(resp, resp->len - dev->ops->rx_tail_len);
- rc = arg->complete_cb(dev, arg->complete_cb_context, resp);
+ rc = cmd->complete_cb(dev, cmd->complete_cb_context, resp);
- kfree(arg);
+done:
+ kfree(cmd);
+ dev->cmd = NULL;
return rc;
}
@@ -736,56 +861,45 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code,
void *complete_cb_context)
{
struct pn533_cmd *cmd;
- struct pn533_send_async_complete_arg *arg;
int rc = 0;
nfc_dev_dbg(&dev->interface->dev, "Sending command 0x%x", cmd_code);
- arg = kzalloc(sizeof(*arg), GFP_KERNEL);
- if (!arg)
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd)
return -ENOMEM;
- arg->complete_cb = complete_cb;
- arg->complete_cb_context = complete_cb_context;
- arg->resp = resp;
- arg->req = req;
+ cmd->code = cmd_code;
+ cmd->req = req;
+ cmd->resp = resp;
+ cmd->resp_len = resp_len;
+ cmd->complete_cb = complete_cb;
+ cmd->complete_cb_context = complete_cb_context;
pn533_build_cmd_frame(dev, cmd_code, req);
mutex_lock(&dev->cmd_lock);
if (!dev->cmd_pending) {
- rc = __pn533_send_frame_async(dev, req, resp, resp_len,
- pn533_send_async_complete, arg);
+ rc = __pn533_send_frame_async(dev, req, resp, resp_len);
if (rc)
goto error;
dev->cmd_pending = 1;
+ dev->cmd = cmd;
goto unlock;
}
nfc_dev_dbg(&dev->interface->dev, "%s Queueing command 0x%x", __func__,
cmd_code);
- cmd = kzalloc(sizeof(struct pn533_cmd), GFP_KERNEL);
- if (!cmd) {
- rc = -ENOMEM;
- goto error;
- }
-
INIT_LIST_HEAD(&cmd->queue);
- cmd->cmd_code = cmd_code;
- cmd->req = req;
- cmd->resp = resp;
- cmd->resp_len = resp_len;
- cmd->arg = arg;
-
list_add_tail(&cmd->queue, &dev->cmd_queue);
goto unlock;
error:
- kfree(arg);
+ kfree(cmd);
unlock:
mutex_unlock(&dev->cmd_lock);
return rc;
@@ -850,8 +964,8 @@ static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code,
pn533_send_async_complete_t complete_cb,
void *complete_cb_context)
{
- struct pn533_send_async_complete_arg *arg;
struct sk_buff *resp;
+ struct pn533_cmd *cmd;
int rc;
int resp_len = dev->ops->rx_header_len +
dev->ops->max_payload_len +
@@ -861,33 +975,47 @@ static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code,
if (!resp)
return -ENOMEM;
- arg = kzalloc(sizeof(*arg), GFP_KERNEL);
- if (!arg) {
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
dev_kfree_skb(resp);
return -ENOMEM;
}
- arg->complete_cb = complete_cb;
- arg->complete_cb_context = complete_cb_context;
- arg->resp = resp;
- arg->req = req;
+ cmd->code = cmd_code;
+ cmd->req = req;
+ cmd->resp = resp;
+ cmd->resp_len = resp_len;
+ cmd->complete_cb = complete_cb;
+ cmd->complete_cb_context = complete_cb_context;
pn533_build_cmd_frame(dev, cmd_code, req);
- rc = __pn533_send_frame_async(dev, req, resp, resp_len,
- pn533_send_async_complete, arg);
+ rc = __pn533_send_frame_async(dev, req, resp, resp_len);
if (rc < 0) {
dev_kfree_skb(resp);
- kfree(arg);
+ kfree(cmd);
+ } else {
+ dev->cmd = cmd;
}
return rc;
}
+static void pn533_wq_cmd_complete(struct work_struct *work)
+{
+ struct pn533 *dev = container_of(work, struct pn533, cmd_complete_work);
+ int rc;
+
+ rc = pn533_send_async_complete(dev);
+ if (rc != -EINPROGRESS)
+ queue_work(dev->wq, &dev->cmd_work);
+}
+
static void pn533_wq_cmd(struct work_struct *work)
{
struct pn533 *dev = container_of(work, struct pn533, cmd_work);
struct pn533_cmd *cmd;
+ int rc;
mutex_lock(&dev->cmd_lock);
@@ -903,10 +1031,15 @@ static void pn533_wq_cmd(struct work_struct *work)
mutex_unlock(&dev->cmd_lock);
- __pn533_send_frame_async(dev, cmd->req, cmd->resp, cmd->resp_len,
- pn533_send_async_complete, cmd->arg);
+ rc = __pn533_send_frame_async(dev, cmd->req, cmd->resp, cmd->resp_len);
+ if (rc < 0) {
+ dev_kfree_skb(cmd->req);
+ dev_kfree_skb(cmd->resp);
+ kfree(cmd);
+ return;
+ }
- kfree(cmd);
+ dev->cmd = cmd;
}
struct pn533_sync_cmd_response {
@@ -982,6 +1115,23 @@ static void pn533_send_complete(struct urb *urb)
}
}
+static void pn533_abort_cmd(struct pn533 *dev, gfp_t flags)
+{
+ /* ACR122U does not support any command which aborts last
+ * issued command i.e. as ACK for standard PN533. Additionally,
+ * it behaves stange, sending broken or incorrect responses,
+ * when we cancel urb before the chip will send response.
+ */
+ if (dev->device_type == PN533_DEVICE_ACR122U)
+ return;
+
+ /* An ack will cancel the last issued command */
+ pn533_send_ack(dev, flags);
+
+ /* cancel the urb request */
+ usb_kill_urb(dev->in_urb);
+}
+
static struct sk_buff *pn533_alloc_skb(struct pn533 *dev, unsigned int size)
{
struct sk_buff *skb;
@@ -1500,9 +1650,6 @@ static void pn533_listen_mode_timer(unsigned long data)
nfc_dev_dbg(&dev->interface->dev, "Listen mode timeout");
- /* An ack will cancel the last issued command (poll) */
- pn533_send_ack(dev, GFP_ATOMIC);
-
dev->cancel_listen = 1;
pn533_poll_next_mod(dev);
@@ -1549,6 +1696,11 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg,
if (!rc)
goto done;
+ if (!dev->poll_mod_count) {
+ nfc_dev_dbg(&dev->interface->dev, "Polling has been stoped.");
+ goto done;
+ }
+
pn533_poll_next_mod(dev);
queue_work(dev->wq, &dev->poll_work);
@@ -1627,7 +1779,7 @@ static void pn533_wq_poll(struct work_struct *work)
if (dev->cancel_listen == 1) {
dev->cancel_listen = 0;
- usb_kill_urb(dev->in_urb);
+ pn533_abort_cmd(dev, GFP_ATOMIC);
}
rc = pn533_send_poll_frame(dev);
@@ -1689,12 +1841,7 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev)
return;
}
- /* An ack will cancel the last issued command (poll) */
- pn533_send_ack(dev, GFP_KERNEL);
-
- /* prevent pn533_start_poll_complete to issue a new poll meanwhile */
- usb_kill_urb(dev->in_urb);
-
+ pn533_abort_cmd(dev, GFP_KERNEL);
pn533_poll_reset_mod_list(dev);
}
@@ -1723,6 +1870,8 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev)
rsp = (struct pn533_cmd_activate_response *)resp->data;
rc = rsp->status & PN533_CMD_RET_MASK;
if (rc != PN533_CMD_RET_SUCCESS) {
+ nfc_dev_err(&dev->interface->dev,
+ "Target activation failed (error 0x%x)", rc);
dev_kfree_skb(resp);
return -EIO;
}
@@ -1850,7 +1999,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
rc = rsp->status & PN533_CMD_RET_MASK;
if (rc != PN533_CMD_RET_SUCCESS) {
nfc_dev_err(&dev->interface->dev,
- "Bringing DEP link up failed %d", rc);
+ "Bringing DEP link up failed (error 0x%x)", rc);
goto error;
}
@@ -1985,10 +2134,8 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
pn533_poll_reset_mod_list(dev);
- if (dev->tgt_mode || dev->tgt_active_prot) {
- pn533_send_ack(dev, GFP_KERNEL);
- usb_kill_urb(dev->in_urb);
- }
+ if (dev->tgt_mode || dev->tgt_active_prot)
+ pn533_abort_cmd(dev, GFP_KERNEL);
dev->tgt_active_prot = 0;
dev->tgt_mode = 0;
@@ -2064,8 +2211,7 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg,
if (ret != PN533_CMD_RET_SUCCESS) {
nfc_dev_err(&dev->interface->dev,
- "PN533 reported error %d when exchanging data",
- ret);
+ "Exchanging data failed (error 0x%x)", ret);
rc = -EIO;
goto error;
}
@@ -2253,7 +2399,7 @@ static void pn533_wq_mi_recv(struct work_struct *work)
"Error %d when trying to perform data_exchange", rc);
dev_kfree_skb(skb);
- kfree(dev->cmd_complete_arg);
+ kfree(dev->cmd_complete_mi_arg);
error:
pn533_send_ack(dev, GFP_KERNEL);
@@ -2310,7 +2456,7 @@ static int pn533_get_firmware_version(struct pn533 *dev,
return 0;
}
-static int pn533_fw_reset(struct pn533 *dev)
+static int pn533_pasori_fw_reset(struct pn533 *dev)
{
struct sk_buff *skb;
struct sk_buff *resp;
@@ -2332,9 +2478,102 @@ static int pn533_fw_reset(struct pn533 *dev)
return 0;
}
+struct pn533_acr122_poweron_rdr_arg {
+ int rc;
+ struct completion done;
+};
+
+static void pn533_acr122_poweron_rdr_resp(struct urb *urb)
+{
+ struct pn533_acr122_poweron_rdr_arg *arg = urb->context;
+
+ nfc_dev_dbg(&urb->dev->dev, "%s", __func__);
+
+ print_hex_dump(KERN_ERR, "ACR122 RX: ", DUMP_PREFIX_NONE, 16, 1,
+ urb->transfer_buffer, urb->transfer_buffer_length,
+ false);
+
+ arg->rc = urb->status;
+ complete(&arg->done);
+}
+
+static int pn533_acr122_poweron_rdr(struct pn533 *dev)
+{
+ /* Power on th reader (CCID cmd) */
+ u8 cmd[10] = {PN533_ACR122_PC_TO_RDR_ICCPOWERON,
+ 0, 0, 0, 0, 0, 0, 3, 0, 0};
+ u8 buf[255];
+ int rc;
+ void *cntx;
+ struct pn533_acr122_poweron_rdr_arg arg;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ init_completion(&arg.done);
+ cntx = dev->in_urb->context; /* backup context */
+
+ dev->in_urb->transfer_buffer = buf;
+ dev->in_urb->transfer_buffer_length = 255;
+ dev->in_urb->complete = pn533_acr122_poweron_rdr_resp;
+ dev->in_urb->context = &arg;
+
+ dev->out_urb->transfer_buffer = cmd;
+ dev->out_urb->transfer_buffer_length = sizeof(cmd);
+
+ print_hex_dump(KERN_ERR, "ACR122 TX: ", DUMP_PREFIX_NONE, 16, 1,
+ cmd, sizeof(cmd), false);
+
+ rc = usb_submit_urb(dev->out_urb, GFP_KERNEL);
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev,
+ "Reader power on cmd error %d", rc);
+ return rc;
+ }
+
+ rc = usb_submit_urb(dev->in_urb, GFP_KERNEL);
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev,
+ "Can't submit for reader power on cmd response %d",
+ rc);
+ return rc;
+ }
+
+ wait_for_completion(&arg.done);
+ dev->in_urb->context = cntx; /* restore context */
+
+ return arg.rc;
+}
+
+static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf)
+{
+ struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+ u8 rf_field = !!rf;
+ int rc;
+
+ rc = pn533_set_configuration(dev, PN533_CFGITEM_RF_FIELD,
+ (u8 *)&rf_field, 1);
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev,
+ "Error on setting RF field");
+ return rc;
+ }
+
+ return rc;
+}
+
+int pn533_dev_up(struct nfc_dev *nfc_dev)
+{
+ return pn533_rf_field(nfc_dev, 1);
+}
+
+int pn533_dev_down(struct nfc_dev *nfc_dev)
+{
+ return pn533_rf_field(nfc_dev, 0);
+}
+
static struct nfc_ops pn533_nfc_ops = {
- .dev_up = NULL,
- .dev_down = NULL,
+ .dev_up = pn533_dev_up,
+ .dev_down = pn533_dev_down,
.dep_link_up = pn533_dep_link_up,
.dep_link_down = pn533_dep_link_down,
.start_poll = pn533_start_poll,
@@ -2366,6 +2605,7 @@ static int pn533_setup(struct pn533 *dev)
break;
case PN533_DEVICE_PASORI:
+ case PN533_DEVICE_ACR122U:
max_retries.mx_rty_atr = 0x2;
max_retries.mx_rty_psl = 0x1;
max_retries.mx_rty_passive_act =
@@ -2405,7 +2645,7 @@ static int pn533_setup(struct pn533 *dev)
break;
case PN533_DEVICE_PASORI:
- pn533_fw_reset(dev);
+ pn533_pasori_fw_reset(dev);
rc = pn533_set_configuration(dev, PN533_CFGITEM_PASORI,
pasori_cfg, 3);
@@ -2415,7 +2655,7 @@ static int pn533_setup(struct pn533 *dev)
return rc;
}
- pn533_fw_reset(dev);
+ pn533_pasori_fw_reset(dev);
break;
}
@@ -2496,6 +2736,7 @@ static int pn533_probe(struct usb_interface *interface,
dev->ops = &pn533_std_frame_ops;
+ dev->protocol_type = PN533_PROTO_REQ_ACK_RESP;
dev->device_type = id->driver_info;
switch (dev->device_type) {
case PN533_DEVICE_STD:
@@ -2506,6 +2747,20 @@ static int pn533_probe(struct usb_interface *interface,
protocols = PN533_NO_TYPE_B_PROTOCOLS;
break;
+ case PN533_DEVICE_ACR122U:
+ protocols = PN533_NO_TYPE_B_PROTOCOLS;
+ dev->ops = &pn533_acr122_frame_ops;
+ dev->protocol_type = PN533_PROTO_REQ_RESP,
+
+ rc = pn533_acr122_poweron_rdr(dev);
+ if (rc < 0) {
+ nfc_dev_err(&dev->interface->dev,
+ "Couldn't poweron the reader (error %d)",
+ rc);
+ goto destroy_wq;
+ }
+ break;
+
default:
nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n",
dev->device_type);
@@ -2555,6 +2810,7 @@ destroy_wq:
error:
usb_free_urb(dev->in_urb);
usb_free_urb(dev->out_urb);
+ usb_put_dev(dev->udev);
kfree(dev);
return rc;
}
@@ -2600,8 +2856,9 @@ static struct usb_driver pn533_driver = {
module_usb_driver(pn533_driver);
-MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>,"
- " Aloisio Almeida Jr <aloisio.almeida@openbossa.org>");
+MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>");
+MODULE_AUTHOR("Aloisio Almeida Jr <aloisio.almeida@openbossa.org>");
+MODULE_AUTHOR("Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>");
MODULE_DESCRIPTION("PN533 usb driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/nfc/pn544/Kconfig b/drivers/nfc/pn544/Kconfig
index c277790ac71c..ccf06f5f6ebb 100644
--- a/drivers/nfc/pn544/Kconfig
+++ b/drivers/nfc/pn544/Kconfig
@@ -20,4 +20,15 @@ config NFC_PN544_I2C
Select this if your platform is using the i2c bus.
If you choose to build a module, it'll be called pn544_i2c.
- Say N if unsure. \ No newline at end of file
+ Say N if unsure.
+
+config NFC_PN544_MEI
+ tristate "NFC PN544 MEI support"
+ depends on NFC_PN544 && NFC_MEI_PHY
+ ---help---
+ This module adds support for the mei interface of adapters using
+ NXP pn544 chipsets. Select this if your pn544 chipset
+ is handled by Intel's Management Engine Interface on your platform.
+
+ If you choose to build a module, it'll be called pn544_mei.
+ Say N if unsure.
diff --git a/drivers/nfc/pn544/Makefile b/drivers/nfc/pn544/Makefile
index ac076793687d..29fb5a174036 100644
--- a/drivers/nfc/pn544/Makefile
+++ b/drivers/nfc/pn544/Makefile
@@ -3,6 +3,8 @@
#
pn544_i2c-objs = i2c.o
+pn544_mei-objs = mei.o
obj-$(CONFIG_NFC_PN544) += pn544.o
obj-$(CONFIG_NFC_PN544_I2C) += pn544_i2c.o
+obj-$(CONFIG_NFC_PN544_MEI) += pn544_mei.o
diff --git a/drivers/nfc/pn544/mei.c b/drivers/nfc/pn544/mei.c
new file mode 100644
index 000000000000..1eb48848a35a
--- /dev/null
+++ b/drivers/nfc/pn544/mei.c
@@ -0,0 +1,121 @@
+/*
+ * HCI based Driver for NXP pn544 NFC Chip
+ *
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/nfc.h>
+#include <net/nfc/hci.h>
+#include <net/nfc/llc.h>
+
+#include "../mei_phy.h"
+#include "pn544.h"
+
+#define PN544_DRIVER_NAME "pn544"
+
+static int pn544_mei_probe(struct mei_cl_device *device,
+ const struct mei_cl_device_id *id)
+{
+ struct nfc_mei_phy *phy;
+ int r;
+
+ pr_info("Probing NFC pn544\n");
+
+ phy = nfc_mei_phy_alloc(device);
+ if (!phy) {
+ pr_err("Cannot allocate memory for pn544 mei phy.\n");
+ return -ENOMEM;
+ }
+
+ r = mei_cl_register_event_cb(device, nfc_mei_event_cb, phy);
+ if (r) {
+ pr_err(PN544_DRIVER_NAME ": event cb registration failed\n");
+ goto err_out;
+ }
+
+ r = pn544_hci_probe(phy, &mei_phy_ops, LLC_NOP_NAME,
+ MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
+ &phy->hdev);
+ if (r < 0)
+ goto err_out;
+
+ return 0;
+
+err_out:
+ nfc_mei_phy_free(phy);
+
+ return r;
+}
+
+static int pn544_mei_remove(struct mei_cl_device *device)
+{
+ struct nfc_mei_phy *phy = mei_cl_get_drvdata(device);
+
+ pr_info("Removing pn544\n");
+
+ pn544_hci_remove(phy->hdev);
+
+ nfc_mei_phy_disable(phy);
+
+ nfc_mei_phy_free(phy);
+
+ return 0;
+}
+
+static struct mei_cl_device_id pn544_mei_tbl[] = {
+ { PN544_DRIVER_NAME },
+
+ /* required last entry */
+ { }
+};
+MODULE_DEVICE_TABLE(mei, pn544_mei_tbl);
+
+static struct mei_cl_driver pn544_driver = {
+ .id_table = pn544_mei_tbl,
+ .name = PN544_DRIVER_NAME,
+
+ .probe = pn544_mei_probe,
+ .remove = pn544_mei_remove,
+};
+
+static int pn544_mei_init(void)
+{
+ int r;
+
+ pr_debug(DRIVER_DESC ": %s\n", __func__);
+
+ r = mei_cl_driver_register(&pn544_driver);
+ if (r) {
+ pr_err(PN544_DRIVER_NAME ": driver registration failed\n");
+ return r;
+ }
+
+ return 0;
+}
+
+static void pn544_mei_exit(void)
+{
+ mei_cl_driver_unregister(&pn544_driver);
+}
+
+module_init(pn544_mei_init);
+module_exit(pn544_mei_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 0ab6712fd76b..f14a98a79c9d 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -134,6 +134,7 @@ struct bcma_host_ops {
#define BCMA_CORE_I2S 0x834
#define BCMA_CORE_SDR_DDR1_MEM_CTL 0x835 /* SDR/DDR1 memory controller core */
#define BCMA_CORE_SHIM 0x837 /* SHIM component in ubus/6362 */
+#define BCMA_CORE_ARM_CR4 0x83e
#define BCMA_CORE_DEFAULT 0xFFF
#define BCMA_MAX_NR_CORES 16
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index 453fcc914683..b8b09eac60a4 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -316,6 +316,9 @@
#define BCMA_CC_PMU_CTL 0x0600 /* PMU control */
#define BCMA_CC_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */
#define BCMA_CC_PMU_CTL_ILP_DIV_SHIFT 16
+#define BCMA_CC_PMU_CTL_RES 0x00006000 /* reset control mask */
+#define BCMA_CC_PMU_CTL_RES_SHIFT 13
+#define BCMA_CC_PMU_CTL_RES_RELOAD 0x2 /* reload POR values */
#define BCMA_CC_PMU_CTL_PLL_UPD 0x00000400
#define BCMA_CC_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */
#define BCMA_CC_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */
diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h
index 7e8104bb7a7e..917dcd7965e7 100644
--- a/include/linux/bcma/bcma_regs.h
+++ b/include/linux/bcma/bcma_regs.h
@@ -37,6 +37,7 @@
#define BCMA_IOST_BIST_DONE 0x8000
#define BCMA_RESET_CTL 0x0800
#define BCMA_RESET_CTL_RESET 0x0001
+#define BCMA_RESET_ST 0x0804
/* BCMA PCI config space registers. */
#define BCMA_PCI_PMCSR 0x44
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 4cf0c9e4dd99..06b0ed0154a4 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -673,6 +673,36 @@ struct ieee80211_channel_sw_ie {
} __packed;
/**
+ * struct ieee80211_ext_chansw_ie
+ *
+ * This structure represents the "Extended Channel Switch Announcement element"
+ */
+struct ieee80211_ext_chansw_ie {
+ u8 mode;
+ u8 new_operating_class;
+ u8 new_ch_num;
+ u8 count;
+} __packed;
+
+/**
+ * struct ieee80211_sec_chan_offs_ie - secondary channel offset IE
+ * @sec_chan_offs: secondary channel offset, uses IEEE80211_HT_PARAM_CHA_SEC_*
+ * values here
+ * This structure represents the "Secondary Channel Offset element"
+ */
+struct ieee80211_sec_chan_offs_ie {
+ u8 sec_chan_offs;
+} __packed;
+
+/**
+ * struct ieee80211_wide_bw_chansw_ie - wide bandwidth channel switch IE
+ */
+struct ieee80211_wide_bw_chansw_ie {
+ u8 new_channel_width;
+ u8 new_center_freq_seg0, new_center_freq_seg1;
+} __packed;
+
+/**
* struct ieee80211_tim
*
* This structure refers to "Traffic Indication Map information element"
@@ -840,12 +870,15 @@ struct ieee80211_mgmt {
} __packed wme_action;
struct{
u8 action_code;
- u8 element_id;
- u8 length;
- struct ieee80211_channel_sw_ie sw_elem;
+ u8 variable[0];
} __packed chan_switch;
struct{
u8 action_code;
+ struct ieee80211_ext_chansw_ie data;
+ u8 variable[0];
+ } __packed ext_chan_switch;
+ struct{
+ u8 action_code;
u8 dialog_token;
u8 element_id;
u8 length;
@@ -1027,6 +1060,26 @@ enum ieee80211_p2p_attr_id {
IEEE80211_P2P_ATTR_MAX
};
+/* Notice of Absence attribute - described in P2P spec 4.1.14 */
+/* Typical max value used here */
+#define IEEE80211_P2P_NOA_DESC_MAX 4
+
+struct ieee80211_p2p_noa_desc {
+ u8 count;
+ __le32 duration;
+ __le32 interval;
+ __le32 start_time;
+} __packed;
+
+struct ieee80211_p2p_noa_attr {
+ u8 index;
+ u8 oppps_ctwindow;
+ struct ieee80211_p2p_noa_desc desc[IEEE80211_P2P_NOA_DESC_MAX];
+} __packed;
+
+#define IEEE80211_P2P_OPPPS_ENABLE_BIT BIT(7)
+#define IEEE80211_P2P_OPPPS_CTWINDOW_MASK 0x7F
+
/**
* struct ieee80211_bar - HT Block Ack Request
*
@@ -1618,6 +1671,7 @@ enum ieee80211_eid {
WLAN_EID_HT_CAPABILITY = 45,
WLAN_EID_HT_OPERATION = 61,
+ WLAN_EID_SECONDARY_CHANNEL_OFFSET = 62,
WLAN_EID_RSN = 48,
WLAN_EID_MMIE = 76,
@@ -1652,6 +1706,8 @@ enum ieee80211_eid {
WLAN_EID_VHT_CAPABILITY = 191,
WLAN_EID_VHT_OPERATION = 192,
WLAN_EID_OPMODE_NOTIF = 199,
+ WLAN_EID_WIDE_BW_CHANNEL_SWITCH = 194,
+ WLAN_EID_CHANNEL_SWITCH_WRAPPER = 196,
/* 802.11ad */
WLAN_EID_NON_TX_BSSID_CAP = 83,
@@ -1775,6 +1831,7 @@ enum ieee80211_key_len {
/* Public action codes */
enum ieee80211_pub_actioncode {
+ WLAN_PUB_ACTION_EXT_CHANSW_ANN = 4,
WLAN_PUB_ACTION_TDLS_DISCOVER_RES = 14,
};
@@ -1935,6 +1992,16 @@ enum ieee80211_timeout_interval_type {
WLAN_TIMEOUT_ASSOC_COMEBACK = 3 /* 802.11w */,
};
+/**
+ * struct ieee80211_timeout_interval_ie - Timeout Interval element
+ * @type: type, see &enum ieee80211_timeout_interval_type
+ * @value: timeout interval value
+ */
+struct ieee80211_timeout_interval_ie {
+ u8 type;
+ __le32 value;
+} __packed;
+
/* BACK action code */
enum ieee80211_back_actioncode {
WLAN_ACTION_ADDBA_REQ = 0,
diff --git a/include/linux/platform_data/brcmfmac-sdio.h b/include/linux/platform_data/brcmfmac-sdio.h
new file mode 100644
index 000000000000..1ade657d5fc1
--- /dev/null
+++ b/include/linux/platform_data/brcmfmac-sdio.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2013 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.
+ */
+
+#ifndef _LINUX_BRCMFMAC_PLATFORM_H
+#define _LINUX_BRCMFMAC_PLATFORM_H
+
+/*
+ * Platform specific driver functions and data. Through the platform specific
+ * device data functions can be provided to help the brcmfmac driver to
+ * operate with the device in combination with the used platform.
+ *
+ * Use the platform data in the following (similar) way:
+ *
+ *
+#include <brcmfmac_platform.h>
+
+
+static void brcmfmac_power_on(void)
+{
+}
+
+static void brcmfmac_power_off(void)
+{
+}
+
+static void brcmfmac_reset(void)
+{
+}
+
+static struct brcmfmac_sdio_platform_data brcmfmac_sdio_pdata = {
+ .power_on = brcmfmac_power_on,
+ .power_off = brcmfmac_power_off,
+ .reset = brcmfmac_reset
+};
+
+static struct platform_device brcmfmac_device = {
+ .name = BRCMFMAC_SDIO_PDATA_NAME,
+ .id = PLATFORM_DEVID_NONE,
+ .dev.platform_data = &brcmfmac_sdio_pdata
+};
+
+void __init brcmfmac_init_pdata(void)
+{
+ brcmfmac_sdio_pdata.oob_irq_supported = true;
+ brcmfmac_sdio_pdata.oob_irq_nr = gpio_to_irq(GPIO_BRCMF_SDIO_OOB);
+ brcmfmac_sdio_pdata.oob_irq_flags = IORESOURCE_IRQ |
+ IORESOURCE_IRQ_HIGHLEVEL;
+ platform_device_register(&brcmfmac_device);
+}
+ *
+ *
+ * Note: the brcmfmac can be loaded as module or be statically built-in into
+ * the kernel. If built-in then do note that it uses module_init (and
+ * module_exit) routines which equal device_initcall. So if you intend to
+ * create a module with the platform specific data for the brcmfmac and have
+ * it built-in to the kernel then use a higher initcall then device_initcall
+ * (see init.h). If this is not done then brcmfmac will load without problems
+ * but will not pickup the platform data.
+ *
+ * When the driver does not "detect" platform driver data then it will continue
+ * without reporting anything and just assume there is no data needed. Which is
+ * probably true for most platforms.
+ *
+ * Explanation of the platform_data fields:
+ *
+ * drive_strength: is the preferred drive_strength to be used for the SDIO
+ * pins. If 0 then a default value will be used. This is the target drive
+ * strength, the exact drive strength which will be used depends on the
+ * capabilities of the device.
+ *
+ * oob_irq_supported: does the board have support for OOB interrupts. SDIO
+ * in-band interrupts are relatively slow and for having less overhead on
+ * interrupt processing an out of band interrupt can be used. If the HW
+ * supports this then enable this by setting this field to true and configure
+ * the oob related fields.
+ *
+ * oob_irq_nr, oob_irq_flags: the OOB interrupt information. The values are
+ * used for registering the irq using request_irq function.
+ *
+ * power_on: This function is called by the brcmfmac when the module gets
+ * loaded. This can be particularly useful for low power devices. The platform
+ * spcific routine may for example decide to power up the complete device.
+ * If there is no use-case for this function then provide NULL.
+ *
+ * power_off: This function is called by the brcmfmac when the module gets
+ * unloaded. At this point the device can be powered down or otherwise be reset.
+ * So if an actual power_off is not supported but reset is then reset the device
+ * when this function gets called. This can be particularly useful for low power
+ * devices. If there is no use-case for this function (either power-down or
+ * reset) then provide NULL.
+ *
+ * reset: This function can get called if the device communication broke down.
+ * This functionality is particularly useful in case of SDIO type devices. It is
+ * possible to reset a dongle via sdio data interface, but it requires that
+ * this is fully functional. This function is chip/module specific and this
+ * function should return only after the complete reset has completed.
+ */
+
+#define BRCMFMAC_SDIO_PDATA_NAME "brcmfmac_sdio"
+
+struct brcmfmac_sdio_platform_data {
+ unsigned int drive_strength;
+ bool oob_irq_supported;
+ unsigned int oob_irq_nr;
+ unsigned long oob_irq_flags;
+ void (*power_on)(void);
+ void (*power_off)(void);
+ void (*reset)(void);
+};
+
+#endif /* _LINUX_BRCMFMAC_PLATFORM_H */
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index ed6e9552252e..6912ef9a1881 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -193,11 +193,11 @@ static inline bool bdaddr_type_is_le(__u8 type)
#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)
+static inline int bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2)
{
return memcmp(ba1, ba2, sizeof(bdaddr_t));
}
-static inline void bacpy(bdaddr_t *dst, bdaddr_t *src)
+static inline void bacpy(bdaddr_t *dst, const bdaddr_t *src)
{
memcpy(dst, src, sizeof(bdaddr_t));
}
@@ -266,6 +266,7 @@ typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status);
struct hci_req_ctrl {
bool start;
+ u8 event;
hci_req_complete_t complete;
};
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index b3308927a0a1..e0512aaef4b8 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -984,6 +984,9 @@ struct hci_cp_le_set_adv_data {
#define HCI_OP_LE_SET_ADV_ENABLE 0x200a
+#define LE_SCAN_PASSIVE 0x00
+#define LE_SCAN_ACTIVE 0x01
+
#define HCI_OP_LE_SET_SCAN_PARAM 0x200b
struct hci_cp_le_set_scan_param {
__u8 type;
@@ -993,8 +996,10 @@ struct hci_cp_le_set_scan_param {
__u8 filter_policy;
} __packed;
-#define LE_SCANNING_DISABLED 0x00
-#define LE_SCANNING_ENABLED 0x01
+#define LE_SCAN_DISABLE 0x00
+#define LE_SCAN_ENABLE 0x01
+#define LE_SCAN_FILTER_DUP_DISABLE 0x00
+#define LE_SCAN_FILTER_DUP_ENABLE 0x01
#define HCI_OP_LE_SET_SCAN_ENABLE 0x200c
struct hci_cp_le_set_scan_enable {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 358a6983d3bb..80d718a9b31f 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -134,6 +134,8 @@ struct amp_assoc {
__u8 data[HCI_MAX_AMP_ASSOC_SIZE];
};
+#define HCI_MAX_PAGES 3
+
#define NUM_REASSEMBLY 4
struct hci_dev {
struct list_head list;
@@ -151,8 +153,8 @@ struct hci_dev {
__u8 dev_class[3];
__u8 major_class;
__u8 minor_class;
- __u8 features[8];
- __u8 host_features[8];
+ __u8 max_page;
+ __u8 features[HCI_MAX_PAGES][8];
__u8 le_features[8];
__u8 le_white_list_size;
__u8 le_states[8];
@@ -244,6 +246,7 @@ struct hci_dev {
struct sk_buff_head raw_q;
struct sk_buff_head cmd_q;
+ struct sk_buff *recv_evt;
struct sk_buff *sent_cmd;
struct sk_buff *reassembly[NUM_REASSEMBLY];
@@ -268,8 +271,6 @@ struct hci_dev {
struct hci_dev_stats stat;
- struct sk_buff_head driver_init;
-
atomic_t promisc;
struct dentry *debugfs;
@@ -292,6 +293,7 @@ struct hci_dev {
int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev);
int (*flush)(struct hci_dev *hdev);
+ int (*setup)(struct hci_dev *hdev);
int (*send)(struct sk_buff *skb);
void (*notify)(struct hci_dev *hdev, unsigned int evt);
int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
@@ -313,7 +315,7 @@ struct hci_conn {
bool out;
__u8 attempt;
__u8 dev_class[3];
- __u8 features[8];
+ __u8 features[HCI_MAX_PAGES][8];
__u16 interval;
__u16 pkt_type;
__u16 link_policy;
@@ -345,7 +347,6 @@ struct hci_conn {
struct timer_list auto_accept_timer;
struct device dev;
- atomic_t devref;
struct hci_dev *hdev;
void *l2cap_data;
@@ -584,7 +585,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
int hci_conn_del(struct hci_conn *conn);
void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);
-void hci_conn_accept(struct hci_conn *conn, int mask);
struct hci_chan *hci_chan_create(struct hci_conn *conn);
void hci_chan_del(struct hci_chan *chan);
@@ -601,8 +601,36 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
-void hci_conn_hold_device(struct hci_conn *conn);
-void hci_conn_put_device(struct hci_conn *conn);
+/*
+ * hci_conn_get() and hci_conn_put() are used to control the life-time of an
+ * "hci_conn" object. They do not guarantee that the hci_conn object is running,
+ * working or anything else. They just guarantee that the object is available
+ * and can be dereferenced. So you can use its locks, local variables and any
+ * other constant data.
+ * Before accessing runtime data, you _must_ lock the object and then check that
+ * it is still running. As soon as you release the locks, the connection might
+ * get dropped, though.
+ *
+ * On the other hand, hci_conn_hold() and hci_conn_drop() are used to control
+ * how long the underlying connection is held. So every channel that runs on the
+ * hci_conn object calls this to prevent the connection from disappearing. As
+ * long as you hold a device, you must also guarantee that you have a valid
+ * reference to the device via hci_conn_get() (or the initial reference from
+ * hci_conn_add()).
+ * The hold()/drop() ref-count is known to drop below 0 sometimes, which doesn't
+ * break because nobody cares for that. But this means, we cannot use
+ * _get()/_drop() in it, but require the caller to have a valid ref (FIXME).
+ */
+
+static inline void hci_conn_get(struct hci_conn *conn)
+{
+ get_device(&conn->dev);
+}
+
+static inline void hci_conn_put(struct hci_conn *conn)
+{
+ put_device(&conn->dev);
+}
static inline void hci_conn_hold(struct hci_conn *conn)
{
@@ -612,7 +640,7 @@ static inline void hci_conn_hold(struct hci_conn *conn)
cancel_delayed_work(&conn->disc_work);
}
-static inline void hci_conn_put(struct hci_conn *conn)
+static inline void hci_conn_drop(struct hci_conn *conn)
{
BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt));
@@ -760,29 +788,29 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev))
/* ----- LMP capabilities ----- */
-#define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT)
-#define lmp_rswitch_capable(dev) ((dev)->features[0] & LMP_RSWITCH)
-#define lmp_hold_capable(dev) ((dev)->features[0] & LMP_HOLD)
-#define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF)
-#define lmp_park_capable(dev) ((dev)->features[1] & LMP_PARK)
-#define lmp_inq_rssi_capable(dev) ((dev)->features[3] & LMP_RSSI_INQ)
-#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
-#define lmp_bredr_capable(dev) (!((dev)->features[4] & LMP_NO_BREDR))
-#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)
-#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
-#define lmp_pause_enc_capable(dev) ((dev)->features[5] & LMP_PAUSE_ENC)
-#define lmp_ext_inq_capable(dev) ((dev)->features[6] & LMP_EXT_INQ)
-#define lmp_le_br_capable(dev) !!((dev)->features[6] & LMP_SIMUL_LE_BR)
-#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)
-#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH)
-#define lmp_lsto_capable(dev) ((dev)->features[7] & LMP_LSTO)
-#define lmp_inq_tx_pwr_capable(dev) ((dev)->features[7] & LMP_INQ_TX_PWR)
-#define lmp_ext_feat_capable(dev) ((dev)->features[7] & LMP_EXTFEATURES)
+#define lmp_encrypt_capable(dev) ((dev)->features[0][0] & LMP_ENCRYPT)
+#define lmp_rswitch_capable(dev) ((dev)->features[0][0] & LMP_RSWITCH)
+#define lmp_hold_capable(dev) ((dev)->features[0][0] & LMP_HOLD)
+#define lmp_sniff_capable(dev) ((dev)->features[0][0] & LMP_SNIFF)
+#define lmp_park_capable(dev) ((dev)->features[0][1] & LMP_PARK)
+#define lmp_inq_rssi_capable(dev) ((dev)->features[0][3] & LMP_RSSI_INQ)
+#define lmp_esco_capable(dev) ((dev)->features[0][3] & LMP_ESCO)
+#define lmp_bredr_capable(dev) (!((dev)->features[0][4] & LMP_NO_BREDR))
+#define lmp_le_capable(dev) ((dev)->features[0][4] & LMP_LE)
+#define lmp_sniffsubr_capable(dev) ((dev)->features[0][5] & LMP_SNIFF_SUBR)
+#define lmp_pause_enc_capable(dev) ((dev)->features[0][5] & LMP_PAUSE_ENC)
+#define lmp_ext_inq_capable(dev) ((dev)->features[0][6] & LMP_EXT_INQ)
+#define lmp_le_br_capable(dev) (!!((dev)->features[0][6] & LMP_SIMUL_LE_BR))
+#define lmp_ssp_capable(dev) ((dev)->features[0][6] & LMP_SIMPLE_PAIR)
+#define lmp_no_flush_capable(dev) ((dev)->features[0][6] & LMP_NO_FLUSH)
+#define lmp_lsto_capable(dev) ((dev)->features[0][7] & LMP_LSTO)
+#define lmp_inq_tx_pwr_capable(dev) ((dev)->features[0][7] & LMP_INQ_TX_PWR)
+#define lmp_ext_feat_capable(dev) ((dev)->features[0][7] & LMP_EXTFEATURES)
/* ----- Extended LMP capabilities ----- */
-#define lmp_host_ssp_capable(dev) ((dev)->host_features[0] & LMP_HOST_SSP)
-#define lmp_host_le_capable(dev) !!((dev)->host_features[0] & LMP_HOST_LE)
-#define lmp_host_le_br_capable(dev) !!((dev)->host_features[0] & LMP_HOST_LE_BREDR)
+#define lmp_host_ssp_capable(dev) ((dev)->features[1][0] & LMP_HOST_SSP)
+#define lmp_host_le_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE))
+#define lmp_host_le_br_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE_BREDR))
/* returns true if at least one AMP active */
static inline bool hci_amp_capable(void)
@@ -1054,8 +1082,14 @@ struct hci_request {
void hci_req_init(struct hci_request *req, struct hci_dev *hdev);
int hci_req_run(struct hci_request *req, hci_req_complete_t complete);
void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param);
+void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void *param,
+ u8 event);
void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status);
-void hci_req_cmd_status(struct hci_dev *hdev, u16 opcode, u8 status);
+
+struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
+ void *param, u32 timeout);
+struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
+ void *param, u8 event, u32 timeout);
int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index cdd33021f831..fb94cf13c777 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -583,6 +583,14 @@ struct l2cap_conn {
struct list_head chan_l;
struct mutex chan_lock;
+ struct kref ref;
+ struct list_head users;
+};
+
+struct l2cap_user {
+ struct list_head list;
+ int (*probe) (struct l2cap_conn *conn, struct l2cap_user *user);
+ void (*remove) (struct l2cap_conn *conn, struct l2cap_user *user);
};
#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
@@ -786,6 +794,7 @@ extern bool disable_ertm;
int l2cap_init_sockets(void);
void l2cap_cleanup_sockets(void);
+bool l2cap_is_socket(struct socket *sock);
void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
int __l2cap_wait_ack(struct sock *sk);
@@ -812,4 +821,10 @@ void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
u8 status);
void __l2cap_physical_cfm(struct l2cap_chan *chan, int result);
+void l2cap_conn_get(struct l2cap_conn *conn);
+void l2cap_conn_put(struct l2cap_conn *conn);
+
+int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user);
+void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user);
+
#endif /* __L2CAP_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index bdba9b619064..26b5b692c22b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1998,6 +1998,16 @@ struct cfg80211_update_ft_ies_params {
* advertise the support for MAC based ACL have to implement this callback.
*
* @start_radar_detection: Start radar detection in the driver.
+ *
+ * @update_ft_ies: Provide updated Fast BSS Transition information to the
+ * driver. If the SME is in the driver/firmware, this information can be
+ * used in building Authentication and Reassociation Request frames.
+ *
+ * @crit_proto_start: Indicates a critical protocol needs more link reliability
+ * for a given duration (milliseconds). The protocol is provided so the
+ * driver can take the most appropriate actions.
+ * @crit_proto_stop: Indicates critical protocol no longer needs increased link
+ * reliability. This operation can not fail.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2227,6 +2237,12 @@ struct cfg80211_ops {
struct cfg80211_chan_def *chandef);
int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_update_ft_ies_params *ftie);
+ int (*crit_proto_start)(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ enum nl80211_crit_proto_id protocol,
+ u16 duration);
+ void (*crit_proto_stop)(struct wiphy *wiphy,
+ struct wireless_dev *wdev);
};
/*
@@ -4020,6 +4036,17 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
void cfg80211_ch_switch_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef);
+/**
+ * ieee80211_operating_class_to_band - convert operating class to band
+ *
+ * @operating_class: the operating class to convert
+ * @band: band pointer to fill
+ *
+ * Returns %true if the conversion was successful, %false otherwise.
+ */
+bool ieee80211_operating_class_to_band(u8 operating_class,
+ enum ieee80211_band *band);
+
/*
* cfg80211_tdls_oper_request - request userspace to perform TDLS operation
* @dev: the device on which the operation is requested
@@ -4122,6 +4149,17 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
struct cfg80211_wowlan_wakeup *wakeup,
gfp_t gfp);
+/**
+ * cfg80211_crit_proto_stopped() - indicate critical protocol stopped by driver.
+ *
+ * @wdev: the wireless device for which critical protocol is stopped.
+ *
+ * This function can be called by the driver to indicate it has reverted
+ * operation back to normal. One reason could be that the duration given
+ * by .crit_proto_start() has expired.
+ */
+void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp);
+
/* Logging, debugging and troubleshooting/diagnostic helpers. */
/* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index dd73b8c6746b..04c2d4670dc6 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -128,6 +128,7 @@ enum ieee80211_ac_numbers {
* 2^n-1 in the range 1..32767]
* @cw_max: maximum contention window [like @cw_min]
* @txop: maximum burst time in units of 32 usecs, 0 meaning disabled
+ * @acm: is mandatory admission control required for the access category
* @uapsd: is U-APSD mode enabled for the queue
*/
struct ieee80211_tx_queue_params {
@@ -135,6 +136,7 @@ struct ieee80211_tx_queue_params {
u16 cw_min;
u16 cw_max;
u8 aifs;
+ bool acm;
bool uapsd;
};
@@ -209,7 +211,7 @@ struct ieee80211_chanctx_conf {
* @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note
* that it is only ever disabled for station mode.
* @BSS_CHANGED_IDLE: Idle changed for this BSS/interface.
- * @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode)
+ * @BSS_CHANGED_SSID: SSID changed for this BSS (AP and IBSS mode)
* @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode)
* @BSS_CHANGED_PS: PS changed for this BSS (STA mode)
* @BSS_CHANGED_TXPOWER: TX power setting changed for this interface
@@ -326,12 +328,11 @@ enum ieee80211_rssi_event {
* your driver/device needs to do.
* @ps: power-save mode (STA only). This flag is NOT affected by
* offchannel/dynamic_ps operations.
- * @ssid: The SSID of the current vif. Only valid in AP-mode.
+ * @ssid: The SSID of the current vif. Valid in AP and IBSS mode.
* @ssid_len: Length of SSID given in @ssid.
* @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
* @txpower: TX power in dBm
- * @p2p_ctwindow: P2P CTWindow, only for P2P client interfaces
- * @p2p_oppps: P2P opportunistic PS is enabled
+ * @p2p_noa_attr: P2P NoA attribute for P2P powersave
*/
struct ieee80211_bss_conf {
const u8 *bssid;
@@ -365,8 +366,7 @@ struct ieee80211_bss_conf {
size_t ssid_len;
bool hidden_ssid;
int txpower;
- u8 p2p_ctwindow;
- bool p2p_oppps;
+ struct ieee80211_p2p_noa_attr p2p_noa_attr;
};
/**
@@ -563,6 +563,9 @@ enum mac80211_rate_control_flags {
/* maximum number of rate stages */
#define IEEE80211_TX_MAX_RATES 4
+/* maximum number of rate table entries */
+#define IEEE80211_TX_RATE_TABLE_SIZE 4
+
/**
* struct ieee80211_tx_rate - rate selection/status
*
@@ -603,8 +606,8 @@ static inline void ieee80211_rate_set_vht(struct ieee80211_tx_rate *rate,
u8 mcs, u8 nss)
{
WARN_ON(mcs & ~0xF);
- WARN_ON(nss & ~0x7);
- rate->idx = (nss << 4) | mcs;
+ WARN_ON((nss - 1) & ~0x7);
+ rate->idx = ((nss - 1) << 4) | mcs;
}
static inline u8
@@ -616,7 +619,7 @@ ieee80211_rate_get_vht_mcs(const struct ieee80211_tx_rate *rate)
static inline u8
ieee80211_rate_get_vht_nss(const struct ieee80211_tx_rate *rate)
{
- return rate->idx >> 4;
+ return (rate->idx >> 4) + 1;
}
/**
@@ -657,7 +660,11 @@ struct ieee80211_tx_info {
struct ieee80211_tx_rate rates[
IEEE80211_TX_MAX_RATES];
s8 rts_cts_rate_idx;
- /* 3 bytes free */
+ u8 use_rts:1;
+ u8 use_cts_prot:1;
+ u8 short_preamble:1;
+ u8 skip_table:1;
+ /* 2 bytes free */
};
/* only needed before rate control */
unsigned long jiffies;
@@ -678,6 +685,8 @@ struct ieee80211_tx_info {
struct {
struct ieee80211_tx_rate driver_rates[
IEEE80211_TX_MAX_RATES];
+ u8 pad[4];
+
void *rate_driver_data[
IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE / sizeof(void *)];
};
@@ -976,8 +985,7 @@ enum ieee80211_smps_mode {
* @power_level: requested transmit power (in dBm), backward compatibility
* value only that is set to the minimum of all interfaces
*
- * @channel: the channel to tune to
- * @channel_type: the channel (HT) type
+ * @chandef: the channel definition to tune to
* @radar_enabled: whether radar detection is enabled
*
* @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame
@@ -1003,8 +1011,7 @@ struct ieee80211_conf {
u8 long_frame_max_tx_count, short_frame_max_tx_count;
- struct ieee80211_channel *channel;
- enum nl80211_channel_type channel_type;
+ struct cfg80211_chan_def chandef;
bool radar_enabled;
enum ieee80211_smps_mode smps_mode;
};
@@ -1021,13 +1028,13 @@ struct ieee80211_conf {
* the driver passed into mac80211.
* @block_tx: Indicates whether transmission must be blocked before the
* scheduled channel switch, as indicated by the AP.
- * @channel: the new channel to switch to
+ * @chandef: the new channel to switch to
* @count: the number of TBTT's until the channel switch event
*/
struct ieee80211_channel_switch {
u64 timestamp;
bool block_tx;
- struct ieee80211_channel *channel;
+ struct cfg80211_chan_def chandef;
u8 count;
};
@@ -1225,6 +1232,24 @@ enum ieee80211_sta_rx_bandwidth {
};
/**
+ * struct ieee80211_sta_rates - station rate selection table
+ *
+ * @rcu_head: RCU head used for freeing the table on update
+ * @rates: transmit rates/flags to be used by default.
+ * Overriding entries per-packet is possible by using cb tx control.
+ */
+struct ieee80211_sta_rates {
+ struct rcu_head rcu_head;
+ struct {
+ s8 idx;
+ u8 count;
+ u8 count_cts;
+ u8 count_rts;
+ u16 flags;
+ } rate[IEEE80211_TX_RATE_TABLE_SIZE];
+};
+
+/**
* struct ieee80211_sta - station table entry
*
* A station table entry represents a station we are possibly
@@ -1251,6 +1276,7 @@ enum ieee80211_sta_rx_bandwidth {
* notifications and capabilities. The value is only valid after
* the station moves to associated state.
* @smps_mode: current SMPS mode (off, static or dynamic)
+ * @tx_rates: rate control selection table
*/
struct ieee80211_sta {
u32 supp_rates[IEEE80211_NUM_BANDS];
@@ -1264,6 +1290,7 @@ struct ieee80211_sta {
u8 rx_nss;
enum ieee80211_sta_rx_bandwidth bandwidth;
enum ieee80211_smps_mode smps_mode;
+ struct ieee80211_sta_rates __rcu *rates;
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
@@ -1419,6 +1446,9 @@ struct ieee80211_tx_control {
* for different virtual interfaces. See the doc section on HW queue
* control for more details.
*
+ * @IEEE80211_HW_SUPPORTS_RC_TABLE: The driver supports using a rate
+ * selection table provided by the rate control algorithm.
+ *
* @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any
* P2P Interface. This will be honoured even if more than one interface
* is supported.
@@ -1451,6 +1481,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21,
IEEE80211_HW_AP_LINK_PS = 1<<22,
IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23,
+ IEEE80211_HW_SUPPORTS_RC_TABLE = 1<<24,
IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25,
IEEE80211_HW_TIMING_BEACON_ONLY = 1<<26,
};
@@ -1536,6 +1567,17 @@ enum ieee80211_hw_flags {
* @netdev_features: netdev features to be set in each netdev created
* from this HW. Note only HW checksum features are currently
* compatible with mac80211. Other feature bits will be rejected.
+ *
+ * @uapsd_queues: This bitmap is included in (re)association frame to indicate
+ * for each access category if it is uAPSD trigger-enabled and delivery-
+ * enabled. Use IEEE80211_WMM_IE_STA_QOSINFO_AC_* to set this bitmap.
+ * Each bit corresponds to different AC. Value '1' in specific bit means
+ * that corresponding AC is both trigger- and delivery-enabled. '0' means
+ * neither enabled.
+ *
+ * @uapsd_max_sp_len: maximum number of total buffered frames the WMM AP may
+ * deliver to a WMM STA during any Service Period triggered by the WMM STA.
+ * Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct values.
*/
struct ieee80211_hw {
struct ieee80211_conf conf;
@@ -1561,6 +1603,8 @@ struct ieee80211_hw {
u8 radiotap_mcs_details;
u16 radiotap_vht_details;
netdev_features_t netdev_features;
+ u8 uapsd_queues;
+ u8 uapsd_max_sp_len;
};
/**
@@ -3124,6 +3168,25 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *sta,
u8 tid, bool buffered);
/**
+ * ieee80211_get_tx_rates - get the selected transmit rates for a packet
+ *
+ * Call this function in a driver with per-packet rate selection support
+ * to combine the rate info in the packet tx info with the most recent
+ * rate selection table for the station entry.
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @sta: the receiver station to which this packet is sent.
+ * @skb: the frame to be transmitted.
+ * @dest: buffer for extracted rate/retry information
+ * @max_rates: maximum number of rates to fetch
+ */
+void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct sk_buff *skb,
+ struct ieee80211_tx_rate *dest,
+ int max_rates);
+
+/**
* ieee80211_tx_status - transmit status callback
*
* Call this function for all transmitted frames after they have been
@@ -4098,7 +4161,7 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
* (deprecated; this will be removed once drivers get updated to use
* rate_idx_mask)
* @rate_idx_mask: user-requested (legacy) rate mask
- * @rate_idx_mcs_mask: user-requested MCS rate mask
+ * @rate_idx_mcs_mask: user-requested MCS rate mask (NULL if not in use)
* @bss: whether this frame is sent out in AP or IBSS mode
*/
struct ieee80211_tx_rate_control {
@@ -4110,7 +4173,7 @@ struct ieee80211_tx_rate_control {
bool rts, short_preamble;
u8 max_rate_idx;
u32 rate_idx_mask;
- u8 rate_idx_mcs_mask[IEEE80211_HT_MCS_MASK_LEN];
+ u8 *rate_idx_mcs_mask;
bool bss;
};
@@ -4199,37 +4262,55 @@ bool rate_usable_index_exists(struct ieee80211_supported_band *sband,
return false;
}
+/**
+ * rate_control_set_rates - pass the sta rate selection to mac80211/driver
+ *
+ * When not doing a rate control probe to test rates, rate control should pass
+ * its rate selection to mac80211. If the driver supports receiving a station
+ * rate table, it will use it to ensure that frames are always sent based on
+ * the most recent rate control module decision.
+ *
+ * @hw: pointer as obtained from ieee80211_alloc_hw()
+ * @pubsta: &struct ieee80211_sta pointer to the target destination.
+ * @rates: new tx rate set to be used for this station.
+ */
+int rate_control_set_rates(struct ieee80211_hw *hw,
+ struct ieee80211_sta *pubsta,
+ struct ieee80211_sta_rates *rates);
+
int ieee80211_rate_control_register(struct rate_control_ops *ops);
void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
static inline bool
conf_is_ht20(struct ieee80211_conf *conf)
{
- return conf->channel_type == NL80211_CHAN_HT20;
+ return conf->chandef.width == NL80211_CHAN_WIDTH_20;
}
static inline bool
conf_is_ht40_minus(struct ieee80211_conf *conf)
{
- return conf->channel_type == NL80211_CHAN_HT40MINUS;
+ return conf->chandef.width == NL80211_CHAN_WIDTH_40 &&
+ conf->chandef.center_freq1 < conf->chandef.chan->center_freq;
}
static inline bool
conf_is_ht40_plus(struct ieee80211_conf *conf)
{
- return conf->channel_type == NL80211_CHAN_HT40PLUS;
+ return conf->chandef.width == NL80211_CHAN_WIDTH_40 &&
+ conf->chandef.center_freq1 > conf->chandef.chan->center_freq;
}
static inline bool
conf_is_ht40(struct ieee80211_conf *conf)
{
- return conf_is_ht40_minus(conf) || conf_is_ht40_plus(conf);
+ return conf->chandef.width == NL80211_CHAN_WIDTH_40;
}
static inline bool
conf_is_ht(struct ieee80211_conf *conf)
{
- return conf->channel_type != NL80211_CHAN_NO_HT;
+ return conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT;
}
static inline enum nl80211_iftype
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 87a6417fc934..5eb80bb3cbb2 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -122,6 +122,8 @@ struct nfc_dev {
bool shutting_down;
+ struct rfkill *rfkill;
+
struct nfc_ops *ops;
};
#define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev)
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h
index 7440bc81a04b..7c6f627a717d 100644
--- a/include/uapi/linux/nfc.h
+++ b/include/uapi/linux/nfc.h
@@ -233,7 +233,10 @@ struct sockaddr_nfc_llcp {
#define NFC_LLCP_DIRECTION_TX 0x01
/* socket option names */
-#define NFC_LLCP_RW 0
-#define NFC_LLCP_MIUX 1
+#define NFC_LLCP_RW 0
+#define NFC_LLCP_MIUX 1
+#define NFC_LLCP_REMOTE_MIU 2
+#define NFC_LLCP_REMOTE_LTO 3
+#define NFC_LLCP_REMOTE_RW 4
#endif /*__LINUX_NFC_H */
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 79da8710448e..d1e48b5e348f 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -639,6 +639,13 @@
* with the relevant Information Elements. This event is used to report
* received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE).
*
+ * @NL80211_CMD_CRIT_PROTOCOL_START: Indicates user-space will start running
+ * a critical protocol that needs more reliability in the connection to
+ * complete.
+ *
+ * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can
+ * return back to normal.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -798,6 +805,9 @@ enum nl80211_commands {
NL80211_CMD_UPDATE_FT_IES,
NL80211_CMD_FT_EVENT,
+ NL80211_CMD_CRIT_PROTOCOL_START,
+ NL80211_CMD_CRIT_PROTOCOL_STOP,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -1414,6 +1424,11 @@ enum nl80211_commands {
* @NL80211_ATTR_IE_RIC: Resource Information Container Information
* Element
*
+ * @NL80211_ATTR_CRIT_PROT_ID: critical protocol identifier requiring increased
+ * reliability, see &enum nl80211_crit_proto_id (u16).
+ * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which
+ * the connection should have increased reliability (u16).
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1709,6 +1724,9 @@ enum nl80211_attrs {
NL80211_ATTR_MDID,
NL80211_ATTR_IE_RIC,
+ NL80211_ATTR_CRIT_PROT_ID,
+ NL80211_ATTR_MAX_CRIT_PROT_DURATION,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -3682,4 +3700,25 @@ enum nl80211_protocol_features {
NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 1 << 0,
};
+/**
+ * enum nl80211_crit_proto_id - nl80211 critical protocol identifiers
+ *
+ * @NL80211_CRIT_PROTO_UNSPEC: protocol unspecified.
+ * @NL80211_CRIT_PROTO_DHCP: BOOTP or DHCPv6 protocol.
+ * @NL80211_CRIT_PROTO_EAPOL: EAPOL protocol.
+ * @NL80211_CRIT_PROTO_APIPA: APIPA protocol.
+ * @NUM_NL80211_CRIT_PROTO: must be kept last.
+ */
+enum nl80211_crit_proto_id {
+ NL80211_CRIT_PROTO_UNSPEC,
+ NL80211_CRIT_PROTO_DHCP,
+ NL80211_CRIT_PROTO_EAPOL,
+ NL80211_CRIT_PROTO_APIPA,
+ /* add other protocols before this one */
+ NUM_NL80211_CRIT_PROTO
+};
+
+/* maximum duration for critical protocol measures */
+#define NL80211_CRIT_PROTO_MAX_DURATION 5000 /* msec */
+
#endif /* __LINUX_NL80211_H */
diff --git a/include/uapi/linux/rfkill.h b/include/uapi/linux/rfkill.h
index 2753c6cc9740..058757f7a733 100644
--- a/include/uapi/linux/rfkill.h
+++ b/include/uapi/linux/rfkill.h
@@ -37,6 +37,7 @@
* @RFKILL_TYPE_WWAN: switch is on a wireless WAN device.
* @RFKILL_TYPE_GPS: switch is on a GPS device.
* @RFKILL_TYPE_FM: switch is on a FM radio device.
+ * @RFKILL_TYPE_NFC: switch is on an NFC device.
* @NUM_RFKILL_TYPES: number of defined rfkill types
*/
enum rfkill_type {
@@ -48,6 +49,7 @@ enum rfkill_type {
RFKILL_TYPE_WWAN,
RFKILL_TYPE_GPS,
RFKILL_TYPE_FM,
+ RFKILL_TYPE_NFC,
NUM_RFKILL_TYPES,
};
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index b9f90169940b..6c7f36379722 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -117,6 +117,16 @@ static void hci_acl_create_connection_cancel(struct hci_conn *conn)
hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp);
}
+static void hci_reject_sco(struct hci_conn *conn)
+{
+ struct hci_cp_reject_sync_conn_req cp;
+
+ cp.reason = HCI_ERROR_REMOTE_USER_TERM;
+ bacpy(&cp.bdaddr, &conn->dst);
+
+ hci_send_cmd(conn->hdev, HCI_OP_REJECT_SYNC_CONN_REQ, sizeof(cp), &cp);
+}
+
void hci_disconnect(struct hci_conn *conn, __u8 reason)
{
struct hci_cp_disconnect cp;
@@ -276,6 +286,8 @@ static void hci_conn_timeout(struct work_struct *work)
hci_acl_create_connection_cancel(conn);
else if (conn->type == LE_LINK)
hci_le_create_connection_cancel(conn);
+ } else if (conn->type == SCO_LINK || conn->type == ESCO_LINK) {
+ hci_reject_sco(conn);
}
break;
case BT_CONFIG:
@@ -398,8 +410,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
if (hdev->notify)
hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
- atomic_set(&conn->devref, 0);
-
hci_conn_init_sysfs(conn);
return conn;
@@ -433,7 +443,7 @@ int hci_conn_del(struct hci_conn *conn)
struct hci_conn *acl = conn->link;
if (acl) {
acl->link = NULL;
- hci_conn_put(acl);
+ hci_conn_drop(acl);
}
}
@@ -448,12 +458,11 @@ int hci_conn_del(struct hci_conn *conn)
skb_queue_purge(&conn->data_q);
- hci_conn_put_device(conn);
+ hci_conn_del_sysfs(conn);
hci_dev_put(hdev);
- if (conn->handle == 0)
- kfree(conn);
+ hci_conn_put(conn);
return 0;
}
@@ -565,7 +574,7 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type,
if (!sco) {
sco = hci_conn_add(hdev, type, dst);
if (!sco) {
- hci_conn_put(acl);
+ hci_conn_drop(acl);
return ERR_PTR(-ENOMEM);
}
}
@@ -835,19 +844,6 @@ void hci_conn_check_pending(struct hci_dev *hdev)
hci_dev_unlock(hdev);
}
-void hci_conn_hold_device(struct hci_conn *conn)
-{
- atomic_inc(&conn->devref);
-}
-EXPORT_SYMBOL(hci_conn_hold_device);
-
-void hci_conn_put_device(struct hci_conn *conn)
-{
- if (atomic_dec_and_test(&conn->devref))
- hci_conn_del_sysfs(conn);
-}
-EXPORT_SYMBOL(hci_conn_put_device);
-
int hci_get_conn_list(void __user *arg)
{
struct hci_conn *c;
@@ -980,7 +976,7 @@ void hci_chan_del(struct hci_chan *chan)
synchronize_rcu();
- hci_conn_put(conn);
+ hci_conn_drop(conn);
skb_queue_purge(&chan->data_q);
kfree(chan);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index cfcad5423f1c..ce82265f5619 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -79,6 +79,121 @@ static void hci_req_cancel(struct hci_dev *hdev, int err)
}
}
+struct sk_buff *hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 event)
+{
+ struct hci_ev_cmd_complete *ev;
+ struct hci_event_hdr *hdr;
+ struct sk_buff *skb;
+
+ hci_dev_lock(hdev);
+
+ skb = hdev->recv_evt;
+ hdev->recv_evt = NULL;
+
+ hci_dev_unlock(hdev);
+
+ if (!skb)
+ return ERR_PTR(-ENODATA);
+
+ if (skb->len < sizeof(*hdr)) {
+ BT_ERR("Too short HCI event");
+ goto failed;
+ }
+
+ hdr = (void *) skb->data;
+ skb_pull(skb, HCI_EVENT_HDR_SIZE);
+
+ if (event) {
+ if (hdr->evt != event)
+ goto failed;
+ return skb;
+ }
+
+ if (hdr->evt != HCI_EV_CMD_COMPLETE) {
+ BT_DBG("Last event is not cmd complete (0x%2.2x)", hdr->evt);
+ goto failed;
+ }
+
+ if (skb->len < sizeof(*ev)) {
+ BT_ERR("Too short cmd_complete event");
+ goto failed;
+ }
+
+ ev = (void *) skb->data;
+ skb_pull(skb, sizeof(*ev));
+
+ if (opcode == __le16_to_cpu(ev->opcode))
+ return skb;
+
+ BT_DBG("opcode doesn't match (0x%2.2x != 0x%2.2x)", opcode,
+ __le16_to_cpu(ev->opcode));
+
+failed:
+ kfree_skb(skb);
+ return ERR_PTR(-ENODATA);
+}
+
+struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
+ void *param, u8 event, u32 timeout)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ struct hci_request req;
+ int err = 0;
+
+ BT_DBG("%s", hdev->name);
+
+ hci_req_init(&req, hdev);
+
+ hci_req_add_ev(&req, opcode, plen, param, event);
+
+ hdev->req_status = HCI_REQ_PEND;
+
+ err = hci_req_run(&req, hci_req_sync_complete);
+ if (err < 0)
+ return ERR_PTR(err);
+
+ add_wait_queue(&hdev->req_wait_q, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ schedule_timeout(timeout);
+
+ remove_wait_queue(&hdev->req_wait_q, &wait);
+
+ if (signal_pending(current))
+ return ERR_PTR(-EINTR);
+
+ switch (hdev->req_status) {
+ case HCI_REQ_DONE:
+ err = -bt_to_errno(hdev->req_result);
+ break;
+
+ case HCI_REQ_CANCELED:
+ err = -hdev->req_result;
+ break;
+
+ default:
+ err = -ETIMEDOUT;
+ break;
+ }
+
+ hdev->req_status = hdev->req_result = 0;
+
+ BT_DBG("%s end: err %d", hdev->name, err);
+
+ if (err < 0)
+ return ERR_PTR(err);
+
+ return hci_get_cmd_complete(hdev, opcode, event);
+}
+EXPORT_SYMBOL(__hci_cmd_sync_ev);
+
+struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
+ void *param, u32 timeout)
+{
+ return __hci_cmd_sync_ev(hdev, opcode, plen, param, 0, timeout);
+}
+EXPORT_SYMBOL(__hci_cmd_sync);
+
/* Execute request and wait for completion. */
static int __hci_req_sync(struct hci_dev *hdev,
void (*func)(struct hci_request *req,
@@ -201,29 +316,9 @@ static void amp_init(struct hci_request *req)
static void hci_init1_req(struct hci_request *req, unsigned long opt)
{
struct hci_dev *hdev = req->hdev;
- struct hci_request init_req;
- struct sk_buff *skb;
BT_DBG("%s %ld", hdev->name, opt);
- /* Driver initialization */
-
- hci_req_init(&init_req, hdev);
-
- /* Special commands */
- while ((skb = skb_dequeue(&hdev->driver_init))) {
- bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
- skb->dev = (void *) hdev;
-
- if (skb_queue_empty(&init_req.cmd_q))
- bt_cb(skb)->req.start = true;
-
- skb_queue_tail(&init_req.cmd_q, skb);
- }
- skb_queue_purge(&hdev->driver_init);
-
- hci_req_run(&init_req, NULL);
-
/* Reset */
if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks))
hci_reset_req(req, 0);
@@ -494,6 +589,7 @@ static void hci_set_le_support(struct hci_request *req)
static void hci_init3_req(struct hci_request *req, unsigned long opt)
{
struct hci_dev *hdev = req->hdev;
+ u8 p;
if (hdev->commands[5] & 0x10)
hci_setup_link_policy(req);
@@ -502,6 +598,15 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
hci_set_le_support(req);
hci_update_ad(req);
}
+
+ /* Read features beyond page 1 if available */
+ for (p = 2; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) {
+ struct hci_cp_read_local_ext_features cp;
+
+ cp.page = p;
+ hci_req_add(req, HCI_OP_READ_LOCAL_EXT_FEATURES,
+ sizeof(cp), &cp);
+ }
}
static int __hci_init(struct hci_dev *hdev)
@@ -818,6 +923,12 @@ static void hci_inq_req(struct hci_request *req, unsigned long opt)
hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
}
+static int wait_inquiry(void *word)
+{
+ schedule();
+ return signal_pending(current);
+}
+
int hci_inquiry(void __user *arg)
{
__u8 __user *ptr = arg;
@@ -849,6 +960,13 @@ int hci_inquiry(void __user *arg)
timeo);
if (err < 0)
goto done;
+
+ /* Wait until Inquiry procedure finishes (HCI_INQUIRY flag is
+ * cleared). If it is interrupted by a signal, return -EINTR.
+ */
+ if (wait_on_bit(&hdev->flags, HCI_INQUIRY, wait_inquiry,
+ TASK_INTERRUPTIBLE))
+ return -EINTR;
}
/* for unlimited number of responses we will use buffer with
@@ -999,26 +1117,33 @@ int hci_dev_open(__u16 dev)
goto done;
}
- if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
- set_bit(HCI_RAW, &hdev->flags);
-
- /* Treat all non BR/EDR controllers as raw devices if
- enable_hs is not set */
- if (hdev->dev_type != HCI_BREDR && !enable_hs)
- set_bit(HCI_RAW, &hdev->flags);
-
if (hdev->open(hdev)) {
ret = -EIO;
goto done;
}
- if (!test_bit(HCI_RAW, &hdev->flags)) {
- atomic_set(&hdev->cmd_cnt, 1);
- set_bit(HCI_INIT, &hdev->flags);
- ret = __hci_init(hdev);
- clear_bit(HCI_INIT, &hdev->flags);
+ atomic_set(&hdev->cmd_cnt, 1);
+ set_bit(HCI_INIT, &hdev->flags);
+
+ if (hdev->setup && test_bit(HCI_SETUP, &hdev->dev_flags))
+ ret = hdev->setup(hdev);
+
+ if (!ret) {
+ /* Treat all non BR/EDR controllers as raw devices if
+ * enable_hs is not set.
+ */
+ if (hdev->dev_type != HCI_BREDR && !enable_hs)
+ set_bit(HCI_RAW, &hdev->flags);
+
+ if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+ set_bit(HCI_RAW, &hdev->flags);
+
+ if (!test_bit(HCI_RAW, &hdev->flags))
+ ret = __hci_init(hdev);
}
+ clear_bit(HCI_INIT, &hdev->flags);
+
if (!ret) {
hci_dev_hold(hdev);
set_bit(HCI_UP, &hdev->flags);
@@ -1123,6 +1248,9 @@ static int hci_dev_do_close(struct hci_dev *hdev)
hdev->sent_cmd = NULL;
}
+ kfree_skb(hdev->recv_evt);
+ hdev->recv_evt = NULL;
+
/* After this point our queues are empty
* and no tasks are scheduled. */
hdev->close(hdev);
@@ -1861,8 +1989,8 @@ static void le_scan_enable_req(struct hci_request *req, unsigned long opt)
struct hci_cp_le_set_scan_enable cp;
memset(&cp, 0, sizeof(cp));
- cp.enable = 1;
- cp.filter_dup = 1;
+ cp.enable = LE_SCAN_ENABLE;
+ cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
}
@@ -1896,7 +2024,7 @@ static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval,
return err;
queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
- msecs_to_jiffies(timeout));
+ timeout);
return 0;
}
@@ -2006,7 +2134,6 @@ struct hci_dev *hci_alloc_dev(void)
INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off);
INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work);
- skb_queue_head_init(&hdev->driver_init);
skb_queue_head_init(&hdev->rx_q);
skb_queue_head_init(&hdev->cmd_q);
skb_queue_head_init(&hdev->raw_q);
@@ -2025,8 +2152,6 @@ EXPORT_SYMBOL(hci_alloc_dev);
/* Free HCI device */
void hci_free_dev(struct hci_dev *hdev)
{
- skb_queue_purge(&hdev->driver_init);
-
/* will free via device release */
put_device(&hdev->dev);
}
@@ -2527,7 +2652,8 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
}
/* Queue a command to an asynchronous HCI request */
-void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param)
+void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void *param,
+ u8 event)
{
struct hci_dev *hdev = req->hdev;
struct sk_buff *skb;
@@ -2551,9 +2677,16 @@ void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param)
if (skb_queue_empty(&req->cmd_q))
bt_cb(skb)->req.start = true;
+ bt_cb(skb)->req.event = event;
+
skb_queue_tail(&req->cmd_q, skb);
}
+void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param)
+{
+ hci_req_add_ev(req, opcode, plen, param, 0);
+}
+
/* Get data from the previously sent command */
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
{
@@ -3309,32 +3442,6 @@ call_complete:
req_complete(hdev, status);
}
-void hci_req_cmd_status(struct hci_dev *hdev, u16 opcode, u8 status)
-{
- hci_req_complete_t req_complete = NULL;
-
- BT_DBG("opcode 0x%04x status 0x%02x", opcode, status);
-
- if (status) {
- hci_req_cmd_complete(hdev, opcode, status);
- return;
- }
-
- /* No need to handle success status if there are more commands */
- if (!hci_req_is_complete(hdev))
- return;
-
- if (hdev->sent_cmd)
- req_complete = bt_cb(hdev->sent_cmd)->req.complete;
-
- /* If the request doesn't have a complete callback or there
- * are other commands/requests in the hdev queue we consider
- * this request as completed.
- */
- if (!req_complete || !skb_queue_empty(&hdev->cmd_q))
- hci_req_cmd_complete(hdev, opcode, status);
-}
-
static void hci_rx_work(struct work_struct *work)
{
struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 138580745c2c..b93cd2eb5d58 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -48,13 +48,13 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
}
clear_bit(HCI_INQUIRY, &hdev->flags);
+ smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
+ wake_up_bit(&hdev->flags, HCI_INQUIRY);
hci_dev_lock(hdev);
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
hci_dev_unlock(hdev);
- hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
-
hci_conn_check_pending(hdev);
}
@@ -433,9 +433,9 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
if (!status) {
if (sent->mode)
- hdev->host_features[0] |= LMP_HOST_SSP;
+ hdev->features[1][0] |= LMP_HOST_SSP;
else
- hdev->host_features[0] &= ~LMP_HOST_SSP;
+ hdev->features[1][0] &= ~LMP_HOST_SSP;
}
if (test_bit(HCI_MGMT, &hdev->dev_flags))
@@ -493,18 +493,18 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
/* Adjust default settings according to features
* supported by device. */
- if (hdev->features[0] & LMP_3SLOT)
+ if (hdev->features[0][0] & LMP_3SLOT)
hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
- if (hdev->features[0] & LMP_5SLOT)
+ if (hdev->features[0][0] & LMP_5SLOT)
hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
- if (hdev->features[1] & LMP_HV2) {
+ if (hdev->features[0][1] & LMP_HV2) {
hdev->pkt_type |= (HCI_HV2);
hdev->esco_type |= (ESCO_HV2);
}
- if (hdev->features[1] & LMP_HV3) {
+ if (hdev->features[0][1] & LMP_HV3) {
hdev->pkt_type |= (HCI_HV3);
hdev->esco_type |= (ESCO_HV3);
}
@@ -512,26 +512,26 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
if (lmp_esco_capable(hdev))
hdev->esco_type |= (ESCO_EV3);
- if (hdev->features[4] & LMP_EV4)
+ if (hdev->features[0][4] & LMP_EV4)
hdev->esco_type |= (ESCO_EV4);
- if (hdev->features[4] & LMP_EV5)
+ if (hdev->features[0][4] & LMP_EV5)
hdev->esco_type |= (ESCO_EV5);
- if (hdev->features[5] & LMP_EDR_ESCO_2M)
+ if (hdev->features[0][5] & LMP_EDR_ESCO_2M)
hdev->esco_type |= (ESCO_2EV3);
- if (hdev->features[5] & LMP_EDR_ESCO_3M)
+ if (hdev->features[0][5] & LMP_EDR_ESCO_3M)
hdev->esco_type |= (ESCO_3EV3);
- if (hdev->features[5] & LMP_EDR_3S_ESCO)
+ if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
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][0], hdev->features[0][1],
+ hdev->features[0][2], hdev->features[0][3],
+ hdev->features[0][4], hdev->features[0][5],
+ hdev->features[0][6], hdev->features[0][7]);
}
static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
@@ -544,14 +544,10 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
if (rp->status)
return;
- switch (rp->page) {
- case 0:
- memcpy(hdev->features, rp->features, 8);
- break;
- case 1:
- memcpy(hdev->host_features, rp->features, 8);
- break;
- }
+ hdev->max_page = rp->max_page;
+
+ if (rp->page < HCI_MAX_PAGES)
+ memcpy(hdev->features[rp->page], rp->features, 8);
}
static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
@@ -968,7 +964,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
return;
switch (cp->enable) {
- case LE_SCANNING_ENABLED:
+ case LE_SCAN_ENABLE:
if (status) {
hci_dev_lock(hdev);
mgmt_start_discovery_failed(hdev, status);
@@ -983,7 +979,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
hci_dev_unlock(hdev);
break;
- case LE_SCANNING_DISABLED:
+ case LE_SCAN_DISABLE:
if (status) {
hci_dev_lock(hdev);
mgmt_stop_discovery_failed(hdev, status);
@@ -1046,14 +1042,14 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
if (!status) {
if (sent->le)
- hdev->host_features[0] |= LMP_HOST_LE;
+ hdev->features[1][0] |= LMP_HOST_LE;
else
- hdev->host_features[0] &= ~LMP_HOST_LE;
+ hdev->features[1][0] &= ~LMP_HOST_LE;
if (sent->simul)
- hdev->host_features[0] |= LMP_HOST_LE_BREDR;
+ hdev->features[1][0] |= LMP_HOST_LE_BREDR;
else
- hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
+ hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
}
if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
@@ -1190,7 +1186,7 @@ static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
if (conn) {
if (conn->state == BT_CONFIG) {
hci_proto_connect_cfm(conn, status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
}
@@ -1217,7 +1213,7 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
if (conn) {
if (conn->state == BT_CONFIG) {
hci_proto_connect_cfm(conn, status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
}
@@ -1379,7 +1375,7 @@ static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
if (conn) {
if (conn->state == BT_CONFIG) {
hci_proto_connect_cfm(conn, status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
}
@@ -1406,7 +1402,7 @@ static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
if (conn) {
if (conn->state == BT_CONFIG) {
hci_proto_connect_cfm(conn, status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
}
@@ -1600,13 +1596,14 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s status 0x%2.2x", hdev->name, status);
- hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
-
hci_conn_check_pending(hdev);
if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
return;
+ smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
+ wake_up_bit(&hdev->flags, HCI_INQUIRY);
+
if (!test_bit(HCI_MGMT, &hdev->dev_flags))
return;
@@ -1705,7 +1702,6 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
} else
conn->state = BT_CONNECTED;
- hci_conn_hold_device(conn);
hci_conn_add_sysfs(conn);
if (test_bit(HCI_AUTH, &hdev->flags))
@@ -1752,42 +1748,6 @@ unlock:
hci_conn_check_pending(hdev);
}
-void hci_conn_accept(struct hci_conn *conn, int mask)
-{
- struct hci_dev *hdev = conn->hdev;
-
- BT_DBG("conn %p", conn);
-
- conn->state = BT_CONFIG;
-
- if (!lmp_esco_capable(hdev)) {
- struct hci_cp_accept_conn_req cp;
-
- bacpy(&cp.bdaddr, &conn->dst);
-
- if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
- cp.role = 0x00; /* Become master */
- else
- cp.role = 0x01; /* Remain slave */
-
- hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
- } else /* lmp_esco_capable(hdev)) */ {
- struct hci_cp_accept_sync_conn_req cp;
-
- bacpy(&cp.bdaddr, &conn->dst);
- cp.pkt_type = cpu_to_le16(conn->pkt_type);
-
- 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;
-
- hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
- sizeof(cp), &cp);
- }
-}
-
static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_conn_request *ev = (void *) skb->data;
@@ -1859,7 +1819,6 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
} else {
conn->state = BT_CONNECT2;
hci_proto_connect_cfm(conn, 0);
- hci_conn_put(conn);
}
} else {
/* Connection rejected */
@@ -1966,14 +1925,14 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
} else {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
} else {
hci_auth_cfm(conn, ev->status);
hci_conn_hold(conn);
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
@@ -2057,7 +2016,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (ev->status && conn->state == BT_CONNECTED) {
hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
goto unlock;
}
@@ -2066,7 +2025,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
} else
hci_encrypt_cfm(conn, ev->status, ev->encrypt);
}
@@ -2113,7 +2072,7 @@ static void hci_remote_features_evt(struct hci_dev *hdev,
goto unlock;
if (!ev->status)
- memcpy(conn->features, ev->features, 8);
+ memcpy(conn->features[0], ev->features, 8);
if (conn->state != BT_CONFIG)
goto unlock;
@@ -2141,7 +2100,7 @@ static void hci_remote_features_evt(struct hci_dev *hdev,
if (!hci_outgoing_auth_needed(hdev, conn)) {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
unlock:
@@ -2462,7 +2421,9 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (opcode != HCI_OP_NOP)
del_timer(&hdev->cmd_timer);
- hci_req_cmd_status(hdev, opcode, ev->status);
+ if (ev->status ||
+ (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event))
+ hci_req_cmd_complete(hdev, opcode, ev->status);
if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
atomic_set(&hdev->cmd_cnt, 1);
@@ -2679,7 +2640,7 @@ static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (conn->state == BT_CONNECTED) {
hci_conn_hold(conn);
conn->disc_timeout = HCI_PAIRING_TIMEOUT;
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
@@ -2782,7 +2743,7 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
conn->key_type = ev->key_type;
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
@@ -2923,6 +2884,9 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev,
if (!conn)
goto unlock;
+ if (ev->page < HCI_MAX_PAGES)
+ memcpy(conn->features[ev->page], ev->features, 8);
+
if (!ev->status && ev->page == 0x01) {
struct inquiry_entry *ie;
@@ -2930,8 +2894,19 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev,
if (ie)
ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
- if (ev->features[0] & LMP_HOST_SSP)
+ if (ev->features[0] & LMP_HOST_SSP) {
set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
+ } else {
+ /* It is mandatory by the Bluetooth specification that
+ * Extended Inquiry Results are only used when Secure
+ * Simple Pairing is enabled, but some devices violate
+ * this.
+ *
+ * To make these devices work, the internal SSP
+ * enabled flag needs to be cleared if the remote host
+ * features do not indicate SSP support */
+ clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
+ }
}
if (conn->state != BT_CONFIG)
@@ -2951,7 +2926,7 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev,
if (!hci_outgoing_auth_needed(hdev, conn)) {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
unlock:
@@ -2985,7 +2960,6 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
conn->handle = __le16_to_cpu(ev->handle);
conn->state = BT_CONNECTED;
- hci_conn_hold_device(conn);
hci_conn_add_sysfs(conn);
break;
@@ -3084,7 +3058,7 @@ static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
if (ev->status && conn->state == BT_CONNECTED) {
hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
goto unlock;
}
@@ -3093,13 +3067,13 @@ static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
} else {
hci_auth_cfm(conn, ev->status);
hci_conn_hold(conn);
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
unlock:
@@ -3360,7 +3334,7 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
ev->status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
unlock:
hci_dev_unlock(hdev);
@@ -3371,11 +3345,16 @@ static void hci_remote_host_features_evt(struct hci_dev *hdev,
{
struct hci_ev_remote_host_features *ev = (void *) skb->data;
struct inquiry_entry *ie;
+ struct hci_conn *conn;
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+ if (conn)
+ memcpy(conn->features[1], ev->features, 8);
+
ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
if (ie)
ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
@@ -3448,9 +3427,8 @@ static void hci_phy_link_complete_evt(struct hci_dev *hdev,
hci_conn_hold(hcon);
hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
- hci_conn_put(hcon);
+ hci_conn_drop(hcon);
- hci_conn_hold_device(hcon);
hci_conn_add_sysfs(hcon);
amp_physical_cfm(bredr_hcon, hcon);
@@ -3584,7 +3562,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
conn->handle = __le16_to_cpu(ev->handle);
conn->state = BT_CONNECTED;
- hci_conn_hold_device(conn);
hci_conn_add_sysfs(conn);
hci_proto_connect_cfm(conn, ev->status);
@@ -3698,8 +3675,27 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
struct hci_event_hdr *hdr = (void *) skb->data;
__u8 event = hdr->evt;
+ hci_dev_lock(hdev);
+
+ /* Received events are (currently) only needed when a request is
+ * ongoing so avoid unnecessary memory allocation.
+ */
+ if (hdev->req_status == HCI_REQ_PEND) {
+ kfree_skb(hdev->recv_evt);
+ hdev->recv_evt = skb_clone(skb, GFP_KERNEL);
+ }
+
+ hci_dev_unlock(hdev);
+
skb_pull(skb, HCI_EVENT_HDR_SIZE);
+ if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) {
+ struct hci_command_hdr *hdr = (void *) hdev->sent_cmd->data;
+ u16 opcode = __le16_to_cpu(hdr->opcode);
+
+ hci_req_cmd_complete(hdev, opcode, 0);
+ }
+
switch (event) {
case HCI_EV_INQUIRY_COMPLETE:
hci_inquiry_complete_evt(hdev, skb);
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index ff38561385de..7ad6ecf36f20 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -48,10 +48,10 @@ static ssize_t show_link_features(struct device *dev,
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][0], conn->features[0][1],
+ conn->features[0][2], conn->features[0][3],
+ conn->features[0][4], conn->features[0][5],
+ conn->features[0][6], conn->features[0][7]);
}
#define LINK_ATTR(_name, _mode, _show, _store) \
@@ -146,7 +146,6 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
}
device_del(&conn->dev);
- put_device(&conn->dev);
hci_dev_put(hdev);
}
@@ -234,10 +233,10 @@ static ssize_t show_features(struct device *dev,
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][0], hdev->features[0][1],
+ hdev->features[0][2], hdev->features[0][3],
+ hdev->features[0][4], hdev->features[0][5],
+ hdev->features[0][6], hdev->features[0][7]);
}
static ssize_t show_manufacturer(struct device *dev,
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 2342327f3335..940f5acb6694 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -1,6 +1,7 @@
/*
HIDP implementation for Linux Bluetooth stack (BlueZ).
Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
+ Copyright (C) 2013 David Herrmann <dh.herrmann@gmail.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
@@ -20,6 +21,7 @@
SOFTWARE IS DISCLAIMED.
*/
+#include <linux/kref.h>
#include <linux/module.h>
#include <linux/file.h>
#include <linux/kthread.h>
@@ -59,39 +61,20 @@ static unsigned char hidp_keycode[256] = {
static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
-static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
-{
- struct hidp_session *session;
-
- BT_DBG("");
+static int hidp_session_probe(struct l2cap_conn *conn,
+ struct l2cap_user *user);
+static void hidp_session_remove(struct l2cap_conn *conn,
+ struct l2cap_user *user);
+static int hidp_session_thread(void *arg);
+static void hidp_session_terminate(struct hidp_session *s);
- list_for_each_entry(session, &hidp_session_list, list) {
- if (!bacmp(bdaddr, &session->bdaddr))
- return session;
- }
-
- return NULL;
-}
-
-static void __hidp_link_session(struct hidp_session *session)
-{
- list_add(&session->list, &hidp_session_list);
-}
-
-static void __hidp_unlink_session(struct hidp_session *session)
-{
- hci_conn_put_device(session->conn);
-
- list_del(&session->list);
-}
-
-static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
+static void hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
{
memset(ci, 0, sizeof(*ci));
bacpy(&ci->bdaddr, &session->bdaddr);
ci->flags = session->flags;
- ci->state = session->state;
+ ci->state = BT_CONNECTED;
ci->vendor = 0x0000;
ci->product = 0x0000;
@@ -115,58 +98,80 @@ static void __hidp_copy_session(struct hidp_session *session, struct hidp_connin
}
}
-static int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
- unsigned int type, unsigned int code, int value)
+/* assemble skb, queue message on @transmit and wake up the session thread */
+static int hidp_send_message(struct hidp_session *session, struct socket *sock,
+ struct sk_buff_head *transmit, unsigned char hdr,
+ const unsigned char *data, int size)
{
- unsigned char newleds;
struct sk_buff *skb;
+ struct sock *sk = sock->sk;
- BT_DBG("session %p type %d code %d value %d", session, type, code, value);
-
- if (type != EV_LED)
- return -1;
-
- newleds = (!!test_bit(LED_KANA, dev->led) << 3) |
- (!!test_bit(LED_COMPOSE, dev->led) << 3) |
- (!!test_bit(LED_SCROLLL, dev->led) << 2) |
- (!!test_bit(LED_CAPSL, dev->led) << 1) |
- (!!test_bit(LED_NUML, dev->led));
-
- if (session->leds == newleds)
- return 0;
+ BT_DBG("session %p data %p size %d", session, data, size);
- session->leds = newleds;
+ if (atomic_read(&session->terminate))
+ return -EIO;
- skb = alloc_skb(3, GFP_ATOMIC);
+ skb = alloc_skb(size + 1, GFP_ATOMIC);
if (!skb) {
BT_ERR("Can't allocate memory for new frame");
return -ENOMEM;
}
- *skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
- *skb_put(skb, 1) = 0x01;
- *skb_put(skb, 1) = newleds;
-
- skb_queue_tail(&session->intr_transmit, skb);
+ *skb_put(skb, 1) = hdr;
+ if (data && size > 0)
+ memcpy(skb_put(skb, size), data, size);
- hidp_schedule(session);
+ skb_queue_tail(transmit, skb);
+ wake_up_interruptible(sk_sleep(sk));
return 0;
}
-static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+static int hidp_send_ctrl_message(struct hidp_session *session,
+ unsigned char hdr, const unsigned char *data,
+ int size)
{
- struct hid_device *hid = input_get_drvdata(dev);
- struct hidp_session *session = hid->driver_data;
+ return hidp_send_message(session, session->ctrl_sock,
+ &session->ctrl_transmit, hdr, data, size);
+}
- return hidp_queue_event(session, dev, type, code, value);
+static int hidp_send_intr_message(struct hidp_session *session,
+ unsigned char hdr, const unsigned char *data,
+ int size)
+{
+ return hidp_send_message(session, session->intr_sock,
+ &session->intr_transmit, hdr, data, size);
}
-static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+static int hidp_input_event(struct input_dev *dev, unsigned int type,
+ unsigned int code, int value)
{
struct hidp_session *session = input_get_drvdata(dev);
+ unsigned char newleds;
+ unsigned char hdr, data[2];
+
+ BT_DBG("session %p type %d code %d value %d",
+ session, type, code, value);
+
+ if (type != EV_LED)
+ return -1;
+
+ newleds = (!!test_bit(LED_KANA, dev->led) << 3) |
+ (!!test_bit(LED_COMPOSE, dev->led) << 3) |
+ (!!test_bit(LED_SCROLLL, dev->led) << 2) |
+ (!!test_bit(LED_CAPSL, dev->led) << 1) |
+ (!!test_bit(LED_NUML, dev->led));
- return hidp_queue_event(session, dev, type, code, value);
+ if (session->leds == newleds)
+ return 0;
+
+ session->leds = newleds;
+
+ hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
+ data[0] = 0x01;
+ data[1] = newleds;
+
+ return hidp_send_intr_message(session, hdr, data, 2);
}
static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
@@ -224,71 +229,9 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
input_sync(dev);
}
-static int __hidp_send_ctrl_message(struct hidp_session *session,
- unsigned char hdr, unsigned char *data,
- int size)
-{
- struct sk_buff *skb;
-
- BT_DBG("session %p data %p size %d", session, data, size);
-
- if (atomic_read(&session->terminate))
- return -EIO;
-
- skb = alloc_skb(size + 1, GFP_ATOMIC);
- if (!skb) {
- BT_ERR("Can't allocate memory for new frame");
- return -ENOMEM;
- }
-
- *skb_put(skb, 1) = hdr;
- if (data && size > 0)
- memcpy(skb_put(skb, size), data, size);
-
- skb_queue_tail(&session->ctrl_transmit, skb);
-
- return 0;
-}
-
-static int hidp_send_ctrl_message(struct hidp_session *session,
- unsigned char hdr, unsigned char *data, int size)
-{
- int err;
-
- err = __hidp_send_ctrl_message(session, hdr, data, size);
-
- hidp_schedule(session);
-
- return err;
-}
-
-static int hidp_queue_report(struct hidp_session *session,
- unsigned char *data, int size)
-{
- struct sk_buff *skb;
-
- BT_DBG("session %p hid %p data %p size %d", session, session->hid, data, size);
-
- skb = alloc_skb(size + 1, GFP_ATOMIC);
- if (!skb) {
- BT_ERR("Can't allocate memory for new frame");
- return -ENOMEM;
- }
-
- *skb_put(skb, 1) = 0xa2;
- if (size > 0)
- memcpy(skb_put(skb, size), data, size);
-
- skb_queue_tail(&session->intr_transmit, skb);
-
- hidp_schedule(session);
-
- return 0;
-}
-
static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
{
- unsigned char buf[32];
+ unsigned char buf[32], hdr;
int rsize;
rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
@@ -296,8 +239,9 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep
return -EIO;
hid_output_report(report, buf);
+ hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
- return hidp_queue_report(session, buf, rsize);
+ return hidp_send_intr_message(session, hdr, buf, rsize);
}
static int hidp_get_raw_report(struct hid_device *hid,
@@ -336,17 +280,19 @@ static int hidp_get_raw_report(struct hid_device *hid,
session->waiting_report_number = numbered_reports ? report_number : -1;
set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
data[0] = report_number;
- ret = hidp_send_ctrl_message(hid->driver_data, report_type, data, 1);
+ ret = hidp_send_ctrl_message(session, report_type, data, 1);
if (ret)
goto err;
/* Wait for the return of the report. The returned report
gets put in session->report_return. */
- while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
+ while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
+ !atomic_read(&session->terminate)) {
int res;
res = wait_event_interruptible_timeout(session->report_queue,
- !test_bit(HIDP_WAITING_FOR_RETURN, &session->flags),
+ !test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)
+ || atomic_read(&session->terminate),
5*HZ);
if (res == 0) {
/* timeout */
@@ -389,14 +335,11 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s
struct hidp_session *session = hid->driver_data;
int ret;
- switch (report_type) {
- case HID_FEATURE_REPORT:
- report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
- break;
- case HID_OUTPUT_REPORT:
- report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
- break;
- default:
+ if (report_type == HID_OUTPUT_REPORT) {
+ report_type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
+ return hidp_send_intr_message(session, report_type,
+ data, count);
+ } else if (report_type != HID_FEATURE_REPORT) {
return -EINVAL;
}
@@ -405,17 +348,19 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s
/* Set up our wait, and send the report request to the device. */
set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
- ret = hidp_send_ctrl_message(hid->driver_data, report_type, data,
- count);
+ report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
+ ret = hidp_send_ctrl_message(session, report_type, data, count);
if (ret)
goto err;
/* Wait for the ACK from the device. */
- while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
+ while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags) &&
+ !atomic_read(&session->terminate)) {
int res;
res = wait_event_interruptible_timeout(session->report_queue,
- !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags),
+ !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)
+ || atomic_read(&session->terminate),
10*HZ);
if (res == 0) {
/* timeout */
@@ -446,8 +391,7 @@ static void hidp_idle_timeout(unsigned long arg)
{
struct hidp_session *session = (struct hidp_session *) arg;
- atomic_inc(&session->terminate);
- wake_up_process(session->task);
+ hidp_session_terminate(session);
}
static void hidp_set_timer(struct hidp_session *session)
@@ -490,12 +434,12 @@ static void hidp_process_handshake(struct hidp_session *session,
case HIDP_HSHK_ERR_FATAL:
/* Device requests a reboot, as this is the only way this error
* can be recovered. */
- __hidp_send_ctrl_message(session,
+ hidp_send_ctrl_message(session,
HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
break;
default:
- __hidp_send_ctrl_message(session,
+ hidp_send_ctrl_message(session,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
break;
}
@@ -515,8 +459,7 @@ static void hidp_process_hid_control(struct hidp_session *session,
skb_queue_purge(&session->ctrl_transmit);
skb_queue_purge(&session->intr_transmit);
- atomic_inc(&session->terminate);
- wake_up_process(current);
+ hidp_session_terminate(session);
}
}
@@ -544,7 +487,7 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
break;
default:
- __hidp_send_ctrl_message(session,
+ hidp_send_ctrl_message(session,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
}
@@ -591,7 +534,7 @@ static void hidp_recv_ctrl_frame(struct hidp_session *session,
break;
default:
- __hidp_send_ctrl_message(session,
+ hidp_send_ctrl_message(session,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
break;
}
@@ -642,32 +585,24 @@ static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
return kernel_sendmsg(sock, &msg, &iv, 1, len);
}
-static void hidp_process_intr_transmit(struct hidp_session *session)
+/* dequeue message from @transmit and send via @sock */
+static void hidp_process_transmit(struct hidp_session *session,
+ struct sk_buff_head *transmit,
+ struct socket *sock)
{
struct sk_buff *skb;
+ int ret;
BT_DBG("session %p", session);
- while ((skb = skb_dequeue(&session->intr_transmit))) {
- if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
- skb_queue_head(&session->intr_transmit, skb);
+ while ((skb = skb_dequeue(transmit))) {
+ ret = hidp_send_frame(sock, skb->data, skb->len);
+ if (ret == -EAGAIN) {
+ skb_queue_head(transmit, skb);
break;
- }
-
- hidp_set_timer(session);
- kfree_skb(skb);
- }
-}
-
-static void hidp_process_ctrl_transmit(struct hidp_session *session)
-{
- struct sk_buff *skb;
-
- BT_DBG("session %p", session);
-
- while ((skb = skb_dequeue(&session->ctrl_transmit))) {
- if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
- skb_queue_head(&session->ctrl_transmit, skb);
+ } else if (ret < 0) {
+ hidp_session_terminate(session);
+ kfree_skb(skb);
break;
}
@@ -676,122 +611,6 @@ static void hidp_process_ctrl_transmit(struct hidp_session *session)
}
}
-static int hidp_session(void *arg)
-{
- struct hidp_session *session = arg;
- struct sock *ctrl_sk = session->ctrl_sock->sk;
- struct sock *intr_sk = session->intr_sock->sk;
- struct sk_buff *skb;
- wait_queue_t ctrl_wait, intr_wait;
-
- BT_DBG("session %p", session);
-
- __module_get(THIS_MODULE);
- set_user_nice(current, -15);
-
- init_waitqueue_entry(&ctrl_wait, current);
- init_waitqueue_entry(&intr_wait, current);
- add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
- add_wait_queue(sk_sleep(intr_sk), &intr_wait);
- session->waiting_for_startup = 0;
- wake_up_interruptible(&session->startup_queue);
- set_current_state(TASK_INTERRUPTIBLE);
- while (!atomic_read(&session->terminate)) {
- if (ctrl_sk->sk_state != BT_CONNECTED ||
- intr_sk->sk_state != BT_CONNECTED)
- break;
-
- while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
- skb_orphan(skb);
- if (!skb_linearize(skb))
- hidp_recv_intr_frame(session, skb);
- else
- kfree_skb(skb);
- }
-
- hidp_process_intr_transmit(session);
-
- while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
- skb_orphan(skb);
- if (!skb_linearize(skb))
- hidp_recv_ctrl_frame(session, skb);
- else
- kfree_skb(skb);
- }
-
- hidp_process_ctrl_transmit(session);
-
- schedule();
- set_current_state(TASK_INTERRUPTIBLE);
- }
- set_current_state(TASK_RUNNING);
- atomic_inc(&session->terminate);
- remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
- remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
-
- clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
- clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
- wake_up_interruptible(&session->report_queue);
-
- down_write(&hidp_session_sem);
-
- hidp_del_timer(session);
-
- if (session->input) {
- input_unregister_device(session->input);
- session->input = NULL;
- }
-
- if (session->hid) {
- hid_destroy_device(session->hid);
- session->hid = NULL;
- }
-
- /* Wakeup user-space polling for socket errors */
- session->intr_sock->sk->sk_err = EUNATCH;
- session->ctrl_sock->sk->sk_err = EUNATCH;
-
- hidp_schedule(session);
-
- fput(session->intr_sock->file);
-
- wait_event_timeout(*(sk_sleep(ctrl_sk)),
- (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
-
- fput(session->ctrl_sock->file);
-
- __hidp_unlink_session(session);
-
- up_write(&hidp_session_sem);
-
- kfree(session->rd_data);
- kfree(session);
- module_put_and_exit(0);
- return 0;
-}
-
-static struct hci_conn *hidp_get_connection(struct hidp_session *session)
-{
- bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
- bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
- struct hci_conn *conn;
- struct hci_dev *hdev;
-
- hdev = hci_get_route(dst, src);
- if (!hdev)
- return NULL;
-
- hci_dev_lock(hdev);
- conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
- if (conn)
- hci_conn_hold_device(conn);
- hci_dev_unlock(hdev);
-
- hci_dev_put(hdev);
-
- return conn;
-}
-
static int hidp_setup_input(struct hidp_session *session,
struct hidp_connadd_req *req)
{
@@ -839,7 +658,7 @@ static int hidp_setup_input(struct hidp_session *session,
input->relbit[0] |= BIT_MASK(REL_WHEEL);
}
- input->dev.parent = &session->conn->dev;
+ input->dev.parent = &session->conn->hcon->dev;
input->event = hidp_input_event;
@@ -898,7 +717,6 @@ static struct hid_ll_driver hidp_hid_driver = {
.stop = hidp_stop,
.open = hidp_open,
.close = hidp_close,
- .hidinput_input_event = hidp_hidinput_event,
};
/* This function sets up the hid device. It does not add it
@@ -943,7 +761,7 @@ static int hidp_setup_hid(struct hidp_session *session,
snprintf(hid->uniq, sizeof(hid->uniq), "%pMR",
&bt_sk(session->ctrl_sock->sk)->dst);
- hid->dev.parent = &session->conn->dev;
+ hid->dev.parent = &session->conn->hcon->dev;
hid->ll_driver = &hidp_hid_driver;
hid->hid_get_raw_report = hidp_get_raw_report;
@@ -965,80 +783,217 @@ fault:
return err;
}
-int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
+/* initialize session devices */
+static int hidp_session_dev_init(struct hidp_session *session,
+ struct hidp_connadd_req *req)
{
- struct hidp_session *session, *s;
- int vendor, product;
- int err;
+ int ret;
- BT_DBG("");
+ if (req->rd_size > 0) {
+ ret = hidp_setup_hid(session, req);
+ if (ret && ret != -ENODEV)
+ return ret;
+ }
- if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
- bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
- return -ENOTUNIQ;
+ if (!session->hid) {
+ ret = hidp_setup_input(session, req);
+ if (ret < 0)
+ return ret;
+ }
- BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
+ return 0;
+}
- down_write(&hidp_session_sem);
+/* destroy session devices */
+static void hidp_session_dev_destroy(struct hidp_session *session)
+{
+ if (session->hid)
+ put_device(&session->hid->dev);
+ else if (session->input)
+ input_put_device(session->input);
- s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
- if (s && s->state == BT_CONNECTED) {
- up_write(&hidp_session_sem);
- return -EEXIST;
- }
+ kfree(session->rd_data);
+ session->rd_data = NULL;
+}
- session = kzalloc(sizeof(struct hidp_session), GFP_KERNEL);
- if (!session) {
- up_write(&hidp_session_sem);
- return -ENOMEM;
- }
+/* add HID/input devices to their underlying bus systems */
+static int hidp_session_dev_add(struct hidp_session *session)
+{
+ int ret;
- bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
+ /* Both HID and input systems drop a ref-count when unregistering the
+ * device but they don't take a ref-count when registering them. Work
+ * around this by explicitly taking a refcount during registration
+ * which is dropped automatically by unregistering the devices. */
- session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->chan->omtu,
- l2cap_pi(ctrl_sock->sk)->chan->imtu);
- session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->chan->omtu,
- l2cap_pi(intr_sock->sk)->chan->imtu);
+ if (session->hid) {
+ ret = hid_add_device(session->hid);
+ if (ret)
+ return ret;
+ get_device(&session->hid->dev);
+ } else if (session->input) {
+ ret = input_register_device(session->input);
+ if (ret)
+ return ret;
+ input_get_device(session->input);
+ }
- BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
+ return 0;
+}
- session->ctrl_sock = ctrl_sock;
- session->intr_sock = intr_sock;
- session->state = BT_CONNECTED;
+/* remove HID/input devices from their bus systems */
+static void hidp_session_dev_del(struct hidp_session *session)
+{
+ if (session->hid)
+ hid_destroy_device(session->hid);
+ else if (session->input)
+ input_unregister_device(session->input);
+}
- session->conn = hidp_get_connection(session);
- if (!session->conn) {
- err = -ENOTCONN;
- goto failed;
- }
+/*
+ * Create new session object
+ * Allocate session object, initialize static fields, copy input data into the
+ * object and take a reference to all sub-objects.
+ * This returns 0 on success and puts a pointer to the new session object in
+ * \out. Otherwise, an error code is returned.
+ * The new session object has an initial ref-count of 1.
+ */
+static int hidp_session_new(struct hidp_session **out, const bdaddr_t *bdaddr,
+ struct socket *ctrl_sock,
+ struct socket *intr_sock,
+ struct hidp_connadd_req *req,
+ struct l2cap_conn *conn)
+{
+ struct hidp_session *session;
+ int ret;
+ struct bt_sock *ctrl, *intr;
+
+ ctrl = bt_sk(ctrl_sock->sk);
+ intr = bt_sk(intr_sock->sk);
- setup_timer(&session->timer, hidp_idle_timeout, (unsigned long)session);
+ session = kzalloc(sizeof(*session), GFP_KERNEL);
+ if (!session)
+ return -ENOMEM;
+ /* object and runtime management */
+ kref_init(&session->ref);
+ atomic_set(&session->state, HIDP_SESSION_IDLING);
+ init_waitqueue_head(&session->state_queue);
+ session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
+
+ /* connection management */
+ bacpy(&session->bdaddr, bdaddr);
+ session->conn = conn;
+ session->user.probe = hidp_session_probe;
+ session->user.remove = hidp_session_remove;
+ session->ctrl_sock = ctrl_sock;
+ session->intr_sock = intr_sock;
skb_queue_head_init(&session->ctrl_transmit);
skb_queue_head_init(&session->intr_transmit);
+ session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl)->chan->omtu,
+ l2cap_pi(ctrl)->chan->imtu);
+ session->intr_mtu = min_t(uint, l2cap_pi(intr)->chan->omtu,
+ l2cap_pi(intr)->chan->imtu);
+ session->idle_to = req->idle_to;
+
+ /* device management */
+ setup_timer(&session->timer, hidp_idle_timeout,
+ (unsigned long)session);
+ /* session data */
mutex_init(&session->report_mutex);
init_waitqueue_head(&session->report_queue);
- init_waitqueue_head(&session->startup_queue);
- session->waiting_for_startup = 1;
- session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
- session->idle_to = req->idle_to;
- __hidp_link_session(session);
+ ret = hidp_session_dev_init(session, req);
+ if (ret)
+ goto err_free;
- if (req->rd_size > 0) {
- err = hidp_setup_hid(session, req);
- if (err && err != -ENODEV)
- goto purge;
- }
+ l2cap_conn_get(session->conn);
+ get_file(session->intr_sock->file);
+ get_file(session->ctrl_sock->file);
+ *out = session;
+ return 0;
- if (!session->hid) {
- err = hidp_setup_input(session, req);
- if (err < 0)
- goto purge;
+err_free:
+ kfree(session);
+ return ret;
+}
+
+/* increase ref-count of the given session by one */
+static void hidp_session_get(struct hidp_session *session)
+{
+ kref_get(&session->ref);
+}
+
+/* release callback */
+static void session_free(struct kref *ref)
+{
+ struct hidp_session *session = container_of(ref, struct hidp_session,
+ ref);
+
+ hidp_session_dev_destroy(session);
+ skb_queue_purge(&session->ctrl_transmit);
+ skb_queue_purge(&session->intr_transmit);
+ fput(session->intr_sock->file);
+ fput(session->ctrl_sock->file);
+ l2cap_conn_put(session->conn);
+ kfree(session);
+}
+
+/* decrease ref-count of the given session by one */
+static void hidp_session_put(struct hidp_session *session)
+{
+ kref_put(&session->ref, session_free);
+}
+
+/*
+ * Search the list of active sessions for a session with target address
+ * \bdaddr. You must hold at least a read-lock on \hidp_session_sem. As long as
+ * you do not release this lock, the session objects cannot vanish and you can
+ * safely take a reference to the session yourself.
+ */
+static struct hidp_session *__hidp_session_find(const bdaddr_t *bdaddr)
+{
+ struct hidp_session *session;
+
+ list_for_each_entry(session, &hidp_session_list, list) {
+ if (!bacmp(bdaddr, &session->bdaddr))
+ return session;
}
- hidp_set_timer(session);
+ return NULL;
+}
+
+/*
+ * Same as __hidp_session_find() but no locks must be held. This also takes a
+ * reference of the returned session (if non-NULL) so you must drop this
+ * reference if you no longer use the object.
+ */
+static struct hidp_session *hidp_session_find(const bdaddr_t *bdaddr)
+{
+ struct hidp_session *session;
+
+ down_read(&hidp_session_sem);
+
+ session = __hidp_session_find(bdaddr);
+ if (session)
+ hidp_session_get(session);
+
+ up_read(&hidp_session_sem);
+
+ return session;
+}
+
+/*
+ * Start session synchronously
+ * This starts a session thread and waits until initialization
+ * is done or returns an error if it couldn't be started.
+ * If this returns 0 the session thread is up and running. You must call
+ * hipd_session_stop_sync() before deleting any runtime resources.
+ */
+static int hidp_session_start_sync(struct hidp_session *session)
+{
+ unsigned int vendor, product;
if (session->hid) {
vendor = session->hid->vendor;
@@ -1051,98 +1006,320 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
product = 0x0000;
}
- session->task = kthread_run(hidp_session, session, "khidpd_%04x%04x",
- vendor, product);
- if (IS_ERR(session->task)) {
- err = PTR_ERR(session->task);
- goto unlink;
- }
+ session->task = kthread_run(hidp_session_thread, session,
+ "khidpd_%04x%04x", vendor, product);
+ if (IS_ERR(session->task))
+ return PTR_ERR(session->task);
- while (session->waiting_for_startup) {
- wait_event_interruptible(session->startup_queue,
- !session->waiting_for_startup);
- }
+ while (atomic_read(&session->state) <= HIDP_SESSION_IDLING)
+ wait_event(session->state_queue,
+ atomic_read(&session->state) > HIDP_SESSION_IDLING);
- if (session->hid)
- err = hid_add_device(session->hid);
- else
- err = input_register_device(session->input);
+ return 0;
+}
- if (err < 0) {
- atomic_inc(&session->terminate);
- wake_up_process(session->task);
- up_write(&hidp_session_sem);
- return err;
- }
+/*
+ * Terminate session thread
+ * Wake up session thread and notify it to stop. This is asynchronous and
+ * returns immediately. Call this whenever a runtime error occurs and you want
+ * the session to stop.
+ * Note: wake_up_process() performs any necessary memory-barriers for us.
+ */
+static void hidp_session_terminate(struct hidp_session *session)
+{
+ atomic_inc(&session->terminate);
+ wake_up_process(session->task);
+}
- if (session->input) {
- hidp_send_ctrl_message(session,
- HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
- session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
+/*
+ * Probe HIDP session
+ * This is called from the l2cap_conn core when our l2cap_user object is bound
+ * to the hci-connection. We get the session via the \user object and can now
+ * start the session thread, register the HID/input devices and link it into
+ * the global session list.
+ * The global session-list owns its own reference to the session object so you
+ * can drop your own reference after registering the l2cap_user object.
+ */
+static int hidp_session_probe(struct l2cap_conn *conn,
+ struct l2cap_user *user)
+{
+ struct hidp_session *session = container_of(user,
+ struct hidp_session,
+ user);
+ struct hidp_session *s;
+ int ret;
+
+ down_write(&hidp_session_sem);
- session->leds = 0xff;
- hidp_input_event(session->input, EV_LED, 0, 0);
+ /* check that no other session for this device exists */
+ s = __hidp_session_find(&session->bdaddr);
+ if (s) {
+ ret = -EEXIST;
+ goto out_unlock;
}
+ ret = hidp_session_start_sync(session);
+ if (ret)
+ goto out_unlock;
+
+ ret = hidp_session_dev_add(session);
+ if (ret)
+ goto out_stop;
+
+ hidp_session_get(session);
+ list_add(&session->list, &hidp_session_list);
+ ret = 0;
+ goto out_unlock;
+
+out_stop:
+ hidp_session_terminate(session);
+out_unlock:
up_write(&hidp_session_sem);
- return 0;
+ return ret;
+}
+
+/*
+ * Remove HIDP session
+ * Called from the l2cap_conn core when either we explicitly unregistered
+ * the l2cap_user object or if the underlying connection is shut down.
+ * We signal the hidp-session thread to shut down, unregister the HID/input
+ * devices and unlink the session from the global list.
+ * This drops the reference to the session that is owned by the global
+ * session-list.
+ * Note: We _must_ not synchronosly wait for the session-thread to shut down.
+ * This is, because the session-thread might be waiting for an HCI lock that is
+ * held while we are called. Therefore, we only unregister the devices and
+ * notify the session-thread to terminate. The thread itself owns a reference
+ * to the session object so it can safely shut down.
+ */
+static void hidp_session_remove(struct l2cap_conn *conn,
+ struct l2cap_user *user)
+{
+ struct hidp_session *session = container_of(user,
+ struct hidp_session,
+ user);
+
+ down_write(&hidp_session_sem);
+
+ hidp_session_terminate(session);
+ hidp_session_dev_del(session);
+ list_del(&session->list);
+
+ up_write(&hidp_session_sem);
+
+ hidp_session_put(session);
+}
+
+/*
+ * Session Worker
+ * This performs the actual main-loop of the HIDP worker. We first check
+ * whether the underlying connection is still alive, then parse all pending
+ * messages and finally send all outstanding messages.
+ */
+static void hidp_session_run(struct hidp_session *session)
+{
+ struct sock *ctrl_sk = session->ctrl_sock->sk;
+ struct sock *intr_sk = session->intr_sock->sk;
+ struct sk_buff *skb;
+
+ for (;;) {
+ /*
+ * This thread can be woken up two ways:
+ * - You call hidp_session_terminate() which sets the
+ * session->terminate flag and wakes this thread up.
+ * - Via modifying the socket state of ctrl/intr_sock. This
+ * thread is woken up by ->sk_state_changed().
+ *
+ * Note: set_current_state() performs any necessary
+ * memory-barriers for us.
+ */
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (atomic_read(&session->terminate))
+ break;
+
+ if (ctrl_sk->sk_state != BT_CONNECTED ||
+ intr_sk->sk_state != BT_CONNECTED)
+ break;
+
+ /* parse incoming intr-skbs */
+ while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
+ skb_orphan(skb);
+ if (!skb_linearize(skb))
+ hidp_recv_intr_frame(session, skb);
+ else
+ kfree_skb(skb);
+ }
+
+ /* send pending intr-skbs */
+ hidp_process_transmit(session, &session->intr_transmit,
+ session->intr_sock);
-unlink:
+ /* parse incoming ctrl-skbs */
+ while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
+ skb_orphan(skb);
+ if (!skb_linearize(skb))
+ hidp_recv_ctrl_frame(session, skb);
+ else
+ kfree_skb(skb);
+ }
+
+ /* send pending ctrl-skbs */
+ hidp_process_transmit(session, &session->ctrl_transmit,
+ session->ctrl_sock);
+
+ schedule();
+ }
+
+ atomic_inc(&session->terminate);
+ set_current_state(TASK_RUNNING);
+}
+
+/*
+ * HIDP session thread
+ * This thread runs the I/O for a single HIDP session. Startup is synchronous
+ * which allows us to take references to ourself here instead of doing that in
+ * the caller.
+ * When we are ready to run we notify the caller and call hidp_session_run().
+ */
+static int hidp_session_thread(void *arg)
+{
+ struct hidp_session *session = arg;
+ wait_queue_t ctrl_wait, intr_wait;
+
+ BT_DBG("session %p", session);
+
+ /* initialize runtime environment */
+ hidp_session_get(session);
+ __module_get(THIS_MODULE);
+ set_user_nice(current, -15);
+ hidp_set_timer(session);
+
+ init_waitqueue_entry(&ctrl_wait, current);
+ init_waitqueue_entry(&intr_wait, current);
+ add_wait_queue(sk_sleep(session->ctrl_sock->sk), &ctrl_wait);
+ add_wait_queue(sk_sleep(session->intr_sock->sk), &intr_wait);
+ /* This memory barrier is paired with wq_has_sleeper(). See
+ * sock_poll_wait() for more information why this is needed. */
+ smp_mb();
+
+ /* notify synchronous startup that we're ready */
+ atomic_inc(&session->state);
+ wake_up(&session->state_queue);
+
+ /* run session */
+ hidp_session_run(session);
+
+ /* cleanup runtime environment */
+ remove_wait_queue(sk_sleep(session->intr_sock->sk), &intr_wait);
+ remove_wait_queue(sk_sleep(session->intr_sock->sk), &ctrl_wait);
+ wake_up_interruptible(&session->report_queue);
hidp_del_timer(session);
- if (session->input) {
- input_unregister_device(session->input);
- session->input = NULL;
+ /*
+ * If we stopped ourself due to any internal signal, we should try to
+ * unregister our own session here to avoid having it linger until the
+ * parent l2cap_conn dies or user-space cleans it up.
+ * This does not deadlock as we don't do any synchronous shutdown.
+ * Instead, this call has the same semantics as if user-space tried to
+ * delete the session.
+ */
+ l2cap_unregister_user(session->conn, &session->user);
+ hidp_session_put(session);
+
+ module_put_and_exit(0);
+ return 0;
+}
+
+static int hidp_verify_sockets(struct socket *ctrl_sock,
+ struct socket *intr_sock)
+{
+ struct bt_sock *ctrl, *intr;
+ struct hidp_session *session;
+
+ if (!l2cap_is_socket(ctrl_sock) || !l2cap_is_socket(intr_sock))
+ return -EINVAL;
+
+ ctrl = bt_sk(ctrl_sock->sk);
+ intr = bt_sk(intr_sock->sk);
+
+ if (bacmp(&ctrl->src, &intr->src) || bacmp(&ctrl->dst, &intr->dst))
+ return -ENOTUNIQ;
+ if (ctrl->sk.sk_state != BT_CONNECTED ||
+ intr->sk.sk_state != BT_CONNECTED)
+ return -EBADFD;
+
+ /* early session check, we check again during session registration */
+ session = hidp_session_find(&ctrl->dst);
+ if (session) {
+ hidp_session_put(session);
+ return -EEXIST;
}
- if (session->hid) {
- hid_destroy_device(session->hid);
- session->hid = NULL;
+ return 0;
+}
+
+int hidp_connection_add(struct hidp_connadd_req *req,
+ struct socket *ctrl_sock,
+ struct socket *intr_sock)
+{
+ struct hidp_session *session;
+ struct l2cap_conn *conn;
+ struct l2cap_chan *chan = l2cap_pi(ctrl_sock->sk)->chan;
+ int ret;
+
+ ret = hidp_verify_sockets(ctrl_sock, intr_sock);
+ if (ret)
+ return ret;
+
+ conn = NULL;
+ l2cap_chan_lock(chan);
+ if (chan->conn) {
+ l2cap_conn_get(chan->conn);
+ conn = chan->conn;
}
+ l2cap_chan_unlock(chan);
- kfree(session->rd_data);
- session->rd_data = NULL;
+ if (!conn)
+ return -EBADFD;
-purge:
- __hidp_unlink_session(session);
+ ret = hidp_session_new(&session, &bt_sk(ctrl_sock->sk)->dst, ctrl_sock,
+ intr_sock, req, conn);
+ if (ret)
+ goto out_conn;
- skb_queue_purge(&session->ctrl_transmit);
- skb_queue_purge(&session->intr_transmit);
+ ret = l2cap_register_user(conn, &session->user);
+ if (ret)
+ goto out_session;
-failed:
- up_write(&hidp_session_sem);
+ ret = 0;
- kfree(session);
- return err;
+out_session:
+ hidp_session_put(session);
+out_conn:
+ l2cap_conn_put(conn);
+ return ret;
}
-int hidp_del_connection(struct hidp_conndel_req *req)
+int hidp_connection_del(struct hidp_conndel_req *req)
{
struct hidp_session *session;
- int err = 0;
- BT_DBG("");
+ session = hidp_session_find(&req->bdaddr);
+ if (!session)
+ return -ENOENT;
- down_read(&hidp_session_sem);
+ if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG))
+ hidp_send_ctrl_message(session,
+ HIDP_TRANS_HID_CONTROL |
+ HIDP_CTRL_VIRTUAL_CABLE_UNPLUG,
+ NULL, 0);
+ else
+ l2cap_unregister_user(session->conn, &session->user);
- session = __hidp_get_session(&req->bdaddr);
- if (session) {
- if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
- hidp_send_ctrl_message(session,
- HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
- } else {
- /* Flush the transmit queues */
- skb_queue_purge(&session->ctrl_transmit);
- skb_queue_purge(&session->intr_transmit);
-
- atomic_inc(&session->terminate);
- wake_up_process(session->task);
- }
- } else
- err = -ENOENT;
+ hidp_session_put(session);
- up_read(&hidp_session_sem);
- return err;
+ return 0;
}
int hidp_get_connlist(struct hidp_connlist_req *req)
@@ -1157,7 +1334,7 @@ int hidp_get_connlist(struct hidp_connlist_req *req)
list_for_each_entry(session, &hidp_session_list, list) {
struct hidp_conninfo ci;
- __hidp_copy_session(session, &ci);
+ hidp_copy_session(session, &ci);
if (copy_to_user(req->ci, &ci, sizeof(ci))) {
err = -EFAULT;
@@ -1178,18 +1355,14 @@ int hidp_get_connlist(struct hidp_connlist_req *req)
int hidp_get_conninfo(struct hidp_conninfo *ci)
{
struct hidp_session *session;
- int err = 0;
-
- down_read(&hidp_session_sem);
- session = __hidp_get_session(&ci->bdaddr);
- if (session)
- __hidp_copy_session(session, ci);
- else
- err = -ENOENT;
+ session = hidp_session_find(&ci->bdaddr);
+ if (session) {
+ hidp_copy_session(session, ci);
+ hidp_session_put(session);
+ }
- up_read(&hidp_session_sem);
- return err;
+ return session ? 0 : -ENOENT;
}
static int __init hidp_init(void)
@@ -1208,6 +1381,7 @@ module_init(hidp_init);
module_exit(hidp_exit);
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
+MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index af1bcc823f26..6162ce8606ac 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -24,7 +24,9 @@
#define __HIDP_H
#include <linux/types.h>
+#include <linux/kref.h>
#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/l2cap.h>
/* HIDP header masks */
#define HIDP_HEADER_TRANS_MASK 0xf0
@@ -119,43 +121,52 @@ struct hidp_connlist_req {
struct hidp_conninfo __user *ci;
};
-int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock);
-int hidp_del_connection(struct hidp_conndel_req *req);
+int hidp_connection_add(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock);
+int hidp_connection_del(struct hidp_conndel_req *req);
int hidp_get_connlist(struct hidp_connlist_req *req);
int hidp_get_conninfo(struct hidp_conninfo *ci);
+enum hidp_session_state {
+ HIDP_SESSION_IDLING,
+ HIDP_SESSION_RUNNING,
+};
+
/* HIDP session defines */
struct hidp_session {
struct list_head list;
+ struct kref ref;
- struct hci_conn *conn;
+ /* runtime management */
+ atomic_t state;
+ wait_queue_head_t state_queue;
+ atomic_t terminate;
+ struct task_struct *task;
+ unsigned long flags;
+ /* connection management */
+ bdaddr_t bdaddr;
+ struct l2cap_conn *conn;
+ struct l2cap_user user;
struct socket *ctrl_sock;
struct socket *intr_sock;
-
- bdaddr_t bdaddr;
-
- unsigned long state;
- unsigned long flags;
- unsigned long idle_to;
-
+ struct sk_buff_head ctrl_transmit;
+ struct sk_buff_head intr_transmit;
uint ctrl_mtu;
uint intr_mtu;
+ unsigned long idle_to;
- atomic_t terminate;
- struct task_struct *task;
-
- unsigned char keys[8];
- unsigned char leds;
-
+ /* device management */
struct input_dev *input;
-
struct hid_device *hid;
-
struct timer_list timer;
- struct sk_buff_head ctrl_transmit;
- struct sk_buff_head intr_transmit;
+ /* Report descriptor */
+ __u8 *rd_data;
+ uint rd_size;
+
+ /* session data */
+ unsigned char keys[8];
+ unsigned char leds;
/* Used in hidp_get_raw_report() */
int waiting_report_type; /* HIDP_DATA_RTYPE_* */
@@ -166,24 +177,8 @@ struct hidp_session {
/* Used in hidp_output_raw_report() */
int output_report_success; /* boolean */
-
- /* Report descriptor */
- __u8 *rd_data;
- uint rd_size;
-
- wait_queue_head_t startup_queue;
- int waiting_for_startup;
};
-static inline void hidp_schedule(struct hidp_session *session)
-{
- struct sock *ctrl_sk = session->ctrl_sock->sk;
- struct sock *intr_sk = session->intr_sock->sk;
-
- wake_up_interruptible(sk_sleep(ctrl_sk));
- wake_up_interruptible(sk_sleep(intr_sk));
-}
-
/* HIDP init defines */
extern int __init hidp_init_sockets(void);
extern void __exit hidp_cleanup_sockets(void);
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index 5d0f1ca0a314..2f4cbb0865ca 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -77,21 +77,12 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return err;
}
- if (csock->sk->sk_state != BT_CONNECTED ||
- isock->sk->sk_state != BT_CONNECTED) {
- sockfd_put(csock);
- sockfd_put(isock);
- return -EBADFD;
- }
+ err = hidp_connection_add(&ca, csock, isock);
+ if (!err && copy_to_user(argp, &ca, sizeof(ca)))
+ err = -EFAULT;
- err = hidp_add_connection(&ca, csock, isock);
- if (!err) {
- if (copy_to_user(argp, &ca, sizeof(ca)))
- err = -EFAULT;
- } else {
- sockfd_put(csock);
- sockfd_put(isock);
- }
+ sockfd_put(csock);
+ sockfd_put(isock);
return err;
@@ -102,7 +93,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
if (copy_from_user(&cd, argp, sizeof(cd)))
return -EFAULT;
- return hidp_del_connection(&cd);
+ return hidp_connection_del(&cd);
case HIDPGETCONNLIST:
if (copy_from_user(&cl, argp, sizeof(cl)))
@@ -296,7 +287,6 @@ int __init hidp_init_sockets(void)
return 0;
error:
- BT_ERR("Can't register HIDP socket");
proto_unregister(&hidp_proto);
return err;
}
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 7c7e9321f1ea..eae1d9f90b68 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -571,7 +571,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
chan->conn = NULL;
if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP)
- hci_conn_put(conn->hcon);
+ hci_conn_drop(conn->hcon);
if (mgr && mgr->bredr_chan == chan)
mgr->bredr_chan = NULL;
@@ -1446,6 +1446,89 @@ static void l2cap_info_timeout(struct work_struct *work)
l2cap_conn_start(conn);
}
+/*
+ * l2cap_user
+ * External modules can register l2cap_user objects on l2cap_conn. The ->probe
+ * callback is called during registration. The ->remove callback is called
+ * during unregistration.
+ * An l2cap_user object can either be explicitly unregistered or when the
+ * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon,
+ * l2cap->hchan, .. are valid as long as the remove callback hasn't been called.
+ * External modules must own a reference to the l2cap_conn object if they intend
+ * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at
+ * any time if they don't.
+ */
+
+int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
+{
+ struct hci_dev *hdev = conn->hcon->hdev;
+ int ret;
+
+ /* We need to check whether l2cap_conn is registered. If it is not, we
+ * must not register the l2cap_user. l2cap_conn_del() is unregisters
+ * l2cap_conn objects, but doesn't provide its own locking. Instead, it
+ * relies on the parent hci_conn object to be locked. This itself relies
+ * on the hci_dev object to be locked. So we must lock the hci device
+ * here, too. */
+
+ hci_dev_lock(hdev);
+
+ if (user->list.next || user->list.prev) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ /* conn->hchan is NULL after l2cap_conn_del() was called */
+ if (!conn->hchan) {
+ ret = -ENODEV;
+ goto out_unlock;
+ }
+
+ ret = user->probe(conn, user);
+ if (ret)
+ goto out_unlock;
+
+ list_add(&user->list, &conn->users);
+ ret = 0;
+
+out_unlock:
+ hci_dev_unlock(hdev);
+ return ret;
+}
+EXPORT_SYMBOL(l2cap_register_user);
+
+void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
+{
+ struct hci_dev *hdev = conn->hcon->hdev;
+
+ hci_dev_lock(hdev);
+
+ if (!user->list.next || !user->list.prev)
+ goto out_unlock;
+
+ list_del(&user->list);
+ user->list.next = NULL;
+ user->list.prev = NULL;
+ user->remove(conn, user);
+
+out_unlock:
+ hci_dev_unlock(hdev);
+}
+EXPORT_SYMBOL(l2cap_unregister_user);
+
+static void l2cap_unregister_all_users(struct l2cap_conn *conn)
+{
+ struct l2cap_user *user;
+
+ while (!list_empty(&conn->users)) {
+ user = list_first_entry(&conn->users, struct l2cap_user, list);
+ list_del(&user->list);
+ user->list.next = NULL;
+ user->list.prev = NULL;
+ user->remove(conn, user);
+ }
+}
+
static void l2cap_conn_del(struct hci_conn *hcon, int err)
{
struct l2cap_conn *conn = hcon->l2cap_data;
@@ -1458,6 +1541,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
kfree_skb(conn->rx_skb);
+ l2cap_unregister_all_users(conn);
+
mutex_lock(&conn->chan_lock);
/* Kill channels */
@@ -1486,7 +1571,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
}
hcon->l2cap_data = NULL;
- kfree(conn);
+ conn->hchan = NULL;
+ l2cap_conn_put(conn);
}
static void security_timeout(struct work_struct *work)
@@ -1502,12 +1588,12 @@ static void security_timeout(struct work_struct *work)
}
}
-static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
+static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
{
struct l2cap_conn *conn = hcon->l2cap_data;
struct hci_chan *hchan;
- if (conn || status)
+ if (conn)
return conn;
hchan = hci_chan_create(hcon);
@@ -1520,8 +1606,10 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
return NULL;
}
+ kref_init(&conn->ref);
hcon->l2cap_data = conn;
conn->hcon = hcon;
+ hci_conn_get(conn->hcon);
conn->hchan = hchan;
BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
@@ -1547,6 +1635,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
mutex_init(&conn->chan_lock);
INIT_LIST_HEAD(&conn->chan_l);
+ INIT_LIST_HEAD(&conn->users);
if (hcon->type == LE_LINK)
INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
@@ -1558,6 +1647,26 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
return conn;
}
+static void l2cap_conn_free(struct kref *ref)
+{
+ struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref);
+
+ hci_conn_put(conn->hcon);
+ kfree(conn);
+}
+
+void l2cap_conn_get(struct l2cap_conn *conn)
+{
+ kref_get(&conn->ref);
+}
+EXPORT_SYMBOL(l2cap_conn_get);
+
+void l2cap_conn_put(struct l2cap_conn *conn)
+{
+ kref_put(&conn->ref, l2cap_conn_free);
+}
+EXPORT_SYMBOL(l2cap_conn_put);
+
/* ---- Socket interface ---- */
/* Find socket with psm and source / destination bdaddr.
@@ -1695,9 +1804,9 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
goto done;
}
- conn = l2cap_conn_add(hcon, 0);
+ conn = l2cap_conn_add(hcon);
if (!conn) {
- hci_conn_put(hcon);
+ hci_conn_drop(hcon);
err = -ENOMEM;
goto done;
}
@@ -1707,7 +1816,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
if (!list_empty(&conn->chan_l)) {
err = -EBUSY;
- hci_conn_put(hcon);
+ hci_conn_drop(hcon);
}
if (err)
@@ -6313,7 +6422,7 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
if (!status) {
- conn = l2cap_conn_add(hcon, status);
+ conn = l2cap_conn_add(hcon);
if (conn)
l2cap_conn_ready(conn);
} else {
@@ -6482,7 +6591,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
goto drop;
if (!conn)
- conn = l2cap_conn_add(hcon, 0);
+ conn = l2cap_conn_add(hcon);
if (!conn)
goto drop;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 7f9704993b74..141e7b058b7e 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -43,6 +43,12 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent);
static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
int proto, gfp_t prio);
+bool l2cap_is_socket(struct socket *sock)
+{
+ return sock && sock->ops == &l2cap_sock_ops;
+}
+EXPORT_SYMBOL(l2cap_is_socket);
+
static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
{
struct sock *sk = sock->sk;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 03e7e732215f..4c830c62ef74 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -106,11 +106,10 @@ static const u16 mgmt_events[] = {
* These LE scan and inquiry parameters were chosen according to LE General
* Discovery Procedure specification.
*/
-#define LE_SCAN_TYPE 0x01
#define LE_SCAN_WIN 0x12
#define LE_SCAN_INT 0x12
-#define LE_SCAN_TIMEOUT_LE_ONLY 10240 /* TGAP(gen_disc_scan_min) */
-#define LE_SCAN_TIMEOUT_BREDR_LE 5120 /* TGAP(100)/2 */
+#define LE_SCAN_TIMEOUT_LE_ONLY msecs_to_jiffies(10240)
+#define LE_SCAN_TIMEOUT_BREDR_LE msecs_to_jiffies(5120)
#define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */
#define INQUIRY_LEN_BREDR_LE 0x04 /* TGAP(100)/2 */
@@ -2131,7 +2130,7 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status)
conn->security_cfm_cb = NULL;
conn->disconn_cfm_cb = NULL;
- hci_conn_put(conn);
+ hci_conn_drop(conn);
mgmt_pending_remove(cmd);
}
@@ -2222,7 +2221,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
}
if (conn->connect_cfm_cb) {
- hci_conn_put(conn);
+ hci_conn_drop(conn);
err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
MGMT_STATUS_BUSY, &rp, sizeof(rp));
goto unlock;
@@ -2231,7 +2230,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
- hci_conn_put(conn);
+ hci_conn_drop(conn);
goto unlock;
}
@@ -2703,7 +2702,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
goto failed;
}
- err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT,
+ err = hci_le_scan(hdev, LE_SCAN_ACTIVE, LE_SCAN_INT,
LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY);
break;
@@ -2715,8 +2714,8 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
goto failed;
}
- err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT, LE_SCAN_WIN,
- LE_SCAN_TIMEOUT_BREDR_LE);
+ err = hci_le_scan(hdev, LE_SCAN_ACTIVE, LE_SCAN_INT,
+ LE_SCAN_WIN, LE_SCAN_TIMEOUT_BREDR_LE);
break;
default:
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 2c8055350510..373d81e6e8f0 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -83,7 +83,7 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
if (conn)
return conn;
- conn = kzalloc(sizeof(struct sco_conn), GFP_ATOMIC);
+ conn = kzalloc(sizeof(struct sco_conn), GFP_KERNEL);
if (!conn)
return NULL;
@@ -185,7 +185,7 @@ static int sco_connect(struct sock *sk)
conn = sco_conn_add(hcon);
if (!conn) {
- hci_conn_put(hcon);
+ hci_conn_drop(hcon);
err = -ENOMEM;
goto done;
}
@@ -353,7 +353,7 @@ static void __sco_sock_close(struct sock *sk)
if (sco_pi(sk)->conn->hcon) {
sk->sk_state = BT_DISCONN;
sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
- hci_conn_put(sco_pi(sk)->conn->hcon);
+ hci_conn_drop(sco_pi(sk)->conn->hcon);
sco_pi(sk)->conn->hcon = NULL;
} else
sco_chan_del(sk, ECONNRESET);
@@ -481,8 +481,7 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
{
struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
struct sock *sk = sock->sk;
- int err = 0;
-
+ int err;
BT_DBG("sk %p", sk);
@@ -653,6 +652,42 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
return err;
}
+static void sco_conn_defer_accept(struct hci_conn *conn, int mask)
+{
+ struct hci_dev *hdev = conn->hdev;
+
+ BT_DBG("conn %p", conn);
+
+ conn->state = BT_CONFIG;
+
+ if (!lmp_esco_capable(hdev)) {
+ struct hci_cp_accept_conn_req cp;
+
+ bacpy(&cp.bdaddr, &conn->dst);
+
+ if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
+ cp.role = 0x00; /* Become master */
+ else
+ cp.role = 0x01; /* Remain slave */
+
+ hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
+ } else {
+ struct hci_cp_accept_sync_conn_req cp;
+
+ bacpy(&cp.bdaddr, &conn->dst);
+ cp.pkt_type = cpu_to_le16(conn->pkt_type);
+
+ 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;
+
+ hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
+ sizeof(cp), &cp);
+ }
+}
+
static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len, int flags)
{
@@ -663,7 +698,7 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
if (sk->sk_state == BT_CONNECT2 &&
test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
- hci_conn_accept(pi->conn->hcon, 0);
+ sco_conn_defer_accept(pi->conn->hcon, 0);
sk->sk_state = BT_CONFIG;
msg->msg_namelen = 0;
@@ -883,7 +918,7 @@ static void sco_chan_del(struct sock *sk, int err)
sco_conn_unlock(conn);
if (conn->hcon)
- hci_conn_put(conn->hcon);
+ hci_conn_drop(conn->hcon);
}
sk->sk_state = BT_CLOSED;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 5abefb12891d..b2296d3857a0 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -522,7 +522,7 @@ void smp_chan_destroy(struct l2cap_conn *conn)
kfree(smp);
conn->smp_chan = NULL;
conn->hcon->smp_conn = NULL;
- hci_conn_put(conn->hcon);
+ hci_conn_drop(conn->hcon);
}
int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index c50c19402588..1a89c80e6407 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -805,8 +805,7 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
IEEE80211_CHANCTX_EXCLUSIVE);
}
} else if (local->open_count == local->monitors) {
- local->_oper_channel = chandef->chan;
- local->_oper_channel_type = cfg80211_get_chandef_type(chandef);
+ local->_oper_chandef = *chandef;
ieee80211_hw_config(local, 0);
}
@@ -965,8 +964,13 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
sdata->vif.bss_conf.hidden_ssid =
(params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE);
- sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow;
- sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps;
+ memset(&sdata->vif.bss_conf.p2p_noa_attr, 0,
+ sizeof(sdata->vif.bss_conf.p2p_noa_attr));
+ sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow =
+ params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
+ if (params->p2p_opp_ps)
+ sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
+ IEEE80211_P2P_OPPPS_ENABLE_BIT;
err = ieee80211_assign_beacon(sdata, &params->beacon);
if (err < 0)
@@ -1039,6 +1043,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
sta_info_flush_defer(vlan);
sta_info_flush_defer(sdata);
+ synchronize_net();
rcu_barrier();
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
sta_info_flush_cleanup(vlan);
@@ -1048,6 +1053,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
ieee80211_free_keys(sdata);
sdata->vif.bss_conf.enable_beacon = false;
+ sdata->vif.bss_conf.ssid_len = 0;
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
@@ -1536,7 +1542,6 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_sub_if_data *sdata;
struct mesh_path *mpath;
struct sta_info *sta;
- int err;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -1547,17 +1552,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
return -ENOENT;
}
- err = mesh_path_add(sdata, dst);
- if (err) {
+ mpath = mesh_path_add(sdata, dst);
+ if (IS_ERR(mpath)) {
rcu_read_unlock();
- return err;
+ return PTR_ERR(mpath);
}
- mpath = mesh_path_lookup(sdata, dst);
- if (!mpath) {
- rcu_read_unlock();
- return -ENXIO;
- }
mesh_path_fix_nexthop(mpath, sta);
rcu_read_unlock();
@@ -1961,12 +1961,20 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
}
if (params->p2p_ctwindow >= 0) {
- sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow;
+ sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &=
+ ~IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
+ sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
+ params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
changed |= BSS_CHANGED_P2P_PS;
}
- if (params->p2p_opp_ps >= 0) {
- sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps;
+ if (params->p2p_opp_ps > 0) {
+ sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
+ IEEE80211_P2P_OPPPS_ENABLE_BIT;
+ changed |= BSS_CHANGED_P2P_PS;
+ } else if (params->p2p_opp_ps == 0) {
+ sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &=
+ ~IEEE80211_P2P_OPPPS_ENABLE_BIT;
changed |= BSS_CHANGED_P2P_PS;
}
@@ -2410,9 +2418,22 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
}
for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
+ struct ieee80211_supported_band *sband = wiphy->bands[i];
+ int j;
+
sdata->rc_rateidx_mask[i] = mask->control[i].legacy;
memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs,
sizeof(mask->control[i].mcs));
+
+ sdata->rc_has_mcs_mask[i] = false;
+ if (!sband)
+ continue;
+
+ for (j = 0; j < IEEE80211_HT_MCS_MASK_LEN; j++)
+ if (~sdata->rc_rateidx_mcs_mask[i][j]) {
+ sdata->rc_has_mcs_mask[i] = true;
+ break;
+ }
}
return 0;
@@ -3362,9 +3383,7 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
if (local->use_chanctx)
*chandef = local->monitor_chandef;
else
- cfg80211_chandef_create(chandef,
- local->_oper_channel,
- local->_oper_channel_type);
+ *chandef = local->_oper_chandef;
ret = 0;
}
rcu_read_unlock();
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 931be419ab5a..03e8d2e3270e 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -22,7 +22,7 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local,
drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH);
if (!local->use_chanctx) {
- local->_oper_channel_type = cfg80211_get_chandef_type(chandef);
+ local->_oper_chandef = *chandef;
ieee80211_hw_config(local, 0);
}
}
@@ -57,6 +57,22 @@ ieee80211_find_chanctx(struct ieee80211_local *local,
return NULL;
}
+static bool ieee80211_is_radar_required(struct ieee80211_local *local)
+{
+ struct ieee80211_sub_if_data *sdata;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ if (sdata->radar_required) {
+ rcu_read_unlock();
+ return true;
+ }
+ }
+ rcu_read_unlock();
+
+ return false;
+}
+
static struct ieee80211_chanctx *
ieee80211_new_chanctx(struct ieee80211_local *local,
const struct cfg80211_chan_def *chandef,
@@ -76,6 +92,9 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
ctx->conf.rx_chains_static = 1;
ctx->conf.rx_chains_dynamic = 1;
ctx->mode = mode;
+ ctx->conf.radar_enabled = ieee80211_is_radar_required(local);
+ if (!local->use_chanctx)
+ local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
/* acquire mutex to prevent idle from changing */
mutex_lock(&local->mtx);
@@ -85,9 +104,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
ieee80211_hw_config(local, changed);
if (!local->use_chanctx) {
- local->_oper_channel_type =
- cfg80211_get_chandef_type(chandef);
- local->_oper_channel = chandef->chan;
+ local->_oper_chandef = *chandef;
ieee80211_hw_config(local, 0);
} else {
err = drv_add_chanctx(local, ctx);
@@ -112,12 +129,24 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
static void ieee80211_free_chanctx(struct ieee80211_local *local,
struct ieee80211_chanctx *ctx)
{
+ bool check_single_channel = false;
lockdep_assert_held(&local->chanctx_mtx);
WARN_ON_ONCE(ctx->refcount != 0);
if (!local->use_chanctx) {
- local->_oper_channel_type = NL80211_CHAN_NO_HT;
+ struct cfg80211_chan_def *chandef = &local->_oper_chandef;
+ chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
+ chandef->center_freq1 = chandef->chan->center_freq;
+ chandef->center_freq2 = 0;
+
+ /* NOTE: Disabling radar is only valid here for
+ * single channel context. To be sure, check it ...
+ */
+ if (local->hw.conf.radar_enabled)
+ check_single_channel = true;
+ local->hw.conf.radar_enabled = false;
+
ieee80211_hw_config(local, 0);
} else {
drv_remove_chanctx(local, ctx);
@@ -126,6 +155,9 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
list_del_rcu(&ctx->list);
kfree_rcu(ctx, rcu_head);
+ /* throw a warning if this wasn't the only channel context. */
+ WARN_ON(check_single_channel && !list_empty(&local->chanctx_list));
+
mutex_lock(&local->mtx);
ieee80211_recalc_idle(local);
mutex_unlock(&local->mtx);
@@ -237,19 +269,11 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
struct ieee80211_chanctx *chanctx)
{
- struct ieee80211_sub_if_data *sdata;
- bool radar_enabled = false;
+ bool radar_enabled;
lockdep_assert_held(&local->chanctx_mtx);
- rcu_read_lock();
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- if (sdata->radar_required) {
- radar_enabled = true;
- break;
- }
- }
- rcu_read_unlock();
+ radar_enabled = ieee80211_is_radar_required(local);
if (radar_enabled == chanctx->conf.radar_enabled)
return;
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index ddb426867904..14abcf44f974 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -124,6 +124,15 @@ static ssize_t ieee80211_if_fmt_##name( \
return scnprintf(buf, buflen, "%d\n", sdata->field / 16); \
}
+#define IEEE80211_IF_FMT_JIFFIES_TO_MS(name, field) \
+static ssize_t ieee80211_if_fmt_##name( \
+ const struct ieee80211_sub_if_data *sdata, \
+ char *buf, int buflen) \
+{ \
+ return scnprintf(buf, buflen, "%d\n", \
+ jiffies_to_msecs(sdata->field)); \
+}
+
#define __IEEE80211_IF_FILE(name, _write) \
static ssize_t ieee80211_if_read_##name(struct file *file, \
char __user *userbuf, \
@@ -197,6 +206,7 @@ IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
IEEE80211_IF_FILE(aid, u.mgd.aid, DEC);
IEEE80211_IF_FILE(last_beacon, u.mgd.last_beacon_signal, DEC);
IEEE80211_IF_FILE(ave_beacon, u.mgd.ave_beacon_signal, DEC_DIV_16);
+IEEE80211_IF_FILE(beacon_timeout, u.mgd.beacon_timeout, JIFFIES_TO_MS);
static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
enum ieee80211_smps_mode smps_mode)
@@ -542,6 +552,7 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_ADD(aid);
DEBUGFS_ADD(last_beacon);
DEBUGFS_ADD(ave_beacon);
+ DEBUGFS_ADD(beacon_timeout);
DEBUGFS_ADD_MODE(smps, 0600);
DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
DEBUGFS_ADD_MODE(uapsd_queues, 0600);
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 4f841fe559df..44e201d60a13 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -54,6 +54,7 @@ STA_FILE(aid, sta.aid, D);
STA_FILE(dev, sdata->name, S);
STA_FILE(last_signal, last_signal, D);
STA_FILE(last_ack_signal, last_ack_signal, D);
+STA_FILE(beacon_loss_count, beacon_loss_count, D);
static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
@@ -434,6 +435,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
DEBUGFS_ADD(agg_status);
DEBUGFS_ADD(dev);
DEBUGFS_ADD(last_signal);
+ DEBUGFS_ADD(beacon_loss_count);
DEBUGFS_ADD(ht_capa);
DEBUGFS_ADD(vht_capa);
DEBUGFS_ADD(last_ack_signal);
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 539d4a11b47b..170f9a7fa319 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -44,7 +44,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
int rates, i;
- struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
u8 *pos;
struct ieee80211_supported_band *sband;
@@ -52,20 +51,14 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
u32 bss_change;
u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
struct cfg80211_chan_def chandef;
+ struct beacon_data *presp;
+ int frame_len;
lockdep_assert_held(&ifibss->mtx);
/* Reset own TSF to allow time synchronization work. */
drv_reset_tsf(local, sdata);
- skb = ifibss->skb;
- RCU_INIT_POINTER(ifibss->presp, NULL);
- synchronize_rcu();
- skb->data = skb->head;
- skb->len = 0;
- skb_reset_tail_pointer(skb);
- skb_reserve(skb, sdata->local->hw.extra_tx_headroom);
-
if (!ether_addr_equal(ifibss->bssid, bssid))
sta_info_flush(sdata);
@@ -73,10 +66,19 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
if (sdata->vif.bss_conf.ibss_joined) {
sdata->vif.bss_conf.ibss_joined = false;
sdata->vif.bss_conf.ibss_creator = false;
+ sdata->vif.bss_conf.enable_beacon = false;
netif_carrier_off(sdata->dev);
- ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS);
+ ieee80211_bss_info_change_notify(sdata,
+ BSS_CHANGED_IBSS |
+ BSS_CHANGED_BEACON_ENABLED);
}
+ presp = rcu_dereference_protected(ifibss->presp,
+ lockdep_is_held(&ifibss->mtx));
+ rcu_assign_pointer(ifibss->presp, NULL);
+ if (presp)
+ kfree_rcu(presp, rcu_head);
+
sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
cfg80211_chandef_create(&chandef, chan, ifibss->channel_type);
@@ -98,19 +100,24 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
sband = local->hw.wiphy->bands[chan->band];
- /* build supported rates array */
- pos = supp_rates;
- for (i = 0; i < sband->n_bitrates; i++) {
- int rate = sband->bitrates[i].bitrate;
- u8 basic = 0;
- if (basic_rates & BIT(i))
- basic = 0x80;
- *pos++ = basic | (u8) (rate / 5);
- }
-
/* Build IBSS probe response */
- mgmt = (void *) skb_put(skb, 24 + sizeof(mgmt->u.beacon));
- memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
+ frame_len = sizeof(struct ieee80211_hdr_3addr) +
+ 12 /* struct ieee80211_mgmt.u.beacon */ +
+ 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ +
+ 2 + 8 /* max Supported Rates */ +
+ 3 /* max DS params */ +
+ 4 /* IBSS params */ +
+ 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
+ 2 + sizeof(struct ieee80211_ht_cap) +
+ 2 + sizeof(struct ieee80211_ht_operation) +
+ ifibss->ie_len;
+ presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL);
+ if (!presp)
+ return;
+
+ presp->head = (void *)(presp + 1);
+
+ mgmt = (void *) presp->head;
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_RESP);
eth_broadcast_addr(mgmt->da);
@@ -120,27 +127,30 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
mgmt->u.beacon.timestamp = cpu_to_le64(tsf);
mgmt->u.beacon.capab_info = cpu_to_le16(capability);
- pos = skb_put(skb, 2 + ifibss->ssid_len);
+ pos = (u8 *)mgmt + offsetof(struct ieee80211_mgmt, u.beacon.variable);
+
*pos++ = WLAN_EID_SSID;
*pos++ = ifibss->ssid_len;
memcpy(pos, ifibss->ssid, ifibss->ssid_len);
+ pos += ifibss->ssid_len;
- rates = sband->n_bitrates;
- if (rates > 8)
- rates = 8;
- pos = skb_put(skb, 2 + rates);
+ rates = min_t(int, 8, sband->n_bitrates);
*pos++ = WLAN_EID_SUPP_RATES;
*pos++ = rates;
- memcpy(pos, supp_rates, rates);
+ for (i = 0; i < rates; i++) {
+ int rate = sband->bitrates[i].bitrate;
+ u8 basic = 0;
+ if (basic_rates & BIT(i))
+ basic = 0x80;
+ *pos++ = basic | (u8) (rate / 5);
+ }
if (sband->band == IEEE80211_BAND_2GHZ) {
- pos = skb_put(skb, 2 + 1);
*pos++ = WLAN_EID_DS_PARAMS;
*pos++ = 1;
*pos++ = ieee80211_frequency_to_channel(chan->center_freq);
}
- pos = skb_put(skb, 2 + 2);
*pos++ = WLAN_EID_IBSS_PARAMS;
*pos++ = 2;
/* FIX: set ATIM window based on scan results */
@@ -148,23 +158,25 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
*pos++ = 0;
if (sband->n_bitrates > 8) {
- rates = sband->n_bitrates - 8;
- pos = skb_put(skb, 2 + rates);
*pos++ = WLAN_EID_EXT_SUPP_RATES;
- *pos++ = rates;
- memcpy(pos, &supp_rates[8], rates);
+ *pos++ = sband->n_bitrates - 8;
+ for (i = 8; i < sband->n_bitrates; i++) {
+ int rate = sband->bitrates[i].bitrate;
+ u8 basic = 0;
+ if (basic_rates & BIT(i))
+ basic = 0x80;
+ *pos++ = basic | (u8) (rate / 5);
+ }
}
- if (ifibss->ie_len)
- memcpy(skb_put(skb, ifibss->ie_len),
- ifibss->ie, ifibss->ie_len);
+ if (ifibss->ie_len) {
+ memcpy(pos, ifibss->ie, ifibss->ie_len);
+ pos += ifibss->ie_len;
+ }
/* add HT capability and information IEs */
if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
sband->ht_cap.ht_supported) {
- pos = skb_put(skb, 4 +
- sizeof(struct ieee80211_ht_cap) +
- sizeof(struct ieee80211_ht_operation));
pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap,
sband->ht_cap.cap);
/*
@@ -177,7 +189,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
}
if (local->hw.queues >= IEEE80211_NUM_ACS) {
- pos = skb_put(skb, 9);
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 7; /* len */
*pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
@@ -189,11 +200,17 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
*pos++ = 0; /* U-APSD no in use */
}
- rcu_assign_pointer(ifibss->presp, skb);
+ presp->head_len = pos - presp->head;
+ if (WARN_ON(presp->head_len > frame_len))
+ return;
+
+ rcu_assign_pointer(ifibss->presp, presp);
sdata->vif.bss_conf.enable_beacon = true;
sdata->vif.bss_conf.beacon_int = beacon_int;
sdata->vif.bss_conf.basic_rates = basic_rates;
+ sdata->vif.bss_conf.ssid_len = ifibss->ssid_len;
+ memcpy(sdata->vif.bss_conf.ssid, ifibss->ssid, ifibss->ssid_len);
bss_change = BSS_CHANGED_BEACON_INT;
bss_change |= ieee80211_reset_erp_info(sdata);
bss_change |= BSS_CHANGED_BSSID;
@@ -202,6 +219,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
bss_change |= BSS_CHANGED_BASIC_RATES;
bss_change |= BSS_CHANGED_HT;
bss_change |= BSS_CHANGED_IBSS;
+ bss_change |= BSS_CHANGED_SSID;
/*
* In 5 GHz/802.11a, we can always use short slot time.
@@ -227,7 +245,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
bss = cfg80211_inform_bss_frame(local->hw.wiphy, chan,
- mgmt, skb->len, 0, GFP_KERNEL);
+ mgmt, presp->head_len, 0, GFP_KERNEL);
cfg80211_put_bss(local->hw.wiphy, bss);
netif_carrier_on(sdata->dev);
cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
@@ -448,7 +466,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
bool rates_updated = false;
- if (elems->ds_params && elems->ds_params_len == 1)
+ if (elems->ds_params)
freq = ieee80211_channel_to_frequency(elems->ds_params[0],
band);
else
@@ -822,8 +840,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
int tx_last_beacon, len = req->len;
struct sk_buff *skb;
- struct ieee80211_mgmt *resp;
- struct sk_buff *presp;
+ struct beacon_data *presp;
u8 *pos, *end;
lockdep_assert_held(&ifibss->mtx);
@@ -864,13 +881,15 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
}
/* Reply with ProbeResp */
- skb = skb_copy(presp, GFP_KERNEL);
+ skb = dev_alloc_skb(local->tx_headroom + presp->head_len);
if (!skb)
return;
- resp = (struct ieee80211_mgmt *) skb->data;
- memcpy(resp->da, mgmt->sa, ETH_ALEN);
- ibss_dbg(sdata, "Sending ProbeResp to %pM\n", resp->da);
+ skb_reserve(skb, local->tx_headroom);
+ memcpy(skb_put(skb, presp->head_len), presp->head, presp->head_len);
+
+ memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN);
+ ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa);
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
ieee80211_tx_skb(sdata, skb);
}
@@ -895,7 +914,7 @@ void ieee80211_rx_mgmt_probe_beacon(struct ieee80211_sub_if_data *sdata,
return;
ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
- &elems);
+ false, &elems);
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
}
@@ -1020,23 +1039,8 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
struct cfg80211_ibss_params *params)
{
- struct sk_buff *skb;
u32 changed = 0;
- skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
- sizeof(struct ieee80211_hdr_3addr) +
- 12 /* struct ieee80211_mgmt.u.beacon */ +
- 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ +
- 2 + 8 /* max Supported Rates */ +
- 3 /* max DS params */ +
- 4 /* IBSS params */ +
- 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
- 2 + sizeof(struct ieee80211_ht_cap) +
- 2 + sizeof(struct ieee80211_ht_operation) +
- params->ie_len);
- if (!skb)
- return -ENOMEM;
-
mutex_lock(&sdata->u.ibss.mtx);
if (params->bssid) {
@@ -1065,7 +1069,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
sdata->u.ibss.ie_len = params->ie_len;
}
- sdata->u.ibss.skb = skb;
sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
sdata->u.ibss.ibss_join_req = jiffies;
@@ -1101,13 +1104,13 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
{
- struct sk_buff *skb;
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
struct cfg80211_bss *cbss;
u16 capability;
int active_ibss;
struct sta_info *sta;
+ struct beacon_data *presp;
mutex_lock(&sdata->u.ibss.mtx);
@@ -1153,17 +1156,18 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
/* remove beacon */
kfree(sdata->u.ibss.ie);
- skb = rcu_dereference_protected(sdata->u.ibss.presp,
- lockdep_is_held(&sdata->u.ibss.mtx));
+ presp = rcu_dereference_protected(ifibss->presp,
+ lockdep_is_held(&sdata->u.ibss.mtx));
RCU_INIT_POINTER(sdata->u.ibss.presp, NULL);
sdata->vif.bss_conf.ibss_joined = false;
sdata->vif.bss_conf.ibss_creator = false;
sdata->vif.bss_conf.enable_beacon = false;
+ sdata->vif.bss_conf.ssid_len = 0;
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
BSS_CHANGED_IBSS);
synchronize_rcu();
- kfree_skb(skb);
+ kfree(presp);
skb_queue_purge(&sdata->skb_queue);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 0b09716d22ad..158e6eb188d3 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -156,6 +156,7 @@ struct ieee80211_tx_data {
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
struct ieee80211_key *key;
+ struct ieee80211_tx_rate rate;
unsigned int flags;
};
@@ -443,7 +444,7 @@ struct ieee80211_if_managed {
u8 use_4addr;
- u8 p2p_noa_index;
+ s16 p2p_noa_index;
/* Signal strength from the last Beacon frame in the current BSS. */
int last_beacon_signal;
@@ -509,8 +510,7 @@ struct ieee80211_if_ibss {
unsigned long ibss_join_req;
/* probe response/beacon for IBSS */
- struct sk_buff __rcu *presp;
- struct sk_buff *skb;
+ struct beacon_data __rcu *presp;
spinlock_t incomplete_lock;
struct list_head incomplete_stations;
@@ -741,6 +741,8 @@ struct ieee80211_sub_if_data {
/* bitmap of allowed (non-MCS) rate indexes for rate control */
u32 rc_rateidx_mask[IEEE80211_NUM_BANDS];
+
+ bool rc_has_mcs_mask[IEEE80211_NUM_BANDS];
u8 rc_rateidx_mcs_mask[IEEE80211_NUM_BANDS][IEEE80211_HT_MCS_MASK_LEN];
union {
@@ -1021,10 +1023,9 @@ struct ieee80211_local {
enum mac80211_scan_state next_scan_state;
struct delayed_work scan_work;
struct ieee80211_sub_if_data __rcu *scan_sdata;
- struct ieee80211_channel *csa_channel;
+ struct cfg80211_chan_def csa_chandef;
/* For backward compatibility only -- do not use */
- struct ieee80211_channel *_oper_channel;
- enum nl80211_channel_type _oper_channel_type;
+ struct cfg80211_chan_def _oper_chandef;
/* Temporary remain-on-channel for off-channel operations */
struct ieee80211_channel *tmp_channel;
@@ -1160,11 +1161,8 @@ struct ieee802_11_elems {
/* pointers to IEs */
const u8 *ssid;
const u8 *supp_rates;
- const u8 *fh_params;
const u8 *ds_params;
- const u8 *cf_params;
const struct ieee80211_tim_ie *tim;
- const u8 *ibss_params;
const u8 *challenge;
const u8 *rsn;
const u8 *erp_info;
@@ -1184,23 +1182,20 @@ struct ieee802_11_elems {
const u8 *perr;
const struct ieee80211_rann_ie *rann;
const struct ieee80211_channel_sw_ie *ch_switch_ie;
+ const struct ieee80211_ext_chansw_ie *ext_chansw_ie;
+ const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
const u8 *country_elem;
const u8 *pwr_constr_elem;
- const u8 *quiet_elem; /* first quite element */
- const u8 *timeout_int;
+ const struct ieee80211_timeout_interval_ie *timeout_int;
const u8 *opmode_notif;
+ const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
/* length of them, respectively */
u8 ssid_len;
u8 supp_rates_len;
- u8 fh_params_len;
- u8 ds_params_len;
- u8 cf_params_len;
u8 tim_len;
- u8 ibss_params_len;
u8 challenge_len;
u8 rsn_len;
- u8 erp_info_len;
u8 ext_supp_rates_len;
u8 wmm_info_len;
u8 wmm_param_len;
@@ -1210,9 +1205,6 @@ struct ieee802_11_elems {
u8 prep_len;
u8 perr_len;
u8 country_elem_len;
- u8 quiet_elem_len;
- u8 num_of_quiet_elem; /* can be more the one */
- u8 timeout_int_len;
/* whether a parse error occurred while retrieving these elements */
bool parse_error;
@@ -1267,10 +1259,6 @@ void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata);
int ieee80211_max_network_latency(struct notifier_block *nb,
unsigned long data, void *dummy);
int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata);
-void
-ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
- const struct ieee80211_channel_sw_ie *sw_elem,
- struct ieee80211_bss *bss, u64 timestamp);
void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
@@ -1330,7 +1318,8 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local);
void ieee80211_offchannel_return(struct ieee80211_local *local);
void ieee80211_roc_setup(struct ieee80211_local *local);
void ieee80211_start_next_roc(struct ieee80211_local *local);
-void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata);
+void ieee80211_roc_purge(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata);
void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free);
void ieee80211_sw_roc_work(struct work_struct *work);
void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
@@ -1351,6 +1340,8 @@ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
const int offset);
int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up);
void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata);
+int ieee80211_add_virtual_monitor(struct ieee80211_local *local);
+void ieee80211_del_virtual_monitor(struct ieee80211_local *local);
bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
@@ -1505,11 +1496,15 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
ieee80211_tx_skb_tid(sdata, skb, 7);
}
-void ieee802_11_parse_elems(u8 *start, size_t len,
- struct ieee802_11_elems *elems);
-u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
+u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action,
struct ieee802_11_elems *elems,
u64 filter, u32 crc);
+static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action,
+ struct ieee802_11_elems *elems)
+{
+ ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
+}
+
u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
enum ieee80211_band band);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index e8a260f53c16..60f1ce5e5e52 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1,5 +1,5 @@
/*
- * Interface handling (except master interface)
+ * Interface handling
*
* Copyright 2002-2005, Instant802 Networks, Inc.
* Copyright 2005-2006, Devicescape Software, Inc.
@@ -357,7 +357,7 @@ 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;
@@ -410,7 +410,7 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
return 0;
}
-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;
@@ -595,7 +595,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
case NL80211_IFTYPE_P2P_DEVICE:
break;
default:
- netif_carrier_on(dev);
+ /* not reached */
+ WARN_ON(1);
}
/*
@@ -652,8 +653,28 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
ieee80211_recalc_ps(local, -1);
- if (dev)
- netif_tx_start_all_queues(dev);
+ if (dev) {
+ unsigned long flags;
+ int n_acs = IEEE80211_NUM_ACS;
+ int ac;
+
+ if (local->hw.queues < IEEE80211_NUM_ACS)
+ n_acs = 1;
+
+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+ if (sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE ||
+ (local->queue_stop_reasons[sdata->vif.cab_queue] == 0 &&
+ skb_queue_empty(&local->pending[sdata->vif.cab_queue]))) {
+ for (ac = 0; ac < n_acs; ac++) {
+ int ac_queue = sdata->vif.hw_queue[ac];
+
+ if (local->queue_stop_reasons[ac_queue] == 0 &&
+ skb_queue_empty(&local->pending[ac_queue]))
+ netif_start_subqueue(dev, ac);
+ }
+ }
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+ }
return 0;
err_del_interface:
@@ -707,7 +728,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
if (sdata->dev)
netif_tx_stop_all_queues(sdata->dev);
- ieee80211_roc_purge(sdata);
+ ieee80211_roc_purge(local, sdata);
if (sdata->vif.type == NL80211_IFTYPE_STATION)
ieee80211_mgd_stop(sdata);
@@ -732,12 +753,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
(sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1));
- /*
- * Don't count this interface for promisc/allmulti while it
- * is down. dev_mc_unsync() will invoke set_multicast_list
- * on the master interface which will sync these down to the
- * hardware as filter flags.
- */
+ /* don't count this interface for promisc/allmulti while it is down */
if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
atomic_dec(&local->iff_allmultis);
@@ -758,8 +774,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
sdata->dev->addr_len);
spin_unlock_bh(&local->filter_lock);
netif_addr_unlock_bh(sdata->dev);
-
- ieee80211_configure_filter(local);
}
del_timer_sync(&local->dynamic_ps_timer);
@@ -770,6 +784,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
if (sdata->wdev.cac_started) {
+ WARN_ON(local->suspended);
mutex_lock(&local->iflist_mtx);
ieee80211_vif_release_channel(sdata);
mutex_unlock(&local->iflist_mtx);
@@ -820,14 +835,9 @@ 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);
- ieee80211_configure_filter(local);
- mutex_lock(&local->mtx);
- ieee80211_recalc_idle(local);
- mutex_unlock(&local->mtx);
break;
case NL80211_IFTYPE_P2P_DEVICE:
/* relies on synchronize_rcu() below */
@@ -840,11 +850,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
*
* sta_info_flush_cleanup() requires rcu_barrier()
* first to wait for the station call_rcu() calls
- * to complete, here we need at least sychronize_rcu()
- * it to wait for the RX path in case it is using the
+ * to complete, and we also need synchronize_rcu()
+ * to wait for the RX path in case it is using the
* interface and enqueuing frames at this very time on
* another CPU.
*/
+ synchronize_rcu();
rcu_barrier();
sta_info_flush_cleanup(sdata);
@@ -857,27 +868,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
/* fall through */
case NL80211_IFTYPE_AP:
skb_queue_purge(&sdata->skb_queue);
-
- if (going_down)
- drv_remove_interface(local, sdata);
}
sdata->bss = NULL;
- ieee80211_recalc_ps(local, -1);
-
- if (local->open_count == 0) {
- ieee80211_clear_tx_pending(local);
- ieee80211_stop_device(local);
-
- /* no reconfiguring after stop! */
- hw_reconf_flags = 0;
- }
-
- /* do after stop to avoid reconfiguring when we stop anyway */
- if (hw_reconf_flags)
- ieee80211_hw_config(local, hw_reconf_flags);
-
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
skb_queue_walk_safe(&local->pending[i], skb, tmp) {
@@ -890,7 +884,54 @@ 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)
+ if (local->open_count == 0)
+ ieee80211_clear_tx_pending(local);
+
+ /*
+ * If the interface goes down while suspended, presumably because
+ * the device was unplugged and that happens before our resume,
+ * then the driver is already unconfigured and the remainder of
+ * this function isn't needed.
+ * XXX: what about WoWLAN? If the device has software state, e.g.
+ * memory allocated, it might expect teardown commands from
+ * mac80211 here?
+ */
+ if (local->suspended) {
+ WARN_ON(local->wowlan);
+ WARN_ON(rtnl_dereference(local->monitor_sdata));
+ return;
+ }
+
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_AP_VLAN:
+ break;
+ case NL80211_IFTYPE_MONITOR:
+ if (local->monitors == 0)
+ ieee80211_del_virtual_monitor(local);
+
+ mutex_lock(&local->mtx);
+ ieee80211_recalc_idle(local);
+ mutex_unlock(&local->mtx);
+ break;
+ default:
+ if (going_down)
+ drv_remove_interface(local, sdata);
+ }
+
+ ieee80211_recalc_ps(local, -1);
+
+ if (local->open_count == 0) {
+ ieee80211_stop_device(local);
+
+ /* no reconfiguring after stop! */
+ return;
+ }
+
+ /* do after stop to avoid reconfiguring when we stop anyway */
+ ieee80211_configure_filter(local);
+ ieee80211_hw_config(local, hw_reconf_flags);
+
+ if (local->monitors == local->open_count)
ieee80211_add_virtual_monitor(local);
}
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index c6f81ecc36a1..8a7bfc47d577 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -95,42 +95,47 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata;
- struct ieee80211_channel *chan;
+ struct cfg80211_chan_def chandef = {};
u32 changed = 0;
int power;
- enum nl80211_channel_type channel_type;
u32 offchannel_flag;
offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
+
if (local->scan_channel) {
- chan = local->scan_channel;
+ chandef.chan = local->scan_channel;
/* If scanning on oper channel, use whatever channel-type
* is currently in use.
*/
- if (chan == local->_oper_channel)
- channel_type = local->_oper_channel_type;
- else
- channel_type = NL80211_CHAN_NO_HT;
+ if (chandef.chan == local->_oper_chandef.chan) {
+ chandef = local->_oper_chandef;
+ } else {
+ chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
+ chandef.center_freq1 = chandef.chan->center_freq;
+ }
} else if (local->tmp_channel) {
- chan = local->tmp_channel;
- channel_type = NL80211_CHAN_NO_HT;
- } else {
- chan = local->_oper_channel;
- channel_type = local->_oper_channel_type;
- }
-
- if (chan != local->_oper_channel ||
- channel_type != local->_oper_channel_type)
+ chandef.chan = local->tmp_channel;
+ chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
+ chandef.center_freq1 = chandef.chan->center_freq;
+ } else
+ chandef = local->_oper_chandef;
+
+ WARN(!cfg80211_chandef_valid(&chandef),
+ "control:%d MHz width:%d center: %d/%d MHz",
+ chandef.chan->center_freq, chandef.width,
+ chandef.center_freq1, chandef.center_freq2);
+
+ if (!cfg80211_chandef_identical(&chandef, &local->_oper_chandef))
local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
else
local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
- if (offchannel_flag || chan != local->hw.conf.channel ||
- channel_type != local->hw.conf.channel_type) {
- local->hw.conf.channel = chan;
- local->hw.conf.channel_type = channel_type;
+ if (offchannel_flag ||
+ !cfg80211_chandef_identical(&local->hw.conf.chandef,
+ &local->_oper_chandef)) {
+ local->hw.conf.chandef = chandef;
changed |= IEEE80211_CONF_CHANGE_CHANNEL;
}
@@ -146,7 +151,7 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
changed |= IEEE80211_CONF_CHANGE_SMPS;
}
- power = chan->max_power;
+ power = chandef.chan->max_power;
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
@@ -587,6 +592,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
IEEE80211_RADIOTAP_MCS_HAVE_BW;
local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
+ local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
+ local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
wiphy->vht_capa_mod_mask = &mac80211_vht_capa_mod_mask;
@@ -661,6 +668,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
int channels, max_bitrates;
bool supp_ht, supp_vht;
netdev_features_t feature_whitelist;
+ struct cfg80211_chan_def dflt_chandef = {};
static const u32 cipher_suites[] = {
/* keep WEP first, it may be removed below */
WLAN_CIPHER_SUITE_WEP40,
@@ -738,15 +746,19 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
sband = local->hw.wiphy->bands[band];
if (!sband)
continue;
- if (!local->use_chanctx && !local->_oper_channel) {
+
+ if (!dflt_chandef.chan) {
+ cfg80211_chandef_create(&dflt_chandef,
+ &sband->channels[0],
+ NL80211_CHAN_NO_HT);
/* init channel we're on */
- local->hw.conf.channel =
- local->_oper_channel = &sband->channels[0];
- local->hw.conf.channel_type = NL80211_CHAN_NO_HT;
+ if (!local->use_chanctx && !local->_oper_chandef.chan) {
+ local->hw.conf.chandef = dflt_chandef;
+ local->_oper_chandef = dflt_chandef;
+ }
+ local->monitor_chandef = dflt_chandef;
}
- cfg80211_chandef_create(&local->monitor_chandef,
- &sband->channels[0],
- NL80211_CHAN_NO_HT);
+
channels += sband->n_channels;
if (max_bitrates < sband->n_bitrates)
@@ -829,22 +841,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) {
+ if (supp_vht)
local->scan_ies_len +=
2 + sizeof(struct ieee80211_vht_cap);
- /*
- * (for now at least), drivers wanting to use VHT must
- * support channel contexts, as they contain all the
- * necessary VHT information and the global hw config
- * doesn't (yet)
- */
- if (WARN_ON(!local->use_chanctx)) {
- result = -EINVAL;
- goto fail_wiphy_register;
- }
- }
-
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 123a300cef57..6952760881c8 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -838,7 +838,7 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata,
if (baselen > len)
return;
- ieee802_11_parse_elems(pos, len - baselen, &elems);
+ ieee802_11_parse_elems(pos, len - baselen, false, &elems);
/* 802.11-2012 10.1.4.3.2 */
if ((!ether_addr_equal(mgmt->da, sdata->vif.addr) &&
@@ -899,7 +899,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
return;
ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
- &elems);
+ false, &elems);
/* ignore non-mesh or secure / unsecure mismatch */
if ((!elems.mesh_id || !elems.mesh_config) ||
@@ -907,7 +907,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
(!elems.rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE))
return;
- if (elems.ds_params && elems.ds_params_len == 1)
+ if (elems.ds_params)
freq = ieee80211_channel_to_frequency(elems.ds_params[0], band);
else
freq = rx_status->freq;
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 6ffabbe99c46..da158774eebb 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -275,7 +275,8 @@ void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
void mesh_path_expire(struct ieee80211_sub_if_data *sdata);
void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, size_t len);
-int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst);
+struct mesh_path *
+mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst);
int mesh_path_add_gate(struct mesh_path *mpath);
int mesh_path_send_to_gates(struct mesh_path *mpath);
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index bdb8d3b14587..486819cd02cd 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -144,7 +144,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
*pos++ = WLAN_EID_PREQ;
break;
case MPATH_PREP:
- mhwmp_dbg(sdata, "sending PREP to %pM\n", target);
+ mhwmp_dbg(sdata, "sending PREP to %pM\n", orig_addr);
ie_len = 31;
pos = skb_put(skb, 2 + ie_len);
*pos++ = WLAN_EID_PREP;
@@ -445,9 +445,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
}
}
} else {
- mesh_path_add(sdata, orig_addr);
- mpath = mesh_path_lookup(sdata, orig_addr);
- if (!mpath) {
+ mpath = mesh_path_add(sdata, orig_addr);
+ if (IS_ERR(mpath)) {
rcu_read_unlock();
return 0;
}
@@ -486,9 +485,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
(last_hop_metric > mpath->metric)))
fresh_info = false;
} else {
- mesh_path_add(sdata, ta);
- mpath = mesh_path_lookup(sdata, ta);
- if (!mpath) {
+ mpath = mesh_path_add(sdata, ta);
+ if (IS_ERR(mpath)) {
rcu_read_unlock();
return 0;
}
@@ -661,7 +659,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
u32 target_sn, orig_sn, lifetime;
mhwmp_dbg(sdata, "received PREP from %pM\n",
- PREP_IE_ORIG_ADDR(prep_elem));
+ PREP_IE_TARGET_ADDR(prep_elem));
orig_addr = PREP_IE_ORIG_ADDR(prep_elem);
if (ether_addr_equal(orig_addr, sdata->vif.addr))
@@ -804,9 +802,8 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
mpath = mesh_path_lookup(sdata, orig_addr);
if (!mpath) {
- mesh_path_add(sdata, orig_addr);
- mpath = mesh_path_lookup(sdata, orig_addr);
- if (!mpath) {
+ mpath = mesh_path_add(sdata, orig_addr);
+ if (IS_ERR(mpath)) {
rcu_read_unlock();
sdata->u.mesh.mshstats.dropped_frames_no_route++;
return;
@@ -883,7 +880,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
- len - baselen, &elems);
+ len - baselen, false, &elems);
if (elems.preq) {
if (elems.preq_len != 37)
@@ -1098,11 +1095,10 @@ int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
/* no nexthop found, start resolving */
mpath = mesh_path_lookup(sdata, target_addr);
if (!mpath) {
- mesh_path_add(sdata, target_addr);
- mpath = mesh_path_lookup(sdata, target_addr);
- if (!mpath) {
+ mpath = mesh_path_add(sdata, target_addr);
+ if (IS_ERR(mpath)) {
mesh_path_discard_frame(sdata, skb);
- err = -ENOSPC;
+ err = PTR_ERR(mpath);
goto endlookup;
}
}
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index dc7c8df40c2c..89aacfd2756d 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -493,7 +493,8 @@ int mesh_gate_num(struct ieee80211_sub_if_data *sdata)
*
* State: the initial state of the new path is set to 0
*/
-int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
+struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
+ const u8 *dst)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = sdata->local;
@@ -502,18 +503,33 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
struct mpath_node *node, *new_node;
struct hlist_head *bucket;
int grow = 0;
- int err = 0;
+ int err;
u32 hash_idx;
if (ether_addr_equal(dst, sdata->vif.addr))
/* never add ourselves as neighbours */
- return -ENOTSUPP;
+ return ERR_PTR(-ENOTSUPP);
if (is_multicast_ether_addr(dst))
- return -ENOTSUPP;
+ return ERR_PTR(-ENOTSUPP);
if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0)
- return -ENOSPC;
+ return ERR_PTR(-ENOSPC);
+
+ read_lock_bh(&pathtbl_resize_lock);
+ tbl = resize_dereference_mesh_paths();
+
+ hash_idx = mesh_table_hash(dst, sdata, tbl);
+ bucket = &tbl->hash_buckets[hash_idx];
+
+ spin_lock(&tbl->hashwlock[hash_idx]);
+
+ hlist_for_each_entry(node, bucket, list) {
+ mpath = node->mpath;
+ if (mpath->sdata == sdata &&
+ ether_addr_equal(dst, mpath->dst))
+ goto found;
+ }
err = -ENOMEM;
new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
@@ -524,7 +540,6 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
if (!new_node)
goto err_node_alloc;
- read_lock_bh(&pathtbl_resize_lock);
memcpy(new_mpath->dst, dst, ETH_ALEN);
eth_broadcast_addr(new_mpath->rann_snd_addr);
new_mpath->is_root = false;
@@ -538,21 +553,6 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
spin_lock_init(&new_mpath->state_lock);
init_timer(&new_mpath->timer);
- tbl = resize_dereference_mesh_paths();
-
- hash_idx = mesh_table_hash(dst, sdata, tbl);
- bucket = &tbl->hash_buckets[hash_idx];
-
- spin_lock(&tbl->hashwlock[hash_idx]);
-
- err = -EEXIST;
- hlist_for_each_entry(node, bucket, list) {
- mpath = node->mpath;
- if (mpath->sdata == sdata &&
- ether_addr_equal(dst, mpath->dst))
- goto err_exists;
- }
-
hlist_add_head_rcu(&new_node->list, bucket);
if (atomic_inc_return(&tbl->entries) >=
tbl->mean_chain_len * (tbl->hash_mask + 1))
@@ -560,23 +560,23 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
mesh_paths_generation++;
- spin_unlock(&tbl->hashwlock[hash_idx]);
- read_unlock_bh(&pathtbl_resize_lock);
if (grow) {
set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
ieee80211_queue_work(&local->hw, &sdata->work);
}
- return 0;
-
-err_exists:
+ mpath = new_mpath;
+found:
spin_unlock(&tbl->hashwlock[hash_idx]);
read_unlock_bh(&pathtbl_resize_lock);
- kfree(new_node);
+ return mpath;
+
err_node_alloc:
kfree(new_mpath);
err_path_alloc:
atomic_dec(&sdata->u.mesh.mpaths);
- return err;
+ spin_unlock(&tbl->hashwlock[hash_idx]);
+ read_unlock_bh(&pathtbl_resize_lock);
+ return ERR_PTR(err);
}
static void mesh_table_free_rcu(struct rcu_head *rcu)
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 937e06fe8f2a..09bebed99416 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -544,8 +544,8 @@ static void mesh_plink_timer(unsigned long data)
return;
}
mpl_dbg(sta->sdata,
- "Mesh plink timer for %pM fired on state %d\n",
- sta->sta.addr, sta->plink_state);
+ "Mesh plink timer for %pM fired on state %s\n",
+ sta->sta.addr, mplstates[sta->plink_state]);
reason = 0;
llid = sta->llid;
plid = sta->plid;
@@ -687,7 +687,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
baseaddr += 4;
baselen += 4;
}
- ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
+ ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems);
if (!elems.peering) {
mpl_dbg(sdata,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index dec42ab1fa91..29620bfc7a69 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -56,7 +56,10 @@ MODULE_PARM_DESC(max_probe_tries,
* probe on beacon miss before declaring the connection lost
* default to what we want.
*/
-#define IEEE80211_BEACON_LOSS_COUNT 7
+static int beacon_loss_count = 7;
+module_param(beacon_loss_count, int, 0644);
+MODULE_PARM_DESC(beacon_loss_count,
+ "Number of beacon intervals before we decide beacon was lost.");
/*
* Time the connection can be idle before we probe
@@ -286,6 +289,8 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
} else {
/* 40 MHz (and 80 MHz) must be supported for VHT */
ret = IEEE80211_STA_DISABLE_VHT;
+ /* also mark 40 MHz disabled */
+ ret |= IEEE80211_STA_DISABLE_40MHZ;
goto out;
}
@@ -300,12 +305,6 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
channel->band);
vht_chandef.center_freq2 = 0;
- if (vht_oper->center_freq_seg2_idx)
- vht_chandef.center_freq2 =
- ieee80211_channel_to_frequency(
- vht_oper->center_freq_seg2_idx,
- channel->band);
-
switch (vht_oper->chan_width) {
case IEEE80211_VHT_CHANWIDTH_USE_HT:
vht_chandef.width = chandef->width;
@@ -318,6 +317,10 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
break;
case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
vht_chandef.width = NL80211_CHAN_WIDTH_80P80;
+ vht_chandef.center_freq2 =
+ ieee80211_channel_to_frequency(
+ vht_oper->center_freq_seg2_idx,
+ channel->band);
break;
default:
if (verbose)
@@ -601,7 +604,6 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
u8 *pos;
u32 cap;
struct ieee80211_sta_vht_cap vht_cap;
- int i;
BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap));
@@ -629,37 +631,6 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)))
cap &= ~IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
- if (!(ap_vht_cap->vht_cap_info &
- cpu_to_le32(IEEE80211_VHT_CAP_TXSTBC)))
- cap &= ~(IEEE80211_VHT_CAP_RXSTBC_1 |
- IEEE80211_VHT_CAP_RXSTBC_3 |
- IEEE80211_VHT_CAP_RXSTBC_4);
-
- for (i = 0; i < 8; i++) {
- int shift = i * 2;
- u16 mask = IEEE80211_VHT_MCS_NOT_SUPPORTED << shift;
- u16 ap_mcs, our_mcs;
-
- ap_mcs = (le16_to_cpu(ap_vht_cap->supp_mcs.tx_mcs_map) &
- mask) >> shift;
- our_mcs = (le16_to_cpu(vht_cap.vht_mcs.rx_mcs_map) &
- mask) >> shift;
-
- if (our_mcs == IEEE80211_VHT_MCS_NOT_SUPPORTED)
- continue;
-
- switch (ap_mcs) {
- default:
- if (our_mcs <= ap_mcs)
- break;
- /* fall through */
- case IEEE80211_VHT_MCS_NOT_SUPPORTED:
- vht_cap.vht_mcs.rx_mcs_map &= cpu_to_le16(~mask);
- vht_cap.vht_mcs.rx_mcs_map |=
- cpu_to_le16(ap_mcs << shift);
- }
- }
-
/* reserve and fill IE */
pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
ieee80211_ie_build_vht_cap(pos, &vht_cap, cap);
@@ -985,6 +956,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
{
struct ieee80211_sub_if_data *sdata =
container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work);
+ struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
if (!ieee80211_sdata_running(sdata))
@@ -994,21 +966,21 @@ static void ieee80211_chswitch_work(struct work_struct *work)
if (!ifmgd->associated)
goto out;
- sdata->local->_oper_channel = sdata->local->csa_channel;
- if (!sdata->local->ops->channel_switch) {
+ local->_oper_chandef = local->csa_chandef;
+
+ if (!local->ops->channel_switch) {
/* call "hw_config" only if doing sw channel switch */
- ieee80211_hw_config(sdata->local,
- IEEE80211_CONF_CHANGE_CHANNEL);
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
} else {
/* update the device channel directly */
- sdata->local->hw.conf.channel = sdata->local->_oper_channel;
+ local->hw.conf.chandef = local->_oper_chandef;
}
/* XXX: shouldn't really modify cfg80211-owned data! */
- ifmgd->associated->channel = sdata->local->_oper_channel;
+ ifmgd->associated->channel = local->_oper_chandef.chan;
/* XXX: wait for a beacon first? */
- ieee80211_wake_queues_by_reason(&sdata->local->hw,
+ ieee80211_wake_queues_by_reason(&local->hw,
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_CSA);
out:
@@ -1041,56 +1013,193 @@ static void ieee80211_chswitch_timer(unsigned long data)
ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work);
}
-void
+static void
ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
- const struct ieee80211_channel_sw_ie *sw_elem,
- struct ieee80211_bss *bss, u64 timestamp)
+ u64 timestamp, struct ieee802_11_elems *elems)
{
- struct cfg80211_bss *cbss =
- container_of((void *)bss, struct cfg80211_bss, priv);
- struct ieee80211_channel *new_ch;
+ struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num,
- cbss->channel->band);
+ struct cfg80211_bss *cbss = ifmgd->associated;
+ struct ieee80211_bss *bss;
struct ieee80211_chanctx *chanctx;
+ enum ieee80211_band new_band;
+ int new_freq;
+ u8 new_chan_no;
+ u8 count;
+ u8 mode;
+ struct ieee80211_channel *new_chan;
+ struct cfg80211_chan_def new_chandef = {};
+ struct cfg80211_chan_def new_vht_chandef = {};
+ const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
+ const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
+ int secondary_channel_offset = -1;
ASSERT_MGD_MTX(ifmgd);
- if (!ifmgd->associated)
+ if (!cbss)
return;
- if (sdata->local->scanning)
+ if (local->scanning)
return;
- /* Disregard subsequent beacons if we are already running a timer
- processing a CSA */
-
+ /* disregard subsequent announcements if we are already processing */
if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED)
return;
- new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq);
- if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) {
+ sec_chan_offs = elems->sec_chan_offs;
+ wide_bw_chansw_ie = elems->wide_bw_chansw_ie;
+
+ if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT |
+ IEEE80211_STA_DISABLE_40MHZ)) {
+ sec_chan_offs = NULL;
+ wide_bw_chansw_ie = NULL;
+ }
+
+ if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT)
+ wide_bw_chansw_ie = NULL;
+
+ if (elems->ext_chansw_ie) {
+ if (!ieee80211_operating_class_to_band(
+ elems->ext_chansw_ie->new_operating_class,
+ &new_band)) {
+ sdata_info(sdata,
+ "cannot understand ECSA IE operating class %d, disconnecting\n",
+ elems->ext_chansw_ie->new_operating_class);
+ ieee80211_queue_work(&local->hw,
+ &ifmgd->csa_connection_drop_work);
+ }
+ new_chan_no = elems->ext_chansw_ie->new_ch_num;
+ count = elems->ext_chansw_ie->count;
+ mode = elems->ext_chansw_ie->mode;
+ } else if (elems->ch_switch_ie) {
+ new_band = cbss->channel->band;
+ new_chan_no = elems->ch_switch_ie->new_ch_num;
+ count = elems->ch_switch_ie->count;
+ mode = elems->ch_switch_ie->mode;
+ } else {
+ /* nothing here we understand */
+ return;
+ }
+
+ bss = (void *)cbss->priv;
+
+ new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band);
+ new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq);
+ if (!new_chan || new_chan->flags & IEEE80211_CHAN_DISABLED) {
sdata_info(sdata,
"AP %pM switches to unsupported channel (%d MHz), disconnecting\n",
ifmgd->associated->bssid, new_freq);
- ieee80211_queue_work(&sdata->local->hw,
+ ieee80211_queue_work(&local->hw,
+ &ifmgd->csa_connection_drop_work);
+ return;
+ }
+
+ if (sec_chan_offs) {
+ secondary_channel_offset = sec_chan_offs->sec_chan_offs;
+ } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
+ /* if HT is enabled and the IE not present, it's still HT */
+ secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ }
+
+ switch (secondary_channel_offset) {
+ default:
+ /* secondary_channel_offset was present but is invalid */
+ case IEEE80211_HT_PARAM_CHA_SEC_NONE:
+ cfg80211_chandef_create(&new_chandef, new_chan,
+ NL80211_CHAN_HT20);
+ break;
+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+ cfg80211_chandef_create(&new_chandef, new_chan,
+ NL80211_CHAN_HT40PLUS);
+ break;
+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+ cfg80211_chandef_create(&new_chandef, new_chan,
+ NL80211_CHAN_HT40MINUS);
+ break;
+ case -1:
+ cfg80211_chandef_create(&new_chandef, new_chan,
+ NL80211_CHAN_NO_HT);
+ break;
+ }
+
+ if (wide_bw_chansw_ie) {
+ new_vht_chandef.chan = new_chan;
+ new_vht_chandef.center_freq1 =
+ ieee80211_channel_to_frequency(
+ wide_bw_chansw_ie->new_center_freq_seg0,
+ new_band);
+
+ switch (wide_bw_chansw_ie->new_channel_width) {
+ default:
+ /* hmmm, ignore VHT and use HT if present */
+ case IEEE80211_VHT_CHANWIDTH_USE_HT:
+ new_vht_chandef.chan = NULL;
+ break;
+ case IEEE80211_VHT_CHANWIDTH_80MHZ:
+ new_vht_chandef.width = NL80211_CHAN_WIDTH_80;
+ break;
+ case IEEE80211_VHT_CHANWIDTH_160MHZ:
+ new_vht_chandef.width = NL80211_CHAN_WIDTH_160;
+ break;
+ case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
+ /* field is otherwise reserved */
+ new_vht_chandef.center_freq2 =
+ ieee80211_channel_to_frequency(
+ wide_bw_chansw_ie->new_center_freq_seg1,
+ new_band);
+ new_vht_chandef.width = NL80211_CHAN_WIDTH_80P80;
+ break;
+ }
+ if (ifmgd->flags & IEEE80211_STA_DISABLE_80P80MHZ &&
+ new_vht_chandef.width == NL80211_CHAN_WIDTH_80P80)
+ chandef_downgrade(&new_vht_chandef);
+ if (ifmgd->flags & IEEE80211_STA_DISABLE_160MHZ &&
+ new_vht_chandef.width == NL80211_CHAN_WIDTH_160)
+ chandef_downgrade(&new_vht_chandef);
+ if (ifmgd->flags & IEEE80211_STA_DISABLE_40MHZ &&
+ new_vht_chandef.width > NL80211_CHAN_WIDTH_20)
+ chandef_downgrade(&new_vht_chandef);
+ }
+
+ /* if VHT data is there validate & use it */
+ if (new_vht_chandef.chan) {
+ if (!cfg80211_chandef_compatible(&new_vht_chandef,
+ &new_chandef)) {
+ sdata_info(sdata,
+ "AP %pM CSA has inconsistent channel data, disconnecting\n",
+ ifmgd->associated->bssid);
+ ieee80211_queue_work(&local->hw,
+ &ifmgd->csa_connection_drop_work);
+ return;
+ }
+ new_chandef = new_vht_chandef;
+ }
+
+ if (!cfg80211_chandef_usable(local->hw.wiphy, &new_chandef,
+ IEEE80211_CHAN_DISABLED)) {
+ sdata_info(sdata,
+ "AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
+ ifmgd->associated->bssid, new_freq,
+ new_chandef.width, new_chandef.center_freq1,
+ new_chandef.center_freq2);
+ ieee80211_queue_work(&local->hw,
&ifmgd->csa_connection_drop_work);
return;
}
ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
- if (sdata->local->use_chanctx) {
+ if (local->use_chanctx) {
sdata_info(sdata,
"not handling channel switch with channel contexts\n");
- ieee80211_queue_work(&sdata->local->hw,
+ ieee80211_queue_work(&local->hw,
&ifmgd->csa_connection_drop_work);
return;
}
- mutex_lock(&sdata->local->chanctx_mtx);
+ mutex_lock(&local->chanctx_mtx);
if (WARN_ON(!rcu_access_pointer(sdata->vif.chanctx_conf))) {
- mutex_unlock(&sdata->local->chanctx_mtx);
+ mutex_unlock(&local->chanctx_mtx);
return;
}
chanctx = container_of(rcu_access_pointer(sdata->vif.chanctx_conf),
@@ -1098,40 +1207,39 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
if (chanctx->refcount > 1) {
sdata_info(sdata,
"channel switch with multiple interfaces on the same channel, disconnecting\n");
- ieee80211_queue_work(&sdata->local->hw,
+ ieee80211_queue_work(&local->hw,
&ifmgd->csa_connection_drop_work);
- mutex_unlock(&sdata->local->chanctx_mtx);
+ mutex_unlock(&local->chanctx_mtx);
return;
}
- mutex_unlock(&sdata->local->chanctx_mtx);
+ mutex_unlock(&local->chanctx_mtx);
- sdata->local->csa_channel = new_ch;
+ local->csa_chandef = new_chandef;
- if (sw_elem->mode)
- ieee80211_stop_queues_by_reason(&sdata->local->hw,
+ if (mode)
+ ieee80211_stop_queues_by_reason(&local->hw,
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_CSA);
- if (sdata->local->ops->channel_switch) {
+ if (local->ops->channel_switch) {
/* use driver's channel switch callback */
struct ieee80211_channel_switch ch_switch = {
.timestamp = timestamp,
- .block_tx = sw_elem->mode,
- .channel = new_ch,
- .count = sw_elem->count,
+ .block_tx = mode,
+ .chandef = new_chandef,
+ .count = count,
};
- drv_channel_switch(sdata->local, &ch_switch);
+ drv_channel_switch(local, &ch_switch);
return;
}
/* channel switch handled in software */
- if (sw_elem->count <= 1)
- ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
+ if (count <= 1)
+ ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work);
else
mod_timer(&ifmgd->chswitch_timer,
- TU_TO_EXP_TIME(sw_elem->count *
- cbss->beacon_interval));
+ TU_TO_EXP_TIME(count * cbss->beacon_interval));
}
static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
@@ -1430,13 +1538,11 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
- netif_tx_stop_all_queues(sdata->dev);
-
- if (drv_tx_frames_pending(local))
+ if (drv_tx_frames_pending(local)) {
mod_timer(&local->dynamic_ps_timer, jiffies +
msecs_to_jiffies(
local->hw.conf.dynamic_ps_timeout));
- else {
+ } else {
ieee80211_send_nullfunc(local, sdata, 1);
/* Flush to get the tx status of nullfunc frame */
ieee80211_flush_queues(local, sdata);
@@ -1450,9 +1556,6 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
local->hw.conf.flags |= IEEE80211_CONF_PS;
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
}
-
- if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
- netif_tx_wake_all_queues(sdata->dev);
}
void ieee80211_dynamic_ps_timer(unsigned long data)
@@ -1558,6 +1661,7 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
params.cw_min = ecw2cw(pos[1] & 0x0f);
params.txop = get_unaligned_le16(pos + 2);
+ params.acm = acm;
params.uapsd = uapsd;
mlme_dbg(sdata,
@@ -1645,7 +1749,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
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));
+ beacon_loss_count * bss_conf->beacon_int));
sdata->u.mgd.associated = cbss;
memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN);
@@ -1658,18 +1762,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
rcu_read_lock();
ies = rcu_dereference(cbss->ies);
if (ies) {
- u8 noa[2];
int ret;
ret = cfg80211_get_p2p_attr(
ies->data, ies->len,
IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
- noa, sizeof(noa));
+ (u8 *) &bss_conf->p2p_noa_attr,
+ sizeof(bss_conf->p2p_noa_attr));
if (ret >= 2) {
- bss_conf->p2p_oppps = noa[1] & 0x80;
- bss_conf->p2p_ctwindow = noa[1] & 0x7f;
+ sdata->u.mgd.p2p_noa_index =
+ bss_conf->p2p_noa_attr.index;
bss_info_changed |= BSS_CHANGED_P2P_PS;
- sdata->u.mgd.p2p_noa_index = noa[0];
}
}
rcu_read_unlock();
@@ -1713,7 +1816,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
ieee80211_recalc_smps(sdata);
ieee80211_recalc_ps_vif(sdata);
- netif_tx_start_all_queues(sdata->dev);
netif_carrier_on(sdata->dev);
}
@@ -1736,22 +1838,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
ieee80211_stop_poll(sdata);
ifmgd->associated = NULL;
-
- /*
- * we need to commit the associated = NULL change because the
- * scan code uses that to determine whether this iface should
- * go to/wake up from powersave or not -- and could otherwise
- * wake the queues erroneously.
- */
- smp_mb();
-
- /*
- * Thus, we can only afterwards stop the queues -- to account
- * for the case where another CPU is finishing a scan at this
- * time -- we don't want the scan code to enable queues.
- */
-
- netif_tx_stop_all_queues(sdata->dev);
netif_carrier_off(sdata->dev);
/*
@@ -1794,8 +1880,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_ASSOC;
sdata->vif.bss_conf.assoc = false;
- sdata->vif.bss_conf.p2p_ctwindow = 0;
- sdata->vif.bss_conf.p2p_oppps = false;
+ ifmgd->p2p_noa_index = -1;
+ memset(&sdata->vif.bss_conf.p2p_noa_attr, 0,
+ sizeof(sdata->vif.bss_conf.p2p_noa_attr));
/* on the next assoc, re-program HT/VHT parameters */
memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
@@ -1975,12 +2062,15 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
goto out;
}
- if (beacon)
+ if (beacon) {
mlme_dbg_ratelimited(sdata,
- "detected beacon loss from AP - probing\n");
+ "detected beacon loss from AP (missed %d beacons) - probing\n",
+ beacon_loss_count);
- ieee80211_cqm_rssi_notify(&sdata->vif,
- NL80211_CQM_RSSI_BEACON_LOSS_EVENT, GFP_KERNEL);
+ ieee80211_cqm_rssi_notify(&sdata->vif,
+ NL80211_CQM_RSSI_BEACON_LOSS_EVENT,
+ GFP_KERNEL);
+ }
/*
* The driver/our work has already reported this event or the
@@ -2126,7 +2216,6 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif)
trace_api_beacon_loss(sdata);
- WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR);
sdata->u.mgd.connection_loss = false;
ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
}
@@ -2176,7 +2265,7 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
u32 tx_flags = 0;
pos = mgmt->u.auth.variable;
- ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
+ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems);
if (!elems.challenge)
return;
auth_data->expected_transaction = 4;
@@ -2441,7 +2530,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
}
pos = mgmt->u.assoc_resp.variable;
- ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
+ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems);
if (!elems.supp_rates) {
sdata_info(sdata, "no SuppRates element in AssocResp\n");
@@ -2610,13 +2699,13 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
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);
+ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems);
if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
- elems.timeout_int && elems.timeout_int_len == 5 &&
- elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
+ elems.timeout_int &&
+ elems.timeout_int->type == WLAN_TIMEOUT_ASSOC_COMEBACK) {
u32 tu, ms;
- tu = get_unaligned_le32(elems.timeout_int + 1);
+ tu = le32_to_cpu(elems.timeout_int->value);
ms = tu * 1024 / 1000;
sdata_info(sdata,
"%pM rejected association temporarily; comeback duration %u TU (%u ms)\n",
@@ -2665,6 +2754,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *channel;
bool need_ps = false;
+ lockdep_assert_held(&sdata->u.mgd.mtx);
+
if ((sdata->u.mgd.associated &&
ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) ||
(sdata->u.mgd.assoc_data &&
@@ -2679,7 +2770,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
}
}
- if (elems->ds_params && elems->ds_params_len == 1)
+ if (elems->ds_params)
freq = ieee80211_channel_to_frequency(elems->ds_params[0],
rx_status->band);
else
@@ -2695,7 +2786,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
if (bss)
ieee80211_rx_bss_put(local, bss);
- if (!sdata->u.mgd.associated)
+ if (!sdata->u.mgd.associated ||
+ !ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid))
return;
if (need_ps) {
@@ -2704,10 +2796,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
mutex_unlock(&local->iflist_mtx);
}
- if (elems->ch_switch_ie &&
- memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, ETH_ALEN) == 0)
- ieee80211_sta_process_chanswitch(sdata, elems->ch_switch_ie,
- bss, rx_status->mactime);
+ ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, elems);
+
}
@@ -2732,7 +2822,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
return;
ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
- &elems);
+ false, &elems);
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
@@ -2815,7 +2905,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
ieee802_11_parse_elems(mgmt->u.beacon.variable,
- len - baselen, &elems);
+ len - baselen, false, &elems);
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
ifmgd->assoc_data->have_beacon = true;
@@ -2925,7 +3015,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable,
- len - baselen, &elems,
+ len - baselen, false, &elems,
care_about_ies, ncrc);
if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) {
@@ -2957,22 +3047,30 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
}
if (sdata->vif.p2p) {
- u8 noa[2];
+ struct ieee80211_p2p_noa_attr noa = {};
int ret;
ret = cfg80211_get_p2p_attr(mgmt->u.beacon.variable,
len - baselen,
IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
- noa, sizeof(noa));
- if (ret >= 2 && sdata->u.mgd.p2p_noa_index != noa[0]) {
- bss_conf->p2p_oppps = noa[1] & 0x80;
- bss_conf->p2p_ctwindow = noa[1] & 0x7f;
+ (u8 *) &noa, sizeof(noa));
+ if (ret >= 2) {
+ if (sdata->u.mgd.p2p_noa_index != noa.index) {
+ /* valid noa_attr and index changed */
+ sdata->u.mgd.p2p_noa_index = noa.index;
+ memcpy(&bss_conf->p2p_noa_attr, &noa, sizeof(noa));
+ changed |= BSS_CHANGED_P2P_PS;
+ /*
+ * make sure we update all information, the CRC
+ * mechanism doesn't look at P2P attributes.
+ */
+ ifmgd->beacon_crc_valid = false;
+ }
+ } else if (sdata->u.mgd.p2p_noa_index != -1) {
+ /* noa_attr not found and we had valid noa_attr before */
+ sdata->u.mgd.p2p_noa_index = -1;
+ memset(&bss_conf->p2p_noa_attr, 0, sizeof(bss_conf->p2p_noa_attr));
changed |= BSS_CHANGED_P2P_PS;
- sdata->u.mgd.p2p_noa_index = noa[0];
- /*
- * make sure we update all information, the CRC
- * mechanism doesn't look at P2P attributes.
- */
ifmgd->beacon_crc_valid = false;
}
}
@@ -3014,7 +3112,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_DTIM_PERIOD;
}
- if (elems.erp_info && elems.erp_info_len >= 1) {
+ if (elems.erp_info) {
erp_valid = true;
erp_value = elems.erp_info[0];
} else {
@@ -3064,6 +3162,8 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
enum rx_mgmt_action rma = RX_MGMT_NONE;
u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
u16 fc;
+ struct ieee802_11_elems elems;
+ int ies_len;
rx_status = (struct ieee80211_rx_status *) skb->cb;
mgmt = (struct ieee80211_mgmt *) skb->data;
@@ -3093,14 +3193,48 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
rma = ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, &bss);
break;
case IEEE80211_STYPE_ACTION:
- switch (mgmt->u.action.category) {
- case WLAN_CATEGORY_SPECTRUM_MGMT:
+ if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {
+ ies_len = skb->len -
+ offsetof(struct ieee80211_mgmt,
+ u.action.u.chan_switch.variable);
+
+ if (ies_len < 0)
+ break;
+
+ ieee802_11_parse_elems(
+ mgmt->u.action.u.chan_switch.variable,
+ ies_len, true, &elems);
+
+ if (elems.parse_error)
+ break;
+
ieee80211_sta_process_chanswitch(sdata,
- &mgmt->u.action.u.chan_switch.sw_elem,
- (void *)ifmgd->associated->priv,
- rx_status->mactime);
- break;
+ rx_status->mactime,
+ &elems);
+ } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
+ ies_len = skb->len -
+ offsetof(struct ieee80211_mgmt,
+ u.action.u.ext_chan_switch.variable);
+
+ if (ies_len < 0)
+ break;
+
+ ieee802_11_parse_elems(
+ mgmt->u.action.u.ext_chan_switch.variable,
+ ies_len, true, &elems);
+
+ if (elems.parse_error)
+ break;
+
+ /* for the handling code pretend this was also an IE */
+ elems.ext_chansw_ie =
+ &mgmt->u.action.u.ext_chan_switch.data;
+
+ ieee80211_sta_process_chanswitch(sdata,
+ rx_status->mactime,
+ &elems);
}
+ break;
}
mutex_unlock(&ifmgd->mtx);
@@ -3513,8 +3647,9 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
ifmgd->flags = 0;
ifmgd->powersave = sdata->wdev.ps;
- ifmgd->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
- ifmgd->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
+ ifmgd->uapsd_queues = sdata->local->hw.uapsd_queues;
+ ifmgd->uapsd_max_sp_len = sdata->local->hw.uapsd_max_sp_len;
+ ifmgd->p2p_noa_index = -1;
mutex_init(&ifmgd->mtx);
@@ -4079,7 +4214,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
rcu_read_unlock();
if (bss->wmm_used && bss->uapsd_supported &&
- (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
+ (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) &&
+ sdata->wmm_acm != 0xff) {
assoc_data->uapsd = true;
ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
} else {
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index cce795871ab1..acd1f71adc03 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -445,15 +445,15 @@ void ieee80211_roc_setup(struct ieee80211_local *local)
INIT_LIST_HEAD(&local->roc_list);
}
-void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata)
+void ieee80211_roc_purge(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata)
{
- struct ieee80211_local *local = sdata->local;
struct ieee80211_roc_work *roc, *tmp;
LIST_HEAD(tmp_list);
mutex_lock(&local->mtx);
list_for_each_entry_safe(roc, tmp, &local->roc_list, list) {
- if (roc->sdata != sdata)
+ if (sdata && roc->sdata != sdata)
continue;
if (roc->started && local->ops->remain_on_channel) {
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 3d16f4e61743..7fc5d0d8149a 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -19,6 +19,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
ieee80211_dfs_cac_cancel(local);
+ ieee80211_roc_purge(local, NULL);
+
+ ieee80211_del_virtual_monitor(local);
+
if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
mutex_lock(&local->sta_mtx);
list_for_each_entry(sta, &local->sta_list, list) {
@@ -33,8 +37,9 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
- /* flush out all packets */
+ /* flush out all packets and station cleanup call_rcu()s */
synchronize_net();
+ rcu_barrier();
ieee80211_flush_queues(local, NULL);
@@ -101,10 +106,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
drv_remove_interface(local, sdata);
}
- sdata = rtnl_dereference(local->monitor_sdata);
- if (sdata)
- drv_remove_interface(local, sdata);
-
/*
* We disconnected on all interfaces before suspend, all channel
* contexts should be released.
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index dd88381c53b7..0d51877efdb7 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -252,6 +252,25 @@ rate_lowest_non_cck_index(struct ieee80211_supported_band *sband,
return 0;
}
+static void __rate_control_send_low(struct ieee80211_hw *hw,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta,
+ struct ieee80211_tx_info *info)
+{
+ if ((sband->band != IEEE80211_BAND_2GHZ) ||
+ !(info->flags & IEEE80211_TX_CTL_NO_CCK_RATE))
+ info->control.rates[0].idx = rate_lowest_index(sband, sta);
+ else
+ info->control.rates[0].idx =
+ rate_lowest_non_cck_index(sband, sta);
+
+ info->control.rates[0].count =
+ (info->flags & IEEE80211_TX_CTL_NO_ACK) ?
+ 1 : hw->max_rate_tries;
+
+ info->control.skip_table = 1;
+}
+
bool rate_control_send_low(struct ieee80211_sta *sta,
void *priv_sta,
@@ -262,16 +281,8 @@ bool rate_control_send_low(struct ieee80211_sta *sta,
int mcast_rate;
if (!sta || !priv_sta || rc_no_data_or_no_ack_use_min(txrc)) {
- if ((sband->band != IEEE80211_BAND_2GHZ) ||
- !(info->flags & IEEE80211_TX_CTL_NO_CCK_RATE))
- info->control.rates[0].idx =
- rate_lowest_index(txrc->sband, sta);
- else
- info->control.rates[0].idx =
- rate_lowest_non_cck_index(txrc->sband, sta);
- info->control.rates[0].count =
- (info->flags & IEEE80211_TX_CTL_NO_ACK) ?
- 1 : txrc->hw->max_rate_tries;
+ __rate_control_send_low(txrc->hw, sband, sta, info);
+
if (!sta && txrc->bss) {
mcast_rate = txrc->bss_conf->mcast_rate[sband->band];
if (mcast_rate > 0) {
@@ -355,7 +366,8 @@ static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate,
static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
- struct ieee80211_tx_rate_control *txrc,
+ struct ieee80211_supported_band *sband,
+ enum nl80211_chan_width chan_width,
u32 mask,
u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
{
@@ -375,27 +387,17 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
alt_rate.count = rate->count;
if (rate_idx_match_legacy_mask(&alt_rate,
- txrc->sband->n_bitrates,
- mask)) {
+ sband->n_bitrates, mask)) {
*rate = alt_rate;
return;
}
} else {
- struct sk_buff *skb = txrc->skb;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- __le16 fc;
-
/* handle legacy rates */
- if (rate_idx_match_legacy_mask(rate, txrc->sband->n_bitrates,
- mask))
+ if (rate_idx_match_legacy_mask(rate, sband->n_bitrates, mask))
return;
/* if HT BSS, and we handle a data frame, also try HT rates */
- if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
- return;
-
- fc = hdr->frame_control;
- if (!ieee80211_is_data(fc))
+ if (chan_width == NL80211_CHAN_WIDTH_20_NOHT)
return;
alt_rate.idx = 0;
@@ -408,7 +410,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
alt_rate.flags |= IEEE80211_TX_RC_MCS;
- if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_40)
+ if (chan_width == NL80211_CHAN_WIDTH_40)
alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) {
@@ -426,6 +428,228 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
*/
}
+static void rate_fixup_ratelist(struct ieee80211_vif *vif,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_tx_rate *rates,
+ int max_rates)
+{
+ struct ieee80211_rate *rate;
+ bool inval = false;
+ int i;
+
+ /*
+ * Set up the RTS/CTS rate as the fastest basic rate
+ * that is not faster than the data rate unless there
+ * is no basic rate slower than the data rate, in which
+ * case we pick the slowest basic rate
+ *
+ * XXX: Should this check all retry rates?
+ */
+ if (!(rates[0].flags & IEEE80211_TX_RC_MCS)) {
+ u32 basic_rates = vif->bss_conf.basic_rates;
+ s8 baserate = basic_rates ? ffs(basic_rates - 1) : 0;
+
+ rate = &sband->bitrates[rates[0].idx];
+
+ for (i = 0; i < sband->n_bitrates; i++) {
+ /* must be a basic rate */
+ if (!(basic_rates & BIT(i)))
+ continue;
+ /* must not be faster than the data rate */
+ if (sband->bitrates[i].bitrate > rate->bitrate)
+ continue;
+ /* maximum */
+ if (sband->bitrates[baserate].bitrate <
+ sband->bitrates[i].bitrate)
+ baserate = i;
+ }
+
+ info->control.rts_cts_rate_idx = baserate;
+ }
+
+ for (i = 0; i < max_rates; i++) {
+ /*
+ * make sure there's no valid rate following
+ * an invalid one, just in case drivers don't
+ * take the API seriously to stop at -1.
+ */
+ if (inval) {
+ rates[i].idx = -1;
+ continue;
+ }
+ if (rates[i].idx < 0) {
+ inval = true;
+ continue;
+ }
+
+ /*
+ * For now assume MCS is already set up correctly, this
+ * needs to be fixed.
+ */
+ if (rates[i].flags & IEEE80211_TX_RC_MCS) {
+ WARN_ON(rates[i].idx > 76);
+
+ if (!(rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) &&
+ info->control.use_cts_prot)
+ rates[i].flags |=
+ IEEE80211_TX_RC_USE_CTS_PROTECT;
+ continue;
+ }
+
+ if (rates[i].flags & IEEE80211_TX_RC_VHT_MCS) {
+ WARN_ON(ieee80211_rate_get_vht_mcs(&rates[i]) > 9);
+ continue;
+ }
+
+ /* set up RTS protection if desired */
+ if (info->control.use_rts) {
+ rates[i].flags |= IEEE80211_TX_RC_USE_RTS_CTS;
+ info->control.use_cts_prot = false;
+ }
+
+ /* RC is busted */
+ if (WARN_ON_ONCE(rates[i].idx >= sband->n_bitrates)) {
+ rates[i].idx = -1;
+ continue;
+ }
+
+ rate = &sband->bitrates[rates[i].idx];
+
+ /* set up short preamble */
+ if (info->control.short_preamble &&
+ rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
+ rates[i].flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
+
+ /* set up G protection */
+ if (!(rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) &&
+ info->control.use_cts_prot &&
+ rate->flags & IEEE80211_RATE_ERP_G)
+ rates[i].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT;
+ }
+}
+
+
+static void rate_control_fill_sta_table(struct ieee80211_sta *sta,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_tx_rate *rates,
+ int max_rates)
+{
+ struct ieee80211_sta_rates *ratetbl = NULL;
+ int i;
+
+ if (sta && !info->control.skip_table)
+ ratetbl = rcu_dereference(sta->rates);
+
+ /* Fill remaining rate slots with data from the sta rate table. */
+ max_rates = min_t(int, max_rates, IEEE80211_TX_RATE_TABLE_SIZE);
+ for (i = 0; i < max_rates; i++) {
+ if (i < ARRAY_SIZE(info->control.rates) &&
+ info->control.rates[i].idx >= 0 &&
+ info->control.rates[i].count) {
+ if (rates != info->control.rates)
+ rates[i] = info->control.rates[i];
+ } else if (ratetbl) {
+ rates[i].idx = ratetbl->rate[i].idx;
+ rates[i].flags = ratetbl->rate[i].flags;
+ if (info->control.use_rts)
+ rates[i].count = ratetbl->rate[i].count_rts;
+ else if (info->control.use_cts_prot)
+ rates[i].count = ratetbl->rate[i].count_cts;
+ else
+ rates[i].count = ratetbl->rate[i].count;
+ } else {
+ rates[i].idx = -1;
+ rates[i].count = 0;
+ }
+
+ if (rates[i].idx < 0 || !rates[i].count)
+ break;
+ }
+}
+
+static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta *sta,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_tx_rate *rates,
+ int max_rates)
+{
+ enum nl80211_chan_width chan_width;
+ u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN];
+ bool has_mcs_mask;
+ u32 mask;
+ int i;
+
+ /*
+ * Try to enforce the rateidx mask the user wanted. skip this if the
+ * default mask (allow all rates) is used to save some processing for
+ * the common case.
+ */
+ mask = sdata->rc_rateidx_mask[info->band];
+ has_mcs_mask = sdata->rc_has_mcs_mask[info->band];
+ if (mask == (1 << sband->n_bitrates) - 1 && !has_mcs_mask)
+ return;
+
+ if (has_mcs_mask)
+ memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[info->band],
+ sizeof(mcs_mask));
+ else
+ memset(mcs_mask, 0xff, sizeof(mcs_mask));
+
+ if (sta) {
+ /* Filter out rates that the STA does not support */
+ mask &= sta->supp_rates[info->band];
+ for (i = 0; i < sizeof(mcs_mask); i++)
+ mcs_mask[i] &= sta->ht_cap.mcs.rx_mask[i];
+ }
+
+ /*
+ * Make sure the rate index selected for each TX rate is
+ * included in the configured mask and change the rate indexes
+ * if needed.
+ */
+ chan_width = sdata->vif.bss_conf.chandef.width;
+ for (i = 0; i < max_rates; i++) {
+ /* Skip invalid rates */
+ if (rates[i].idx < 0)
+ break;
+
+ rate_idx_match_mask(&rates[i], sband, mask, chan_width,
+ mcs_mask);
+ }
+}
+
+void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct sk_buff *skb,
+ struct ieee80211_tx_rate *dest,
+ int max_rates)
+{
+ struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_supported_band *sband;
+
+ rate_control_fill_sta_table(sta, info, dest, max_rates);
+
+ if (!vif)
+ return;
+
+ sdata = vif_to_sdata(vif);
+ sband = sdata->local->hw.wiphy->bands[info->band];
+
+ if (ieee80211_is_data(hdr->frame_control))
+ rate_control_apply_mask(sdata, sta, sband, info, dest, max_rates);
+
+ if (dest[0].idx < 0)
+ __rate_control_send_low(&sdata->local->hw, sband, sta, info);
+
+ if (sta)
+ rate_fixup_ratelist(vif, sband, info, dest, max_rates);
+}
+EXPORT_SYMBOL(ieee80211_get_tx_rates);
+
void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta,
struct ieee80211_tx_rate_control *txrc)
@@ -435,8 +659,6 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta *ista = NULL;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
int i;
- u32 mask;
- u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN];
if (sta && test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) {
ista = &sta->sta;
@@ -454,37 +676,27 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
ref->ops->get_rate(ref->priv, ista, priv_sta, txrc);
- /*
- * Try to enforce the rateidx mask the user wanted. skip this if the
- * default mask (allow all rates) is used to save some processing for
- * the common case.
- */
- mask = sdata->rc_rateidx_mask[info->band];
- memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[info->band],
- sizeof(mcs_mask));
- if (mask != (1 << txrc->sband->n_bitrates) - 1) {
- if (sta) {
- /* Filter out rates that the STA does not support */
- mask &= sta->sta.supp_rates[info->band];
- for (i = 0; i < sizeof(mcs_mask); i++)
- mcs_mask[i] &= sta->sta.ht_cap.mcs.rx_mask[i];
- }
- /*
- * Make sure the rate index selected for each TX rate is
- * included in the configured mask and change the rate indexes
- * if needed.
- */
- for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
- /* Skip invalid rates */
- if (info->control.rates[i].idx < 0)
- break;
- rate_idx_match_mask(&info->control.rates[i], txrc,
- mask, mcs_mask);
- }
- }
+ if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_RC_TABLE)
+ return;
+
+ ieee80211_get_tx_rates(&sdata->vif, ista, txrc->skb,
+ info->control.rates,
+ ARRAY_SIZE(info->control.rates));
+}
- BUG_ON(info->control.rates[0].idx < 0);
+int rate_control_set_rates(struct ieee80211_hw *hw,
+ struct ieee80211_sta *pubsta,
+ struct ieee80211_sta_rates *rates)
+{
+ struct ieee80211_sta_rates *old = rcu_dereference(pubsta->rates);
+
+ rcu_assign_pointer(pubsta->rates, rates);
+ if (old)
+ kfree_rcu(old, rcu_head);
+
+ return 0;
}
+EXPORT_SYMBOL(rate_control_set_rates);
int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
const char *name)
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 1c36c9b4fa4a..ac7ef5414bde 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -84,6 +84,50 @@ minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
}
static void
+minstrel_set_rate(struct minstrel_sta_info *mi, struct ieee80211_sta_rates *ratetbl,
+ int offset, int idx)
+{
+ struct minstrel_rate *r = &mi->r[idx];
+
+ ratetbl->rate[offset].idx = r->rix;
+ ratetbl->rate[offset].count = r->adjusted_retry_count;
+ ratetbl->rate[offset].count_cts = r->retry_count_cts;
+ ratetbl->rate[offset].count_rts = r->retry_count_rtscts;
+}
+
+static void
+minstrel_update_rates(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
+{
+ struct ieee80211_sta_rates *ratetbl;
+ int i = 0;
+
+ ratetbl = kzalloc(sizeof(*ratetbl), GFP_ATOMIC);
+ if (!ratetbl)
+ return;
+
+ /* Start with max_tp_rate */
+ minstrel_set_rate(mi, ratetbl, i++, mi->max_tp_rate[0]);
+
+ if (mp->hw->max_rates >= 3) {
+ /* At least 3 tx rates supported, use max_tp_rate2 next */
+ minstrel_set_rate(mi, ratetbl, i++, mi->max_tp_rate[1]);
+ }
+
+ if (mp->hw->max_rates >= 2) {
+ /* At least 2 tx rates supported, use max_prob_rate next */
+ minstrel_set_rate(mi, ratetbl, i++, mi->max_prob_rate);
+ }
+
+ /* Use lowest rate last */
+ ratetbl->rate[i].idx = mi->lowest_rix;
+ ratetbl->rate[i].count = mp->max_retry;
+ ratetbl->rate[i].count_cts = mp->max_retry;
+ ratetbl->rate[i].count_rts = mp->max_retry;
+
+ rate_control_set_rates(mp->hw, mi->sta, ratetbl);
+}
+
+static void
minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
{
u8 tmp_tp_rate[MAX_THR_RATES];
@@ -161,6 +205,8 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
/* Reset update timer */
mi->stats_update = jiffies;
+
+ minstrel_update_rates(mp, mi);
}
static void
@@ -209,9 +255,9 @@ minstrel_get_retry_count(struct minstrel_rate *mr,
{
unsigned int retry = mr->adjusted_retry_count;
- if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+ if (info->control.use_rts)
retry = max(2U, min(mr->retry_count_rtscts, retry));
- else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
+ else if (info->control.use_cts_prot)
retry = max(2U, min(mr->retry_count_cts, retry));
return retry;
}
@@ -240,13 +286,12 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct minstrel_sta_info *mi = priv_sta;
struct minstrel_priv *mp = priv;
- struct ieee80211_tx_rate *ar = info->control.rates;
- unsigned int ndx, sample_ndx = 0;
+ struct ieee80211_tx_rate *rate = &info->control.rates[0];
+ struct minstrel_rate *msr, *mr;
+ unsigned int ndx;
bool mrr_capable;
- bool indirect_rate_sampling = false;
- bool rate_sampling = false;
- int i, delta;
- int mrr_ndx[3];
+ bool prev_sample = mi->prev_sample;
+ int delta;
int sampling_ratio;
/* management/no-ack frames do not use rate control */
@@ -262,107 +307,75 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
else
sampling_ratio = mp->lookaround_rate;
- /* init rateindex [ndx] with max throughput rate */
- ndx = mi->max_tp_rate[0];
-
/* increase sum packet counter */
mi->packet_count++;
delta = (mi->packet_count * sampling_ratio / 100) -
(mi->sample_count + mi->sample_deferred / 2);
- /* delta > 0: sampling required */
- if ((delta > 0) && (mrr_capable || !mi->prev_sample)) {
- struct minstrel_rate *msr;
- if (mi->packet_count >= 10000) {
- mi->sample_deferred = 0;
- mi->sample_count = 0;
- mi->packet_count = 0;
- } else if (delta > mi->n_rates * 2) {
- /* With multi-rate retry, not every planned sample
- * attempt actually gets used, due to the way the retry
- * chain is set up - [max_tp,sample,prob,lowest] for
- * sample_rate < max_tp.
- *
- * If there's too much sampling backlog and the link
- * starts getting worse, minstrel would start bursting
- * out lots of sampling frames, which would result
- * in a large throughput loss. */
- mi->sample_count += (delta - mi->n_rates * 2);
- }
+ /* delta < 0: no sampling required */
+ mi->prev_sample = false;
+ if (delta < 0 || (!mrr_capable && prev_sample))
+ return;
- /* get next random rate sample */
- sample_ndx = minstrel_get_next_sample(mi);
- msr = &mi->r[sample_ndx];
- rate_sampling = true;
-
- /* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)
- * rate sampling method should be used.
- * Respect such rates that are not sampled for 20 interations.
- */
- if (mrr_capable &&
- msr->perfect_tx_time > mi->r[ndx].perfect_tx_time &&
- msr->sample_skipped < 20)
- indirect_rate_sampling = true;
-
- if (!indirect_rate_sampling) {
- if (msr->sample_limit != 0) {
- ndx = sample_ndx;
- mi->sample_count++;
- if (msr->sample_limit > 0)
- msr->sample_limit--;
- } else
- rate_sampling = false;
- } else {
- /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
- * packets that have the sampling rate deferred to the
- * second MRR stage. Increase the sample counter only
- * if the deferred sample rate was actually used.
- * Use the sample_deferred counter to make sure that
- * the sampling is not done in large bursts */
- info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
- mi->sample_deferred++;
- }
+ if (mi->packet_count >= 10000) {
+ mi->sample_deferred = 0;
+ mi->sample_count = 0;
+ mi->packet_count = 0;
+ } else if (delta > mi->n_rates * 2) {
+ /* With multi-rate retry, not every planned sample
+ * attempt actually gets used, due to the way the retry
+ * chain is set up - [max_tp,sample,prob,lowest] for
+ * sample_rate < max_tp.
+ *
+ * If there's too much sampling backlog and the link
+ * starts getting worse, minstrel would start bursting
+ * out lots of sampling frames, which would result
+ * in a large throughput loss. */
+ mi->sample_count += (delta - mi->n_rates * 2);
+ }
+
+ /* get next random rate sample */
+ ndx = minstrel_get_next_sample(mi);
+ msr = &mi->r[ndx];
+ mr = &mi->r[mi->max_tp_rate[0]];
+
+ /* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)
+ * rate sampling method should be used.
+ * Respect such rates that are not sampled for 20 interations.
+ */
+ if (mrr_capable &&
+ msr->perfect_tx_time > mr->perfect_tx_time &&
+ msr->sample_skipped < 20) {
+ /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
+ * packets that have the sampling rate deferred to the
+ * second MRR stage. Increase the sample counter only
+ * if the deferred sample rate was actually used.
+ * Use the sample_deferred counter to make sure that
+ * the sampling is not done in large bursts */
+ info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
+ rate++;
+ mi->sample_deferred++;
+ } else {
+ if (!msr->sample_limit != 0)
+ return;
+
+ mi->sample_count++;
+ if (msr->sample_limit > 0)
+ msr->sample_limit--;
}
- mi->prev_sample = rate_sampling;
/* If we're not using MRR and the sampling rate already
* has a probability of >95%, we shouldn't be attempting
* to use it, as this only wastes precious airtime */
- if (!mrr_capable && rate_sampling &&
+ if (!mrr_capable &&
(mi->r[ndx].probability > MINSTREL_FRAC(95, 100)))
- ndx = mi->max_tp_rate[0];
-
- /* mrr setup for 1st stage */
- ar[0].idx = mi->r[ndx].rix;
- ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info);
-
- /* non mrr setup for 2nd stage */
- if (!mrr_capable) {
- if (!rate_sampling)
- ar[0].count = mp->max_retry;
- ar[1].idx = mi->lowest_rix;
- ar[1].count = mp->max_retry;
return;
- }
- /* mrr setup for 2nd stage */
- if (rate_sampling) {
- if (indirect_rate_sampling)
- mrr_ndx[0] = sample_ndx;
- else
- mrr_ndx[0] = mi->max_tp_rate[0];
- } else {
- mrr_ndx[0] = mi->max_tp_rate[1];
- }
+ mi->prev_sample = true;
- /* mrr setup for 3rd & 4th stage */
- mrr_ndx[1] = mi->max_prob_rate;
- mrr_ndx[2] = 0;
- for (i = 1; i < 4; i++) {
- ar[i].idx = mi->r[mrr_ndx[i - 1]].rix;
- ar[i].count = mi->r[mrr_ndx[i - 1]].adjusted_retry_count;
- }
+ rate->idx = mi->r[ndx].rix;
+ rate->count = minstrel_get_retry_count(&mi->r[ndx], info);
}
@@ -412,12 +425,16 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
unsigned int i, n = 0;
unsigned int t_slot = 9; /* FIXME: get real slot time */
+ mi->sta = sta;
mi->lowest_rix = rate_lowest_index(sband, sta);
ctl_rate = &sband->bitrates[mi->lowest_rix];
mi->sp_ack_dur = ieee80211_frame_duration(sband->band, 10,
ctl_rate->bitrate,
!!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1);
+ memset(mi->max_tp_rate, 0, sizeof(mi->max_tp_rate));
+ mi->max_prob_rate = 0;
+
for (i = 0; i < sband->n_bitrates; i++) {
struct minstrel_rate *mr = &mi->r[n];
unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0;
@@ -460,6 +477,8 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
} while ((tx_time < mp->segment_size) &&
(++mr->retry_count < mp->max_retry));
mr->adjusted_retry_count = mr->retry_count;
+ if (!(sband->bitrates[i].flags & IEEE80211_RATE_ERP_G))
+ mr->retry_count_cts = mr->retry_count;
}
for (i = n; i < sband->n_bitrates; i++) {
@@ -471,6 +490,7 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
mi->stats_update = jiffies;
init_sample_table(mi);
+ minstrel_update_rates(mp, mi);
}
static void *
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 85ebf42cb46d..f4301f4b2e41 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -9,7 +9,8 @@
#ifndef __RC_MINSTREL_H
#define __RC_MINSTREL_H
-#define EWMA_LEVEL 75 /* ewma weighting factor [%] */
+#define EWMA_LEVEL 96 /* ewma weighting factor [/EWMA_DIV] */
+#define EWMA_DIV 128
#define SAMPLE_COLUMNS 10 /* number of columns in sample table */
@@ -27,7 +28,7 @@
static inline int
minstrel_ewma(int old, int new, int weight)
{
- return (new * (100 - weight) + old * weight) / 100;
+ return (new * (EWMA_DIV - weight) + old * weight) / EWMA_DIV;
}
@@ -62,6 +63,8 @@ struct minstrel_rate {
};
struct minstrel_sta_info {
+ struct ieee80211_sta *sta;
+
unsigned long stats_update;
unsigned int sp_ack_dur;
unsigned int rate_avg;
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index d1048348d399..fd0b9ca1570e 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -68,7 +68,7 @@ minstrel_stats_open(struct inode *inode, struct file *file)
file->private_data = ms;
p = ms->buf;
- p += sprintf(p, "rate throughput ewma prob this prob "
+ p += sprintf(p, "rate throughput ewma prob this prob "
"this succ/attempt success attempts\n");
for (i = 0; i < mi->n_rates; i++) {
struct minstrel_rate *mr = &mi->r[i];
@@ -86,7 +86,7 @@ minstrel_stats_open(struct inode *inode, struct file *file)
eprob = MINSTREL_TRUNC(mr->probability * 1000);
p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u "
- "%3u(%3u) %8llu %8llu\n",
+ " %3u(%3u) %8llu %8llu\n",
tp / 10, tp % 10,
eprob / 10, eprob % 10,
prob / 10, prob % 10,
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index d2b264d1311d..5b2d3012b983 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -126,6 +126,9 @@ const struct mcs_group minstrel_mcs_groups[] = {
static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES];
+static void
+minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi);
+
/*
* Look up an MCS group index based on mac80211 rate information
*/
@@ -244,6 +247,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
struct minstrel_rate_stats *mr;
int cur_prob, cur_prob_tp, cur_tp, cur_tp2;
int group, i, index;
+ bool mi_rates_valid = false;
if (mi->ampdu_packets > 0) {
mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len,
@@ -254,11 +258,10 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
mi->sample_slow = 0;
mi->sample_count = 0;
- mi->max_tp_rate = 0;
- mi->max_tp_rate2 = 0;
- mi->max_prob_rate = 0;
for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
+ bool mg_rates_valid = false;
+
cur_prob = 0;
cur_prob_tp = 0;
cur_tp = 0;
@@ -268,15 +271,24 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
if (!mg->supported)
continue;
- mg->max_tp_rate = 0;
- mg->max_tp_rate2 = 0;
- mg->max_prob_rate = 0;
mi->sample_count++;
for (i = 0; i < MCS_GROUP_RATES; i++) {
if (!(mg->supported & BIT(i)))
continue;
+ /* initialize rates selections starting indexes */
+ if (!mg_rates_valid) {
+ mg->max_tp_rate = mg->max_tp_rate2 =
+ mg->max_prob_rate = i;
+ if (!mi_rates_valid) {
+ mi->max_tp_rate = mi->max_tp_rate2 =
+ mi->max_prob_rate = i;
+ mi_rates_valid = true;
+ }
+ mg_rates_valid = true;
+ }
+
mr = &mg->rates[i];
mr->retry_updated = false;
index = MCS_GROUP_RATES * group + i;
@@ -456,7 +468,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_tx_rate *ar = info->status.rates;
struct minstrel_rate_stats *rate, *rate2;
struct minstrel_priv *mp = priv;
- bool last;
+ bool last, update = false;
int i;
if (!msp->is_ht)
@@ -505,21 +517,29 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
rate = minstrel_get_ratestats(mi, mi->max_tp_rate);
if (rate->attempts > 30 &&
MINSTREL_FRAC(rate->success, rate->attempts) <
- MINSTREL_FRAC(20, 100))
+ MINSTREL_FRAC(20, 100)) {
minstrel_downgrade_rate(mi, &mi->max_tp_rate, true);
+ update = true;
+ }
rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate2);
if (rate2->attempts > 30 &&
MINSTREL_FRAC(rate2->success, rate2->attempts) <
- MINSTREL_FRAC(20, 100))
+ MINSTREL_FRAC(20, 100)) {
minstrel_downgrade_rate(mi, &mi->max_tp_rate2, false);
+ update = true;
+ }
if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
+ update = true;
minstrel_ht_update_stats(mp, mi);
if (!(info->flags & IEEE80211_TX_CTL_AMPDU) &&
mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP)
minstrel_aggr_check(sta, skb);
}
+
+ if (update)
+ minstrel_ht_update_rates(mp, mi);
}
static void
@@ -583,36 +603,71 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
static void
minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
- struct ieee80211_tx_rate *rate, int index,
- bool sample, bool rtscts)
+ struct ieee80211_sta_rates *ratetbl, int offset, int index)
{
const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
struct minstrel_rate_stats *mr;
+ u8 idx;
+ u16 flags;
mr = minstrel_get_ratestats(mi, index);
if (!mr->retry_updated)
minstrel_calc_retransmit(mp, mi, index);
- if (sample)
- rate->count = 1;
- else if (mr->probability < MINSTREL_FRAC(20, 100))
- rate->count = 2;
- else if (rtscts)
- rate->count = mr->retry_count_rtscts;
- else
- rate->count = mr->retry_count;
-
- rate->flags = 0;
- if (rtscts)
- rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
+ if (mr->probability < MINSTREL_FRAC(20, 100) || !mr->retry_count) {
+ ratetbl->rate[offset].count = 2;
+ ratetbl->rate[offset].count_rts = 2;
+ ratetbl->rate[offset].count_cts = 2;
+ } else {
+ ratetbl->rate[offset].count = mr->retry_count;
+ ratetbl->rate[offset].count_cts = mr->retry_count;
+ ratetbl->rate[offset].count_rts = mr->retry_count_rtscts;
+ }
if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
- rate->idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)];
+ idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)];
+ flags = 0;
+ } else {
+ idx = index % MCS_GROUP_RATES +
+ (group->streams - 1) * MCS_GROUP_RATES;
+ flags = IEEE80211_TX_RC_MCS | group->flags;
+ }
+
+ if (offset > 0) {
+ ratetbl->rate[offset].count = ratetbl->rate[offset].count_rts;
+ flags |= IEEE80211_TX_RC_USE_RTS_CTS;
+ }
+
+ ratetbl->rate[offset].idx = idx;
+ ratetbl->rate[offset].flags = flags;
+}
+
+static void
+minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
+{
+ struct ieee80211_sta_rates *rates;
+ int i = 0;
+
+ rates = kzalloc(sizeof(*rates), GFP_ATOMIC);
+ if (!rates)
return;
+
+ /* Start with max_tp_rate */
+ minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate);
+
+ if (mp->hw->max_rates >= 3) {
+ /* At least 3 tx rates supported, use max_tp_rate2 next */
+ minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate2);
+ }
+
+ if (mp->hw->max_rates >= 2) {
+ /*
+ * At least 2 tx rates supported, use max_prob_rate next */
+ minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_prob_rate);
}
- rate->flags |= IEEE80211_TX_RC_MCS | group->flags;
- rate->idx = index % MCS_GROUP_RATES + (group->streams - 1) * MCS_GROUP_RATES;
+ rates->rate[i].idx = -1;
+ rate_control_set_rates(mp->hw, mi->sta, rates);
}
static inline int
@@ -702,13 +757,13 @@ static void
minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
struct ieee80211_tx_rate_control *txrc)
{
+ const struct mcs_group *sample_group;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
- struct ieee80211_tx_rate *ar = info->status.rates;
+ struct ieee80211_tx_rate *rate = &info->status.rates[0];
struct minstrel_ht_sta_priv *msp = priv_sta;
struct minstrel_ht_sta *mi = &msp->ht;
struct minstrel_priv *mp = priv;
int sample_idx;
- bool sample = false;
if (rate_control_send_low(sta, priv_sta, txrc))
return;
@@ -736,51 +791,6 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
}
#endif
- if (sample_idx >= 0) {
- sample = true;
- minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
- true, false);
- info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
- } else {
- minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
- false, false);
- }
-
- if (mp->hw->max_rates >= 3) {
- /*
- * At least 3 tx rates supported, use
- * sample_rate -> max_tp_rate -> max_prob_rate for sampling and
- * max_tp_rate -> max_tp_rate2 -> max_prob_rate by default.
- */
- if (sample_idx >= 0)
- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
- false, false);
- else
- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
- false, true);
-
- minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate,
- false, !sample);
-
- ar[3].count = 0;
- ar[3].idx = -1;
- } else if (mp->hw->max_rates == 2) {
- /*
- * Only 2 tx rates supported, use
- * sample_rate -> max_prob_rate for sampling and
- * max_tp_rate -> max_prob_rate by default.
- */
- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate,
- false, !sample);
-
- ar[2].count = 0;
- ar[2].idx = -1;
- } else {
- /* Not using MRR, only use the first rate */
- ar[1].count = 0;
- ar[1].idx = -1;
- }
-
mi->total_packets++;
/* wraparound */
@@ -788,6 +798,16 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
mi->total_packets = 0;
mi->sample_packets = 0;
}
+
+ if (sample_idx < 0)
+ return;
+
+ sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];
+ info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
+ rate->idx = sample_idx % MCS_GROUP_RATES +
+ (sample_group->streams - 1) * MCS_GROUP_RATES;
+ rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags;
+ rate->count = 1;
}
static void
@@ -837,6 +857,8 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
msp->is_ht = true;
memset(mi, 0, sizeof(*mi));
+
+ mi->sta = sta;
mi->stats_update = jiffies;
ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1);
@@ -898,6 +920,10 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
if (!n_supported)
goto use_legacy;
+ /* create an initial rate table with the lowest supported rates */
+ minstrel_ht_update_stats(mp, mi);
+ minstrel_ht_update_rates(mp, mi);
+
return;
use_legacy:
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index 9b16e9de9923..d655586773ac 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -65,6 +65,8 @@ struct minstrel_mcs_group_data {
};
struct minstrel_ht_sta {
+ struct ieee80211_sta *sta;
+
/* ampdu length (average, per sampling interval) */
unsigned int ampdu_len;
unsigned int ampdu_packets;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 2528b5a4d6d4..c8447af76ead 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2085,6 +2085,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
}
fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
+ fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY);
info = IEEE80211_SKB_CB(fwd_skb);
memset(info, 0, sizeof(*info));
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
@@ -2423,6 +2424,22 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
}
break;
+ case WLAN_CATEGORY_PUBLIC:
+ if (len < IEEE80211_MIN_ACTION_SIZE + 1)
+ goto invalid;
+ if (sdata->vif.type != NL80211_IFTYPE_STATION)
+ break;
+ if (!rx->sta)
+ break;
+ if (!ether_addr_equal(mgmt->bssid, sdata->u.mgd.bssid))
+ break;
+ if (mgmt->u.action.u.ext_chan_switch.action_code !=
+ WLAN_PUB_ACTION_EXT_CHANSW_ANN)
+ break;
+ if (len < offsetof(struct ieee80211_mgmt,
+ u.action.u.ext_chan_switch.variable))
+ goto invalid;
+ goto queue;
case WLAN_CATEGORY_VHT:
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
@@ -2506,10 +2523,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
ieee80211_process_measurement_req(sdata, mgmt, len);
goto handled;
case WLAN_ACTION_SPCT_CHL_SWITCH:
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.chan_switch)))
- break;
-
if (sdata->vif.type != NL80211_IFTYPE_STATION)
break;
@@ -3042,7 +3055,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
!ieee80211_is_probe_resp(hdr->frame_control) &&
!ieee80211_is_beacon(hdr->frame_control))
return 0;
- if (!ether_addr_equal(sdata->vif.addr, hdr->addr1))
+ if (!ether_addr_equal(sdata->vif.addr, hdr->addr1) &&
+ !multicast)
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
break;
default:
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index cb34cbbaa20c..99b103921a4b 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -98,9 +98,8 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
}
/* save the ERP value so that it is available at association time */
- if (elems->erp_info && elems->erp_info_len >= 1 &&
- (!elems->parse_error ||
- !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) {
+ if (elems->erp_info && (!elems->parse_error ||
+ !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) {
bss->erp_value = elems->erp_info[0];
bss->has_erp_value = true;
if (!elems->parse_error)
@@ -182,7 +181,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
if (baselen > skb->len)
return;
- ieee802_11_parse_elems(elements, skb->len - baselen, &elems);
+ ieee802_11_parse_elems(elements, skb->len - baselen, false, &elems);
channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
@@ -384,7 +383,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
{
int i;
struct ieee80211_sub_if_data *sdata;
- enum ieee80211_band band = local->hw.conf.channel->band;
+ enum ieee80211_band band = local->hw.conf.chandef.chan->band;
u32 tx_flags;
tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
@@ -401,7 +400,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
local->scan_req->ssids[i].ssid_len,
local->scan_req->ie, local->scan_req->ie_len,
local->scan_req->rates[band], false,
- tx_flags, local->hw.conf.channel, true);
+ tx_flags, local->hw.conf.chandef.chan, true);
/*
* After sending probe requests, wait for probe responses
@@ -467,7 +466,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
if (local->ops->hw_scan) {
__set_bit(SCAN_HW_SCANNING, &local->scanning);
} else if ((req->n_channels == 1) &&
- (req->channels[0] == local->_oper_channel)) {
+ (req->channels[0] == local->_oper_chandef.chan)) {
/*
* If we are scanning only on the operating channel
* then we do not need to stop normal activities
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index c5899797a8d4..c215fafd7a2f 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -28,27 +28,27 @@
#define VIF_PR_FMT " vif:%s(%d%s)"
#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
-#define CHANDEF_ENTRY __field(u32, control_freq) \
- __field(u32, chan_width) \
- __field(u32, center_freq1) \
+#define CHANDEF_ENTRY __field(u32, control_freq) \
+ __field(u32, chan_width) \
+ __field(u32, center_freq1) \
__field(u32, center_freq2)
-#define CHANDEF_ASSIGN(c) \
- __entry->control_freq = (c)->chan->center_freq; \
- __entry->chan_width = (c)->width; \
- __entry->center_freq1 = (c)->center_freq1; \
+#define CHANDEF_ASSIGN(c) \
+ __entry->control_freq = (c)->chan ? (c)->chan->center_freq : 0; \
+ __entry->chan_width = (c)->width; \
+ __entry->center_freq1 = (c)->center_freq1; \
__entry->center_freq2 = (c)->center_freq2;
#define CHANDEF_PR_FMT " control:%d MHz width:%d center: %d/%d MHz"
-#define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \
+#define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \
__entry->center_freq1, __entry->center_freq2
-#define CHANCTX_ENTRY CHANDEF_ENTRY \
- __field(u8, rx_chains_static) \
+#define CHANCTX_ENTRY CHANDEF_ENTRY \
+ __field(u8, rx_chains_static) \
__field(u8, rx_chains_dynamic)
-#define CHANCTX_ASSIGN CHANDEF_ASSIGN(&ctx->conf.def) \
- __entry->rx_chains_static = ctx->conf.rx_chains_static; \
+#define CHANCTX_ASSIGN CHANDEF_ASSIGN(&ctx->conf.def) \
+ __entry->rx_chains_static = ctx->conf.rx_chains_static; \
__entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic
#define CHANCTX_PR_FMT CHANDEF_PR_FMT " chains:%d/%d"
-#define CHANCTX_PR_ARG CHANDEF_PR_ARG, \
+#define CHANCTX_PR_ARG CHANDEF_PR_ARG, \
__entry->rx_chains_static, __entry->rx_chains_dynamic
@@ -286,8 +286,7 @@ TRACE_EVENT(drv_config,
__field(u16, listen_interval)
__field(u8, long_frame_max_tx_count)
__field(u8, short_frame_max_tx_count)
- __field(int, center_freq)
- __field(int, channel_type)
+ CHANDEF_ENTRY
__field(int, smps)
),
@@ -303,15 +302,13 @@ TRACE_EVENT(drv_config,
local->hw.conf.long_frame_max_tx_count;
__entry->short_frame_max_tx_count =
local->hw.conf.short_frame_max_tx_count;
- __entry->center_freq = local->hw.conf.channel ?
- local->hw.conf.channel->center_freq : 0;
- __entry->channel_type = local->hw.conf.channel_type;
+ CHANDEF_ASSIGN(&local->hw.conf.chandef)
__entry->smps = local->hw.conf.smps_mode;
),
TP_printk(
- LOCAL_PR_FMT " ch:%#x freq:%d",
- LOCAL_PR_ARG, __entry->changed, __entry->center_freq
+ LOCAL_PR_FMT " ch:%#x" CHANDEF_PR_FMT,
+ LOCAL_PR_ARG, __entry->changed, CHANDEF_PR_ARG
)
);
@@ -359,8 +356,7 @@ TRACE_EVENT(drv_bss_info_changed,
__dynamic_array(u8, ssid, info->ssid_len);
__field(bool, hidden_ssid);
__field(int, txpower)
- __field(u8, p2p_ctwindow)
- __field(bool, p2p_oppps)
+ __field(u8, p2p_oppps_ctwindow)
),
TP_fast_assign(
@@ -400,8 +396,7 @@ TRACE_EVENT(drv_bss_info_changed,
memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len);
__entry->hidden_ssid = info->hidden_ssid;
__entry->txpower = info->txpower;
- __entry->p2p_ctwindow = info->p2p_ctwindow;
- __entry->p2p_oppps = info->p2p_oppps;
+ __entry->p2p_oppps_ctwindow = info->p2p_noa_attr.oppps_ctwindow;
),
TP_printk(
@@ -995,23 +990,23 @@ TRACE_EVENT(drv_channel_switch,
TP_STRUCT__entry(
LOCAL_ENTRY
+ CHANDEF_ENTRY
__field(u64, timestamp)
__field(bool, block_tx)
- __field(u16, freq)
__field(u8, count)
),
TP_fast_assign(
LOCAL_ASSIGN;
+ CHANDEF_ASSIGN(&ch_switch->chandef)
__entry->timestamp = ch_switch->timestamp;
__entry->block_tx = ch_switch->block_tx;
- __entry->freq = ch_switch->channel->center_freq;
__entry->count = ch_switch->count;
),
TP_printk(
- LOCAL_PR_FMT " new freq:%u count:%d",
- LOCAL_PR_ARG, __entry->freq, __entry->count
+ LOCAL_PR_FMT " new " CHANDEF_PR_FMT " count:%d",
+ LOCAL_PR_ARG, CHANDEF_PR_ARG, __entry->count
)
);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 9e67cc97b87b..9972e07a2f96 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -48,15 +48,15 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
/* assume HW handles this */
- if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
+ if (tx->rate.flags & IEEE80211_TX_RC_MCS)
return 0;
/* uh huh? */
- if (WARN_ON_ONCE(info->control.rates[0].idx < 0))
+ if (WARN_ON_ONCE(tx->rate.idx < 0))
return 0;
sband = local->hw.wiphy->bands[info->band];
- txrate = &sband->bitrates[info->control.rates[0].idx];
+ txrate = &sband->bitrates[tx->rate.idx];
erp = txrate->flags & IEEE80211_RATE_ERP_G;
@@ -617,11 +617,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
struct ieee80211_hdr *hdr = (void *)tx->skb->data;
struct ieee80211_supported_band *sband;
- struct ieee80211_rate *rate;
- int i;
u32 len;
- bool inval = false, rts = false, short_preamble = false;
struct ieee80211_tx_rate_control txrc;
+ struct ieee80211_sta_rates *ratetbl = NULL;
bool assoc = false;
memset(&txrc, 0, sizeof(txrc));
@@ -642,18 +640,23 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
txrc.max_rate_idx = -1;
else
txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
- memcpy(txrc.rate_idx_mcs_mask,
- tx->sdata->rc_rateidx_mcs_mask[info->band],
- sizeof(txrc.rate_idx_mcs_mask));
+
+ if (tx->sdata->rc_has_mcs_mask[info->band])
+ txrc.rate_idx_mcs_mask =
+ tx->sdata->rc_rateidx_mcs_mask[info->band];
+
txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
tx->sdata->vif.type == NL80211_IFTYPE_ADHOC);
/* set up RTS protection if desired */
if (len > tx->local->hw.wiphy->rts_threshold) {
- txrc.rts = rts = true;
+ txrc.rts = true;
}
+ info->control.use_rts = txrc.rts;
+ info->control.use_cts_prot = tx->sdata->vif.bss_conf.use_cts_prot;
+
/*
* Use short preamble if the BSS can handle it, but not for
* management frames unless we know the receiver can handle
@@ -663,7 +666,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
if (tx->sdata->vif.bss_conf.use_short_preamble &&
(ieee80211_is_data(hdr->frame_control) ||
(tx->sta && test_sta_flag(tx->sta, WLAN_STA_SHORT_PREAMBLE))))
- txrc.short_preamble = short_preamble = true;
+ txrc.short_preamble = true;
+
+ info->control.short_preamble = txrc.short_preamble;
if (tx->sta)
assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
@@ -687,16 +692,38 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
*/
rate_control_get_rate(tx->sdata, tx->sta, &txrc);
- if (unlikely(info->control.rates[0].idx < 0))
- return TX_DROP;
+ if (tx->sta && !info->control.skip_table)
+ ratetbl = rcu_dereference(tx->sta->sta.rates);
+
+ if (unlikely(info->control.rates[0].idx < 0)) {
+ if (ratetbl) {
+ struct ieee80211_tx_rate rate = {
+ .idx = ratetbl->rate[0].idx,
+ .flags = ratetbl->rate[0].flags,
+ .count = ratetbl->rate[0].count
+ };
+
+ if (ratetbl->rate[0].idx < 0)
+ return TX_DROP;
+
+ tx->rate = rate;
+ } else {
+ return TX_DROP;
+ }
+ } else {
+ tx->rate = info->control.rates[0];
+ }
if (txrc.reported_rate.idx < 0) {
- txrc.reported_rate = info->control.rates[0];
+ txrc.reported_rate = tx->rate;
if (tx->sta && ieee80211_is_data(hdr->frame_control))
tx->sta->last_tx_rate = txrc.reported_rate;
} else if (tx->sta)
tx->sta->last_tx_rate = txrc.reported_rate;
+ if (ratetbl)
+ return TX_CONTINUE;
+
if (unlikely(!info->control.rates[0].count))
info->control.rates[0].count = 1;
@@ -704,91 +731,6 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
(info->flags & IEEE80211_TX_CTL_NO_ACK)))
info->control.rates[0].count = 1;
- if (is_multicast_ether_addr(hdr->addr1)) {
- /*
- * XXX: verify the rate is in the basic rateset
- */
- return TX_CONTINUE;
- }
-
- /*
- * set up the RTS/CTS rate as the fastest basic rate
- * that is not faster than the data rate
- *
- * XXX: Should this check all retry rates?
- */
- if (!(info->control.rates[0].flags & IEEE80211_TX_RC_MCS)) {
- s8 baserate = 0;
-
- rate = &sband->bitrates[info->control.rates[0].idx];
-
- for (i = 0; i < sband->n_bitrates; i++) {
- /* must be a basic rate */
- if (!(tx->sdata->vif.bss_conf.basic_rates & BIT(i)))
- continue;
- /* must not be faster than the data rate */
- if (sband->bitrates[i].bitrate > rate->bitrate)
- continue;
- /* maximum */
- if (sband->bitrates[baserate].bitrate <
- sband->bitrates[i].bitrate)
- baserate = i;
- }
-
- info->control.rts_cts_rate_idx = baserate;
- }
-
- for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
- /*
- * make sure there's no valid rate following
- * an invalid one, just in case drivers don't
- * take the API seriously to stop at -1.
- */
- if (inval) {
- info->control.rates[i].idx = -1;
- continue;
- }
- if (info->control.rates[i].idx < 0) {
- inval = true;
- continue;
- }
-
- /*
- * For now assume MCS is already set up correctly, this
- * needs to be fixed.
- */
- if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) {
- WARN_ON(info->control.rates[i].idx > 76);
- continue;
- }
-
- /* set up RTS protection if desired */
- if (rts)
- info->control.rates[i].flags |=
- IEEE80211_TX_RC_USE_RTS_CTS;
-
- /* RC is busted */
- if (WARN_ON_ONCE(info->control.rates[i].idx >=
- sband->n_bitrates)) {
- info->control.rates[i].idx = -1;
- continue;
- }
-
- rate = &sband->bitrates[info->control.rates[i].idx];
-
- /* set up short preamble */
- if (short_preamble &&
- rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
- info->control.rates[i].flags |=
- IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
-
- /* set up G protection */
- if (!rts && tx->sdata->vif.bss_conf.use_cts_prot &&
- rate->flags & IEEE80211_RATE_ERP_G)
- info->control.rates[i].flags |=
- IEEE80211_TX_RC_USE_CTS_PROTECT;
- }
-
return TX_CONTINUE;
}
@@ -1709,7 +1651,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
if (chanctx_conf)
chan = chanctx_conf->def.chan;
else if (!local->use_chanctx)
- chan = local->_oper_channel;
+ chan = local->_oper_chandef.chan;
else
goto fail_rcu;
@@ -1843,7 +1785,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
* This is the exception! WDS style interfaces are prohibited
* when channel contexts are in used so this must be valid
*/
- band = local->hw.conf.channel->band;
+ band = local->hw.conf.chandef.chan->band;
break;
#ifdef CONFIG_MAC80211_MESH
case NL80211_IFTYPE_MESH_POINT:
@@ -2442,14 +2384,17 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_hdr *hdr;
- struct sk_buff *presp = rcu_dereference(ifibss->presp);
+ struct beacon_data *presp = rcu_dereference(ifibss->presp);
if (!presp)
goto out;
- skb = skb_copy(presp, GFP_ATOMIC);
+ skb = dev_alloc_skb(local->tx_headroom + presp->head_len);
if (!skb)
goto out;
+ skb_reserve(skb, local->tx_headroom);
+ memcpy(skb_put(skb, presp->head_len), presp->head,
+ presp->head_len);
hdr = (struct ieee80211_hdr *) skb->data;
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
@@ -2499,8 +2444,6 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
txrc.max_rate_idx = -1;
else
txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
- memcpy(txrc.rate_idx_mcs_mask, sdata->rc_rateidx_mcs_mask[band],
- sizeof(txrc.rate_idx_mcs_mask));
txrc.bss = true;
rate_control_get_rate(sdata, NULL, &txrc);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index a7368870c8ee..3f87fa468b1f 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -485,7 +485,8 @@ int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
return true;
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
- ret = !!local->queue_stop_reasons[queue];
+ ret = test_bit(IEEE80211_QUEUE_STOP_REASON_DRIVER,
+ &local->queue_stop_reasons[queue]);
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
return ret;
}
@@ -660,7 +661,7 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL(ieee80211_queue_delayed_work);
-u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
+u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action,
struct ieee802_11_elems *elems,
u64 filter, u32 crc)
{
@@ -668,6 +669,7 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
u8 *pos = start;
bool calc_crc = filter != 0;
DECLARE_BITMAP(seen_elems, 256);
+ const u8 *ie;
bitmap_zero(seen_elems, 256);
memset(elems, 0, sizeof(*elems));
@@ -715,6 +717,12 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
case WLAN_EID_COUNTRY:
case WLAN_EID_PWR_CONSTRAINT:
case WLAN_EID_TIMEOUT_INTERVAL:
+ case WLAN_EID_SECONDARY_CHANNEL_OFFSET:
+ case WLAN_EID_WIDE_BW_CHANNEL_SWITCH:
+ /*
+ * not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible
+ * that if the content gets bigger it might be needed more than once
+ */
if (test_bit(id, seen_elems)) {
elems->parse_error = true;
left -= elen;
@@ -738,17 +746,11 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
elems->supp_rates = pos;
elems->supp_rates_len = elen;
break;
- case WLAN_EID_FH_PARAMS:
- elems->fh_params = pos;
- elems->fh_params_len = elen;
- break;
case WLAN_EID_DS_PARAMS:
- elems->ds_params = pos;
- elems->ds_params_len = elen;
- break;
- case WLAN_EID_CF_PARAMS:
- elems->cf_params = pos;
- elems->cf_params_len = elen;
+ if (elen >= 1)
+ elems->ds_params = pos;
+ else
+ elem_parse_failed = true;
break;
case WLAN_EID_TIM:
if (elen >= sizeof(struct ieee80211_tim_ie)) {
@@ -757,10 +759,6 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
} else
elem_parse_failed = true;
break;
- case WLAN_EID_IBSS_PARAMS:
- elems->ibss_params = pos;
- elems->ibss_params_len = elen;
- break;
case WLAN_EID_CHALLENGE:
elems->challenge = pos;
elems->challenge_len = elen;
@@ -790,8 +788,10 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
elems->rsn_len = elen;
break;
case WLAN_EID_ERP_INFO:
- elems->erp_info = pos;
- elems->erp_info_len = elen;
+ if (elen >= 1)
+ elems->erp_info = pos;
+ else
+ elem_parse_failed = true;
break;
case WLAN_EID_EXT_SUPP_RATES:
elems->ext_supp_rates = pos;
@@ -870,12 +870,47 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
}
elems->ch_switch_ie = (void *)pos;
break;
- case WLAN_EID_QUIET:
- if (!elems->quiet_elem) {
- elems->quiet_elem = pos;
- elems->quiet_elem_len = elen;
+ case WLAN_EID_EXT_CHANSWITCH_ANN:
+ if (elen != sizeof(struct ieee80211_ext_chansw_ie)) {
+ elem_parse_failed = true;
+ break;
+ }
+ elems->ext_chansw_ie = (void *)pos;
+ break;
+ case WLAN_EID_SECONDARY_CHANNEL_OFFSET:
+ if (elen != sizeof(struct ieee80211_sec_chan_offs_ie)) {
+ elem_parse_failed = true;
+ break;
+ }
+ elems->sec_chan_offs = (void *)pos;
+ break;
+ case WLAN_EID_WIDE_BW_CHANNEL_SWITCH:
+ if (!action ||
+ elen != sizeof(*elems->wide_bw_chansw_ie)) {
+ elem_parse_failed = true;
+ break;
+ }
+ elems->wide_bw_chansw_ie = (void *)pos;
+ break;
+ case WLAN_EID_CHANNEL_SWITCH_WRAPPER:
+ if (action) {
+ elem_parse_failed = true;
+ break;
+ }
+ /*
+ * This is a bit tricky, but as we only care about
+ * the wide bandwidth channel switch element, so
+ * just parse it out manually.
+ */
+ ie = cfg80211_find_ie(WLAN_EID_WIDE_BW_CHANNEL_SWITCH,
+ pos, elen);
+ if (ie) {
+ if (ie[1] == sizeof(*elems->wide_bw_chansw_ie))
+ elems->wide_bw_chansw_ie =
+ (void *)(ie + 2);
+ else
+ elem_parse_failed = true;
}
- elems->num_of_quiet_elem++;
break;
case WLAN_EID_COUNTRY:
elems->country_elem = pos;
@@ -889,8 +924,10 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
elems->pwr_constr_elem = pos;
break;
case WLAN_EID_TIMEOUT_INTERVAL:
- elems->timeout_int = pos;
- elems->timeout_int_len = elen;
+ if (elen >= sizeof(struct ieee80211_timeout_interval_ie))
+ elems->timeout_int = (void *)pos;
+ else
+ elem_parse_failed = true;
break;
default:
break;
@@ -911,12 +948,6 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
return crc;
}
-void ieee802_11_parse_elems(u8 *start, size_t len,
- struct ieee802_11_elems *elems)
-{
- ieee802_11_parse_elems_crc(start, len, elems, 0, 0);
-}
-
void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
bool bss_notify)
{
@@ -1474,6 +1505,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
/* add interfaces */
sdata = rtnl_dereference(local->monitor_sdata);
if (sdata) {
+ /* in HW restart it exists already */
+ WARN_ON(local->resuming);
res = drv_add_interface(local, sdata);
if (WARN_ON(res)) {
rcu_assign_pointer(local->monitor_sdata, NULL);
@@ -1663,6 +1696,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
local->in_reconfig = false;
barrier();
+ if (local->monitors == local->open_count && local->monitors > 0)
+ ieee80211_add_virtual_monitor(local);
+
/*
* Clear the WLAN_STA_BLOCK_BA flag so new aggregation
* sessions can be established after a resume.
@@ -2056,7 +2092,7 @@ int ieee80211_ave_rssi(struct ieee80211_vif *vif)
/* non-managed type inferfaces */
return 0;
}
- return ifmgd->ave_beacon_signal;
+ return ifmgd->ave_beacon_signal / 16;
}
EXPORT_SYMBOL_GPL(ieee80211_ave_rssi);
@@ -2171,8 +2207,7 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work)
/* currently not handled */
WARN_ON(1);
else {
- cfg80211_chandef_create(&chandef, local->hw.conf.channel,
- local->hw.conf.channel_type);
+ chandef = local->hw.conf.chandef;
cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
}
}
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 6ceee8e181ca..40d2527693da 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -27,6 +27,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/rfkill.h>
#include <linux/nfc.h>
#include <net/genetlink.h>
@@ -58,6 +59,11 @@ int nfc_dev_up(struct nfc_dev *dev)
device_lock(&dev->dev);
+ if (dev->rfkill && rfkill_blocked(dev->rfkill)) {
+ rc = -ERFKILL;
+ goto error;
+ }
+
if (!device_is_registered(&dev->dev)) {
rc = -ENODEV;
goto error;
@@ -117,6 +123,24 @@ error:
return rc;
}
+static int nfc_rfkill_set_block(void *data, bool blocked)
+{
+ struct nfc_dev *dev = data;
+
+ pr_debug("%s blocked %d", dev_name(&dev->dev), blocked);
+
+ if (!blocked)
+ return 0;
+
+ nfc_dev_down(dev);
+
+ return 0;
+}
+
+static const struct rfkill_ops nfc_rfkill_ops = {
+ .set_block = nfc_rfkill_set_block,
+};
+
/**
* nfc_start_poll - start polling for nfc targets
*
@@ -143,6 +167,11 @@ int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols)
goto error;
}
+ if (!dev->dev_up) {
+ rc = -ENODEV;
+ goto error;
+ }
+
if (dev->polling) {
rc = -EBUSY;
goto error;
@@ -835,6 +864,15 @@ int nfc_register_device(struct nfc_dev *dev)
pr_debug("The userspace won't be notified that the device %s was added\n",
dev_name(&dev->dev));
+ dev->rfkill = rfkill_alloc(dev_name(&dev->dev), &dev->dev,
+ RFKILL_TYPE_NFC, &nfc_rfkill_ops, dev);
+ if (dev->rfkill) {
+ if (rfkill_register(dev->rfkill) < 0) {
+ rfkill_destroy(dev->rfkill);
+ dev->rfkill = NULL;
+ }
+ }
+
return 0;
}
EXPORT_SYMBOL(nfc_register_device);
@@ -852,6 +890,11 @@ void nfc_unregister_device(struct nfc_dev *dev)
id = dev->idx;
+ if (dev->rfkill) {
+ rfkill_unregister(dev->rfkill);
+ rfkill_destroy(dev->rfkill);
+ }
+
if (dev->ops->check_presence) {
device_lock(&dev->dev);
dev->shutting_down = true;
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index b75a9b3f9e89..094f7e27e910 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -420,7 +420,8 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
}
/* If the socket parameters are not set, use the local ones */
- miux = sock->miux > LLCP_MAX_MIUX ? local->miux : sock->miux;
+ miux = be16_to_cpu(sock->miux) > LLCP_MAX_MIUX ?
+ local->miux : sock->miux;
rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw;
miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
@@ -475,7 +476,8 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
return -ENODEV;
/* If the socket parameters are not set, use the local ones */
- miux = sock->miux > LLCP_MAX_MIUX ? local->miux : sock->miux;
+ miux = be16_to_cpu(sock->miux) > LLCP_MAX_MIUX ?
+ local->miux : sock->miux;
rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw;
miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
@@ -656,6 +658,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
struct nfc_llcp_local *local;
size_t frag_len = 0, remaining_len;
u8 *msg_data, *msg_ptr;
+ u16 remote_miu;
pr_debug("Send I frame len %zd\n", len);
@@ -692,9 +695,11 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
remaining_len = len;
msg_ptr = msg_data;
- while (remaining_len > 0) {
+ do {
+ remote_miu = sock->remote_miu > LLCP_MAX_MIU ?
+ local->remote_miu : sock->remote_miu;
- frag_len = min_t(size_t, sock->remote_miu, remaining_len);
+ frag_len = min_t(size_t, remote_miu, remaining_len);
pr_debug("Fragment %zd bytes remaining %zd",
frag_len, remaining_len);
@@ -706,7 +711,8 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
skb_put(pdu, LLCP_SEQUENCE_SIZE);
- memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
+ if (likely(frag_len > 0))
+ memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
skb_queue_tail(&sock->tx_queue, pdu);
@@ -718,7 +724,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
remaining_len -= frag_len;
msg_ptr += frag_len;
- }
+ } while (remaining_len > 0);
kfree(msg_data);
@@ -732,6 +738,7 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
struct nfc_llcp_local *local;
size_t frag_len = 0, remaining_len;
u8 *msg_ptr, *msg_data;
+ u16 remote_miu;
int err;
pr_debug("Send UI frame len %zd\n", len);
@@ -752,9 +759,11 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
remaining_len = len;
msg_ptr = msg_data;
- while (remaining_len > 0) {
+ do {
+ remote_miu = sock->remote_miu > LLCP_MAX_MIU ?
+ local->remote_miu : sock->remote_miu;
- frag_len = min_t(size_t, sock->remote_miu, remaining_len);
+ frag_len = min_t(size_t, remote_miu, remaining_len);
pr_debug("Fragment %zd bytes remaining %zd",
frag_len, remaining_len);
@@ -768,14 +777,15 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI);
- memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
+ if (likely(frag_len > 0))
+ memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
/* No need to check for the peer RW for UI frames */
skb_queue_tail(&local->tx_queue, pdu);
remaining_len -= frag_len;
msg_ptr += frag_len;
- }
+ } while (remaining_len > 0);
kfree(msg_data);
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 7de0368aff0c..9e483c8e52f8 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -31,6 +31,8 @@ static u8 llcp_magic[3] = {0x46, 0x66, 0x6d};
static struct list_head llcp_devices;
+static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb);
+
void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *sk)
{
write_lock(&l->lock);
@@ -45,6 +47,12 @@ void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk)
write_unlock(&l->lock);
}
+void nfc_llcp_socket_remote_param_init(struct nfc_llcp_sock *sock)
+{
+ sock->remote_rw = LLCP_DEFAULT_RW;
+ sock->remote_miu = LLCP_MAX_MIU + 1;
+}
+
static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock)
{
struct nfc_llcp_local *local = sock->local;
@@ -68,7 +76,7 @@ static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock)
}
}
-static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
+static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool device,
int err)
{
struct sock *sk;
@@ -108,21 +116,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
bh_unlock_sock(accept_sk);
}
-
- if (listen == true) {
- bh_unlock_sock(sk);
- continue;
- }
- }
-
- /*
- * If we have a connection less socket bound, we keep it alive
- * if the device is still present.
- */
- if (sk->sk_state == LLCP_BOUND && sk->sk_type == SOCK_DGRAM &&
- listen == true) {
- bh_unlock_sock(sk);
- continue;
}
if (err)
@@ -137,11 +130,8 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
write_unlock(&local->sockets.lock);
- /*
- * If we want to keep the listening sockets alive,
- * we don't touch the RAW ones.
- */
- if (listen == true)
+ /* If we still have a device, we keep the RAW sockets alive */
+ if (device == true)
return;
write_lock(&local->raw_sockets.lock);
@@ -173,9 +163,9 @@ struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
return local;
}
-static void local_cleanup(struct nfc_llcp_local *local, bool listen)
+static void local_cleanup(struct nfc_llcp_local *local)
{
- nfc_llcp_socket_release(local, listen, ENXIO);
+ nfc_llcp_socket_release(local, false, ENXIO);
del_timer_sync(&local->link_timer);
skb_queue_purge(&local->tx_queue);
cancel_work_sync(&local->tx_work);
@@ -194,7 +184,7 @@ static void local_release(struct kref *ref)
local = container_of(ref, struct nfc_llcp_local, ref);
list_del(&local->list);
- local_cleanup(local, false);
+ local_cleanup(local);
kfree(local);
}
@@ -1116,6 +1106,12 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local,
dsap = nfc_llcp_dsap(skb);
ssap = nfc_llcp_ssap(skb);
+ if ((dsap == 0) && (ssap == 0)) {
+ pr_debug("Connection termination");
+ nfc_dep_link_down(local->dev);
+ return;
+ }
+
llcp_sock = nfc_llcp_sock_get(local, dsap, ssap);
if (llcp_sock == NULL) {
nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN);
@@ -1349,19 +1345,54 @@ exit:
nfc_llcp_send_snl_sdres(local, &llc_sdres_list, sdres_tlvs_len);
}
-static void nfc_llcp_rx_work(struct work_struct *work)
+static void nfc_llcp_recv_agf(struct nfc_llcp_local *local, struct sk_buff *skb)
{
- struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
- rx_work);
- u8 dsap, ssap, ptype;
- struct sk_buff *skb;
+ u8 ptype;
+ u16 pdu_len;
+ struct sk_buff *new_skb;
- skb = local->rx_pending;
- if (skb == NULL) {
- pr_debug("No pending SKB\n");
+ if (skb->len <= LLCP_HEADER_SIZE) {
+ pr_err("Malformed AGF PDU\n");
return;
}
+ skb_pull(skb, LLCP_HEADER_SIZE);
+
+ while (skb->len > LLCP_AGF_PDU_HEADER_SIZE) {
+ pdu_len = skb->data[0] << 8 | skb->data[1];
+
+ skb_pull(skb, LLCP_AGF_PDU_HEADER_SIZE);
+
+ if (pdu_len < LLCP_HEADER_SIZE || pdu_len > skb->len) {
+ pr_err("Malformed AGF PDU\n");
+ return;
+ }
+
+ ptype = nfc_llcp_ptype(skb);
+
+ if (ptype == LLCP_PDU_SYMM || ptype == LLCP_PDU_AGF)
+ goto next;
+
+ new_skb = nfc_alloc_recv_skb(pdu_len, GFP_KERNEL);
+ if (new_skb == NULL) {
+ pr_err("Could not allocate PDU\n");
+ return;
+ }
+
+ memcpy(skb_put(new_skb, pdu_len), skb->data, pdu_len);
+
+ nfc_llcp_rx_skb(local, new_skb);
+
+ kfree_skb(new_skb);
+next:
+ skb_pull(skb, pdu_len);
+ }
+}
+
+static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb)
+{
+ u8 dsap, ssap, ptype;
+
ptype = nfc_llcp_ptype(skb);
dsap = nfc_llcp_dsap(skb);
ssap = nfc_llcp_ssap(skb);
@@ -1372,10 +1403,6 @@ static void nfc_llcp_rx_work(struct work_struct *work)
print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET,
16, 1, skb->data, skb->len, true);
- __net_timestamp(skb);
-
- nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX);
-
switch (ptype) {
case LLCP_PDU_SYMM:
pr_debug("SYMM\n");
@@ -1418,7 +1445,30 @@ static void nfc_llcp_rx_work(struct work_struct *work)
nfc_llcp_recv_hdlc(local, skb);
break;
+ case LLCP_PDU_AGF:
+ pr_debug("AGF frame\n");
+ nfc_llcp_recv_agf(local, skb);
+ break;
}
+}
+
+static void nfc_llcp_rx_work(struct work_struct *work)
+{
+ struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
+ rx_work);
+ struct sk_buff *skb;
+
+ skb = local->rx_pending;
+ if (skb == NULL) {
+ pr_debug("No pending SKB\n");
+ return;
+ }
+
+ __net_timestamp(skb);
+
+ nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX);
+
+ nfc_llcp_rx_skb(local, skb);
schedule_work(&local->tx_work);
kfree_skb(local->rx_pending);
@@ -1466,6 +1516,9 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)
if (local == NULL)
return;
+ local->remote_miu = LLCP_DEFAULT_MIU;
+ local->remote_lto = LLCP_DEFAULT_LTO;
+
/* Close and purge all existing sockets */
nfc_llcp_socket_release(local, true, 0);
}
@@ -1553,7 +1606,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
return;
}
- local_cleanup(local, false);
+ local_cleanup(local);
nfc_llcp_local_put(local);
}
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index 7e87a66b02ec..ff8c434f7df8 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -31,6 +31,7 @@ enum llcp_state {
#define LLCP_MAX_LTO 0xff
#define LLCP_MAX_RW 15
#define LLCP_MAX_MIUX 0x7ff
+#define LLCP_MAX_MIU (LLCP_MAX_MIUX + 128)
#define LLCP_WKS_NUM_SAP 16
#define LLCP_SDP_NUM_SAP 16
@@ -124,7 +125,7 @@ struct nfc_llcp_sock {
char *service_name;
size_t service_name_len;
u8 rw;
- u16 miux;
+ __be16 miux;
/* Remote link parameters */
@@ -162,6 +163,7 @@ struct nfc_llcp_ui_cb {
#define LLCP_HEADER_SIZE 2
#define LLCP_SEQUENCE_SIZE 1
+#define LLCP_AGF_PDU_HEADER_SIZE 2
/* LLCP versions: 1.1 is 1.0 plus SDP */
#define LLCP_VERSION_10 0x10
@@ -210,6 +212,7 @@ struct nfc_llcp_ui_cb {
void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s);
void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s);
+void nfc_llcp_socket_remote_param_init(struct nfc_llcp_sock *sock);
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local);
int nfc_llcp_local_put(struct nfc_llcp_local *local);
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index c1101e6de170..d6faa47c9bba 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -279,7 +279,7 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname,
break;
}
- llcp_sock->miux = (u16) opt;
+ llcp_sock->miux = cpu_to_be16((u16) opt);
break;
@@ -299,9 +299,12 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname,
static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
+ struct nfc_llcp_local *local;
struct sock *sk = sock->sk;
struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
int len, err = 0;
+ u16 miux, remote_miu;
+ u8 rw;
pr_debug("%p optname %d\n", sk, optname);
@@ -311,19 +314,48 @@ static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
if (get_user(len, optlen))
return -EFAULT;
+ local = llcp_sock->local;
+ if (!local)
+ return -ENODEV;
+
len = min_t(u32, len, sizeof(u32));
lock_sock(sk);
switch (optname) {
case NFC_LLCP_RW:
- if (put_user(llcp_sock->rw, (u32 __user *) optval))
+ rw = llcp_sock->rw > LLCP_MAX_RW ? local->rw : llcp_sock->rw;
+ if (put_user(rw, (u32 __user *) optval))
err = -EFAULT;
break;
case NFC_LLCP_MIUX:
- if (put_user(llcp_sock->miux, (u32 __user *) optval))
+ miux = be16_to_cpu(llcp_sock->miux) > LLCP_MAX_MIUX ?
+ be16_to_cpu(local->miux) : be16_to_cpu(llcp_sock->miux);
+
+ if (put_user(miux, (u32 __user *) optval))
+ err = -EFAULT;
+
+ break;
+
+ case NFC_LLCP_REMOTE_MIU:
+ remote_miu = llcp_sock->remote_miu > LLCP_MAX_MIU ?
+ local->remote_miu : llcp_sock->remote_miu;
+
+ if (put_user(remote_miu, (u32 __user *) optval))
+ err = -EFAULT;
+
+ break;
+
+ case NFC_LLCP_REMOTE_LTO:
+ if (put_user(local->remote_lto / 10, (u32 __user *) optval))
+ err = -EFAULT;
+
+ break;
+
+ case NFC_LLCP_REMOTE_RW:
+ if (put_user(llcp_sock->remote_rw, (u32 __user *) optval))
err = -EFAULT;
break;
@@ -925,13 +957,12 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
llcp_sock->ssap = 0;
llcp_sock->dsap = LLCP_SAP_SDP;
llcp_sock->rw = LLCP_MAX_RW + 1;
- llcp_sock->miux = LLCP_MAX_MIUX + 1;
- llcp_sock->remote_rw = LLCP_DEFAULT_RW;
- llcp_sock->remote_miu = LLCP_DEFAULT_MIU;
+ llcp_sock->miux = cpu_to_be16(LLCP_MAX_MIUX + 1);
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;
+ nfc_llcp_socket_remote_param_init(llcp_sock);
skb_queue_head_init(&llcp_sock->tx_queue);
skb_queue_head_init(&llcp_sock->tx_pending_queue);
INIT_LIST_HEAD(&llcp_sock->accept_queue);
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index 9b9be5279f5d..1cec5e4f3a5e 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -587,7 +587,7 @@ static ssize_t rfkill_name_show(struct device *dev,
static const char *rfkill_get_type_str(enum rfkill_type type)
{
- BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_FM + 1);
+ BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_NFC + 1);
switch (type) {
case RFKILL_TYPE_WLAN:
@@ -604,6 +604,8 @@ static const char *rfkill_get_type_str(enum rfkill_type type)
return "gps";
case RFKILL_TYPE_FM:
return "fm";
+ case RFKILL_TYPE_NFC:
+ return "nfc";
default:
BUG();
}
diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
index 78fc0937948d..fb076cd6f808 100644
--- a/net/rfkill/rfkill-gpio.c
+++ b/net/rfkill/rfkill-gpio.c
@@ -131,6 +131,7 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
rfkill->pwr_clk = clk_get(&pdev->dev, pdata->power_clk_name);
if (IS_ERR(rfkill->pwr_clk)) {
pr_warn("%s: can't find pwr_clk.\n", __func__);
+ ret = PTR_ERR(rfkill->pwr_clk);
goto fail_shutdown_name;
}
}
@@ -152,9 +153,11 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
}
rfkill->rfkill_dev = rfkill_alloc(pdata->name, &pdev->dev, pdata->type,
- &rfkill_gpio_ops, rfkill);
- if (!rfkill->rfkill_dev)
+ &rfkill_gpio_ops, rfkill);
+ if (!rfkill->rfkill_dev) {
+ ret = -ENOMEM;
goto fail_shutdown;
+ }
ret = rfkill_register(rfkill->rfkill_dev);
if (ret < 0)
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 124e5e773fbc..fd35dae547c4 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -88,6 +88,9 @@ struct cfg80211_registered_device {
struct delayed_work dfs_update_channels_wk;
+ /* netlink port which started critical protocol (0 means not started) */
+ u32 crit_proto_nlportid;
+
/* must be last because of the way we do wiphy_priv(),
* and it should at least be aligned to NETDEV_ALIGN */
struct wiphy wiphy __aligned(NETDEV_ALIGN);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 390198bf4b36..0c7b7dd855f6 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -648,6 +648,11 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
spin_unlock_bh(&wdev->mgmt_registrations_lock);
+ if (nlportid && rdev->crit_proto_nlportid == nlportid) {
+ rdev->crit_proto_nlportid = 0;
+ rdev_crit_proto_stop(rdev, wdev);
+ }
+
if (nlportid == wdev->ap_unexpected_nlportid)
wdev->ap_unexpected_nlportid = 0;
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 671b69a3c136..afa283841e8c 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -447,62 +447,69 @@ nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
};
-/* ifidx get helper */
-static int nl80211_get_ifidx(struct netlink_callback *cb)
+static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct cfg80211_registered_device **rdev,
+ struct wireless_dev **wdev)
{
- int res;
-
- res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
- nl80211_fam.attrbuf, nl80211_fam.maxattr,
- nl80211_policy);
- if (res)
- return res;
-
- if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
- return -EINVAL;
+ int err;
- res = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
- if (!res)
- return -EINVAL;
- return res;
-}
+ rtnl_lock();
+ mutex_lock(&cfg80211_mutex);
-static int nl80211_prepare_netdev_dump(struct sk_buff *skb,
- struct netlink_callback *cb,
- struct cfg80211_registered_device **rdev,
- struct net_device **dev)
-{
- int ifidx = cb->args[0];
- int err;
+ if (!cb->args[0]) {
+ err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
+ nl80211_fam.attrbuf, nl80211_fam.maxattr,
+ nl80211_policy);
+ if (err)
+ goto out_unlock;
- if (!ifidx)
- ifidx = nl80211_get_ifidx(cb);
- if (ifidx < 0)
- return ifidx;
+ *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk),
+ nl80211_fam.attrbuf);
+ if (IS_ERR(*wdev)) {
+ err = PTR_ERR(*wdev);
+ goto out_unlock;
+ }
+ *rdev = wiphy_to_dev((*wdev)->wiphy);
+ cb->args[0] = (*rdev)->wiphy_idx;
+ cb->args[1] = (*wdev)->identifier;
+ } else {
+ struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0]);
+ struct wireless_dev *tmp;
- cb->args[0] = ifidx;
+ if (!wiphy) {
+ err = -ENODEV;
+ goto out_unlock;
+ }
+ *rdev = wiphy_to_dev(wiphy);
+ *wdev = NULL;
- rtnl_lock();
+ mutex_lock(&(*rdev)->devlist_mtx);
+ list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
+ if (tmp->identifier == cb->args[1]) {
+ *wdev = tmp;
+ break;
+ }
+ }
+ mutex_unlock(&(*rdev)->devlist_mtx);
- *dev = __dev_get_by_index(sock_net(skb->sk), ifidx);
- if (!*dev) {
- err = -ENODEV;
- goto out_rtnl;
+ if (!*wdev) {
+ err = -ENODEV;
+ goto out_unlock;
+ }
}
- *rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
- if (IS_ERR(*rdev)) {
- err = PTR_ERR(*rdev);
- goto out_rtnl;
- }
+ cfg80211_lock_rdev(*rdev);
+ mutex_unlock(&cfg80211_mutex);
return 0;
- out_rtnl:
+ out_unlock:
+ mutex_unlock(&cfg80211_mutex);
rtnl_unlock();
return err;
}
-static void nl80211_finish_netdev_dump(struct cfg80211_registered_device *rdev)
+static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)
{
cfg80211_unlock_rdev(rdev);
rtnl_unlock();
@@ -1417,6 +1424,10 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
}
CMD(start_p2p_device, START_P2P_DEVICE);
CMD(set_mcast_rate, SET_MCAST_RATE);
+ if (split) {
+ CMD(crit_proto_start, CRIT_PROTOCOL_START);
+ CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
+ }
#ifdef CONFIG_NL80211_TESTMODE
CMD(testmode_cmd, TESTMODE);
@@ -3525,15 +3536,20 @@ static int nl80211_dump_station(struct sk_buff *skb,
{
struct station_info sinfo;
struct cfg80211_registered_device *dev;
- struct net_device *netdev;
+ struct wireless_dev *wdev;
u8 mac_addr[ETH_ALEN];
- int sta_idx = cb->args[1];
+ int sta_idx = cb->args[2];
int err;
- err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
+ err = nl80211_prepare_wdev_dump(skb, cb, &dev, &wdev);
if (err)
return err;
+ if (!wdev->netdev) {
+ err = -EINVAL;
+ goto out_err;
+ }
+
if (!dev->ops->dump_station) {
err = -EOPNOTSUPP;
goto out_err;
@@ -3541,7 +3557,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
while (1) {
memset(&sinfo, 0, sizeof(sinfo));
- err = rdev_dump_station(dev, netdev, sta_idx,
+ err = rdev_dump_station(dev, wdev->netdev, sta_idx,
mac_addr, &sinfo);
if (err == -ENOENT)
break;
@@ -3551,7 +3567,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
if (nl80211_send_station(skb,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
- dev, netdev, mac_addr,
+ dev, wdev->netdev, mac_addr,
&sinfo) < 0)
goto out;
@@ -3560,10 +3576,10 @@ static int nl80211_dump_station(struct sk_buff *skb,
out:
- cb->args[1] = sta_idx;
+ cb->args[2] = sta_idx;
err = skb->len;
out_err:
- nl80211_finish_netdev_dump(dev);
+ nl80211_finish_wdev_dump(dev);
return err;
}
@@ -4167,13 +4183,13 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
{
struct mpath_info pinfo;
struct cfg80211_registered_device *dev;
- struct net_device *netdev;
+ struct wireless_dev *wdev;
u8 dst[ETH_ALEN];
u8 next_hop[ETH_ALEN];
- int path_idx = cb->args[1];
+ int path_idx = cb->args[2];
int err;
- err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
+ err = nl80211_prepare_wdev_dump(skb, cb, &dev, &wdev);
if (err)
return err;
@@ -4182,14 +4198,14 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
goto out_err;
}
- if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
+ if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
err = -EOPNOTSUPP;
goto out_err;
}
while (1) {
- err = rdev_dump_mpath(dev, netdev, path_idx, dst, next_hop,
- &pinfo);
+ err = rdev_dump_mpath(dev, wdev->netdev, path_idx, dst,
+ next_hop, &pinfo);
if (err == -ENOENT)
break;
if (err)
@@ -4197,7 +4213,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
- netdev, dst, next_hop,
+ wdev->netdev, dst, next_hop,
&pinfo) < 0)
goto out;
@@ -4206,10 +4222,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
out:
- cb->args[1] = path_idx;
+ cb->args[2] = path_idx;
err = skb->len;
out_err:
- nl80211_finish_netdev_dump(dev);
+ nl80211_finish_wdev_dump(dev);
return err;
}
@@ -5565,9 +5581,13 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
genl_dump_check_consistent(cb, hdr, &nl80211_fam);
- if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation) ||
+ if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation))
+ goto nla_put_failure;
+ if (wdev->netdev &&
nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex))
goto nla_put_failure;
+ if (nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
+ goto nla_put_failure;
bss = nla_nest_start(msg, NL80211_ATTR_BSS);
if (!bss)
@@ -5647,22 +5667,18 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
return -EMSGSIZE;
}
-static int nl80211_dump_scan(struct sk_buff *skb,
- struct netlink_callback *cb)
+static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
{
struct cfg80211_registered_device *rdev;
- struct net_device *dev;
struct cfg80211_internal_bss *scan;
struct wireless_dev *wdev;
- int start = cb->args[1], idx = 0;
+ int start = cb->args[2], idx = 0;
int err;
- err = nl80211_prepare_netdev_dump(skb, cb, &rdev, &dev);
+ err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
if (err)
return err;
- wdev = dev->ieee80211_ptr;
-
wdev_lock(wdev);
spin_lock_bh(&rdev->bss_lock);
cfg80211_bss_expire(rdev);
@@ -5683,8 +5699,8 @@ static int nl80211_dump_scan(struct sk_buff *skb,
spin_unlock_bh(&rdev->bss_lock);
wdev_unlock(wdev);
- cb->args[1] = idx;
- nl80211_finish_netdev_dump(rdev);
+ cb->args[2] = idx;
+ nl80211_finish_wdev_dump(rdev);
return skb->len;
}
@@ -5753,14 +5769,19 @@ static int nl80211_dump_survey(struct sk_buff *skb,
{
struct survey_info survey;
struct cfg80211_registered_device *dev;
- struct net_device *netdev;
- int survey_idx = cb->args[1];
+ struct wireless_dev *wdev;
+ int survey_idx = cb->args[2];
int res;
- res = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
+ res = nl80211_prepare_wdev_dump(skb, cb, &dev, &wdev);
if (res)
return res;
+ if (!wdev->netdev) {
+ res = -EINVAL;
+ goto out_err;
+ }
+
if (!dev->ops->dump_survey) {
res = -EOPNOTSUPP;
goto out_err;
@@ -5769,7 +5790,7 @@ static int nl80211_dump_survey(struct sk_buff *skb,
while (1) {
struct ieee80211_channel *chan;
- res = rdev_dump_survey(dev, netdev, survey_idx, &survey);
+ res = rdev_dump_survey(dev, wdev->netdev, survey_idx, &survey);
if (res == -ENOENT)
break;
if (res)
@@ -5791,17 +5812,16 @@ static int nl80211_dump_survey(struct sk_buff *skb,
if (nl80211_send_survey(skb,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
- netdev,
- &survey) < 0)
+ wdev->netdev, &survey) < 0)
goto out;
survey_idx++;
}
out:
- cb->args[1] = survey_idx;
+ cb->args[2] = survey_idx;
res = skb->len;
out_err:
- nl80211_finish_netdev_dump(dev);
+ nl80211_finish_wdev_dump(dev);
return res;
}
@@ -8143,9 +8163,11 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
if (!rdev->ops->stop_p2p_device)
return -EOPNOTSUPP;
+ mutex_lock(&rdev->devlist_mtx);
mutex_lock(&rdev->sched_scan_mtx);
cfg80211_stop_p2p_device(rdev, wdev);
mutex_unlock(&rdev->sched_scan_mtx);
+ mutex_unlock(&rdev->devlist_mtx);
return 0;
}
@@ -8198,6 +8220,64 @@ static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
return rdev_update_ft_ies(rdev, dev, &ft_params);
}
+static int nl80211_crit_protocol_start(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct wireless_dev *wdev = info->user_ptr[1];
+ enum nl80211_crit_proto_id proto = NL80211_CRIT_PROTO_UNSPEC;
+ u16 duration;
+ int ret;
+
+ if (!rdev->ops->crit_proto_start)
+ return -EOPNOTSUPP;
+
+ if (WARN_ON(!rdev->ops->crit_proto_stop))
+ return -EINVAL;
+
+ if (rdev->crit_proto_nlportid)
+ return -EBUSY;
+
+ /* determine protocol if provided */
+ if (info->attrs[NL80211_ATTR_CRIT_PROT_ID])
+ proto = nla_get_u16(info->attrs[NL80211_ATTR_CRIT_PROT_ID]);
+
+ if (proto >= NUM_NL80211_CRIT_PROTO)
+ return -EINVAL;
+
+ /* timeout must be provided */
+ if (!info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION])
+ return -EINVAL;
+
+ duration =
+ nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]);
+
+ if (duration > NL80211_CRIT_PROTO_MAX_DURATION)
+ return -ERANGE;
+
+ ret = rdev_crit_proto_start(rdev, wdev, proto, duration);
+ if (!ret)
+ rdev->crit_proto_nlportid = info->snd_portid;
+
+ return ret;
+}
+
+static int nl80211_crit_protocol_stop(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct wireless_dev *wdev = info->user_ptr[1];
+
+ if (!rdev->ops->crit_proto_stop)
+ return -EOPNOTSUPP;
+
+ if (rdev->crit_proto_nlportid) {
+ rdev->crit_proto_nlportid = 0;
+ rdev_crit_proto_stop(rdev, wdev);
+ }
+ return 0;
+}
+
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
@@ -8887,6 +8967,22 @@ static struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_CRIT_PROTOCOL_START,
+ .doit = nl80211_crit_protocol_start,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
+ {
+ .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
+ .doit = nl80211_crit_protocol_stop,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ }
};
static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -10632,6 +10728,45 @@ void cfg80211_ft_event(struct net_device *netdev,
}
EXPORT_SYMBOL(cfg80211_ft_event);
+void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
+{
+ struct cfg80211_registered_device *rdev;
+ struct sk_buff *msg;
+ void *hdr;
+ u32 nlportid;
+
+ rdev = wiphy_to_dev(wdev->wiphy);
+ if (!rdev->crit_proto_nlportid)
+ return;
+
+ nlportid = rdev->crit_proto_nlportid;
+ rdev->crit_proto_nlportid = 0;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CRIT_PROTOCOL_STOP);
+ if (!hdr)
+ goto nla_put_failure;
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+ nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
+ goto nla_put_failure;
+
+ genlmsg_end(msg, hdr);
+
+ genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
+ return;
+
+ nla_put_failure:
+ if (hdr)
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+
+}
+EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
+
/* initialisation/exit functions */
int nl80211_init(void)
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index d77e1c1d3a0e..9f15f0ac824d 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -875,7 +875,7 @@ static inline void rdev_stop_p2p_device(struct cfg80211_registered_device *rdev,
trace_rdev_stop_p2p_device(&rdev->wiphy, wdev);
rdev->ops->stop_p2p_device(&rdev->wiphy, wdev);
trace_rdev_return_void(&rdev->wiphy);
-}
+}
static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev,
struct net_device *dev,
@@ -901,4 +901,26 @@ static inline int rdev_update_ft_ies(struct cfg80211_registered_device *rdev,
return ret;
}
+static inline int rdev_crit_proto_start(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ enum nl80211_crit_proto_id protocol,
+ u16 duration)
+{
+ int ret;
+
+ trace_rdev_crit_proto_start(&rdev->wiphy, wdev, protocol, duration);
+ ret = rdev->ops->crit_proto_start(&rdev->wiphy, wdev,
+ protocol, duration);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline void rdev_crit_proto_stop(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev)
+{
+ trace_rdev_crit_proto_stop(&rdev->wiphy, wdev);
+ rdev->ops->crit_proto_stop(&rdev->wiphy, wdev);
+ trace_rdev_return_void(&rdev->wiphy);
+}
+
#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index e6df52dc8c69..cc35fbaa4578 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -855,7 +855,7 @@ static void handle_channel(struct wiphy *wiphy,
return;
REG_DBG_PRINT("Disabling freq %d MHz\n", chan->center_freq);
- chan->flags = IEEE80211_CHAN_DISABLED;
+ chan->flags |= IEEE80211_CHAN_DISABLED;
return;
}
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 3c2033b8f596..ecd4fcec3c94 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1806,6 +1806,41 @@ TRACE_EVENT(rdev_update_ft_ies,
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->md)
);
+TRACE_EVENT(rdev_crit_proto_start,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+ enum nl80211_crit_proto_id protocol, u16 duration),
+ TP_ARGS(wiphy, wdev, protocol, duration),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ __field(u16, proto)
+ __field(u16, duration)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ __entry->proto = protocol;
+ __entry->duration = duration;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", proto=%x, duration=%u",
+ WIPHY_PR_ARG, WDEV_PR_ARG, __entry->proto, __entry->duration)
+);
+
+TRACE_EVENT(rdev_crit_proto_stop,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+ TP_ARGS(wiphy, wdev),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT,
+ WIPHY_PR_ARG, WDEV_PR_ARG)
+);
+
/*************************************************************
* cfg80211 exported functions traces *
*************************************************************/
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 6cbac99ae03d..f5ad4d94ba88 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1155,6 +1155,26 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
}
EXPORT_SYMBOL(cfg80211_get_p2p_attr);
+bool ieee80211_operating_class_to_band(u8 operating_class,
+ enum ieee80211_band *band)
+{
+ switch (operating_class) {
+ case 112:
+ case 115 ... 127:
+ *band = IEEE80211_BAND_5GHZ;
+ return true;
+ case 81:
+ case 82:
+ case 83:
+ case 84:
+ *band = IEEE80211_BAND_2GHZ;
+ return true;
+ }
+
+ return false;
+}
+EXPORT_SYMBOL(ieee80211_operating_class_to_band);
+
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
u32 beacon_int)
{
@@ -1258,12 +1278,12 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
list_for_each_entry(wdev_iter, &rdev->wdev_list, list) {
if (wdev_iter == wdev)
continue;
- if (wdev_iter->netdev) {
- if (!netif_running(wdev_iter->netdev))
- continue;
- } else if (wdev_iter->iftype == NL80211_IFTYPE_P2P_DEVICE) {
+ if (wdev_iter->iftype == NL80211_IFTYPE_P2P_DEVICE) {
if (!wdev_iter->p2p_started)
continue;
+ } else if (wdev_iter->netdev) {
+ if (!netif_running(wdev_iter->netdev))
+ continue;
} else {
WARN_ON(1);
}