summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-05 12:31:59 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-05 12:31:59 -0700
commit5518b69b76680a4f2df96b1deca260059db0c2de (patch)
treef33cd1519c8efb4590500f2f9617400be233238c /drivers/net/wireless
parent8ad06e56dcbc1984ef0ff8f6e3c19982c5809f73 (diff)
parent0e72582270c07850b92cac351c8b97d4f9c123b9 (diff)
downloadop-kernel-dev-5518b69b76680a4f2df96b1deca260059db0c2de.zip
op-kernel-dev-5518b69b76680a4f2df96b1deca260059db0c2de.tar.gz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: "Reasonably busy this cycle, but perhaps not as busy as in the 4.12 merge window: 1) Several optimizations for UDP processing under high load from Paolo Abeni. 2) Support pacing internally in TCP when using the sch_fq packet scheduler for this is not practical. From Eric Dumazet. 3) Support mutliple filter chains per qdisc, from Jiri Pirko. 4) Move to 1ms TCP timestamp clock, from Eric Dumazet. 5) Add batch dequeueing to vhost_net, from Jason Wang. 6) Flesh out more completely SCTP checksum offload support, from Davide Caratti. 7) More plumbing of extended netlink ACKs, from David Ahern, Pablo Neira Ayuso, and Matthias Schiffer. 8) Add devlink support to nfp driver, from Simon Horman. 9) Add RTM_F_FIB_MATCH flag to RTM_GETROUTE queries, from Roopa Prabhu. 10) Add stack depth tracking to BPF verifier and use this information in the various eBPF JITs. From Alexei Starovoitov. 11) Support XDP on qed device VFs, from Yuval Mintz. 12) Introduce BPF PROG ID for better introspection of installed BPF programs. From Martin KaFai Lau. 13) Add bpf_set_hash helper for TC bpf programs, from Daniel Borkmann. 14) For loads, allow narrower accesses in bpf verifier checking, from Yonghong Song. 15) Support MIPS in the BPF selftests and samples infrastructure, the MIPS eBPF JIT will be merged in via the MIPS GIT tree. From David Daney. 16) Support kernel based TLS, from Dave Watson and others. 17) Remove completely DST garbage collection, from Wei Wang. 18) Allow installing TCP MD5 rules using prefixes, from Ivan Delalande. 19) Add XDP support to Intel i40e driver, from Björn Töpel 20) Add support for TC flower offload in nfp driver, from Simon Horman, Pieter Jansen van Vuuren, Benjamin LaHaise, Jakub Kicinski, and Bert van Leeuwen. 21) IPSEC offloading support in mlx5, from Ilan Tayari. 22) Add HW PTP support to macb driver, from Rafal Ozieblo. 23) Networking refcount_t conversions, From Elena Reshetova. 24) Add sock_ops support to BPF, from Lawrence Brako. This is useful for tuning the TCP sockopt settings of a group of applications, currently via CGROUPs" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1899 commits) net: phy: dp83867: add workaround for incorrect RX_CTRL pin strap dt-bindings: phy: dp83867: provide a workaround for incorrect RX_CTRL pin strap cxgb4: Support for get_ts_info ethtool method cxgb4: Add PTP Hardware Clock (PHC) support cxgb4: time stamping interface for PTP nfp: default to chained metadata prepend format nfp: remove legacy MAC address lookup nfp: improve order of interfaces in breakout mode net: macb: remove extraneous return when MACB_EXT_DESC is defined bpf: add missing break in for the TCP_BPF_SNDCWND_CLAMP case bpf: fix return in load_bpf_file mpls: fix rtm policy in mpls_getroute net, ax25: convert ax25_cb.refcount from atomic_t to refcount_t net, ax25: convert ax25_route.refcount from atomic_t to refcount_t net, ax25: convert ax25_uid_assoc.refcount from atomic_t to refcount_t net, sctp: convert sctp_ep_common.refcnt from atomic_t to refcount_t net, sctp: convert sctp_transport.refcnt from atomic_t to refcount_t net, sctp: convert sctp_chunk.refcnt from atomic_t to refcount_t net, sctp: convert sctp_datamsg.refcnt from atomic_t to refcount_t net, sctp: convert sctp_auth_bytes.refcnt from atomic_t to refcount_t ...
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/Kconfig1
-rw-r--r--drivers/net/wireless/Makefile1
-rw-r--r--drivers/net/wireless/admtek/adm8211.c8
-rw-r--r--drivers/net/wireless/ath/ar5523/ar5523.c4
-rw-r--r--drivers/net/wireless/ath/ath10k/Kconfig7
-rw-r--r--drivers/net/wireless/ath/ath10k/Makefile3
-rw-r--r--drivers/net/wireless/ath/ath10k/bmi.c71
-rw-r--r--drivers/net/wireless/ath/ath10k/bmi.h8
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.c168
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.h132
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c89
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h4
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c16
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.h2
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.c244
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.h39
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c27
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.c137
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h140
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c84
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c29
-rw-r--r--drivers/net/wireless/ath/ath10k/sdio.c2113
-rw-r--r--drivers/net/wireless/ath/ath10k/sdio.h229
-rw-r--r--drivers/net/wireless/ath/ath10k/targaddrs.h24
-rw-r--r--drivers/net/wireless/ath/ath10k/testmode.c7
-rw-r--r--drivers/net/wireless/ath/ath10k/testmode_i.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/thermal.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c56
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h3
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.c5
-rw-r--r--drivers/net/wireless/ath/ath6kl/debug.c2
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_pipe.c11
-rw-r--r--drivers/net/wireless/ath/ath6kl/txrx.c13
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/channel.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/common.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_hst.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/mci.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/rng.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/tx99.c15
-rw-r--r--drivers/net/wireless/ath/ath9k/wmi.c6
-rw-r--r--drivers/net/wireless/ath/carl9170/rx.c6
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/Makefile1
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c613
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c61
-rw-r--r--drivers/net/wireless/ath/wil6210/interrupt.c6
-rw-r--r--drivers/net/wireless/ath/wil6210/ioctl.c180
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c7
-rw-r--r--drivers/net/wireless/ath/wil6210/netdev.c8
-rw-r--r--drivers/net/wireless/ath/wil6210/pcie_bus.c98
-rw-r--r--drivers/net/wireless/ath/wil6210/pm.c228
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c73
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h40
-rw-r--r--drivers/net/wireless/ath/wil6210/wil_platform.h7
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c151
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.h27
-rw-r--r--drivers/net/wireless/atmel/atmel.c5
-rw-r--r--drivers/net/wireless/broadcom/b43/main.c10
-rw-r--r--drivers/net/wireless/broadcom/b43legacy/dma.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c15
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h18
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c244
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h23
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c29
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c23
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h6
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h30
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h92
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c452
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h55
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c20
-rw-r--r--drivers/net/wireless/cisco/airo.c4
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2200.c7
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_tx.c9
-rw-r--r--drivers/net/wireless/intel/iwlegacy/3945.c2
-rw-r--r--drivers/net/wireless/intel/iwlegacy/4965-mac.c2
-rw-r--r--drivers/net/wireless/intel/iwlegacy/common.c2
-rw-r--r--drivers/net/wireless/intel/iwlegacy/common.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/Makefile6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/1000.c (renamed from drivers/net/wireless/intel/iwlwifi/iwl-1000.c)0
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/2000.c (renamed from drivers/net/wireless/intel/iwlwifi/iwl-2000.c)0
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/5000.c (renamed from drivers/net/wireless/intel/iwlwifi/iwl-5000.c)0
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/6000.c (renamed from drivers/net/wireless/intel/iwlwifi/iwl-6000.c)0
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/7000.c (renamed from drivers/net/wireless/intel/iwlwifi/iwl-7000.c)0
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/8000.c (renamed from drivers/net/wireless/intel/iwlwifi/iwl-8000.c)10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/9000.c (renamed from drivers/net/wireless/intel/iwlwifi/iwl-9000.c)14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/a000.c (renamed from drivers/net/wireless/intel/iwlwifi/iwl-a000.c)20
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/dev.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/lib.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/main.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/rx.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/rxon.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/tx.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api.h229
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/error-dump.h (renamed from drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h)8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/file.h (renamed from drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h)21
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/img.h (renamed from drivers/net/wireless/intel/iwlwifi/iwl-fw.h)10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/notif-wait.c (renamed from drivers/net/wireless/intel/iwlwifi/iwl-notif-wait.c)2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/notif-wait.h (renamed from drivers/net/wireless/intel/iwlwifi/iwl-notif-wait.h)0
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-config.h13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-csr.h14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h26
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h19
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c20
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.h12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-fh.h30
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-io.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-modparams.h18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c97
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-phy-db.c18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-prph.h17
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.h188
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/coex.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/constants.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c51
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c392
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-coex.h21
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h40
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-mac.h14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-power.h54
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h125
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-scan.h72
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h109
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-stats.h196
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tof.h32
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h158
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h902
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c62
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c160
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/led.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c43
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c137
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h86
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/nvm.c172
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c106
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c85
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c284
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tdls.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tof.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tt.c14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c178
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c101
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/drv.c49
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/internal.h38
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/rx.c157
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c36
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c349
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c184
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx.c53
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_80211_rx.c8
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_80211_tx.c2
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_ap.c11
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_hw.c23
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_main.c6
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_wlan.h3
-rw-r--r--drivers/net/wireless/intersil/orinoco/main.c9
-rw-r--r--drivers/net/wireless/intersil/orinoco/orinoco_usb.c15
-rw-r--r--drivers/net/wireless/intersil/p54/fwio.c48
-rw-r--r--drivers/net/wireless/intersil/p54/p54spi.c4
-rw-r--r--drivers/net/wireless/intersil/p54/txrx.c12
-rw-r--r--drivers/net/wireless/intersil/prism54/islpci_eth.c5
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c17
-rw-r--r--drivers/net/wireless/marvell/libertas/cfg.c104
-rw-r--r--drivers/net/wireless/marvell/libertas/cmd.c116
-rw-r--r--drivers/net/wireless/marvell/libertas/cmdresp.c9
-rw-r--r--drivers/net/wireless/marvell/libertas/defs.h9
-rw-r--r--drivers/net/wireless/marvell/libertas/ethtool.c3
-rw-r--r--drivers/net/wireless/marvell/libertas/if_cs.c36
-rw-r--r--drivers/net/wireless/marvell/libertas/if_sdio.c71
-rw-r--r--drivers/net/wireless/marvell/libertas/if_spi.c38
-rw-r--r--drivers/net/wireless/marvell/libertas/if_usb.c27
-rw-r--r--drivers/net/wireless/marvell/libertas/main.c81
-rw-r--r--drivers/net/wireless/marvell/libertas/mesh.c59
-rw-r--r--drivers/net/wireless/marvell/libertas/rx.c8
-rw-r--r--drivers/net/wireless/marvell/libertas/tx.c3
-rw-r--r--drivers/net/wireless/marvell/libertas_tf/main.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/11h.c6
-rw-r--r--drivers/net/wireless/marvell/mwifiex/11n.c17
-rw-r--r--drivers/net/wireless/marvell/mwifiex/11n_aggr.c18
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c89
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfp.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cmdevt.c18
-rw-r--r--drivers/net/wireless/marvell/mwifiex/debugfs.c3
-rw-r--r--drivers/net/wireless/marvell/mwifiex/fw.h15
-rw-r--r--drivers/net/wireless/marvell/mwifiex/init.c17
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.c4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.h23
-rw-r--r--drivers/net/wireless/marvell/mwifiex/pcie.c207
-rw-r--r--drivers/net/wireless/marvell/mwifiex/scan.c4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sdio.c28
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_cmd.c18
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c24
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_tx.c12
-rw-r--r--drivers/net/wireless/marvell/mwifiex/tdls.c60
-rw-r--r--drivers/net/wireless/marvell/mwifiex/txrx.c15
-rw-r--r--drivers/net/wireless/marvell/mwifiex/uap_cmd.c22
-rw-r--r--drivers/net/wireless/marvell/mwifiex/uap_event.c11
-rw-r--r--drivers/net/wireless/marvell/mwifiex/uap_txrx.c5
-rw-r--r--drivers/net/wireless/marvell/mwifiex/usb.c585
-rw-r--r--drivers/net/wireless/marvell/mwifiex/usb.h23
-rw-r--r--drivers/net/wireless/marvell/mwifiex/wmm.c16
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/dma.c4
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/mcu.c2
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/tx.c2
-rw-r--r--drivers/net/wireless/quantenna/Kconfig16
-rw-r--r--drivers/net/wireless/quantenna/Makefile6
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/Kconfig19
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/Makefile31
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/bus.h139
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/cfg80211.c995
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/cfg80211.h43
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/commands.c1978
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/commands.h74
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/core.c618
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/core.h173
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/debug.c46
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/debug.h50
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/event.c452
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/event.h27
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c1378
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h89
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_ipc.h158
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_regs_pearl.h353
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/qlink.h901
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/qlink_util.c71
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/qlink_util.h74
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h32
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c176
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h80
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h46
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/trans.c224
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/trans.h57
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/util.c114
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/util.h45
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2400pci.c181
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2500pci.c195
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2500usb.c173
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800lib.c911
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800lib.h22
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800mmio.c44
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800pci.c6
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800usb.c20
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00.h12
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00debug.c9
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00debug.h4
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c2
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h7
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00queue.h12
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00usb.c2
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00usb.h16
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt61pci.c285
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt73usb.c189
-rw-r--r--drivers/net/wireless/ray_cs.c7
-rw-r--r--drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c6
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.c288
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.h16
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h22
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c70
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h34
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c2087
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h80
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c80
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c275
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h42
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c515
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h36
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c889
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h73
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c85
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h7
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/core.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/debug.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/debug.h7
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pci.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/ps.c14
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c82
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h14
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c9
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c81
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c12
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h16
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c88
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h17
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/usb.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/wifi.h34
-rw-r--r--drivers/net/wireless/rsi/Makefile2
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_core.c2
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_debugfs.c2
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_hal.c742
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_main.c9
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mgmt.c132
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_pkt.c215
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_sdio.c228
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_sdio_ops.c190
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_usb.c167
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_usb_ops.c125
-rw-r--r--drivers/net/wireless/rsi/rsi_boot_params.h15
-rw-r--r--drivers/net/wireless/rsi/rsi_common.h3
-rw-r--r--drivers/net/wireless/rsi/rsi_hal.h84
-rw-r--r--drivers/net/wireless/rsi/rsi_main.h64
-rw-r--r--drivers/net/wireless/rsi/rsi_mgmt.h76
-rw-r--r--drivers/net/wireless/rsi/rsi_sdio.h6
-rw-r--r--drivers/net/wireless/rsi/rsi_usb.h5
-rw-r--r--drivers/net/wireless/st/cw1200/cw1200_sdio.c2
-rw-r--r--drivers/net/wireless/st/cw1200/cw1200_spi.c2
-rw-r--r--drivers/net/wireless/st/cw1200/scan.c2
-rw-r--r--drivers/net/wireless/st/cw1200/txrx.c2
-rw-r--r--drivers/net/wireless/ti/wl1251/main.c2
-rw-r--r--drivers/net/wireless/ti/wl1251/tx.c3
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c6
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c9
-rw-r--r--drivers/net/wireless/ti/wlcore/debugfs.c13
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c5
-rw-r--r--drivers/net/wireless/ti/wlcore/rx.c5
-rw-r--r--drivers/net/wireless/ti/wlcore/sdio.c1
-rw-r--r--drivers/net/wireless/ti/wlcore/spi.c14
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.c3
-rw-r--r--drivers/net/wireless/zydas/zd1201.c26
-rw-r--r--drivers/net/wireless/zydas/zd1211rw/zd_mac.c5
370 files changed, 24987 insertions, 6553 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 8f5a3f4..166920a 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -45,6 +45,7 @@ source "drivers/net/wireless/rsi/Kconfig"
source "drivers/net/wireless/st/Kconfig"
source "drivers/net/wireless/ti/Kconfig"
source "drivers/net/wireless/zydas/Kconfig"
+source "drivers/net/wireless/quantenna/Kconfig"
config PCMCIA_RAYCS
tristate "Aviator/Raytheon 2.4GHz wireless support"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index f00d429..54b41ac 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_WLAN_VENDOR_RSI) += rsi/
obj-$(CONFIG_WLAN_VENDOR_ST) += st/
obj-$(CONFIG_WLAN_VENDOR_TI) += ti/
obj-$(CONFIG_WLAN_VENDOR_ZYDAS) += zydas/
+obj-$(CONFIG_WLAN_VENDOR_QUANTENNA) += quantenna/
# 16-bit wireless PCMCIA client drivers
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
diff --git a/drivers/net/wireless/admtek/adm8211.c b/drivers/net/wireless/admtek/adm8211.c
index ed626f56..3b0802f 100644
--- a/drivers/net/wireless/admtek/adm8211.c
+++ b/drivers/net/wireless/admtek/adm8211.c
@@ -390,9 +390,9 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev)
priv->pdev,
priv->rx_buffers[entry].mapping,
pktlen, PCI_DMA_FROMDEVICE);
- memcpy(skb_put(skb, pktlen),
- skb_tail_pointer(priv->rx_buffers[entry].skb),
- pktlen);
+ skb_put_data(skb,
+ skb_tail_pointer(priv->rx_buffers[entry].skb),
+ pktlen);
pci_dma_sync_single_for_device(
priv->pdev,
priv->rx_buffers[entry].mapping,
@@ -1700,7 +1700,7 @@ static void adm8211_tx(struct ieee80211_hw *dev,
skb_pull(skb, hdrlen);
payload_len = skb->len;
- txhdr = (struct adm8211_tx_hdr *) skb_push(skb, sizeof(*txhdr));
+ txhdr = skb_push(skb, sizeof(*txhdr));
memset(txhdr, 0, sizeof(*txhdr));
memcpy(txhdr->da, ieee80211_get_DA(hdr), ETH_ALEN);
txhdr->signal = plcp_signal;
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c
index f2f4ccf..106d6f8 100644
--- a/drivers/net/wireless/ath/ar5523/ar5523.c
+++ b/drivers/net/wireless/ath/ar5523/ar5523.c
@@ -829,8 +829,8 @@ static void ar5523_tx_work_locked(struct ar5523 *ar)
data->ar = ar;
data->urb = urb;
- desc = (struct ar5523_tx_desc *)skb_push(skb, sizeof(*desc));
- chunk = (struct ar5523_chunk *)skb_push(skb, sizeof(*chunk));
+ desc = skb_push(skb, sizeof(*desc));
+ chunk = skb_push(skb, sizeof(*chunk));
chunk->seqnum = 0;
chunk->flags = UATH_CFLAGS_FINAL;
diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index b4241cf..412eb13 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -22,6 +22,13 @@ config ATH10K_AHB
---help---
This module adds support for AHB bus
+config ATH10K_SDIO
+ tristate "Atheros ath10k SDIO support (EXPERIMENTAL)"
+ depends on ATH10K && MMC
+ ---help---
+ This module adds experimental support for SDIO/MMC bus. Currently
+ work in progress and will not fully work.
+
config ATH10K_DEBUG
bool "Atheros ath10k debugging"
depends on ATH10K
diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile
index 930fadd..b0b19a7 100644
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -27,5 +27,8 @@ ath10k_pci-y += pci.o \
ath10k_pci-$(CONFIG_ATH10K_AHB) += ahb.o
+obj-$(CONFIG_ATH10K_SDIO) += ath10k_sdio.o
+ath10k_sdio-y += sdio.o
+
# for tracing framework to find trace.h
CFLAGS_trace.o := -I$(src)
diff --git a/drivers/net/wireless/ath/ath10k/bmi.c b/drivers/net/wireless/ath/ath10k/bmi.c
index abeee20..2d3a2f3 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.c
+++ b/drivers/net/wireless/ath/ath10k/bmi.c
@@ -97,6 +97,77 @@ int ath10k_bmi_get_target_info(struct ath10k *ar,
return 0;
}
+#define TARGET_VERSION_SENTINAL 0xffffffffu
+
+int ath10k_bmi_get_target_info_sdio(struct ath10k *ar,
+ struct bmi_target_info *target_info)
+{
+ struct bmi_cmd cmd;
+ union bmi_resp resp;
+ u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.get_target_info);
+ u32 resplen, ver_len;
+ __le32 tmp;
+ int ret;
+
+ ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi get target info SDIO\n");
+
+ if (ar->bmi.done_sent) {
+ ath10k_warn(ar, "BMI Get Target Info Command disallowed\n");
+ return -EBUSY;
+ }
+
+ cmd.id = __cpu_to_le32(BMI_GET_TARGET_INFO);
+
+ /* Step 1: Read 4 bytes of the target info and check if it is
+ * the special sentinal version word or the first word in the
+ * version response.
+ */
+ resplen = sizeof(u32);
+ ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &tmp, &resplen);
+ if (ret) {
+ ath10k_warn(ar, "unable to read from device\n");
+ return ret;
+ }
+
+ /* Some SDIO boards have a special sentinal byte before the real
+ * version response.
+ */
+ if (__le32_to_cpu(tmp) == TARGET_VERSION_SENTINAL) {
+ /* Step 1b: Read the version length */
+ resplen = sizeof(u32);
+ ret = ath10k_hif_exchange_bmi_msg(ar, NULL, 0, &tmp,
+ &resplen);
+ if (ret) {
+ ath10k_warn(ar, "unable to read from device\n");
+ return ret;
+ }
+ }
+
+ ver_len = __le32_to_cpu(tmp);
+
+ /* Step 2: Check the target info length */
+ if (ver_len != sizeof(resp.get_target_info)) {
+ ath10k_warn(ar, "Unexpected target info len: %u. Expected: %zu\n",
+ ver_len, sizeof(resp.get_target_info));
+ return -EINVAL;
+ }
+
+ /* Step 3: Read the rest of the version response */
+ resplen = sizeof(resp.get_target_info) - sizeof(u32);
+ ret = ath10k_hif_exchange_bmi_msg(ar, NULL, 0,
+ &resp.get_target_info.version,
+ &resplen);
+ if (ret) {
+ ath10k_warn(ar, "unable to read from device\n");
+ return ret;
+ }
+
+ target_info->version = __le32_to_cpu(resp.get_target_info.version);
+ target_info->type = __le32_to_cpu(resp.get_target_info.type);
+
+ return 0;
+}
+
int ath10k_bmi_read_memory(struct ath10k *ar,
u32 address, void *buffer, u32 length)
{
diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h
index cc45b63..9c0839b 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.h
+++ b/drivers/net/wireless/ath/ath10k/bmi.h
@@ -83,6 +83,8 @@ enum bmi_cmd_id {
#define BMI_NVRAM_SEG_NAME_SZ 16
#define BMI_PARAM_GET_EEPROM_BOARD_ID 0x10
+#define BMI_PARAM_GET_FLASH_BOARD_ID 0x8000
+#define BMI_PARAM_FLASH_SECTION_ALL 0x10000
#define ATH10K_BMI_BOARD_ID_FROM_OTP_MASK 0x7c00
#define ATH10K_BMI_BOARD_ID_FROM_OTP_LSB 10
@@ -188,8 +190,8 @@ struct bmi_target_info {
u32 type;
};
-/* in msec */
-#define BMI_COMMUNICATION_TIMEOUT_HZ (2 * HZ)
+/* in jiffies */
+#define BMI_COMMUNICATION_TIMEOUT_HZ (3 * HZ)
#define BMI_CE_NUM_TO_TARG 0
#define BMI_CE_NUM_TO_HOST 1
@@ -198,6 +200,8 @@ void ath10k_bmi_start(struct ath10k *ar);
int ath10k_bmi_done(struct ath10k *ar);
int ath10k_bmi_get_target_info(struct ath10k *ar,
struct bmi_target_info *target_info);
+int ath10k_bmi_get_target_info_sdio(struct ath10k *ar,
+ struct bmi_target_info *target_info);
int ath10k_bmi_read_memory(struct ath10k *ar, u32 address,
void *buffer, u32 length);
int ath10k_bmi_write_memory(struct ath10k *ar, u32 address,
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index ee1090c..08b84c8 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -59,205 +59,243 @@
* the buffer is sent/received.
*/
+static inline unsigned int
+ath10k_set_ring_byte(unsigned int offset,
+ struct ath10k_hw_ce_regs_addr_map *addr_map)
+{
+ return ((offset << addr_map->lsb) & addr_map->mask);
+}
+
+static inline unsigned int
+ath10k_get_ring_byte(unsigned int offset,
+ struct ath10k_hw_ce_regs_addr_map *addr_map)
+{
+ return ((offset & addr_map->mask) >> (addr_map->lsb));
+}
+
static inline void ath10k_ce_dest_ring_write_index_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS, n);
+ ath10k_pci_write32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->dst_wr_index_addr, n);
}
static inline u32 ath10k_ce_dest_ring_write_index_get(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- return ath10k_pci_read32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS);
+ return ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->dst_wr_index_addr);
}
static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n);
+ ath10k_pci_write32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->sr_wr_index_addr, n);
}
static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- return ath10k_pci_read32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS);
+ return ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->sr_wr_index_addr);
}
static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- return ath10k_pci_read32(ar, ce_ctrl_addr + CURRENT_SRRI_ADDRESS);
+ return ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->current_srri_addr);
}
static inline void ath10k_ce_src_ring_base_addr_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int addr)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + SR_BA_ADDRESS, addr);
+ ath10k_pci_write32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->sr_base_addr, addr);
}
static inline void ath10k_ce_src_ring_size_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + SR_SIZE_ADDRESS, n);
+ ath10k_pci_write32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->sr_size_addr, n);
}
static inline void ath10k_ce_src_ring_dmax_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 ctrl1_addr = ath10k_pci_read32((ar),
- (ce_ctrl_addr) + CE_CTRL1_ADDRESS);
+ struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
+ u32 ctrl1_addr = ath10k_pci_read32(ar,
+ ce_ctrl_addr + ctrl_regs->addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS,
- (ctrl1_addr & ~CE_CTRL1_DMAX_LENGTH_MASK) |
- CE_CTRL1_DMAX_LENGTH_SET(n));
+ ath10k_pci_write32(ar, ce_ctrl_addr + ctrl_regs->addr,
+ (ctrl1_addr & ~(ctrl_regs->dmax->mask)) |
+ ath10k_set_ring_byte(n, ctrl_regs->dmax));
}
static inline void ath10k_ce_src_ring_byte_swap_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS);
+ struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
+ u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + ctrl_regs->addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS,
- (ctrl1_addr & ~CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) |
- CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(n));
+ ath10k_pci_write32(ar, ce_ctrl_addr + ctrl_regs->addr,
+ (ctrl1_addr & ~(ctrl_regs->src_ring->mask)) |
+ ath10k_set_ring_byte(n, ctrl_regs->src_ring));
}
static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS);
+ struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
+ u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + ctrl_regs->addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS,
- (ctrl1_addr & ~CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) |
- CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(n));
+ ath10k_pci_write32(ar, ce_ctrl_addr + ctrl_regs->addr,
+ (ctrl1_addr & ~(ctrl_regs->dst_ring->mask)) |
+ ath10k_set_ring_byte(n, ctrl_regs->dst_ring));
}
static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- return ath10k_pci_read32(ar, ce_ctrl_addr + CURRENT_DRRI_ADDRESS);
+ return ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->current_drri_addr);
}
static inline void ath10k_ce_dest_ring_base_addr_set(struct ath10k *ar,
u32 ce_ctrl_addr,
u32 addr)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + DR_BA_ADDRESS, addr);
+ ath10k_pci_write32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->dr_base_addr, addr);
}
static inline void ath10k_ce_dest_ring_size_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + DR_SIZE_ADDRESS, n);
+ ath10k_pci_write32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->dr_size_addr, n);
}
static inline void ath10k_ce_src_ring_highmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS);
+ struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr;
+ u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + srcr_wm->addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS,
- (addr & ~SRC_WATERMARK_HIGH_MASK) |
- SRC_WATERMARK_HIGH_SET(n));
+ ath10k_pci_write32(ar, ce_ctrl_addr + srcr_wm->addr,
+ (addr & ~(srcr_wm->wm_high->mask)) |
+ (ath10k_set_ring_byte(n, srcr_wm->wm_high)));
}
static inline void ath10k_ce_src_ring_lowmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS);
+ struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr;
+ u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + srcr_wm->addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS,
- (addr & ~SRC_WATERMARK_LOW_MASK) |
- SRC_WATERMARK_LOW_SET(n));
+ ath10k_pci_write32(ar, ce_ctrl_addr + srcr_wm->addr,
+ (addr & ~(srcr_wm->wm_low->mask)) |
+ (ath10k_set_ring_byte(n, srcr_wm->wm_low)));
}
static inline void ath10k_ce_dest_ring_highmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS);
+ struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr;
+ u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + dstr_wm->addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS,
- (addr & ~DST_WATERMARK_HIGH_MASK) |
- DST_WATERMARK_HIGH_SET(n));
+ ath10k_pci_write32(ar, ce_ctrl_addr + dstr_wm->addr,
+ (addr & ~(dstr_wm->wm_high->mask)) |
+ (ath10k_set_ring_byte(n, dstr_wm->wm_high)));
}
static inline void ath10k_ce_dest_ring_lowmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS);
+ struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr;
+ u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + dstr_wm->addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS,
- (addr & ~DST_WATERMARK_LOW_MASK) |
- DST_WATERMARK_LOW_SET(n));
+ ath10k_pci_write32(ar, ce_ctrl_addr + dstr_wm->addr,
+ (addr & ~(dstr_wm->wm_low->mask)) |
+ (ath10k_set_ring_byte(n, dstr_wm->wm_low)));
}
static inline void ath10k_ce_copy_complete_inter_enable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- u32 host_ie_addr = ath10k_pci_read32(ar,
- ce_ctrl_addr + HOST_IE_ADDRESS);
+ struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie;
+ u32 host_ie_addr = ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->host_ie_addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS,
- host_ie_addr | HOST_IE_COPY_COMPLETE_MASK);
+ ath10k_pci_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr,
+ host_ie_addr | host_ie->copy_complete->mask);
}
static inline void ath10k_ce_copy_complete_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- u32 host_ie_addr = ath10k_pci_read32(ar,
- ce_ctrl_addr + HOST_IE_ADDRESS);
+ struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie;
+ u32 host_ie_addr = ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->host_ie_addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS,
- host_ie_addr & ~HOST_IE_COPY_COMPLETE_MASK);
+ ath10k_pci_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr,
+ host_ie_addr & ~(host_ie->copy_complete->mask));
}
static inline void ath10k_ce_watermark_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- u32 host_ie_addr = ath10k_pci_read32(ar,
- ce_ctrl_addr + HOST_IE_ADDRESS);
+ struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
+ u32 host_ie_addr = ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->host_ie_addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS,
- host_ie_addr & ~CE_WATERMARK_MASK);
+ ath10k_pci_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr,
+ host_ie_addr & ~(wm_regs->wm_mask));
}
static inline void ath10k_ce_error_intr_enable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- u32 misc_ie_addr = ath10k_pci_read32(ar,
- ce_ctrl_addr + MISC_IE_ADDRESS);
+ struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs;
+ u32 misc_ie_addr = ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->misc_ie_addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS,
- misc_ie_addr | CE_ERROR_MASK);
+ ath10k_pci_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr,
+ misc_ie_addr | misc_regs->err_mask);
}
static inline void ath10k_ce_error_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
- u32 misc_ie_addr = ath10k_pci_read32(ar,
- ce_ctrl_addr + MISC_IE_ADDRESS);
+ struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs;
+ u32 misc_ie_addr = ath10k_pci_read32(ar, ce_ctrl_addr +
+ ar->hw_ce_regs->misc_ie_addr);
- ath10k_pci_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS,
- misc_ie_addr & ~CE_ERROR_MASK);
+ ath10k_pci_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr,
+ misc_ie_addr & ~(misc_regs->err_mask));
}
static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int mask)
{
- ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask);
+ struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
+
+ ath10k_pci_write32(ar, ce_ctrl_addr + wm_regs->addr, mask);
}
/*
@@ -594,6 +632,7 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
unsigned int nentries_mask = src_ring->nentries_mask;
unsigned int sw_index = src_ring->sw_index;
unsigned int read_index;
+ struct ce_desc *desc;
if (src_ring->hw_index == sw_index) {
/*
@@ -623,6 +662,9 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
/* sanity */
src_ring->per_transfer_context[sw_index] = NULL;
+ desc = CE_SRC_RING_TO_DESC(src_ring->base_addr_owner_space,
+ sw_index);
+ desc->nbytes = 0;
/* Update sw_index */
sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
@@ -715,13 +757,13 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
+ struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
u32 ctrl_addr = ce_state->ctrl_addr;
spin_lock_bh(&ar_pci->ce_lock);
/* Clear the copy-complete interrupts that will be handled here. */
- ath10k_ce_engine_int_status_clear(ar, ctrl_addr,
- HOST_IS_COPY_COMPLETE_MASK);
+ ath10k_ce_engine_int_status_clear(ar, ctrl_addr, wm_regs->cc_mask);
spin_unlock_bh(&ar_pci->ce_lock);
@@ -737,7 +779,7 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
* Misc CE interrupts are not being handled, but still need
* to be cleared.
*/
- ath10k_ce_engine_int_status_clear(ar, ctrl_addr, CE_WATERMARK_MASK);
+ ath10k_ce_engine_int_status_clear(ar, ctrl_addr, wm_regs->wm_mask);
spin_unlock_bh(&ar_pci->ce_lock);
}
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index e76a982..95743a5 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -263,143 +263,11 @@ struct ce_attr {
void (*recv_cb)(struct ath10k_ce_pipe *);
};
-#define SR_BA_ADDRESS 0x0000
-#define SR_SIZE_ADDRESS 0x0004
-#define DR_BA_ADDRESS 0x0008
-#define DR_SIZE_ADDRESS 0x000c
-#define CE_CMD_ADDRESS 0x0018
-
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MSB 17
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 17
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00020000
-#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(x) \
- (((0 | (x)) << CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) & \
- CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK)
-
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MSB 16
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00010000
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_GET(x) \
- (((x) & CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) >> \
- CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB)
-#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(x) \
- (((0 | (x)) << CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) & \
- CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK)
-
-#define CE_CTRL1_DMAX_LENGTH_MSB 15
-#define CE_CTRL1_DMAX_LENGTH_LSB 0
-#define CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff
-#define CE_CTRL1_DMAX_LENGTH_GET(x) \
- (((x) & CE_CTRL1_DMAX_LENGTH_MASK) >> CE_CTRL1_DMAX_LENGTH_LSB)
-#define CE_CTRL1_DMAX_LENGTH_SET(x) \
- (((0 | (x)) << CE_CTRL1_DMAX_LENGTH_LSB) & CE_CTRL1_DMAX_LENGTH_MASK)
-
-#define CE_CTRL1_ADDRESS 0x0010
-#define CE_CTRL1_HW_MASK 0x0007ffff
-#define CE_CTRL1_SW_MASK 0x0007ffff
-#define CE_CTRL1_HW_WRITE_MASK 0x00000000
-#define CE_CTRL1_SW_WRITE_MASK 0x0007ffff
-#define CE_CTRL1_RSTMASK 0xffffffff
-#define CE_CTRL1_RESET 0x00000080
-
-#define CE_CMD_HALT_STATUS_MSB 3
-#define CE_CMD_HALT_STATUS_LSB 3
-#define CE_CMD_HALT_STATUS_MASK 0x00000008
-#define CE_CMD_HALT_STATUS_GET(x) \
- (((x) & CE_CMD_HALT_STATUS_MASK) >> CE_CMD_HALT_STATUS_LSB)
-#define CE_CMD_HALT_STATUS_SET(x) \
- (((0 | (x)) << CE_CMD_HALT_STATUS_LSB) & CE_CMD_HALT_STATUS_MASK)
-#define CE_CMD_HALT_STATUS_RESET 0
-#define CE_CMD_HALT_MSB 0
-#define CE_CMD_HALT_MASK 0x00000001
-
-#define HOST_IE_COPY_COMPLETE_MSB 0
-#define HOST_IE_COPY_COMPLETE_LSB 0
-#define HOST_IE_COPY_COMPLETE_MASK 0x00000001
-#define HOST_IE_COPY_COMPLETE_GET(x) \
- (((x) & HOST_IE_COPY_COMPLETE_MASK) >> HOST_IE_COPY_COMPLETE_LSB)
-#define HOST_IE_COPY_COMPLETE_SET(x) \
- (((0 | (x)) << HOST_IE_COPY_COMPLETE_LSB) & HOST_IE_COPY_COMPLETE_MASK)
-#define HOST_IE_COPY_COMPLETE_RESET 0
-#define HOST_IE_ADDRESS 0x002c
-
-#define HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010
-#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008
-#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004
-#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002
-#define HOST_IS_COPY_COMPLETE_MASK 0x00000001
-#define HOST_IS_ADDRESS 0x0030
-
-#define MISC_IE_ADDRESS 0x0034
-
-#define MISC_IS_AXI_ERR_MASK 0x00000400
-
-#define MISC_IS_DST_ADDR_ERR_MASK 0x00000200
-#define MISC_IS_SRC_LEN_ERR_MASK 0x00000100
-#define MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080
-#define MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040
-#define MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020
-
-#define MISC_IS_ADDRESS 0x0038
-
-#define SR_WR_INDEX_ADDRESS 0x003c
-
-#define DST_WR_INDEX_ADDRESS 0x0040
-
-#define CURRENT_SRRI_ADDRESS 0x0044
-
-#define CURRENT_DRRI_ADDRESS 0x0048
-
-#define SRC_WATERMARK_LOW_MSB 31
-#define SRC_WATERMARK_LOW_LSB 16
-#define SRC_WATERMARK_LOW_MASK 0xffff0000
-#define SRC_WATERMARK_LOW_GET(x) \
- (((x) & SRC_WATERMARK_LOW_MASK) >> SRC_WATERMARK_LOW_LSB)
-#define SRC_WATERMARK_LOW_SET(x) \
- (((0 | (x)) << SRC_WATERMARK_LOW_LSB) & SRC_WATERMARK_LOW_MASK)
-#define SRC_WATERMARK_LOW_RESET 0
-#define SRC_WATERMARK_HIGH_MSB 15
-#define SRC_WATERMARK_HIGH_LSB 0
-#define SRC_WATERMARK_HIGH_MASK 0x0000ffff
-#define SRC_WATERMARK_HIGH_GET(x) \
- (((x) & SRC_WATERMARK_HIGH_MASK) >> SRC_WATERMARK_HIGH_LSB)
-#define SRC_WATERMARK_HIGH_SET(x) \
- (((0 | (x)) << SRC_WATERMARK_HIGH_LSB) & SRC_WATERMARK_HIGH_MASK)
-#define SRC_WATERMARK_HIGH_RESET 0
-#define SRC_WATERMARK_ADDRESS 0x004c
-
-#define DST_WATERMARK_LOW_LSB 16
-#define DST_WATERMARK_LOW_MASK 0xffff0000
-#define DST_WATERMARK_LOW_SET(x) \
- (((0 | (x)) << DST_WATERMARK_LOW_LSB) & DST_WATERMARK_LOW_MASK)
-#define DST_WATERMARK_LOW_RESET 0
-#define DST_WATERMARK_HIGH_MSB 15
-#define DST_WATERMARK_HIGH_LSB 0
-#define DST_WATERMARK_HIGH_MASK 0x0000ffff
-#define DST_WATERMARK_HIGH_GET(x) \
- (((x) & DST_WATERMARK_HIGH_MASK) >> DST_WATERMARK_HIGH_LSB)
-#define DST_WATERMARK_HIGH_SET(x) \
- (((0 | (x)) << DST_WATERMARK_HIGH_LSB) & DST_WATERMARK_HIGH_MASK)
-#define DST_WATERMARK_HIGH_RESET 0
-#define DST_WATERMARK_ADDRESS 0x0050
-
static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
{
return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id;
}
-#define CE_WATERMARK_MASK (HOST_IS_SRC_RING_LOW_WATERMARK_MASK | \
- HOST_IS_SRC_RING_HIGH_WATERMARK_MASK | \
- HOST_IS_DST_RING_LOW_WATERMARK_MASK | \
- HOST_IS_DST_RING_HIGH_WATERMARK_MASK)
-
-#define CE_ERROR_MASK (MISC_IS_AXI_ERR_MASK | \
- MISC_IS_DST_ADDR_ERR_MASK | \
- MISC_IS_SRC_LEN_ERR_MASK | \
- MISC_IS_DST_MAX_LEN_VIO_MASK | \
- MISC_IS_DST_RING_OVERFLOW_MASK | \
- MISC_IS_SRC_RING_OVERFLOW_MASK)
-
#define CE_SRC_RING_TO_DESC(baddr, idx) \
(&(((struct ce_desc *)baddr)[idx]))
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 5a06389..75c5c90 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -72,6 +72,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA9887_HW_1_0_VERSION,
@@ -93,6 +95,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA6174_HW_2_1_VERSION,
@@ -113,6 +117,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA6174_HW_2_1_VERSION,
@@ -133,6 +139,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA6174_HW_3_0_VERSION,
@@ -153,6 +161,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA6174_HW_3_2_VERSION,
@@ -176,6 +186,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.target_cpu_freq = 176000000,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA99X0_HW_2_0_DEV_VERSION,
@@ -202,6 +214,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca99x0_ops,
.decap_align_bytes = 1,
.spectral_bin_discard = 4,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA9984_HW_1_0_DEV_VERSION,
@@ -229,6 +243,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca99x0_ops,
.decap_align_bytes = 1,
.spectral_bin_discard = 12,
+
+ /* Can do only 2x2 VHT160 or 80+80. 1560Mbps is 4x4 80Mhz
+ * or 2x2 160Mhz, long-guard-interval.
+ */
+ .vht160_mcs_rx_highest = 1560,
+ .vht160_mcs_tx_highest = 1560,
},
{
.id = QCA9888_HW_2_0_DEV_VERSION,
@@ -255,6 +275,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca99x0_ops,
.decap_align_bytes = 1,
.spectral_bin_discard = 12,
+
+ /* Can do only 1x1 VHT160 or 80+80. 780Mbps is 2x2 80Mhz or
+ * 1x1 160Mhz, long-guard-interval.
+ */
+ .vht160_mcs_rx_highest = 780,
+ .vht160_mcs_tx_highest = 780,
},
{
.id = QCA9377_HW_1_0_DEV_VERSION,
@@ -275,6 +301,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA9377_HW_1_1_DEV_VERSION,
@@ -297,6 +325,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.target_cpu_freq = 176000000,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
{
.id = QCA4019_HW_1_0_DEV_VERSION,
@@ -324,6 +354,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca99x0_ops,
.decap_align_bytes = 1,
.spectral_bin_discard = 4,
+ .vht160_mcs_rx_highest = 0,
+ .vht160_mcs_tx_highest = 0,
},
};
@@ -389,6 +421,21 @@ static void ath10k_send_suspend_complete(struct ath10k *ar)
complete(&ar->target_suspend);
}
+static void ath10k_init_sdio(struct ath10k *ar)
+{
+ u32 param = 0;
+
+ ath10k_bmi_write32(ar, hi_mbox_io_block_sz, 256);
+ ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99);
+ ath10k_bmi_read32(ar, hi_acs_flags, &param);
+
+ param |= (HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET |
+ HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET |
+ HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE);
+
+ ath10k_bmi_write32(ar, hi_acs_flags, param);
+}
+
static int ath10k_init_configure_target(struct ath10k *ar)
{
u32 param_host;
@@ -676,7 +723,7 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
{
u32 result, address;
u8 board_id, chip_id;
- int ret;
+ int ret, bmi_board_id_param;
address = ar->hw_params.patch_load_addr;
@@ -700,8 +747,13 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
return ret;
}
- ret = ath10k_bmi_execute(ar, address, BMI_PARAM_GET_EEPROM_BOARD_ID,
- &result);
+ if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
+ ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
+ bmi_board_id_param = BMI_PARAM_GET_FLASH_BOARD_ID;
+ else
+ bmi_board_id_param = BMI_PARAM_GET_EEPROM_BOARD_ID;
+
+ ret = ath10k_bmi_execute(ar, address, bmi_board_id_param, &result);
if (ret) {
ath10k_err(ar, "could not execute otp for board id check: %d\n",
ret);
@@ -830,6 +882,11 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
return ret;
}
+ /* As of now pre-cal is valid for 10_4 variants */
+ if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
+ ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
+ bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL;
+
ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result);
if (ret) {
ath10k_err(ar, "could not execute otp (%d)\n", ret);
@@ -1395,7 +1452,18 @@ err:
static void ath10k_core_get_fw_name(struct ath10k *ar, char *fw_name,
size_t fw_name_len, int fw_api)
{
- scnprintf(fw_name, fw_name_len, "%s-%d.bin", ATH10K_FW_FILE_BASE, fw_api);
+ switch (ar->hif.bus) {
+ case ATH10K_BUS_SDIO:
+ scnprintf(fw_name, fw_name_len, "%s-%s-%d.bin",
+ ATH10K_FW_FILE_BASE, ath10k_bus_str(ar->hif.bus),
+ fw_api);
+ break;
+ case ATH10K_BUS_PCI:
+ case ATH10K_BUS_AHB:
+ scnprintf(fw_name, fw_name_len, "%s-%d.bin",
+ ATH10K_FW_FILE_BASE, fw_api);
+ break;
+ }
}
static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
@@ -1953,6 +2021,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
if (status)
goto err;
+ if (ar->hif.bus == ATH10K_BUS_SDIO)
+ ath10k_init_sdio(ar);
+
ar->htc.htc_ops.target_send_suspend_complete =
ath10k_send_suspend_complete;
@@ -2200,7 +2271,10 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
}
memset(&target_info, 0, sizeof(target_info));
- ret = ath10k_bmi_get_target_info(ar, &target_info);
+ if (ar->hif.bus == ATH10K_BUS_SDIO)
+ ret = ath10k_bmi_get_target_info_sdio(ar, &target_info);
+ else
+ ret = ath10k_bmi_get_target_info(ar, &target_info);
if (ret) {
ath10k_err(ar, "could not get target info (%d)\n", ret);
goto err_power_down;
@@ -2417,24 +2491,29 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
case ATH10K_HW_QCA988X:
case ATH10K_HW_QCA9887:
ar->regs = &qca988x_regs;
+ ar->hw_ce_regs = &qcax_ce_regs;
ar->hw_values = &qca988x_values;
break;
case ATH10K_HW_QCA6174:
case ATH10K_HW_QCA9377:
ar->regs = &qca6174_regs;
+ ar->hw_ce_regs = &qcax_ce_regs;
ar->hw_values = &qca6174_values;
break;
case ATH10K_HW_QCA99X0:
case ATH10K_HW_QCA9984:
ar->regs = &qca99x0_regs;
+ ar->hw_ce_regs = &qcax_ce_regs;
ar->hw_values = &qca99x0_values;
break;
case ATH10K_HW_QCA9888:
ar->regs = &qca99x0_regs;
+ ar->hw_ce_regs = &qcax_ce_regs;
ar->hw_values = &qca9888_values;
break;
case ATH10K_HW_QCA4019:
ar->regs = &qca4019_regs;
+ ar->hw_ce_regs = &qcax_ce_regs;
ar->hw_values = &qca4019_values;
break;
default:
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index bf09151..1aa5cf1 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -91,6 +91,7 @@ struct ath10k;
enum ath10k_bus {
ATH10K_BUS_PCI,
ATH10K_BUS_AHB,
+ ATH10K_BUS_SDIO,
};
static inline const char *ath10k_bus_str(enum ath10k_bus bus)
@@ -100,6 +101,8 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus)
return "pci";
case ATH10K_BUS_AHB:
return "ahb";
+ case ATH10K_BUS_SDIO:
+ return "sdio";
}
return "unknown";
@@ -791,6 +794,7 @@ struct ath10k {
struct completion target_suspend;
const struct ath10k_hw_regs *regs;
+ const struct ath10k_hw_ce_regs *hw_ce_regs;
const struct ath10k_hw_values *hw_values;
struct ath10k_bmi bmi;
struct ath10k_wmi wmi;
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 4cd2a0f..389fcb7 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -625,17 +625,21 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
- char buf[32];
+ char buf[32] = {0};
+ ssize_t rc;
int ret;
- simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
+ /* filter partial writes and invalid commands */
+ if (*ppos != 0 || count >= sizeof(buf) || count == 0)
+ return -EINVAL;
- /* make sure that buf is null terminated */
- buf[sizeof(buf) - 1] = 0;
+ rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
+ if (rc < 0)
+ return rc;
/* drop the possible '\n' from the end */
- if (buf[count - 1] == '\n')
- buf[count - 1] = 0;
+ if (buf[*ppos - 1] == '\n')
+ buf[*ppos - 1] = '\0';
mutex_lock(&ar->conf_mutex);
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 2368f47..257d109 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -38,6 +38,8 @@ enum ath10k_debug_mask {
ATH10K_DBG_WMI_PRINT = 0x00002000,
ATH10K_DBG_PCI_PS = 0x00004000,
ATH10K_DBG_AHB = 0x00008000,
+ ATH10K_DBG_SDIO = 0x00010000,
+ ATH10K_DBG_SDIO_DUMP = 0x00020000,
ATH10K_DBG_ANY = 0xffffffff,
};
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index b7669b2..e5c80f5 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -57,8 +57,8 @@ static inline void ath10k_htc_restore_tx_skb(struct ath10k_htc *htc,
skb_pull(skb, sizeof(struct ath10k_htc_hdr));
}
-static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
- struct sk_buff *skb)
+void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
+ struct sk_buff *skb)
{
struct ath10k *ar = ep->htc->ar;
@@ -75,6 +75,7 @@ static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
ep->ep_ops.ep_tx_complete(ep->htc->ar, skb);
}
+EXPORT_SYMBOL(ath10k_htc_notify_tx_completion);
static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep,
struct sk_buff *skb)
@@ -230,12 +231,79 @@ ath10k_htc_process_credit_report(struct ath10k_htc *htc,
spin_unlock_bh(&htc->tx_lock);
}
-static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
- u8 *buffer,
- int length,
- enum ath10k_htc_ep_id src_eid)
+static int
+ath10k_htc_process_lookahead(struct ath10k_htc *htc,
+ const struct ath10k_htc_lookahead_report *report,
+ int len,
+ enum ath10k_htc_ep_id eid,
+ void *next_lookaheads,
+ int *next_lookaheads_len)
{
struct ath10k *ar = htc->ar;
+
+ /* Invalid lookahead flags are actually transmitted by
+ * the target in the HTC control message.
+ * Since this will happen at every boot we silently ignore
+ * the lookahead in this case
+ */
+ if (report->pre_valid != ((~report->post_valid) & 0xFF))
+ return 0;
+
+ if (next_lookaheads && next_lookaheads_len) {
+ ath10k_dbg(ar, ATH10K_DBG_HTC,
+ "htc rx lookahead found pre_valid 0x%x post_valid 0x%x\n",
+ report->pre_valid, report->post_valid);
+
+ /* look ahead bytes are valid, copy them over */
+ memcpy((u8 *)next_lookaheads, report->lookahead, 4);
+
+ *next_lookaheads_len = 1;
+ }
+
+ return 0;
+}
+
+static int
+ath10k_htc_process_lookahead_bundle(struct ath10k_htc *htc,
+ const struct ath10k_htc_lookahead_bundle *report,
+ int len,
+ enum ath10k_htc_ep_id eid,
+ void *next_lookaheads,
+ int *next_lookaheads_len)
+{
+ struct ath10k *ar = htc->ar;
+ int bundle_cnt = len / sizeof(*report);
+
+ if (!bundle_cnt || (bundle_cnt > HTC_HOST_MAX_MSG_PER_BUNDLE)) {
+ ath10k_warn(ar, "Invalid lookahead bundle count: %d\n",
+ bundle_cnt);
+ return -EINVAL;
+ }
+
+ if (next_lookaheads && next_lookaheads_len) {
+ int i;
+
+ for (i = 0; i < bundle_cnt; i++) {
+ memcpy(((u8 *)next_lookaheads) + 4 * i,
+ report->lookahead, 4);
+ report++;
+ }
+
+ *next_lookaheads_len = bundle_cnt;
+ }
+
+ return 0;
+}
+
+int ath10k_htc_process_trailer(struct ath10k_htc *htc,
+ u8 *buffer,
+ int length,
+ enum ath10k_htc_ep_id src_eid,
+ void *next_lookaheads,
+ int *next_lookaheads_len)
+{
+ struct ath10k_htc_lookahead_bundle *bundle;
+ struct ath10k *ar = htc->ar;
int status = 0;
struct ath10k_htc_record *record;
u8 *orig_buffer;
@@ -274,6 +342,29 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
record->hdr.len,
src_eid);
break;
+ case ATH10K_HTC_RECORD_LOOKAHEAD:
+ len = sizeof(struct ath10k_htc_lookahead_report);
+ if (record->hdr.len < len) {
+ ath10k_warn(ar, "Lookahead report too long\n");
+ status = -EINVAL;
+ break;
+ }
+ status = ath10k_htc_process_lookahead(htc,
+ record->lookahead_report,
+ record->hdr.len,
+ src_eid,
+ next_lookaheads,
+ next_lookaheads_len);
+ break;
+ case ATH10K_HTC_RECORD_LOOKAHEAD_BUNDLE:
+ bundle = record->lookahead_bundle;
+ status = ath10k_htc_process_lookahead_bundle(htc,
+ bundle,
+ record->hdr.len,
+ src_eid,
+ next_lookaheads,
+ next_lookaheads_len);
+ break;
default:
ath10k_warn(ar, "Unhandled record: id:%d length:%d\n",
record->hdr.id, record->hdr.len);
@@ -294,6 +385,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
return status;
}
+EXPORT_SYMBOL(ath10k_htc_process_trailer);
void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
{
@@ -360,7 +452,8 @@ void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
trailer += payload_len;
trailer -= trailer_len;
status = ath10k_htc_process_trailer(htc, trailer,
- trailer_len, hdr->eid);
+ trailer_len, hdr->eid,
+ NULL, NULL);
if (status)
goto out;
@@ -371,42 +464,6 @@ void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
/* zero length packet with trailer data, just drop these */
goto out;
- if (eid == ATH10K_HTC_EP_0) {
- struct ath10k_htc_msg *msg = (struct ath10k_htc_msg *)skb->data;
-
- switch (__le16_to_cpu(msg->hdr.message_id)) {
- case ATH10K_HTC_MSG_READY_ID:
- case ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID:
- /* handle HTC control message */
- if (completion_done(&htc->ctl_resp)) {
- /*
- * this is a fatal error, target should not be
- * sending unsolicited messages on the ep 0
- */
- ath10k_warn(ar, "HTC rx ctrl still processing\n");
- complete(&htc->ctl_resp);
- goto out;
- }
-
- htc->control_resp_len =
- min_t(int, skb->len,
- ATH10K_HTC_MAX_CTRL_MSG_LEN);
-
- memcpy(htc->control_resp_buffer, skb->data,
- htc->control_resp_len);
-
- complete(&htc->ctl_resp);
- break;
- case ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE:
- htc->htc_ops.target_send_suspend_complete(ar);
- break;
- default:
- ath10k_warn(ar, "ignoring unsolicited htc ep0 event\n");
- break;
- }
- goto out;
- }
-
ath10k_dbg(ar, ATH10K_DBG_HTC, "htc rx completion ep %d skb %pK\n",
eid, skb);
ep->ep_ops.ep_rx_complete(ar, skb);
@@ -421,10 +478,40 @@ EXPORT_SYMBOL(ath10k_htc_rx_completion_handler);
static void ath10k_htc_control_rx_complete(struct ath10k *ar,
struct sk_buff *skb)
{
- /* This is unexpected. FW is not supposed to send regular rx on this
- * endpoint.
- */
- ath10k_warn(ar, "unexpected htc rx\n");
+ struct ath10k_htc *htc = &ar->htc;
+ struct ath10k_htc_msg *msg = (struct ath10k_htc_msg *)skb->data;
+
+ switch (__le16_to_cpu(msg->hdr.message_id)) {
+ case ATH10K_HTC_MSG_READY_ID:
+ case ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID:
+ /* handle HTC control message */
+ if (completion_done(&htc->ctl_resp)) {
+ /* this is a fatal error, target should not be
+ * sending unsolicited messages on the ep 0
+ */
+ ath10k_warn(ar, "HTC rx ctrl still processing\n");
+ complete(&htc->ctl_resp);
+ goto out;
+ }
+
+ htc->control_resp_len =
+ min_t(int, skb->len,
+ ATH10K_HTC_MAX_CTRL_MSG_LEN);
+
+ memcpy(htc->control_resp_buffer, skb->data,
+ htc->control_resp_len);
+
+ complete(&htc->ctl_resp);
+ break;
+ case ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE:
+ htc->htc_ops.target_send_suspend_complete(ar);
+ break;
+ default:
+ ath10k_warn(ar, "ignoring unsolicited htc ep0 event\n");
+ break;
+ }
+
+out:
kfree_skb(skb);
}
@@ -497,12 +584,8 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
struct ath10k *ar = htc->ar;
int i, status = 0;
unsigned long time_left;
- struct ath10k_htc_svc_conn_req conn_req;
- struct ath10k_htc_svc_conn_resp conn_resp;
struct ath10k_htc_msg *msg;
u16 message_id;
- u16 credit_count;
- u16 credit_size;
time_left = wait_for_completion_timeout(&htc->ctl_resp,
ATH10K_HTC_WAIT_TIMEOUT_HZ);
@@ -539,16 +622,14 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
msg = (struct ath10k_htc_msg *)htc->control_resp_buffer;
message_id = __le16_to_cpu(msg->hdr.message_id);
- credit_count = __le16_to_cpu(msg->ready.credit_count);
- credit_size = __le16_to_cpu(msg->ready.credit_size);
if (message_id != ATH10K_HTC_MSG_READY_ID) {
ath10k_err(ar, "Invalid HTC ready msg: 0x%x\n", message_id);
return -ECOMM;
}
- htc->total_transmit_credits = credit_count;
- htc->target_credit_size = credit_size;
+ htc->total_transmit_credits = __le16_to_cpu(msg->ready.credit_count);
+ htc->target_credit_size = __le16_to_cpu(msg->ready.credit_size);
ath10k_dbg(ar, ATH10K_DBG_HTC,
"Target ready! transmit resources: %d size:%d\n",
@@ -561,20 +642,17 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
return -ECOMM;
}
- /* setup our pseudo HTC control endpoint connection */
- memset(&conn_req, 0, sizeof(conn_req));
- memset(&conn_resp, 0, sizeof(conn_resp));
- conn_req.ep_ops.ep_tx_complete = ath10k_htc_control_tx_complete;
- conn_req.ep_ops.ep_rx_complete = ath10k_htc_control_rx_complete;
- conn_req.max_send_queue_depth = ATH10K_NUM_CONTROL_TX_BUFFERS;
- conn_req.service_id = ATH10K_HTC_SVC_ID_RSVD_CTRL;
-
- /* connect fake service */
- status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp);
- if (status) {
- ath10k_err(ar, "could not connect to htc service (%d)\n",
- status);
- return status;
+ /* The only way to determine if the ready message is an extended
+ * message is from the size.
+ */
+ if (htc->control_resp_len >=
+ sizeof(msg->hdr) + sizeof(msg->ready_ext)) {
+ htc->max_msgs_per_htc_bundle =
+ min_t(u8, msg->ready_ext.max_msgs_per_htc_bundle,
+ HTC_HOST_MAX_MSG_PER_BUNDLE);
+ ath10k_dbg(ar, ATH10K_DBG_HTC,
+ "Extended ready message. RX bundle size: %d\n",
+ htc->max_msgs_per_htc_bundle);
}
return 0;
@@ -772,6 +850,13 @@ int ath10k_htc_start(struct ath10k_htc *htc)
msg->hdr.message_id =
__cpu_to_le16(ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID);
+ if (ar->hif.bus == ATH10K_BUS_SDIO) {
+ /* Extra setup params used by SDIO */
+ msg->setup_complete_ext.flags =
+ __cpu_to_le32(ATH10K_HTC_SETUP_COMPLETE_FLAGS_RX_BNDL_EN);
+ msg->setup_complete_ext.max_msgs_per_bundled_recv =
+ htc->max_msgs_per_htc_bundle;
+ }
ath10k_dbg(ar, ATH10K_DBG_HTC, "HTC is using TX credit flow control\n");
status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb);
@@ -786,8 +871,10 @@ int ath10k_htc_start(struct ath10k_htc *htc)
/* registered target arrival callback from the HIF layer */
int ath10k_htc_init(struct ath10k *ar)
{
- struct ath10k_htc_ep *ep = NULL;
+ int status;
struct ath10k_htc *htc = &ar->htc;
+ struct ath10k_htc_svc_conn_req conn_req;
+ struct ath10k_htc_svc_conn_resp conn_resp;
spin_lock_init(&htc->tx_lock);
@@ -795,10 +882,21 @@ int ath10k_htc_init(struct ath10k *ar)
htc->ar = ar;
- /* Get HIF default pipe for HTC message exchange */
- ep = &htc->endpoint[ATH10K_HTC_EP_0];
+ /* setup our pseudo HTC control endpoint connection */
+ memset(&conn_req, 0, sizeof(conn_req));
+ memset(&conn_resp, 0, sizeof(conn_resp));
+ conn_req.ep_ops.ep_tx_complete = ath10k_htc_control_tx_complete;
+ conn_req.ep_ops.ep_rx_complete = ath10k_htc_control_rx_complete;
+ conn_req.max_send_queue_depth = ATH10K_NUM_CONTROL_TX_BUFFERS;
+ conn_req.service_id = ATH10K_HTC_SVC_ID_RSVD_CTRL;
- ath10k_hif_get_default_pipe(ar, &ep->ul_pipe_id, &ep->dl_pipe_id);
+ /* connect fake service */
+ status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp);
+ if (status) {
+ ath10k_err(ar, "could not connect to htc service (%d)\n",
+ status);
+ return status;
+ }
init_completion(&htc->ctl_resp);
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index 6ababa3..24663b0 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -50,6 +50,8 @@ struct ath10k;
* 4-byte aligned.
*/
+#define HTC_HOST_MAX_MSG_PER_BUNDLE 8
+
enum ath10k_htc_tx_flags {
ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01,
ATH10K_HTC_FLAG_SEND_BUNDLE = 0x02
@@ -110,6 +112,10 @@ enum ath10k_htc_conn_svc_status {
ATH10K_HTC_CONN_SVC_STATUS_NO_MORE_EP = 4
};
+enum ath10k_htc_setup_complete_flags {
+ ATH10K_HTC_SETUP_COMPLETE_FLAGS_RX_BNDL_EN = 1
+};
+
struct ath10k_ath10k_htc_msg_hdr {
__le16 message_id; /* @enum htc_message_id */
} __packed;
@@ -174,8 +180,10 @@ struct ath10k_htc_msg {
} __packed __aligned(4);
enum ath10k_ath10k_htc_record_id {
- ATH10K_HTC_RECORD_NULL = 0,
- ATH10K_HTC_RECORD_CREDITS = 1
+ ATH10K_HTC_RECORD_NULL = 0,
+ ATH10K_HTC_RECORD_CREDITS = 1,
+ ATH10K_HTC_RECORD_LOOKAHEAD = 2,
+ ATH10K_HTC_RECORD_LOOKAHEAD_BUNDLE = 3,
};
struct ath10k_ath10k_htc_record_hdr {
@@ -192,10 +200,28 @@ struct ath10k_htc_credit_report {
u8 pad1;
} __packed;
+struct ath10k_htc_lookahead_report {
+ u8 pre_valid;
+ u8 pad0;
+ u8 pad1;
+ u8 pad2;
+ u8 lookahead[4];
+ u8 post_valid;
+ u8 pad3;
+ u8 pad4;
+ u8 pad5;
+} __packed;
+
+struct ath10k_htc_lookahead_bundle {
+ u8 lookahead[4];
+} __packed;
+
struct ath10k_htc_record {
struct ath10k_ath10k_htc_record_hdr hdr;
union {
struct ath10k_htc_credit_report credit_report[0];
+ struct ath10k_htc_lookahead_report lookahead_report[0];
+ struct ath10k_htc_lookahead_bundle lookahead_bundle[0];
u8 pauload[0];
};
} __packed __aligned(4);
@@ -338,6 +364,7 @@ struct ath10k_htc {
int total_transmit_credits;
int target_credit_size;
+ u8 max_msgs_per_htc_bundle;
};
int ath10k_htc_init(struct ath10k *ar);
@@ -351,5 +378,13 @@ int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid,
struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size);
void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb);
void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb);
+void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
+ struct sk_buff *skb);
+int ath10k_htc_process_trailer(struct ath10k_htc *htc,
+ u8 *buffer,
+ int length,
+ enum ath10k_htc_ep_id src_eid,
+ void *next_lookaheads,
+ int *next_lookaheads_len);
#endif
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 84b6067f..398dda9 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -829,6 +829,19 @@ static void ath10k_htt_rx_h_signal(struct ath10k *ar,
struct ieee80211_rx_status *status,
struct htt_rx_desc *rxd)
{
+ int i;
+
+ for (i = 0; i < IEEE80211_MAX_CHAINS ; i++) {
+ status->chains &= ~BIT(i);
+
+ if (rxd->ppdu_start.rssi_chains[i].pri20_mhz != 0x80) {
+ status->chain_signal[i] = ATH10K_DEFAULT_NOISE_FLOOR +
+ rxd->ppdu_start.rssi_chains[i].pri20_mhz;
+
+ status->chains |= BIT(i);
+ }
+ }
+
/* FIXME: Get real NF */
status->signal = ATH10K_DEFAULT_NOISE_FLOOR +
rxd->ppdu_start.rssi_comb;
@@ -2229,9 +2242,15 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
txrate.mcs = ATH10K_HW_MCS_RATE(peer_stats->ratecode);
sgi = ATH10K_HW_GI(peer_stats->flags);
- if (((txrate.flags == WMI_RATE_PREAMBLE_HT) ||
- (txrate.flags == WMI_RATE_PREAMBLE_VHT)) && txrate.mcs > 9) {
- ath10k_warn(ar, "Invalid mcs %hhd peer stats", txrate.mcs);
+ if (txrate.flags == WMI_RATE_PREAMBLE_VHT && txrate.mcs > 9) {
+ ath10k_warn(ar, "Invalid VHT mcs %hhd peer stats", txrate.mcs);
+ return;
+ }
+
+ if (txrate.flags == WMI_RATE_PREAMBLE_HT &&
+ (txrate.mcs > 7 || txrate.nss < 1)) {
+ ath10k_warn(ar, "Invalid HT mcs %hhd nss %hhd peer stats",
+ txrate.mcs, txrate.nss);
return;
}
@@ -2254,7 +2273,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
arsta->txrate.legacy = rate;
} else if (txrate.flags == WMI_RATE_PREAMBLE_HT) {
arsta->txrate.flags = RATE_INFO_FLAGS_MCS;
- arsta->txrate.mcs = txrate.mcs;
+ arsta->txrate.mcs = txrate.mcs + 8 * (txrate.nss - 1);
} else {
arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS;
arsta->txrate.mcs = txrate.mcs;
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c
index c866ab5..afb0c01 100644
--- a/drivers/net/wireless/ath/ath10k/hw.c
+++ b/drivers/net/wireless/ath/ath10k/hw.c
@@ -15,6 +15,7 @@
*/
#include <linux/types.h>
+#include <linux/bitops.h>
#include "core.h"
#include "hw.h"
#include "hif.h"
@@ -191,6 +192,142 @@ const struct ath10k_hw_values qca4019_values = {
.ce_desc_meta_data_lsb = 4,
};
+static struct ath10k_hw_ce_regs_addr_map qcax_src_ring = {
+ .msb = 0x00000010,
+ .lsb = 0x00000010,
+ .mask = GENMASK(16, 16),
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_dst_ring = {
+ .msb = 0x00000011,
+ .lsb = 0x00000011,
+ .mask = GENMASK(17, 17),
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_dmax = {
+ .msb = 0x0000000f,
+ .lsb = 0x00000000,
+ .mask = GENMASK(15, 0),
+};
+
+static struct ath10k_hw_ce_ctrl1 qcax_ctrl1 = {
+ .addr = 0x00000010,
+ .hw_mask = 0x0007ffff,
+ .sw_mask = 0x0007ffff,
+ .hw_wr_mask = 0x00000000,
+ .sw_wr_mask = 0x0007ffff,
+ .reset_mask = 0xffffffff,
+ .reset = 0x00000080,
+ .src_ring = &qcax_src_ring,
+ .dst_ring = &qcax_dst_ring,
+ .dmax = &qcax_dmax,
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_cmd_halt_status = {
+ .msb = 0x00000003,
+ .lsb = 0x00000003,
+ .mask = GENMASK(3, 3),
+};
+
+static struct ath10k_hw_ce_cmd_halt qcax_cmd_halt = {
+ .msb = 0x00000000,
+ .mask = GENMASK(0, 0),
+ .status_reset = 0x00000000,
+ .status = &qcax_cmd_halt_status,
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_host_ie_cc = {
+ .msb = 0x00000000,
+ .lsb = 0x00000000,
+ .mask = GENMASK(0, 0),
+};
+
+static struct ath10k_hw_ce_host_ie qcax_host_ie = {
+ .copy_complete_reset = 0x00000000,
+ .copy_complete = &qcax_host_ie_cc,
+};
+
+static struct ath10k_hw_ce_host_wm_regs qcax_wm_reg = {
+ .dstr_lmask = 0x00000010,
+ .dstr_hmask = 0x00000008,
+ .srcr_lmask = 0x00000004,
+ .srcr_hmask = 0x00000002,
+ .cc_mask = 0x00000001,
+ .wm_mask = 0x0000001E,
+ .addr = 0x00000030,
+};
+
+static struct ath10k_hw_ce_misc_regs qcax_misc_reg = {
+ .axi_err = 0x00000400,
+ .dstr_add_err = 0x00000200,
+ .srcr_len_err = 0x00000100,
+ .dstr_mlen_vio = 0x00000080,
+ .dstr_overflow = 0x00000040,
+ .srcr_overflow = 0x00000020,
+ .err_mask = 0x000007E0,
+ .addr = 0x00000038,
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_src_wm_low = {
+ .msb = 0x0000001f,
+ .lsb = 0x00000010,
+ .mask = GENMASK(31, 16),
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_src_wm_high = {
+ .msb = 0x0000000f,
+ .lsb = 0x00000000,
+ .mask = GENMASK(15, 0),
+};
+
+static struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_src_ring = {
+ .addr = 0x0000004c,
+ .low_rst = 0x00000000,
+ .high_rst = 0x00000000,
+ .wm_low = &qcax_src_wm_low,
+ .wm_high = &qcax_src_wm_high,
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_low = {
+ .lsb = 0x00000010,
+ .mask = GENMASK(31, 16),
+};
+
+static struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_high = {
+ .msb = 0x0000000f,
+ .lsb = 0x00000000,
+ .mask = GENMASK(15, 0),
+};
+
+static struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_dst_ring = {
+ .addr = 0x00000050,
+ .low_rst = 0x00000000,
+ .high_rst = 0x00000000,
+ .wm_low = &qcax_dst_wm_low,
+ .wm_high = &qcax_dst_wm_high,
+};
+
+struct ath10k_hw_ce_regs qcax_ce_regs = {
+ .sr_base_addr = 0x00000000,
+ .sr_size_addr = 0x00000004,
+ .dr_base_addr = 0x00000008,
+ .dr_size_addr = 0x0000000c,
+ .ce_cmd_addr = 0x00000018,
+ .misc_ie_addr = 0x00000034,
+ .sr_wr_index_addr = 0x0000003c,
+ .dst_wr_index_addr = 0x00000040,
+ .current_srri_addr = 0x00000044,
+ .current_drri_addr = 0x00000048,
+ .host_ie_addr = 0x0000002c,
+ .ctrl1_regs = &qcax_ctrl1,
+ .cmd_halt = &qcax_cmd_halt,
+ .host_ie = &qcax_host_ie,
+ .wm_regs = &qcax_wm_reg,
+ .misc_regs = &qcax_misc_reg,
+ .wm_srcr = &qcax_wm_src_ring,
+ .wm_dstr = &qcax_wm_dst_ring,
+};
+
const struct ath10k_hw_clk_params qca6174_clk[ATH10K_HW_REFCLK_COUNT] = {
{
.refclk = 48000000,
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 5b1e90b..97dc147 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -268,6 +268,86 @@ extern const struct ath10k_hw_regs qca6174_regs;
extern const struct ath10k_hw_regs qca99x0_regs;
extern const struct ath10k_hw_regs qca4019_regs;
+struct ath10k_hw_ce_regs_addr_map {
+ u32 msb;
+ u32 lsb;
+ u32 mask;
+};
+
+struct ath10k_hw_ce_ctrl1 {
+ u32 addr;
+ u32 hw_mask;
+ u32 sw_mask;
+ u32 hw_wr_mask;
+ u32 sw_wr_mask;
+ u32 reset_mask;
+ u32 reset;
+ struct ath10k_hw_ce_regs_addr_map *src_ring;
+ struct ath10k_hw_ce_regs_addr_map *dst_ring;
+ struct ath10k_hw_ce_regs_addr_map *dmax; };
+
+struct ath10k_hw_ce_cmd_halt {
+ u32 status_reset;
+ u32 msb;
+ u32 mask;
+ struct ath10k_hw_ce_regs_addr_map *status; };
+
+struct ath10k_hw_ce_host_ie {
+ u32 copy_complete_reset;
+ struct ath10k_hw_ce_regs_addr_map *copy_complete; };
+
+struct ath10k_hw_ce_host_wm_regs {
+ u32 dstr_lmask;
+ u32 dstr_hmask;
+ u32 srcr_lmask;
+ u32 srcr_hmask;
+ u32 cc_mask;
+ u32 wm_mask;
+ u32 addr;
+};
+
+struct ath10k_hw_ce_misc_regs {
+ u32 axi_err;
+ u32 dstr_add_err;
+ u32 srcr_len_err;
+ u32 dstr_mlen_vio;
+ u32 dstr_overflow;
+ u32 srcr_overflow;
+ u32 err_mask;
+ u32 addr;
+};
+
+struct ath10k_hw_ce_dst_src_wm_regs {
+ u32 addr;
+ u32 low_rst;
+ u32 high_rst;
+ struct ath10k_hw_ce_regs_addr_map *wm_low;
+ struct ath10k_hw_ce_regs_addr_map *wm_high; };
+
+struct ath10k_hw_ce_regs {
+ u32 sr_base_addr;
+ u32 sr_size_addr;
+ u32 dr_base_addr;
+ u32 dr_size_addr;
+ u32 ce_cmd_addr;
+ u32 misc_ie_addr;
+ u32 sr_wr_index_addr;
+ u32 dst_wr_index_addr;
+ u32 current_srri_addr;
+ u32 current_drri_addr;
+ u32 ddr_addr_for_rri_low;
+ u32 ddr_addr_for_rri_high;
+ u32 ce_rri_low;
+ u32 ce_rri_high;
+ u32 host_ie_addr;
+ struct ath10k_hw_ce_host_wm_regs *wm_regs;
+ struct ath10k_hw_ce_misc_regs *misc_regs;
+ struct ath10k_hw_ce_ctrl1 *ctrl1_regs;
+ struct ath10k_hw_ce_cmd_halt *cmd_halt;
+ struct ath10k_hw_ce_host_ie *host_ie;
+ struct ath10k_hw_ce_dst_src_wm_regs *wm_srcr;
+ struct ath10k_hw_ce_dst_src_wm_regs *wm_dstr; };
+
struct ath10k_hw_values {
u32 rtc_state_val_on;
u8 ce_count;
@@ -282,6 +362,7 @@ extern const struct ath10k_hw_values qca6174_values;
extern const struct ath10k_hw_values qca99x0_values;
extern const struct ath10k_hw_values qca9888_values;
extern const struct ath10k_hw_values qca4019_values;
+extern struct ath10k_hw_ce_regs qcax_ce_regs;
void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev);
@@ -454,6 +535,12 @@ struct ath10k_hw_params {
/* Number of bytes to be discarded for each FFT sample */
int spectral_bin_discard;
+
+ /* The board may have a restricted NSS for 160 or 80+80 vs what it
+ * can do for 80Mhz.
+ */
+ int vht160_mcs_rx_highest;
+ int vht160_mcs_tx_highest;
};
struct htt_rx_desc;
@@ -863,6 +950,59 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
#define QCA9887_EEPROM_ADDR_LO_MASK 0x00ff0000
#define QCA9887_EEPROM_ADDR_LO_LSB 16
+#define MBOX_RESET_CONTROL_ADDRESS 0x00000000
+#define MBOX_HOST_INT_STATUS_ADDRESS 0x00000800
+#define MBOX_HOST_INT_STATUS_ERROR_LSB 7
+#define MBOX_HOST_INT_STATUS_ERROR_MASK 0x00000080
+#define MBOX_HOST_INT_STATUS_CPU_LSB 6
+#define MBOX_HOST_INT_STATUS_CPU_MASK 0x00000040
+#define MBOX_HOST_INT_STATUS_COUNTER_LSB 4
+#define MBOX_HOST_INT_STATUS_COUNTER_MASK 0x00000010
+#define MBOX_CPU_INT_STATUS_ADDRESS 0x00000801
+#define MBOX_ERROR_INT_STATUS_ADDRESS 0x00000802
+#define MBOX_ERROR_INT_STATUS_WAKEUP_LSB 2
+#define MBOX_ERROR_INT_STATUS_WAKEUP_MASK 0x00000004
+#define MBOX_ERROR_INT_STATUS_RX_UNDERFLOW_LSB 1
+#define MBOX_ERROR_INT_STATUS_RX_UNDERFLOW_MASK 0x00000002
+#define MBOX_ERROR_INT_STATUS_TX_OVERFLOW_LSB 0
+#define MBOX_ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x00000001
+#define MBOX_COUNTER_INT_STATUS_ADDRESS 0x00000803
+#define MBOX_COUNTER_INT_STATUS_COUNTER_LSB 0
+#define MBOX_COUNTER_INT_STATUS_COUNTER_MASK 0x000000ff
+#define MBOX_RX_LOOKAHEAD_VALID_ADDRESS 0x00000805
+#define MBOX_INT_STATUS_ENABLE_ADDRESS 0x00000828
+#define MBOX_INT_STATUS_ENABLE_ERROR_LSB 7
+#define MBOX_INT_STATUS_ENABLE_ERROR_MASK 0x00000080
+#define MBOX_INT_STATUS_ENABLE_CPU_LSB 6
+#define MBOX_INT_STATUS_ENABLE_CPU_MASK 0x00000040
+#define MBOX_INT_STATUS_ENABLE_INT_LSB 5
+#define MBOX_INT_STATUS_ENABLE_INT_MASK 0x00000020
+#define MBOX_INT_STATUS_ENABLE_COUNTER_LSB 4
+#define MBOX_INT_STATUS_ENABLE_COUNTER_MASK 0x00000010
+#define MBOX_INT_STATUS_ENABLE_MBOX_DATA_LSB 0
+#define MBOX_INT_STATUS_ENABLE_MBOX_DATA_MASK 0x0000000f
+#define MBOX_CPU_INT_STATUS_ENABLE_ADDRESS 0x00000819
+#define MBOX_CPU_INT_STATUS_ENABLE_BIT_LSB 0
+#define MBOX_CPU_INT_STATUS_ENABLE_BIT_MASK 0x000000ff
+#define MBOX_ERROR_STATUS_ENABLE_ADDRESS 0x0000081a
+#define MBOX_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB 1
+#define MBOX_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00000002
+#define MBOX_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB 0
+#define MBOX_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK 0x00000001
+#define MBOX_COUNTER_INT_STATUS_ENABLE_ADDRESS 0x0000081b
+#define MBOX_COUNTER_INT_STATUS_ENABLE_BIT_LSB 0
+#define MBOX_COUNTER_INT_STATUS_ENABLE_BIT_MASK 0x000000ff
+#define MBOX_COUNT_ADDRESS 0x00000820
+#define MBOX_COUNT_DEC_ADDRESS 0x00000840
+#define MBOX_WINDOW_DATA_ADDRESS 0x00000874
+#define MBOX_WINDOW_WRITE_ADDR_ADDRESS 0x00000878
+#define MBOX_WINDOW_READ_ADDR_ADDRESS 0x0000087c
+#define MBOX_CPU_DBG_SEL_ADDRESS 0x00000883
+#define MBOX_CPU_DBG_ADDRESS 0x00000884
+#define MBOX_RTC_BASE_ADDRESS 0x00000000
+#define MBOX_GPIO_BASE_ADDRESS 0x00005000
+#define MBOX_MBOX_BASE_ADDRESS 0x00008000
+
#define RTC_STATE_V_GET(x) (((x) & RTC_STATE_V_MASK) >> RTC_STATE_V_LSB)
/* Register definitions for first generation ath10k cards. These cards include
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 4674ff3..55c808f 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1392,7 +1392,7 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif)
ret = ath10k_vdev_setup_sync(ar);
if (ret) {
- ath10k_warn(ar, "failed to syncronise setup for vdev %i: %d\n",
+ ath10k_warn(ar, "failed to synchronize setup for vdev %i: %d\n",
arvif->vdev_id, ret);
return ret;
}
@@ -2519,6 +2519,20 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n",
sta->addr, arg->peer_max_mpdu, arg->peer_flags);
+
+ if (arg->peer_vht_rates.rx_max_rate &&
+ (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK)) {
+ switch (arg->peer_vht_rates.rx_max_rate) {
+ case 1560:
+ /* Must be 2x2 at 160Mhz is all it can do. */
+ arg->peer_bw_rxnss_override = 2;
+ break;
+ case 780:
+ /* Can only do 1x1 at 160Mhz (Long Guard Interval) */
+ arg->peer_bw_rxnss_override = 1;
+ break;
+ }
+ }
}
static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
@@ -3475,9 +3489,8 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar,
if (arvif->u.ap.noa_data)
if (!pskb_expand_head(skb, 0, arvif->u.ap.noa_len,
GFP_ATOMIC))
- memcpy(skb_put(skb, arvif->u.ap.noa_len),
- arvif->u.ap.noa_data,
- arvif->u.ap.noa_len);
+ skb_put_data(skb, arvif->u.ap.noa_data,
+ arvif->u.ap.noa_len);
spin_unlock_bh(&ar->data_lock);
}
}
@@ -4362,6 +4375,7 @@ static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar)
static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
{
struct ieee80211_sta_vht_cap vht_cap = {0};
+ struct ath10k_hw_params *hw = &ar->hw_params;
u16 mcs_map;
u32 val;
int i;
@@ -4391,7 +4405,7 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
* mode until that's resolved.
*/
if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SHORT_GI_160) &&
- !(ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
+ (ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) == 0)
vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
mcs_map = 0;
@@ -4408,6 +4422,17 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
+ /* If we are supporting 160Mhz or 80+80, then the NIC may be able to do
+ * a restricted NSS for 160 or 80+80 vs what it can do for 80Mhz. Give
+ * user-space a clue if that is the case.
+ */
+ if ((vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) &&
+ (hw->vht160_mcs_rx_highest != 0 ||
+ hw->vht160_mcs_tx_highest != 0)) {
+ vht_cap.vht_mcs.rx_highest = cpu_to_le16(hw->vht160_mcs_rx_highest);
+ vht_cap.vht_mcs.tx_highest = cpu_to_le16(hw->vht160_mcs_tx_highest);
+ }
+
return vht_cap;
}
@@ -6073,6 +6098,20 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
ar->num_stations + 1, ar->max_num_stations,
ar->num_peers + 1, ar->max_num_peers);
+ num_tdls_stations = ath10k_mac_tdls_vif_stations_count(hw, vif);
+ num_tdls_vifs = ath10k_mac_tdls_vifs_count(hw);
+
+ if (sta->tdls) {
+ if (num_tdls_stations >= ar->max_num_tdls_vdevs) {
+ ath10k_warn(ar, "vdev %i exceeded maximum number of tdls vdevs %i\n",
+ arvif->vdev_id,
+ ar->max_num_tdls_vdevs);
+ ret = -ELNRNG;
+ goto exit;
+ }
+ peer_type = WMI_PEER_TYPE_TDLS;
+ }
+
ret = ath10k_mac_inc_num_stations(arvif, sta);
if (ret) {
ath10k_warn(ar, "refusing to associate station: too many connected already (%d)\n",
@@ -6080,9 +6119,6 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
goto exit;
}
- if (sta->tdls)
- peer_type = WMI_PEER_TYPE_TDLS;
-
ret = ath10k_peer_create(ar, vif, sta, arvif->vdev_id,
sta->addr, peer_type);
if (ret) {
@@ -6113,35 +6149,17 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
if (!sta->tdls)
goto exit;
- num_tdls_stations = ath10k_mac_tdls_vif_stations_count(hw, vif);
- num_tdls_vifs = ath10k_mac_tdls_vifs_count(hw);
-
- if (num_tdls_vifs >= ar->max_num_tdls_vdevs &&
- num_tdls_stations == 0) {
- ath10k_warn(ar, "vdev %i exceeded maximum number of tdls vdevs %i\n",
- arvif->vdev_id, ar->max_num_tdls_vdevs);
- ath10k_peer_delete(ar, arvif->vdev_id, sta->addr);
+ ret = ath10k_wmi_update_fw_tdls_state(ar, arvif->vdev_id,
+ WMI_TDLS_ENABLE_ACTIVE);
+ if (ret) {
+ ath10k_warn(ar, "failed to update fw tdls state on vdev %i: %i\n",
+ arvif->vdev_id, ret);
+ ath10k_peer_delete(ar, arvif->vdev_id,
+ sta->addr);
ath10k_mac_dec_num_stations(arvif, sta);
- ret = -ENOBUFS;
goto exit;
}
- if (num_tdls_stations == 0) {
- /* This is the first tdls peer in current vif */
- enum wmi_tdls_state state = WMI_TDLS_ENABLE_ACTIVE;
-
- ret = ath10k_wmi_update_fw_tdls_state(ar, arvif->vdev_id,
- state);
- if (ret) {
- ath10k_warn(ar, "failed to update fw tdls state on vdev %i: %i\n",
- arvif->vdev_id, ret);
- ath10k_peer_delete(ar, arvif->vdev_id,
- sta->addr);
- ath10k_mac_dec_num_stations(arvif, sta);
- goto exit;
- }
- }
-
ret = ath10k_mac_tdls_peer_update(ar, arvif->vdev_id, sta,
WMI_TDLS_PEER_STATE_PEERING);
if (ret) {
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 1e9806f..7ebfc40 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -101,7 +101,8 @@ static int ath10k_pci_init_irq(struct ath10k *ar);
static int ath10k_pci_deinit_irq(struct ath10k *ar);
static int ath10k_pci_request_irq(struct ath10k *ar);
static void ath10k_pci_free_irq(struct ath10k *ar);
-static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
+static int ath10k_pci_bmi_wait(struct ath10k *ar,
+ struct ath10k_ce_pipe *tx_pipe,
struct ath10k_ce_pipe *rx_pipe,
struct bmi_xfer *xfer);
static int ath10k_pci_qca99x0_chip_reset(struct ath10k *ar);
@@ -468,7 +469,7 @@ static int ath10k_pci_wake_wait(struct ath10k *ar)
while (tot_delay < PCIE_WAKE_TIMEOUT) {
if (ath10k_pci_is_awake(ar)) {
if (tot_delay > PCIE_WAKE_LATE_US)
- ath10k_warn(ar, "device wakeup took %d ms which is unusally long, otherwise it works normally.\n",
+ ath10k_warn(ar, "device wakeup took %d ms which is unusually long, otherwise it works normally.\n",
tot_delay / 1000);
return 0;
}
@@ -1846,7 +1847,7 @@ int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
if (ret)
goto err_resp;
- ret = ath10k_pci_bmi_wait(ce_tx, ce_rx, &xfer);
+ ret = ath10k_pci_bmi_wait(ar, ce_tx, ce_rx, &xfer);
if (ret) {
u32 unused_buffer;
unsigned int unused_nbytes;
@@ -1913,23 +1914,37 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
xfer->rx_done = true;
}
-static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
+static int ath10k_pci_bmi_wait(struct ath10k *ar,
+ struct ath10k_ce_pipe *tx_pipe,
struct ath10k_ce_pipe *rx_pipe,
struct bmi_xfer *xfer)
{
unsigned long timeout = jiffies + BMI_COMMUNICATION_TIMEOUT_HZ;
+ unsigned long started = jiffies;
+ unsigned long dur;
+ int ret;
while (time_before_eq(jiffies, timeout)) {
ath10k_pci_bmi_send_done(tx_pipe);
ath10k_pci_bmi_recv_data(rx_pipe);
- if (xfer->tx_done && (xfer->rx_done == xfer->wait_for_resp))
- return 0;
+ if (xfer->tx_done && (xfer->rx_done == xfer->wait_for_resp)) {
+ ret = 0;
+ goto out;
+ }
schedule();
}
- return -ETIMEDOUT;
+ ret = -ETIMEDOUT;
+
+out:
+ dur = jiffies - started;
+ if (dur > HZ)
+ ath10k_dbg(ar, ATH10K_DBG_BMI,
+ "bmi cmd took %lu jiffies hz %d ret %d\n",
+ dur, HZ, ret);
+ return ret;
}
/*
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
new file mode 100644
index 0000000..859ed87
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -0,0 +1,2113 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012,2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
+ *
+ * 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/module.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sd.h>
+#include <linux/bitfield.h>
+#include "core.h"
+#include "bmi.h"
+#include "debug.h"
+#include "hif.h"
+#include "htc.h"
+#include "targaddrs.h"
+#include "trace.h"
+#include "sdio.h"
+
+/* inlined helper functions */
+
+static inline int ath10k_sdio_calc_txrx_padded_len(struct ath10k_sdio *ar_sdio,
+ size_t len)
+{
+ return __ALIGN_MASK((len), ar_sdio->mbox_info.block_mask);
+}
+
+static inline enum ath10k_htc_ep_id pipe_id_to_eid(u8 pipe_id)
+{
+ return (enum ath10k_htc_ep_id)pipe_id;
+}
+
+static inline void ath10k_sdio_mbox_free_rx_pkt(struct ath10k_sdio_rx_data *pkt)
+{
+ dev_kfree_skb(pkt->skb);
+ pkt->skb = NULL;
+ pkt->alloc_len = 0;
+ pkt->act_len = 0;
+ pkt->trailer_only = false;
+}
+
+static inline int ath10k_sdio_mbox_alloc_rx_pkt(struct ath10k_sdio_rx_data *pkt,
+ size_t act_len, size_t full_len,
+ bool part_of_bundle,
+ bool last_in_bundle)
+{
+ pkt->skb = dev_alloc_skb(full_len);
+ if (!pkt->skb)
+ return -ENOMEM;
+
+ pkt->act_len = act_len;
+ pkt->alloc_len = full_len;
+ pkt->part_of_bundle = part_of_bundle;
+ pkt->last_in_bundle = last_in_bundle;
+ pkt->trailer_only = false;
+
+ return 0;
+}
+
+static inline bool is_trailer_only_msg(struct ath10k_sdio_rx_data *pkt)
+{
+ bool trailer_only = false;
+ struct ath10k_htc_hdr *htc_hdr =
+ (struct ath10k_htc_hdr *)pkt->skb->data;
+ u16 len = __le16_to_cpu(htc_hdr->len);
+
+ if (len == htc_hdr->trailer_len)
+ trailer_only = true;
+
+ return trailer_only;
+}
+
+/* sdio/mmc functions */
+
+static inline void ath10k_sdio_set_cmd52_arg(u32 *arg, u8 write, u8 raw,
+ unsigned int address,
+ unsigned char val)
+{
+ *arg = FIELD_PREP(BIT(31), write) |
+ FIELD_PREP(BIT(27), raw) |
+ FIELD_PREP(BIT(26), 1) |
+ FIELD_PREP(GENMASK(25, 9), address) |
+ FIELD_PREP(BIT(8), 1) |
+ FIELD_PREP(GENMASK(7, 0), val);
+}
+
+static int ath10k_sdio_func0_cmd52_wr_byte(struct mmc_card *card,
+ unsigned int address,
+ unsigned char byte)
+{
+ struct mmc_command io_cmd;
+
+ memset(&io_cmd, 0, sizeof(io_cmd));
+ ath10k_sdio_set_cmd52_arg(&io_cmd.arg, 1, 0, address, byte);
+ io_cmd.opcode = SD_IO_RW_DIRECT;
+ io_cmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
+
+ return mmc_wait_for_cmd(card->host, &io_cmd, 0);
+}
+
+static int ath10k_sdio_func0_cmd52_rd_byte(struct mmc_card *card,
+ unsigned int address,
+ unsigned char *byte)
+{
+ struct mmc_command io_cmd;
+ int ret;
+
+ memset(&io_cmd, 0, sizeof(io_cmd));
+ ath10k_sdio_set_cmd52_arg(&io_cmd.arg, 0, 0, address, 0);
+ io_cmd.opcode = SD_IO_RW_DIRECT;
+ io_cmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
+
+ ret = mmc_wait_for_cmd(card->host, &io_cmd, 0);
+ if (!ret)
+ *byte = io_cmd.resp[0];
+
+ return ret;
+}
+
+static int ath10k_sdio_config(struct ath10k *ar)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct sdio_func *func = ar_sdio->func;
+ unsigned char byte, asyncintdelay = 2;
+ int ret;
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "sdio configuration\n");
+
+ sdio_claim_host(func);
+
+ byte = 0;
+ ret = ath10k_sdio_func0_cmd52_rd_byte(func->card,
+ SDIO_CCCR_DRIVE_STRENGTH,
+ &byte);
+
+ byte &= ~ATH10K_SDIO_DRIVE_DTSX_MASK;
+ byte |= FIELD_PREP(ATH10K_SDIO_DRIVE_DTSX_MASK,
+ ATH10K_SDIO_DRIVE_DTSX_TYPE_D);
+
+ ret = ath10k_sdio_func0_cmd52_wr_byte(func->card,
+ SDIO_CCCR_DRIVE_STRENGTH,
+ byte);
+
+ byte = 0;
+ ret = ath10k_sdio_func0_cmd52_rd_byte(
+ func->card,
+ CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR,
+ &byte);
+
+ byte |= (CCCR_SDIO_DRIVER_STRENGTH_ENABLE_A |
+ CCCR_SDIO_DRIVER_STRENGTH_ENABLE_C |
+ CCCR_SDIO_DRIVER_STRENGTH_ENABLE_D);
+
+ ret = ath10k_sdio_func0_cmd52_wr_byte(func->card,
+ CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR,
+ byte);
+ if (ret) {
+ ath10k_warn(ar, "failed to enable driver strength: %d\n", ret);
+ goto out;
+ }
+
+ byte = 0;
+ ret = ath10k_sdio_func0_cmd52_rd_byte(func->card,
+ CCCR_SDIO_IRQ_MODE_REG_SDIO3,
+ &byte);
+
+ byte |= SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_SDIO3;
+
+ ret = ath10k_sdio_func0_cmd52_wr_byte(func->card,
+ CCCR_SDIO_IRQ_MODE_REG_SDIO3,
+ byte);
+ if (ret) {
+ ath10k_warn(ar, "failed to enable 4-bit async irq mode: %d\n",
+ ret);
+ goto out;
+ }
+
+ byte = 0;
+ ret = ath10k_sdio_func0_cmd52_rd_byte(func->card,
+ CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS,
+ &byte);
+
+ byte &= ~CCCR_SDIO_ASYNC_INT_DELAY_MASK;
+ byte |= FIELD_PREP(CCCR_SDIO_ASYNC_INT_DELAY_MASK, asyncintdelay);
+
+ ret = ath10k_sdio_func0_cmd52_wr_byte(func->card,
+ CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS,
+ byte);
+
+ /* give us some time to enable, in ms */
+ func->enable_timeout = 100;
+
+ ret = sdio_set_block_size(func, ar_sdio->mbox_info.block_size);
+ if (ret) {
+ ath10k_warn(ar, "failed to set sdio block size to %d: %d\n",
+ ar_sdio->mbox_info.block_size, ret);
+ goto out;
+ }
+
+out:
+ sdio_release_host(func);
+ return ret;
+}
+
+static int ath10k_sdio_write32(struct ath10k *ar, u32 addr, u32 val)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct sdio_func *func = ar_sdio->func;
+ int ret;
+
+ sdio_claim_host(func);
+
+ sdio_writel(func, val, addr, &ret);
+ if (ret) {
+ ath10k_warn(ar, "failed to write 0x%x to address 0x%x: %d\n",
+ val, addr, ret);
+ goto out;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio write32 addr 0x%x val 0x%x\n",
+ addr, val);
+
+out:
+ sdio_release_host(func);
+
+ return ret;
+}
+
+static int ath10k_sdio_writesb32(struct ath10k *ar, u32 addr, u32 val)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct sdio_func *func = ar_sdio->func;
+ __le32 *buf;
+ int ret;
+
+ buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ *buf = cpu_to_le32(val);
+
+ sdio_claim_host(func);
+
+ ret = sdio_writesb(func, addr, buf, sizeof(*buf));
+ if (ret) {
+ ath10k_warn(ar, "failed to write value 0x%x to fixed sb address 0x%x: %d\n",
+ val, addr, ret);
+ goto out;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio writesb32 addr 0x%x val 0x%x\n",
+ addr, val);
+
+out:
+ sdio_release_host(func);
+
+ kfree(buf);
+
+ return ret;
+}
+
+static int ath10k_sdio_read32(struct ath10k *ar, u32 addr, u32 *val)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct sdio_func *func = ar_sdio->func;
+ int ret;
+
+ sdio_claim_host(func);
+ *val = sdio_readl(func, addr, &ret);
+ if (ret) {
+ ath10k_warn(ar, "failed to read from address 0x%x: %d\n",
+ addr, ret);
+ goto out;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio read32 addr 0x%x val 0x%x\n",
+ addr, *val);
+
+out:
+ sdio_release_host(func);
+
+ return ret;
+}
+
+static int ath10k_sdio_read(struct ath10k *ar, u32 addr, void *buf, size_t len)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct sdio_func *func = ar_sdio->func;
+ int ret;
+
+ sdio_claim_host(func);
+
+ ret = sdio_memcpy_fromio(func, buf, addr, len);
+ if (ret) {
+ ath10k_warn(ar, "failed to read from address 0x%x: %d\n",
+ addr, ret);
+ goto out;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio read addr 0x%x buf 0x%p len %zu\n",
+ addr, buf, len);
+ ath10k_dbg_dump(ar, ATH10K_DBG_SDIO_DUMP, NULL, "sdio read ", buf, len);
+
+out:
+ sdio_release_host(func);
+
+ return ret;
+}
+
+static int ath10k_sdio_write(struct ath10k *ar, u32 addr, const void *buf, size_t len)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct sdio_func *func = ar_sdio->func;
+ int ret;
+
+ sdio_claim_host(func);
+
+ /* For some reason toio() doesn't have const for the buffer, need
+ * an ugly hack to workaround that.
+ */
+ ret = sdio_memcpy_toio(func, addr, (void *)buf, len);
+ if (ret) {
+ ath10k_warn(ar, "failed to write to address 0x%x: %d\n",
+ addr, ret);
+ goto out;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio write addr 0x%x buf 0x%p len %zu\n",
+ addr, buf, len);
+ ath10k_dbg_dump(ar, ATH10K_DBG_SDIO_DUMP, NULL, "sdio write ", buf, len);
+
+out:
+ sdio_release_host(func);
+
+ return ret;
+}
+
+static int ath10k_sdio_readsb(struct ath10k *ar, u32 addr, void *buf, size_t len)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct sdio_func *func = ar_sdio->func;
+ int ret;
+
+ sdio_claim_host(func);
+
+ len = round_down(len, ar_sdio->mbox_info.block_size);
+
+ ret = sdio_readsb(func, buf, addr, len);
+ if (ret) {
+ ath10k_warn(ar, "failed to read from fixed (sb) address 0x%x: %d\n",
+ addr, ret);
+ goto out;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio readsb addr 0x%x buf 0x%p len %zu\n",
+ addr, buf, len);
+ ath10k_dbg_dump(ar, ATH10K_DBG_SDIO_DUMP, NULL, "sdio readsb ", buf, len);
+
+out:
+ sdio_release_host(func);
+
+ return ret;
+}
+
+/* HIF mbox functions */
+
+static int ath10k_sdio_mbox_rx_process_packet(struct ath10k *ar,
+ struct ath10k_sdio_rx_data *pkt,
+ u32 *lookaheads,
+ int *n_lookaheads)
+{
+ struct ath10k_htc *htc = &ar->htc;
+ struct sk_buff *skb = pkt->skb;
+ struct ath10k_htc_hdr *htc_hdr = (struct ath10k_htc_hdr *)skb->data;
+ bool trailer_present = htc_hdr->flags & ATH10K_HTC_FLAG_TRAILER_PRESENT;
+ enum ath10k_htc_ep_id eid;
+ u16 payload_len;
+ u8 *trailer;
+ int ret;
+
+ payload_len = le16_to_cpu(htc_hdr->len);
+
+ if (trailer_present) {
+ trailer = skb->data + sizeof(*htc_hdr) +
+ payload_len - htc_hdr->trailer_len;
+
+ eid = pipe_id_to_eid(htc_hdr->eid);
+
+ ret = ath10k_htc_process_trailer(htc,
+ trailer,
+ htc_hdr->trailer_len,
+ eid,
+ lookaheads,
+ n_lookaheads);
+ if (ret)
+ return ret;
+
+ if (is_trailer_only_msg(pkt))
+ pkt->trailer_only = true;
+
+ skb_trim(skb, skb->len - htc_hdr->trailer_len);
+ }
+
+ skb_pull(skb, sizeof(*htc_hdr));
+
+ return 0;
+}
+
+static int ath10k_sdio_mbox_rx_process_packets(struct ath10k *ar,
+ u32 lookaheads[],
+ int *n_lookahead)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct ath10k_htc *htc = &ar->htc;
+ struct ath10k_sdio_rx_data *pkt;
+ struct ath10k_htc_ep *ep;
+ enum ath10k_htc_ep_id id;
+ int ret, i, *n_lookahead_local;
+ u32 *lookaheads_local;
+
+ for (i = 0; i < ar_sdio->n_rx_pkts; i++) {
+ lookaheads_local = lookaheads;
+ n_lookahead_local = n_lookahead;
+
+ id = ((struct ath10k_htc_hdr *)&lookaheads[i])->eid;
+
+ if (id >= ATH10K_HTC_EP_COUNT) {
+ ath10k_warn(ar, "invalid endpoint in look-ahead: %d\n",
+ id);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ep = &htc->endpoint[id];
+
+ if (ep->service_id == 0) {
+ ath10k_warn(ar, "ep %d is not connected\n", id);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ pkt = &ar_sdio->rx_pkts[i];
+
+ if (pkt->part_of_bundle && !pkt->last_in_bundle) {
+ /* Only read lookahead's from RX trailers
+ * for the last packet in a bundle.
+ */
+ lookaheads_local = NULL;
+ n_lookahead_local = NULL;
+ }
+
+ ret = ath10k_sdio_mbox_rx_process_packet(ar,
+ pkt,
+ lookaheads_local,
+ n_lookahead_local);
+ if (ret)
+ goto out;
+
+ if (!pkt->trailer_only)
+ ep->ep_ops.ep_rx_complete(ar_sdio->ar, pkt->skb);
+ else
+ kfree_skb(pkt->skb);
+
+ /* The RX complete handler now owns the skb...*/
+ pkt->skb = NULL;
+ pkt->alloc_len = 0;
+ }
+
+ ret = 0;
+
+out:
+ /* Free all packets that was not passed on to the RX completion
+ * handler...
+ */
+ for (; i < ar_sdio->n_rx_pkts; i++)
+ ath10k_sdio_mbox_free_rx_pkt(&ar_sdio->rx_pkts[i]);
+
+ return ret;
+}
+
+static int ath10k_sdio_mbox_alloc_pkt_bundle(struct ath10k *ar,
+ struct ath10k_sdio_rx_data *rx_pkts,
+ struct ath10k_htc_hdr *htc_hdr,
+ size_t full_len, size_t act_len,
+ size_t *bndl_cnt)
+{
+ int ret, i;
+
+ *bndl_cnt = FIELD_GET(ATH10K_HTC_FLAG_BUNDLE_MASK, htc_hdr->flags);
+
+ if (*bndl_cnt > HTC_HOST_MAX_MSG_PER_BUNDLE) {
+ ath10k_warn(ar,
+ "HTC bundle length %u exceeds maximum %u\n",
+ le16_to_cpu(htc_hdr->len),
+ HTC_HOST_MAX_MSG_PER_BUNDLE);
+ return -ENOMEM;
+ }
+
+ /* Allocate bndl_cnt extra skb's for the bundle.
+ * The package containing the
+ * ATH10K_HTC_FLAG_BUNDLE_MASK flag is not included
+ * in bndl_cnt. The skb for that packet will be
+ * allocated separately.
+ */
+ for (i = 0; i < *bndl_cnt; i++) {
+ ret = ath10k_sdio_mbox_alloc_rx_pkt(&rx_pkts[i],
+ act_len,
+ full_len,
+ true,
+ false);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,
+ u32 lookaheads[], int n_lookaheads)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct ath10k_htc_hdr *htc_hdr;
+ size_t full_len, act_len;
+ bool last_in_bundle;
+ int ret, i;
+
+ if (n_lookaheads > ATH10K_SDIO_MAX_RX_MSGS) {
+ ath10k_warn(ar,
+ "the total number of pkgs to be fetched (%u) exceeds maximum %u\n",
+ n_lookaheads,
+ ATH10K_SDIO_MAX_RX_MSGS);
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ for (i = 0; i < n_lookaheads; i++) {
+ htc_hdr = (struct ath10k_htc_hdr *)&lookaheads[i];
+ last_in_bundle = false;
+
+ if (le16_to_cpu(htc_hdr->len) >
+ ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH) {
+ ath10k_warn(ar,
+ "payload length %d exceeds max htc length: %zu\n",
+ le16_to_cpu(htc_hdr->len),
+ ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH);
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ act_len = le16_to_cpu(htc_hdr->len) + sizeof(*htc_hdr);
+ full_len = ath10k_sdio_calc_txrx_padded_len(ar_sdio, act_len);
+
+ if (full_len > ATH10K_SDIO_MAX_BUFFER_SIZE) {
+ ath10k_warn(ar,
+ "rx buffer requested with invalid htc_hdr length (%d, 0x%x): %d\n",
+ htc_hdr->eid, htc_hdr->flags,
+ le16_to_cpu(htc_hdr->len));
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (htc_hdr->flags & ATH10K_HTC_FLAG_BUNDLE_MASK) {
+ /* HTC header indicates that every packet to follow
+ * has the same padded length so that it can be
+ * optimally fetched as a full bundle.
+ */
+ size_t bndl_cnt;
+
+ ret = ath10k_sdio_mbox_alloc_pkt_bundle(ar,
+ &ar_sdio->rx_pkts[i],
+ htc_hdr,
+ full_len,
+ act_len,
+ &bndl_cnt);
+
+ n_lookaheads += bndl_cnt;
+ i += bndl_cnt;
+ /*Next buffer will be the last in the bundle */
+ last_in_bundle = true;
+ }
+
+ /* Allocate skb for packet. If the packet had the
+ * ATH10K_HTC_FLAG_BUNDLE_MASK flag set, all bundled
+ * packet skb's have been allocated in the previous step.
+ */
+ ret = ath10k_sdio_mbox_alloc_rx_pkt(&ar_sdio->rx_pkts[i],
+ act_len,
+ full_len,
+ last_in_bundle,
+ last_in_bundle);
+ }
+
+ ar_sdio->n_rx_pkts = i;
+
+ return 0;
+
+err:
+ for (i = 0; i < ATH10K_SDIO_MAX_RX_MSGS; i++) {
+ if (!ar_sdio->rx_pkts[i].alloc_len)
+ break;
+ ath10k_sdio_mbox_free_rx_pkt(&ar_sdio->rx_pkts[i]);
+ }
+
+ return ret;
+}
+
+static int ath10k_sdio_mbox_rx_packet(struct ath10k *ar,
+ struct ath10k_sdio_rx_data *pkt)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct sk_buff *skb = pkt->skb;
+ int ret;
+
+ ret = ath10k_sdio_readsb(ar, ar_sdio->mbox_info.htc_addr,
+ skb->data, pkt->alloc_len);
+ pkt->status = ret;
+ if (!ret)
+ skb_put(skb, pkt->act_len);
+
+ return ret;
+}
+
+static int ath10k_sdio_mbox_rx_fetch(struct ath10k *ar)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ int ret, i;
+
+ for (i = 0; i < ar_sdio->n_rx_pkts; i++) {
+ ret = ath10k_sdio_mbox_rx_packet(ar,
+ &ar_sdio->rx_pkts[i]);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ /* Free all packets that was not successfully fetched. */
+ for (; i < ar_sdio->n_rx_pkts; i++)
+ ath10k_sdio_mbox_free_rx_pkt(&ar_sdio->rx_pkts[i]);
+
+ return ret;
+}
+
+/* This is the timeout for mailbox processing done in the sdio irq
+ * handler. The timeout is deliberately set quite high since SDIO dump logs
+ * over serial port can/will add a substantial overhead to the processing
+ * (if enabled).
+ */
+#define SDIO_MBOX_PROCESSING_TIMEOUT_HZ (20 * HZ)
+
+static int ath10k_sdio_mbox_rxmsg_pending_handler(struct ath10k *ar,
+ u32 msg_lookahead, bool *done)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ u32 lookaheads[ATH10K_SDIO_MAX_RX_MSGS];
+ int n_lookaheads = 1;
+ unsigned long timeout;
+ int ret;
+
+ *done = true;
+
+ /* Copy the lookahead obtained from the HTC register table into our
+ * temp array as a start value.
+ */
+ lookaheads[0] = msg_lookahead;
+
+ timeout = jiffies + SDIO_MBOX_PROCESSING_TIMEOUT_HZ;
+ while (time_before(jiffies, timeout)) {
+ /* Try to allocate as many HTC RX packets indicated by
+ * n_lookaheads.
+ */
+ ret = ath10k_sdio_mbox_rx_alloc(ar, lookaheads,
+ n_lookaheads);
+ if (ret)
+ break;
+
+ if (ar_sdio->n_rx_pkts >= 2)
+ /* A recv bundle was detected, force IRQ status
+ * re-check again.
+ */
+ *done = false;
+
+ ret = ath10k_sdio_mbox_rx_fetch(ar);
+
+ /* Process fetched packets. This will potentially update
+ * n_lookaheads depending on if the packets contain lookahead
+ * reports.
+ */
+ n_lookaheads = 0;
+ ret = ath10k_sdio_mbox_rx_process_packets(ar,
+ lookaheads,
+ &n_lookaheads);
+
+ if (!n_lookaheads || ret)
+ break;
+
+ /* For SYNCH processing, if we get here, we are running
+ * through the loop again due to updated lookaheads. Set
+ * flag that we should re-check IRQ status registers again
+ * before leaving IRQ processing, this can net better
+ * performance in high throughput situations.
+ */
+ *done = false;
+ }
+
+ if (ret && (ret != -ECANCELED))
+ ath10k_warn(ar, "failed to get pending recv messages: %d\n",
+ ret);
+
+ return ret;
+}
+
+static int ath10k_sdio_mbox_proc_dbg_intr(struct ath10k *ar)
+{
+ u32 val;
+ int ret;
+
+ /* TODO: Add firmware crash handling */
+ ath10k_warn(ar, "firmware crashed\n");
+
+ /* read counter to clear the interrupt, the debug error interrupt is
+ * counter 0.
+ */
+ ret = ath10k_sdio_read32(ar, MBOX_COUNT_DEC_ADDRESS, &val);
+ if (ret)
+ ath10k_warn(ar, "failed to clear debug interrupt: %d\n", ret);
+
+ return ret;
+}
+
+static int ath10k_sdio_mbox_proc_counter_intr(struct ath10k *ar)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct ath10k_sdio_irq_data *irq_data = &ar_sdio->irq_data;
+ u8 counter_int_status;
+ int ret;
+
+ mutex_lock(&irq_data->mtx);
+ counter_int_status = irq_data->irq_proc_reg->counter_int_status &
+ irq_data->irq_en_reg->cntr_int_status_en;
+
+ /* NOTE: other modules like GMBOX may use the counter interrupt for
+ * credit flow control on other counters, we only need to check for
+ * the debug assertion counter interrupt.
+ */
+ if (counter_int_status & ATH10K_SDIO_TARGET_DEBUG_INTR_MASK)
+ ret = ath10k_sdio_mbox_proc_dbg_intr(ar);
+ else
+ ret = 0;
+
+ mutex_unlock(&irq_data->mtx);
+
+ return ret;
+}
+
+static int ath10k_sdio_mbox_proc_err_intr(struct ath10k *ar)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct ath10k_sdio_irq_data *irq_data = &ar_sdio->irq_data;
+ u8 error_int_status;
+ int ret;
+
+ ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio error interrupt\n");
+
+ error_int_status = irq_data->irq_proc_reg->error_int_status & 0x0F;
+ if (!error_int_status) {
+ ath10k_warn(ar, "invalid error interrupt status: 0x%x\n",
+ error_int_status);
+ return -EIO;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_SDIO,
+ "sdio error_int_status 0x%x\n", error_int_status);
+
+ if (FIELD_GET(MBOX_ERROR_INT_STATUS_WAKEUP_MASK,
+ error_int_status))
+ ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio interrupt error wakeup\n");
+
+ if (FIELD_GET(MBOX_ERROR_INT_STATUS_RX_UNDERFLOW_MASK,
+ error_int_status))
+ ath10k_warn(ar, "rx underflow interrupt error\n");
+
+ if (FIELD_GET(MBOX_ERROR_INT_STATUS_TX_OVERFLOW_MASK,
+ error_int_status))
+ ath10k_warn(ar, "tx overflow interrupt error\n");
+
+ /* Clear the interrupt */
+ irq_data->irq_proc_reg->error_int_status &= ~error_int_status;
+
+ /* set W1C value to clear the interrupt, this hits the register first */
+ ret = ath10k_sdio_writesb32(ar, MBOX_ERROR_INT_STATUS_ADDRESS,
+ error_int_status);
+ if (ret) {
+ ath10k_warn(ar, "unable to write to error int status address: %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ath10k_sdio_mbox_proc_cpu_intr(struct ath10k *ar)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct ath10k_sdio_irq_data *irq_data = &ar_sdio->irq_data;
+ u8 cpu_int_status;
+ int ret;
+
+ mutex_lock(&irq_data->mtx);
+ cpu_int_status = irq_data->irq_proc_reg->cpu_int_status &
+ irq_data->irq_en_reg->cpu_int_status_en;
+ if (!cpu_int_status) {
+ ath10k_warn(ar, "CPU interrupt status is zero\n");
+ ret = -EIO;
+ goto out;
+ }
+
+ /* Clear the interrupt */
+ irq_data->irq_proc_reg->cpu_int_status &= ~cpu_int_status;
+
+ /* Set up the register transfer buffer to hit the register 4 times,
+ * this is done to make the access 4-byte aligned to mitigate issues
+ * with host bus interconnects that restrict bus transfer lengths to
+ * be a multiple of 4-bytes.
+ *
+ * Set W1C value to clear the interrupt, this hits the register first.
+ */
+ ret = ath10k_sdio_writesb32(ar, MBOX_CPU_INT_STATUS_ADDRESS,
+ cpu_int_status);
+ if (ret) {
+ ath10k_warn(ar, "unable to write to cpu interrupt status address: %d\n",
+ ret);
+ goto out;
+ }
+
+out:
+ mutex_unlock(&irq_data->mtx);
+ return ret;
+}
+
+static int ath10k_sdio_mbox_read_int_status(struct ath10k *ar,
+ u8 *host_int_status,
+ u32 *lookahead)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct ath10k_sdio_irq_data *irq_data = &ar_sdio->irq_data;
+ struct ath10k_sdio_irq_proc_regs *irq_proc_reg = irq_data->irq_proc_reg;
+ struct ath10k_sdio_irq_enable_regs *irq_en_reg = irq_data->irq_en_reg;
+ u8 htc_mbox = FIELD_PREP(ATH10K_HTC_MAILBOX_MASK, 1);
+ int ret;
+
+ mutex_lock(&irq_data->mtx);
+
+ *lookahead = 0;
+ *host_int_status = 0;
+
+ /* int_status_en is supposed to be non zero, otherwise interrupts
+ * shouldn't be enabled. There is however a short time frame during
+ * initialization between the irq register and int_status_en init
+ * where this can happen.
+ * We silently ignore this condition.
+ */
+ if (!irq_en_reg->int_status_en) {
+ ret = 0;
+ goto out;
+ }
+
+ /* Read the first sizeof(struct ath10k_irq_proc_registers)
+ * bytes of the HTC register table. This
+ * will yield us the value of different int status
+ * registers and the lookahead registers.
+ */
+ ret = ath10k_sdio_read(ar, MBOX_HOST_INT_STATUS_ADDRESS,
+ irq_proc_reg, sizeof(*irq_proc_reg));
+ if (ret)
+ goto out;
+
+ /* Update only those registers that are enabled */
+ *host_int_status = irq_proc_reg->host_int_status &
+ irq_en_reg->int_status_en;
+
+ /* Look at mbox status */
+ if (!(*host_int_status & htc_mbox)) {
+ *lookahead = 0;
+ ret = 0;
+ goto out;
+ }
+
+ /* Mask out pending mbox value, we use look ahead as
+ * the real flag for mbox processing.
+ */
+ *host_int_status &= ~htc_mbox;
+ if (irq_proc_reg->rx_lookahead_valid & htc_mbox) {
+ *lookahead = le32_to_cpu(
+ irq_proc_reg->rx_lookahead[ATH10K_HTC_MAILBOX]);
+ if (!*lookahead)
+ ath10k_warn(ar, "sdio mbox lookahead is zero\n");
+ }
+
+out:
+ mutex_unlock(&irq_data->mtx);
+ return ret;
+}
+
+static int ath10k_sdio_mbox_proc_pending_irqs(struct ath10k *ar,
+ bool *done)
+{
+ u8 host_int_status;
+ u32 lookahead;
+ int ret;
+
+ /* NOTE: HIF implementation guarantees that the context of this
+ * call allows us to perform SYNCHRONOUS I/O, that is we can block,
+ * sleep or call any API that can block or switch thread/task
+ * contexts. This is a fully schedulable context.
+ */
+
+ ret = ath10k_sdio_mbox_read_int_status(ar,
+ &host_int_status,
+ &lookahead);
+ if (ret) {
+ *done = true;
+ goto out;
+ }
+
+ if (!host_int_status && !lookahead) {
+ ret = 0;
+ *done = true;
+ goto out;
+ }
+
+ if (lookahead) {
+ ath10k_dbg(ar, ATH10K_DBG_SDIO,
+ "sdio pending mailbox msg lookahead 0x%08x\n",
+ lookahead);
+
+ ret = ath10k_sdio_mbox_rxmsg_pending_handler(ar,
+ lookahead,
+ done);
+ if (ret)
+ goto out;
+ }
+
+ /* now, handle the rest of the interrupts */
+ ath10k_dbg(ar, ATH10K_DBG_SDIO,
+ "sdio host_int_status 0x%x\n", host_int_status);
+
+ if (FIELD_GET(MBOX_HOST_INT_STATUS_CPU_MASK, host_int_status)) {
+ /* CPU Interrupt */
+ ret = ath10k_sdio_mbox_proc_cpu_intr(ar);
+ if (ret)
+ goto out;
+ }
+
+ if (FIELD_GET(MBOX_HOST_INT_STATUS_ERROR_MASK, host_int_status)) {
+ /* Error Interrupt */
+ ret = ath10k_sdio_mbox_proc_err_intr(ar);
+ if (ret)
+ goto out;
+ }
+
+ if (FIELD_GET(MBOX_HOST_INT_STATUS_COUNTER_MASK, host_int_status))
+ /* Counter Interrupt */
+ ret = ath10k_sdio_mbox_proc_counter_intr(ar);
+
+ ret = 0;
+
+out:
+ /* An optimization to bypass reading the IRQ status registers
+ * unecessarily which can re-wake the target, if upper layers
+ * determine that we are in a low-throughput mode, we can rely on
+ * taking another interrupt rather than re-checking the status
+ * registers which can re-wake the target.
+ *
+ * NOTE : for host interfaces that makes use of detecting pending
+ * mbox messages at hif can not use this optimization due to
+ * possible side effects, SPI requires the host to drain all
+ * messages from the mailbox before exiting the ISR routine.
+ */
+
+ ath10k_dbg(ar, ATH10K_DBG_SDIO,
+ "sdio pending irqs done %d status %d",
+ *done, ret);
+
+ return ret;
+}
+
+static void ath10k_sdio_set_mbox_info(struct ath10k *ar)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct ath10k_mbox_info *mbox_info = &ar_sdio->mbox_info;
+ u16 device = ar_sdio->func->device, dev_id_base, dev_id_chiprev;
+
+ mbox_info->htc_addr = ATH10K_HIF_MBOX_BASE_ADDR;
+ mbox_info->block_size = ATH10K_HIF_MBOX_BLOCK_SIZE;
+ mbox_info->block_mask = ATH10K_HIF_MBOX_BLOCK_SIZE - 1;
+ mbox_info->gmbox_addr = ATH10K_HIF_GMBOX_BASE_ADDR;
+ mbox_info->gmbox_sz = ATH10K_HIF_GMBOX_WIDTH;
+
+ mbox_info->ext_info[0].htc_ext_addr = ATH10K_HIF_MBOX0_EXT_BASE_ADDR;
+
+ dev_id_base = FIELD_GET(QCA_MANUFACTURER_ID_BASE, device);
+ dev_id_chiprev = FIELD_GET(QCA_MANUFACTURER_ID_REV_MASK, device);
+ switch (dev_id_base) {
+ case QCA_MANUFACTURER_ID_AR6005_BASE:
+ if (dev_id_chiprev < 4)
+ mbox_info->ext_info[0].htc_ext_sz =
+ ATH10K_HIF_MBOX0_EXT_WIDTH;
+ else
+ /* from QCA6174 2.0(0x504), the width has been extended
+ * to 56K
+ */
+ mbox_info->ext_info[0].htc_ext_sz =
+ ATH10K_HIF_MBOX0_EXT_WIDTH_ROME_2_0;
+ break;
+ case QCA_MANUFACTURER_ID_QCA9377_BASE:
+ mbox_info->ext_info[0].htc_ext_sz =
+ ATH10K_HIF_MBOX0_EXT_WIDTH_ROME_2_0;
+ break;
+ default:
+ mbox_info->ext_info[0].htc_ext_sz =
+ ATH10K_HIF_MBOX0_EXT_WIDTH;
+ }
+
+ mbox_info->ext_info[1].htc_ext_addr =
+ mbox_info->ext_info[0].htc_ext_addr +
+ mbox_info->ext_info[0].htc_ext_sz +
+ ATH10K_HIF_MBOX_DUMMY_SPACE_SIZE;
+ mbox_info->ext_info[1].htc_ext_sz = ATH10K_HIF_MBOX1_EXT_WIDTH;
+}
+
+/* BMI functions */
+
+static int ath10k_sdio_bmi_credits(struct ath10k *ar)
+{
+ u32 addr, cmd_credits;
+ unsigned long timeout;
+ int ret;
+
+ /* Read the counter register to get the command credits */
+ addr = MBOX_COUNT_DEC_ADDRESS + ATH10K_HIF_MBOX_NUM_MAX * 4;
+ timeout = jiffies + BMI_COMMUNICATION_TIMEOUT_HZ;
+ cmd_credits = 0;
+
+ while (time_before(jiffies, timeout) && !cmd_credits) {
+ /* Hit the credit counter with a 4-byte access, the first byte
+ * read will hit the counter and cause a decrement, while the
+ * remaining 3 bytes has no effect. The rationale behind this
+ * is to make all HIF accesses 4-byte aligned.
+ */
+ ret = ath10k_sdio_read32(ar, addr, &cmd_credits);
+ if (ret) {
+ ath10k_warn(ar,
+ "unable to decrement the command credit count register: %d\n",
+ ret);
+ return ret;
+ }
+
+ /* The counter is only 8 bits.
+ * Ignore anything in the upper 3 bytes
+ */
+ cmd_credits &= 0xFF;
+ }
+
+ if (!cmd_credits) {
+ ath10k_warn(ar, "bmi communication timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int ath10k_sdio_bmi_get_rx_lookahead(struct ath10k *ar)
+{
+ unsigned long timeout;
+ u32 rx_word;
+ int ret;
+
+ timeout = jiffies + BMI_COMMUNICATION_TIMEOUT_HZ;
+ rx_word = 0;
+
+ while ((time_before(jiffies, timeout)) && !rx_word) {
+ ret = ath10k_sdio_read32(ar,
+ MBOX_HOST_INT_STATUS_ADDRESS,
+ &rx_word);
+ if (ret) {
+ ath10k_warn(ar, "unable to read RX_LOOKAHEAD_VALID: %d\n", ret);
+ return ret;
+ }
+
+ /* all we really want is one bit */
+ rx_word &= 1;
+ }
+
+ if (!rx_word) {
+ ath10k_warn(ar, "bmi_recv_buf FIFO empty\n");
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int ath10k_sdio_bmi_exchange_msg(struct ath10k *ar,
+ void *req, u32 req_len,
+ void *resp, u32 *resp_len)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ u32 addr;
+ int ret;
+
+ if (req) {
+ ret = ath10k_sdio_bmi_credits(ar);
+ if (ret)
+ return ret;
+
+ addr = ar_sdio->mbox_info.htc_addr;
+
+ memcpy(ar_sdio->bmi_buf, req, req_len);
+ ret = ath10k_sdio_write(ar, addr, ar_sdio->bmi_buf, req_len);
+ if (ret) {
+ ath10k_warn(ar,
+ "unable to send the bmi data to the device: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ if (!resp || !resp_len)
+ /* No response expected */
+ return 0;
+
+ /* During normal bootup, small reads may be required.
+ * Rather than issue an HIF Read and then wait as the Target
+ * adds successive bytes to the FIFO, we wait here until
+ * we know that response data is available.
+ *
+ * This allows us to cleanly timeout on an unexpected
+ * Target failure rather than risk problems at the HIF level.
+ * In particular, this avoids SDIO timeouts and possibly garbage
+ * data on some host controllers. And on an interconnect
+ * such as Compact Flash (as well as some SDIO masters) which
+ * does not provide any indication on data timeout, it avoids
+ * a potential hang or garbage response.
+ *
+ * Synchronization is more difficult for reads larger than the
+ * size of the MBOX FIFO (128B), because the Target is unable
+ * to push the 129th byte of data until AFTER the Host posts an
+ * HIF Read and removes some FIFO data. So for large reads the
+ * Host proceeds to post an HIF Read BEFORE all the data is
+ * actually available to read. Fortunately, large BMI reads do
+ * not occur in practice -- they're supported for debug/development.
+ *
+ * So Host/Target BMI synchronization is divided into these cases:
+ * CASE 1: length < 4
+ * Should not happen
+ *
+ * CASE 2: 4 <= length <= 128
+ * Wait for first 4 bytes to be in FIFO
+ * If CONSERVATIVE_BMI_READ is enabled, also wait for
+ * a BMI command credit, which indicates that the ENTIRE
+ * response is available in the the FIFO
+ *
+ * CASE 3: length > 128
+ * Wait for the first 4 bytes to be in FIFO
+ *
+ * For most uses, a small timeout should be sufficient and we will
+ * usually see a response quickly; but there may be some unusual
+ * (debug) cases of BMI_EXECUTE where we want an larger timeout.
+ * For now, we use an unbounded busy loop while waiting for
+ * BMI_EXECUTE.
+ *
+ * If BMI_EXECUTE ever needs to support longer-latency execution,
+ * especially in production, this code needs to be enhanced to sleep
+ * and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently
+ * a function of Host processor speed.
+ */
+ ret = ath10k_sdio_bmi_get_rx_lookahead(ar);
+ if (ret)
+ return ret;
+
+ /* We always read from the start of the mbox address */
+ addr = ar_sdio->mbox_info.htc_addr;
+ ret = ath10k_sdio_read(ar, addr, ar_sdio->bmi_buf, *resp_len);
+ if (ret) {
+ ath10k_warn(ar,
+ "unable to read the bmi data from the device: %d\n",
+ ret);
+ return ret;
+ }
+
+ memcpy(resp, ar_sdio->bmi_buf, *resp_len);
+
+ return 0;
+}
+
+/* sdio async handling functions */
+
+static struct ath10k_sdio_bus_request
+*ath10k_sdio_alloc_busreq(struct ath10k *ar)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct ath10k_sdio_bus_request *bus_req;
+
+ spin_lock_bh(&ar_sdio->lock);
+
+ if (list_empty(&ar_sdio->bus_req_freeq)) {
+ bus_req = NULL;
+ goto out;
+ }
+
+ bus_req = list_first_entry(&ar_sdio->bus_req_freeq,
+ struct ath10k_sdio_bus_request, list);
+ list_del(&bus_req->list);
+
+out:
+ spin_unlock_bh(&ar_sdio->lock);
+ return bus_req;
+}
+
+static void ath10k_sdio_free_bus_req(struct ath10k *ar,
+ struct ath10k_sdio_bus_request *bus_req)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+
+ memset(bus_req, 0, sizeof(*bus_req));
+
+ spin_lock_bh(&ar_sdio->lock);
+ list_add_tail(&bus_req->list, &ar_sdio->bus_req_freeq);
+ spin_unlock_bh(&ar_sdio->lock);
+}
+
+static void __ath10k_sdio_write_async(struct ath10k *ar,
+ struct ath10k_sdio_bus_request *req)
+{
+ struct ath10k_htc_ep *ep;
+ struct sk_buff *skb;
+ int ret;
+
+ skb = req->skb;
+ ret = ath10k_sdio_write(ar, req->address, skb->data, skb->len);
+ if (ret)
+ ath10k_warn(ar, "failed to write skb to 0x%x asynchronously: %d",
+ req->address, ret);
+
+ if (req->htc_msg) {
+ ep = &ar->htc.endpoint[req->eid];
+ ath10k_htc_notify_tx_completion(ep, skb);
+ } else if (req->comp) {
+ complete(req->comp);
+ }
+
+ ath10k_sdio_free_bus_req(ar, req);
+}
+
+static void ath10k_sdio_write_async_work(struct work_struct *work)
+{
+ struct ath10k_sdio *ar_sdio = container_of(work, struct ath10k_sdio,
+ wr_async_work);
+ struct ath10k *ar = ar_sdio->ar;
+ struct ath10k_sdio_bus_request *req, *tmp_req;
+
+ spin_lock_bh(&ar_sdio->wr_async_lock);
+
+ list_for_each_entry_safe(req, tmp_req, &ar_sdio->wr_asyncq, list) {
+ list_del(&req->list);
+ spin_unlock_bh(&ar_sdio->wr_async_lock);
+ __ath10k_sdio_write_async(ar, req);
+ spin_lock_bh(&ar_sdio->wr_async_lock);
+ }
+
+ spin_unlock_bh(&ar_sdio->wr_async_lock);
+}
+
+static int ath10k_sdio_prep_async_req(struct ath10k *ar, u32 addr,
+ struct sk_buff *skb,
+ struct completion *comp,
+ bool htc_msg, enum ath10k_htc_ep_id eid)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct ath10k_sdio_bus_request *bus_req;
+
+ /* Allocate a bus request for the message and queue it on the
+ * SDIO workqueue.
+ */
+ bus_req = ath10k_sdio_alloc_busreq(ar);
+ if (!bus_req) {
+ ath10k_warn(ar,
+ "unable to allocate bus request for async request\n");
+ return -ENOMEM;
+ }
+
+ bus_req->skb = skb;
+ bus_req->eid = eid;
+ bus_req->address = addr;
+ bus_req->htc_msg = htc_msg;
+ bus_req->comp = comp;
+
+ spin_lock_bh(&ar_sdio->wr_async_lock);
+ list_add_tail(&bus_req->list, &ar_sdio->wr_asyncq);
+ spin_unlock_bh(&ar_sdio->wr_async_lock);
+
+ return 0;
+}
+
+/* IRQ handler */
+
+static void ath10k_sdio_irq_handler(struct sdio_func *func)
+{
+ struct ath10k_sdio *ar_sdio = sdio_get_drvdata(func);
+ struct ath10k *ar = ar_sdio->ar;
+ unsigned long timeout;
+ bool done = false;
+ int ret;
+
+ /* Release the host during interrupts so we can pick it back up when
+ * we process commands.
+ */
+ sdio_release_host(ar_sdio->func);
+
+ timeout = jiffies + ATH10K_SDIO_HIF_COMMUNICATION_TIMEOUT_HZ;
+ while (time_before(jiffies, timeout) && !done) {
+ ret = ath10k_sdio_mbox_proc_pending_irqs(ar, &done);
+ if (ret)
+ break;
+ }
+
+ sdio_claim_host(ar_sdio->func);
+
+ wake_up(&ar_sdio->irq_wq);
+
+ if (ret && ret != -ECANCELED)
+ ath10k_warn(ar, "failed to process pending SDIO interrupts: %d\n",
+ ret);
+}
+
+/* sdio HIF functions */
+
+static int ath10k_sdio_hif_disable_intrs(struct ath10k *ar)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct ath10k_sdio_irq_data *irq_data = &ar_sdio->irq_data;
+ struct ath10k_sdio_irq_enable_regs *regs = irq_data->irq_en_reg;
+ int ret;
+
+ mutex_lock(&irq_data->mtx);
+
+ memset(regs, 0, sizeof(*regs));
+ ret = ath10k_sdio_write(ar, MBOX_INT_STATUS_ENABLE_ADDRESS,
+ &regs->int_status_en, sizeof(*regs));
+ if (ret)
+ ath10k_warn(ar, "unable to disable sdio interrupts: %d\n", ret);
+
+ mutex_unlock(&irq_data->mtx);
+
+ return ret;
+}
+
+static int ath10k_sdio_hif_power_up(struct ath10k *ar)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct sdio_func *func = ar_sdio->func;
+ int ret;
+
+ if (!ar_sdio->is_disabled)
+ return 0;
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "sdio power on\n");
+
+ sdio_claim_host(func);
+
+ ret = sdio_enable_func(func);
+ if (ret) {
+ ath10k_warn(ar, "unable to enable sdio function: %d)\n", ret);
+ sdio_release_host(func);
+ return ret;
+ }
+
+ sdio_release_host(func);
+
+ /* Wait for hardware to initialise. It should take a lot less than
+ * 20 ms but let's be conservative here.
+ */
+ msleep(20);
+
+ ar_sdio->is_disabled = false;
+
+ ret = ath10k_sdio_hif_disable_intrs(ar);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void ath10k_sdio_hif_power_down(struct ath10k *ar)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ int ret;
+
+ if (ar_sdio->is_disabled)
+ return;
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "sdio power off\n");
+
+ /* Disable the card */
+ sdio_claim_host(ar_sdio->func);
+ ret = sdio_disable_func(ar_sdio->func);
+ sdio_release_host(ar_sdio->func);
+
+ if (ret)
+ ath10k_warn(ar, "unable to disable sdio function: %d\n", ret);
+
+ ar_sdio->is_disabled = true;
+}
+
+static int ath10k_sdio_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
+ struct ath10k_hif_sg_item *items, int n_items)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ enum ath10k_htc_ep_id eid;
+ struct sk_buff *skb;
+ int ret, i;
+
+ eid = pipe_id_to_eid(pipe_id);
+
+ for (i = 0; i < n_items; i++) {
+ size_t padded_len;
+ u32 address;
+
+ skb = items[i].transfer_context;
+ padded_len = ath10k_sdio_calc_txrx_padded_len(ar_sdio,
+ skb->len);
+ skb_trim(skb, padded_len);
+
+ /* Write TX data to the end of the mbox address space */
+ address = ar_sdio->mbox_addr[eid] + ar_sdio->mbox_size[eid] -
+ skb->len;
+ ret = ath10k_sdio_prep_async_req(ar, address, skb,
+ NULL, true, eid);
+ if (ret)
+ return ret;
+ }
+
+ queue_work(ar_sdio->workqueue, &ar_sdio->wr_async_work);
+
+ return 0;
+}
+
+static int ath10k_sdio_hif_enable_intrs(struct ath10k *ar)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct ath10k_sdio_irq_data *irq_data = &ar_sdio->irq_data;
+ struct ath10k_sdio_irq_enable_regs *regs = irq_data->irq_en_reg;
+ int ret;
+
+ mutex_lock(&irq_data->mtx);
+
+ /* Enable all but CPU interrupts */
+ regs->int_status_en = FIELD_PREP(MBOX_INT_STATUS_ENABLE_ERROR_MASK, 1) |
+ FIELD_PREP(MBOX_INT_STATUS_ENABLE_CPU_MASK, 1) |
+ FIELD_PREP(MBOX_INT_STATUS_ENABLE_COUNTER_MASK, 1);
+
+ /* NOTE: There are some cases where HIF can do detection of
+ * pending mbox messages which is disabled now.
+ */
+ regs->int_status_en |=
+ FIELD_PREP(MBOX_INT_STATUS_ENABLE_MBOX_DATA_MASK, 1);
+
+ /* Set up the CPU Interrupt status Register */
+ regs->cpu_int_status_en = 0;
+
+ /* Set up the Error Interrupt status Register */
+ regs->err_int_status_en =
+ FIELD_PREP(MBOX_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK, 1) |
+ FIELD_PREP(MBOX_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK, 1);
+
+ /* Enable Counter interrupt status register to get fatal errors for
+ * debugging.
+ */
+ regs->cntr_int_status_en =
+ FIELD_PREP(MBOX_COUNTER_INT_STATUS_ENABLE_BIT_MASK,
+ ATH10K_SDIO_TARGET_DEBUG_INTR_MASK);
+
+ ret = ath10k_sdio_write(ar, MBOX_INT_STATUS_ENABLE_ADDRESS,
+ &regs->int_status_en, sizeof(*regs));
+ if (ret)
+ ath10k_warn(ar,
+ "failed to update mbox interrupt status register : %d\n",
+ ret);
+
+ mutex_unlock(&irq_data->mtx);
+ return ret;
+}
+
+static int ath10k_sdio_hif_set_mbox_sleep(struct ath10k *ar, bool enable_sleep)
+{
+ u32 val;
+ int ret;
+
+ ret = ath10k_sdio_read32(ar, ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL, &val);
+ if (ret) {
+ ath10k_warn(ar, "failed to read fifo/chip control register: %d\n",
+ ret);
+ return ret;
+ }
+
+ if (enable_sleep)
+ val &= ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF;
+ else
+ val |= ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_ON;
+
+ ret = ath10k_sdio_write32(ar, ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL, val);
+ if (ret) {
+ ath10k_warn(ar, "failed to write to FIFO_TIMEOUT_AND_CHIP_CONTROL: %d",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* HIF diagnostics */
+
+static int ath10k_sdio_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
+ size_t buf_len)
+{
+ int ret;
+
+ /* set window register to start read cycle */
+ ret = ath10k_sdio_write32(ar, MBOX_WINDOW_READ_ADDR_ADDRESS, address);
+ if (ret) {
+ ath10k_warn(ar, "failed to set mbox window read address: %d", ret);
+ return ret;
+ }
+
+ /* read the data */
+ ret = ath10k_sdio_read(ar, MBOX_WINDOW_DATA_ADDRESS, buf, buf_len);
+ if (ret) {
+ ath10k_warn(ar, "failed to read from mbox window data address: %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ath10k_sdio_hif_diag_read32(struct ath10k *ar, u32 address,
+ u32 *value)
+{
+ __le32 *val;
+ int ret;
+
+ val = kzalloc(sizeof(*val), GFP_KERNEL);
+ if (!val)
+ return -ENOMEM;
+
+ ret = ath10k_sdio_hif_diag_read(ar, address, val, sizeof(*val));
+ if (ret)
+ goto out;
+
+ *value = __le32_to_cpu(*val);
+
+out:
+ kfree(val);
+
+ return ret;
+}
+
+static int ath10k_sdio_hif_diag_write_mem(struct ath10k *ar, u32 address,
+ const void *data, int nbytes)
+{
+ int ret;
+
+ /* set write data */
+ ret = ath10k_sdio_write(ar, MBOX_WINDOW_DATA_ADDRESS, data, nbytes);
+ if (ret) {
+ ath10k_warn(ar,
+ "failed to write 0x%p to mbox window data address: %d\n",
+ data, ret);
+ return ret;
+ }
+
+ /* set window register, which starts the write cycle */
+ ret = ath10k_sdio_write32(ar, MBOX_WINDOW_WRITE_ADDR_ADDRESS, address);
+ if (ret) {
+ ath10k_warn(ar, "failed to set mbox window write address: %d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* HIF start/stop */
+
+static int ath10k_sdio_hif_start(struct ath10k *ar)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ u32 addr, val;
+ int ret;
+
+ /* Sleep 20 ms before HIF interrupts are disabled.
+ * This will give target plenty of time to process the BMI done
+ * request before interrupts are disabled.
+ */
+ msleep(20);
+ ret = ath10k_sdio_hif_disable_intrs(ar);
+ if (ret)
+ return ret;
+
+ /* eid 0 always uses the lower part of the extended mailbox address
+ * space (ext_info[0].htc_ext_addr).
+ */
+ ar_sdio->mbox_addr[0] = ar_sdio->mbox_info.ext_info[0].htc_ext_addr;
+ ar_sdio->mbox_size[0] = ar_sdio->mbox_info.ext_info[0].htc_ext_sz;
+
+ sdio_claim_host(ar_sdio->func);
+
+ /* Register the isr */
+ ret = sdio_claim_irq(ar_sdio->func, ath10k_sdio_irq_handler);
+ if (ret) {
+ ath10k_warn(ar, "failed to claim sdio interrupt: %d\n", ret);
+ sdio_release_host(ar_sdio->func);
+ return ret;
+ }
+
+ sdio_release_host(ar_sdio->func);
+
+ ret = ath10k_sdio_hif_enable_intrs(ar);
+ if (ret)
+ ath10k_warn(ar, "failed to enable sdio interrupts: %d\n", ret);
+
+ addr = host_interest_item_address(HI_ITEM(hi_acs_flags));
+
+ ret = ath10k_sdio_hif_diag_read32(ar, addr, &val);
+ if (ret) {
+ ath10k_warn(ar, "unable to read hi_acs_flags address: %d\n", ret);
+ return ret;
+ }
+
+ if (val & HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_FW_ACK) {
+ ath10k_dbg(ar, ATH10K_DBG_SDIO,
+ "sdio mailbox swap service enabled\n");
+ ar_sdio->swap_mbox = true;
+ }
+
+ /* Enable sleep and then disable it again */
+ ret = ath10k_sdio_hif_set_mbox_sleep(ar, true);
+ if (ret)
+ return ret;
+
+ /* Wait for 20ms for the written value to take effect */
+ msleep(20);
+
+ ret = ath10k_sdio_hif_set_mbox_sleep(ar, false);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+#define SDIO_IRQ_DISABLE_TIMEOUT_HZ (3 * HZ)
+
+static void ath10k_sdio_irq_disable(struct ath10k *ar)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct ath10k_sdio_irq_data *irq_data = &ar_sdio->irq_data;
+ struct ath10k_sdio_irq_enable_regs *regs = irq_data->irq_en_reg;
+ struct sk_buff *skb;
+ struct completion irqs_disabled_comp;
+ int ret;
+
+ skb = dev_alloc_skb(sizeof(*regs));
+ if (!skb)
+ return;
+
+ mutex_lock(&irq_data->mtx);
+
+ memset(regs, 0, sizeof(*regs)); /* disable all interrupts */
+ memcpy(skb->data, regs, sizeof(*regs));
+ skb_put(skb, sizeof(*regs));
+
+ mutex_unlock(&irq_data->mtx);
+
+ init_completion(&irqs_disabled_comp);
+ ret = ath10k_sdio_prep_async_req(ar, MBOX_INT_STATUS_ENABLE_ADDRESS,
+ skb, &irqs_disabled_comp, false, 0);
+ if (ret)
+ goto out;
+
+ queue_work(ar_sdio->workqueue, &ar_sdio->wr_async_work);
+
+ /* Wait for the completion of the IRQ disable request.
+ * If there is a timeout we will try to disable irq's anyway.
+ */
+ ret = wait_for_completion_timeout(&irqs_disabled_comp,
+ SDIO_IRQ_DISABLE_TIMEOUT_HZ);
+ if (!ret)
+ ath10k_warn(ar, "sdio irq disable request timed out\n");
+
+ sdio_claim_host(ar_sdio->func);
+
+ ret = sdio_release_irq(ar_sdio->func);
+ if (ret)
+ ath10k_warn(ar, "failed to release sdio interrupt: %d\n", ret);
+
+ sdio_release_host(ar_sdio->func);
+
+out:
+ kfree_skb(skb);
+}
+
+static void ath10k_sdio_hif_stop(struct ath10k *ar)
+{
+ struct ath10k_sdio_bus_request *req, *tmp_req;
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+
+ ath10k_sdio_irq_disable(ar);
+
+ cancel_work_sync(&ar_sdio->wr_async_work);
+
+ spin_lock_bh(&ar_sdio->wr_async_lock);
+
+ /* Free all bus requests that have not been handled */
+ list_for_each_entry_safe(req, tmp_req, &ar_sdio->wr_asyncq, list) {
+ struct ath10k_htc_ep *ep;
+
+ list_del(&req->list);
+
+ if (req->htc_msg) {
+ ep = &ar->htc.endpoint[req->eid];
+ ath10k_htc_notify_tx_completion(ep, req->skb);
+ } else if (req->skb) {
+ kfree_skb(req->skb);
+ }
+ ath10k_sdio_free_bus_req(ar, req);
+ }
+
+ spin_unlock_bh(&ar_sdio->wr_async_lock);
+}
+
+#ifdef CONFIG_PM
+
+static int ath10k_sdio_hif_suspend(struct ath10k *ar)
+{
+ return -EOPNOTSUPP;
+}
+
+static int ath10k_sdio_hif_resume(struct ath10k *ar)
+{
+ switch (ar->state) {
+ case ATH10K_STATE_OFF:
+ ath10k_dbg(ar, ATH10K_DBG_SDIO,
+ "sdio resume configuring sdio\n");
+
+ /* need to set sdio settings after power is cut from sdio */
+ ath10k_sdio_config(ar);
+ break;
+
+ case ATH10K_STATE_ON:
+ default:
+ break;
+ }
+
+ return 0;
+}
+#endif
+
+static int ath10k_sdio_hif_map_service_to_pipe(struct ath10k *ar,
+ u16 service_id,
+ u8 *ul_pipe, u8 *dl_pipe)
+{
+ struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+ struct ath10k_htc *htc = &ar->htc;
+ u32 htt_addr, wmi_addr, htt_mbox_size, wmi_mbox_size;
+ enum ath10k_htc_ep_id eid;
+ bool ep_found = false;
+ int i;
+
+ /* For sdio, we are interested in the mapping between eid
+ * and pipeid rather than service_id to pipe_id.
+ * First we find out which eid has been allocated to the
+ * service...
+ */
+ for (i = 0; i < ATH10K_HTC_EP_COUNT; i++) {
+ if (htc->endpoint[i].service_id == service_id) {
+ eid = htc->endpoint[i].eid;
+ ep_found = true;
+ break;
+ }
+ }
+
+ if (!ep_found)
+ return -EINVAL;
+
+ /* Then we create the simplest mapping possible between pipeid
+ * and eid
+ */
+ *ul_pipe = *dl_pipe = (u8)eid;
+
+ /* Normally, HTT will use the upper part of the extended
+ * mailbox address space (ext_info[1].htc_ext_addr) and WMI ctrl
+ * the lower part (ext_info[0].htc_ext_addr).
+ * If fw wants swapping of mailbox addresses, the opposite is true.
+ */
+ if (ar_sdio->swap_mbox) {
+ htt_addr = ar_sdio->mbox_info.ext_info[0].htc_ext_addr;
+ wmi_addr = ar_sdio->mbox_info.ext_info[1].htc_ext_addr;
+ htt_mbox_size = ar_sdio->mbox_info.ext_info[0].htc_ext_sz;
+ wmi_mbox_size = ar_sdio->mbox_info.ext_info[1].htc_ext_sz;
+ } else {
+ htt_addr = ar_sdio->mbox_info.ext_info[1].htc_ext_addr;
+ wmi_addr = ar_sdio->mbox_info.ext_info[0].htc_ext_addr;
+ htt_mbox_size = ar_sdio->mbox_info.ext_info[1].htc_ext_sz;
+ wmi_mbox_size = ar_sdio->mbox_info.ext_info[0].htc_ext_sz;
+ }
+
+ switch (service_id) {
+ case ATH10K_HTC_SVC_ID_RSVD_CTRL:
+ /* HTC ctrl ep mbox address has already been setup in
+ * ath10k_sdio_hif_start
+ */
+ break;
+ case ATH10K_HTC_SVC_ID_WMI_CONTROL:
+ ar_sdio->mbox_addr[eid] = wmi_addr;
+ ar_sdio->mbox_size[eid] = wmi_mbox_size;
+ ath10k_dbg(ar, ATH10K_DBG_SDIO,
+ "sdio wmi ctrl mbox_addr 0x%x mbox_size %d\n",
+ ar_sdio->mbox_addr[eid], ar_sdio->mbox_size[eid]);
+ break;
+ case ATH10K_HTC_SVC_ID_HTT_DATA_MSG:
+ ar_sdio->mbox_addr[eid] = htt_addr;
+ ar_sdio->mbox_size[eid] = htt_mbox_size;
+ ath10k_dbg(ar, ATH10K_DBG_SDIO,
+ "sdio htt data mbox_addr 0x%x mbox_size %d\n",
+ ar_sdio->mbox_addr[eid], ar_sdio->mbox_size[eid]);
+ break;
+ default:
+ ath10k_warn(ar, "unsupported HTC service id: %d\n",
+ service_id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void ath10k_sdio_hif_get_default_pipe(struct ath10k *ar,
+ u8 *ul_pipe, u8 *dl_pipe)
+{
+ ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio hif get default pipe\n");
+
+ /* HTC ctrl ep (SVC id 1) always has eid (and pipe_id in our
+ * case) == 0
+ */
+ *ul_pipe = 0;
+ *dl_pipe = 0;
+}
+
+/* This op is currently only used by htc_wait_target if the HTC ready
+ * message times out. It is not applicable for SDIO since there is nothing
+ * we can do if the HTC ready message does not arrive in time.
+ * TODO: Make this op non mandatory by introducing a NULL check in the
+ * hif op wrapper.
+ */
+static void ath10k_sdio_hif_send_complete_check(struct ath10k *ar,
+ u8 pipe, int force)
+{
+}
+
+static const struct ath10k_hif_ops ath10k_sdio_hif_ops = {
+ .tx_sg = ath10k_sdio_hif_tx_sg,
+ .diag_read = ath10k_sdio_hif_diag_read,
+ .diag_write = ath10k_sdio_hif_diag_write_mem,
+ .exchange_bmi_msg = ath10k_sdio_bmi_exchange_msg,
+ .start = ath10k_sdio_hif_start,
+ .stop = ath10k_sdio_hif_stop,
+ .map_service_to_pipe = ath10k_sdio_hif_map_service_to_pipe,
+ .get_default_pipe = ath10k_sdio_hif_get_default_pipe,
+ .send_complete_check = ath10k_sdio_hif_send_complete_check,
+ .power_up = ath10k_sdio_hif_power_up,
+ .power_down = ath10k_sdio_hif_power_down,
+#ifdef CONFIG_PM
+ .suspend = ath10k_sdio_hif_suspend,
+ .resume = ath10k_sdio_hif_resume,
+#endif
+};
+
+#ifdef CONFIG_PM_SLEEP
+
+/* Empty handlers so that mmc subsystem doesn't remove us entirely during
+ * suspend. We instead follow cfg80211 suspend/resume handlers.
+ */
+static int ath10k_sdio_pm_suspend(struct device *device)
+{
+ return 0;
+}
+
+static int ath10k_sdio_pm_resume(struct device *device)
+{
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(ath10k_sdio_pm_ops, ath10k_sdio_pm_suspend,
+ ath10k_sdio_pm_resume);
+
+#define ATH10K_SDIO_PM_OPS (&ath10k_sdio_pm_ops)
+
+#else
+
+#define ATH10K_SDIO_PM_OPS NULL
+
+#endif /* CONFIG_PM_SLEEP */
+
+static int ath10k_sdio_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+{
+ struct ath10k_sdio *ar_sdio;
+ struct ath10k *ar;
+ enum ath10k_hw_rev hw_rev;
+ u32 chip_id, dev_id_base;
+ int ret, i;
+
+ /* Assumption: All SDIO based chipsets (so far) are QCA6174 based.
+ * If there will be newer chipsets that does not use the hw reg
+ * setup as defined in qca6174_regs and qca6174_values, this
+ * assumption is no longer valid and hw_rev must be setup differently
+ * depending on chipset.
+ */
+ hw_rev = ATH10K_HW_QCA6174;
+
+ ar = ath10k_core_create(sizeof(*ar_sdio), &func->dev, ATH10K_BUS_SDIO,
+ hw_rev, &ath10k_sdio_hif_ops);
+ if (!ar) {
+ dev_err(&func->dev, "failed to allocate core\n");
+ return -ENOMEM;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "sdio new func %d vendor 0x%x device 0x%x block 0x%x/0x%x\n",
+ func->num, func->vendor, func->device,
+ func->max_blksize, func->cur_blksize);
+
+ ar_sdio = ath10k_sdio_priv(ar);
+
+ ar_sdio->irq_data.irq_proc_reg =
+ kzalloc(sizeof(struct ath10k_sdio_irq_proc_regs),
+ GFP_KERNEL);
+ if (!ar_sdio->irq_data.irq_proc_reg) {
+ ret = -ENOMEM;
+ goto err_core_destroy;
+ }
+
+ ar_sdio->irq_data.irq_en_reg =
+ kzalloc(sizeof(struct ath10k_sdio_irq_enable_regs),
+ GFP_KERNEL);
+ if (!ar_sdio->irq_data.irq_en_reg) {
+ ret = -ENOMEM;
+ goto err_free_proc_reg;
+ }
+
+ ar_sdio->bmi_buf = kzalloc(BMI_MAX_CMDBUF_SIZE, GFP_KERNEL);
+ if (!ar_sdio->bmi_buf) {
+ ret = -ENOMEM;
+ goto err_free_en_reg;
+ }
+
+ ar_sdio->func = func;
+ sdio_set_drvdata(func, ar_sdio);
+
+ ar_sdio->is_disabled = true;
+ ar_sdio->ar = ar;
+
+ spin_lock_init(&ar_sdio->lock);
+ spin_lock_init(&ar_sdio->wr_async_lock);
+ mutex_init(&ar_sdio->irq_data.mtx);
+
+ INIT_LIST_HEAD(&ar_sdio->bus_req_freeq);
+ INIT_LIST_HEAD(&ar_sdio->wr_asyncq);
+
+ INIT_WORK(&ar_sdio->wr_async_work, ath10k_sdio_write_async_work);
+ ar_sdio->workqueue = create_singlethread_workqueue("ath10k_sdio_wq");
+ if (!ar_sdio->workqueue) {
+ ret = -ENOMEM;
+ goto err_free_bmi_buf;
+ }
+
+ init_waitqueue_head(&ar_sdio->irq_wq);
+
+ for (i = 0; i < ATH10K_SDIO_BUS_REQUEST_MAX_NUM; i++)
+ ath10k_sdio_free_bus_req(ar, &ar_sdio->bus_req[i]);
+
+ dev_id_base = FIELD_GET(QCA_MANUFACTURER_ID_BASE, id->device);
+ switch (dev_id_base) {
+ case QCA_MANUFACTURER_ID_AR6005_BASE:
+ case QCA_MANUFACTURER_ID_QCA9377_BASE:
+ ar->dev_id = QCA9377_1_0_DEVICE_ID;
+ break;
+ default:
+ ret = -ENODEV;
+ ath10k_err(ar, "unsupported device id %u (0x%x)\n",
+ dev_id_base, id->device);
+ goto err_free_bmi_buf;
+ }
+
+ ar->id.vendor = id->vendor;
+ ar->id.device = id->device;
+
+ ath10k_sdio_set_mbox_info(ar);
+
+ ret = ath10k_sdio_config(ar);
+ if (ret) {
+ ath10k_err(ar, "failed to config sdio: %d\n", ret);
+ goto err_free_wq;
+ }
+
+ /* TODO: don't know yet how to get chip_id with SDIO */
+ chip_id = 0;
+ ret = ath10k_core_register(ar, chip_id);
+ if (ret) {
+ ath10k_err(ar, "failed to register driver core: %d\n", ret);
+ goto err_free_wq;
+ }
+
+ /* TODO: remove this once SDIO support is fully implemented */
+ ath10k_warn(ar, "WARNING: ath10k SDIO support is incomplete, don't expect anything to work!\n");
+
+ return 0;
+
+err_free_wq:
+ destroy_workqueue(ar_sdio->workqueue);
+err_free_bmi_buf:
+ kfree(ar_sdio->bmi_buf);
+err_free_en_reg:
+ kfree(ar_sdio->irq_data.irq_en_reg);
+err_free_proc_reg:
+ kfree(ar_sdio->irq_data.irq_proc_reg);
+err_core_destroy:
+ ath10k_core_destroy(ar);
+
+ return ret;
+}
+
+static void ath10k_sdio_remove(struct sdio_func *func)
+{
+ struct ath10k_sdio *ar_sdio = sdio_get_drvdata(func);
+ struct ath10k *ar = ar_sdio->ar;
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "sdio removed func %d vendor 0x%x device 0x%x\n",
+ func->num, func->vendor, func->device);
+
+ (void)ath10k_sdio_hif_disable_intrs(ar);
+ cancel_work_sync(&ar_sdio->wr_async_work);
+ ath10k_core_unregister(ar);
+ ath10k_core_destroy(ar);
+}
+
+static const struct sdio_device_id ath10k_sdio_devices[] = {
+ {SDIO_DEVICE(QCA_MANUFACTURER_CODE,
+ (QCA_SDIO_ID_AR6005_BASE | 0xA))},
+ {SDIO_DEVICE(QCA_MANUFACTURER_CODE,
+ (QCA_SDIO_ID_QCA9377_BASE | 0x1))},
+ {},
+};
+
+MODULE_DEVICE_TABLE(sdio, ath10k_sdio_devices);
+
+static struct sdio_driver ath10k_sdio_driver = {
+ .name = "ath10k_sdio",
+ .id_table = ath10k_sdio_devices,
+ .probe = ath10k_sdio_probe,
+ .remove = ath10k_sdio_remove,
+ .drv.pm = ATH10K_SDIO_PM_OPS,
+};
+
+static int __init ath10k_sdio_init(void)
+{
+ int ret;
+
+ ret = sdio_register_driver(&ath10k_sdio_driver);
+ if (ret)
+ pr_err("sdio driver registration failed: %d\n", ret);
+
+ return ret;
+}
+
+static void __exit ath10k_sdio_exit(void)
+{
+ sdio_unregister_driver(&ath10k_sdio_driver);
+}
+
+module_init(ath10k_sdio_init);
+module_exit(ath10k_sdio_exit);
+
+MODULE_AUTHOR("Qualcomm Atheros");
+MODULE_DESCRIPTION("Driver support for Qualcomm Atheros 802.11ac WLAN SDIO devices");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/ath/ath10k/sdio.h b/drivers/net/wireless/ath/ath10k/sdio.h
new file mode 100644
index 0000000..3f61c67
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/sdio.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
+ * Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
+ *
+ * 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 _SDIO_H_
+#define _SDIO_H_
+
+#define ATH10K_HIF_MBOX_BLOCK_SIZE 256
+
+#define QCA_MANUFACTURER_ID_BASE GENMASK(11, 8)
+#define QCA_MANUFACTURER_ID_AR6005_BASE 0x5
+#define QCA_MANUFACTURER_ID_QCA9377_BASE 0x7
+#define QCA_SDIO_ID_AR6005_BASE 0x500
+#define QCA_SDIO_ID_QCA9377_BASE 0x700
+#define QCA_MANUFACTURER_ID_REV_MASK 0x00FF
+#define QCA_MANUFACTURER_CODE 0x271 /* Qualcomm/Atheros */
+
+#define ATH10K_SDIO_MAX_BUFFER_SIZE 4096 /*Unsure of this constant*/
+
+/* Mailbox address in SDIO address space */
+#define ATH10K_HIF_MBOX_BASE_ADDR 0x1000
+#define ATH10K_HIF_MBOX_WIDTH 0x800
+
+#define ATH10K_HIF_MBOX_TOT_WIDTH \
+ (ATH10K_HIF_MBOX_NUM_MAX * ATH10K_HIF_MBOX_WIDTH)
+
+#define ATH10K_HIF_MBOX0_EXT_BASE_ADDR 0x5000
+#define ATH10K_HIF_MBOX0_EXT_WIDTH (36 * 1024)
+#define ATH10K_HIF_MBOX0_EXT_WIDTH_ROME_2_0 (56 * 1024)
+#define ATH10K_HIF_MBOX1_EXT_WIDTH (36 * 1024)
+#define ATH10K_HIF_MBOX_DUMMY_SPACE_SIZE (2 * 1024)
+
+#define ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH \
+ (ATH10K_SDIO_MAX_BUFFER_SIZE - sizeof(struct ath10k_htc_hdr))
+
+#define ATH10K_HIF_MBOX_NUM_MAX 4
+#define ATH10K_SDIO_BUS_REQUEST_MAX_NUM 64
+
+#define ATH10K_SDIO_HIF_COMMUNICATION_TIMEOUT_HZ (100 * HZ)
+
+/* HTC runs over mailbox 0 */
+#define ATH10K_HTC_MAILBOX 0
+#define ATH10K_HTC_MAILBOX_MASK BIT(ATH10K_HTC_MAILBOX)
+
+/* GMBOX addresses */
+#define ATH10K_HIF_GMBOX_BASE_ADDR 0x7000
+#define ATH10K_HIF_GMBOX_WIDTH 0x4000
+
+/* Modified versions of the sdio.h macros.
+ * The macros in sdio.h can't be used easily with the FIELD_{PREP|GET}
+ * macros in bitfield.h, so we define our own macros here.
+ */
+#define ATH10K_SDIO_DRIVE_DTSX_MASK \
+ (SDIO_DRIVE_DTSx_MASK << SDIO_DRIVE_DTSx_SHIFT)
+
+#define ATH10K_SDIO_DRIVE_DTSX_TYPE_B 0
+#define ATH10K_SDIO_DRIVE_DTSX_TYPE_A 1
+#define ATH10K_SDIO_DRIVE_DTSX_TYPE_C 2
+#define ATH10K_SDIO_DRIVE_DTSX_TYPE_D 3
+
+/* SDIO CCCR register definitions */
+#define CCCR_SDIO_IRQ_MODE_REG 0xF0
+#define CCCR_SDIO_IRQ_MODE_REG_SDIO3 0x16
+
+#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR 0xF2
+
+#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_A 0x02
+#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_C 0x04
+#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_D 0x08
+
+#define CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS 0xF0
+#define CCCR_SDIO_ASYNC_INT_DELAY_MASK 0xC0
+
+/* mode to enable special 4-bit interrupt assertion without clock */
+#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ BIT(0)
+#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_SDIO3 BIT(1)
+
+#define ATH10K_SDIO_TARGET_DEBUG_INTR_MASK 0x01
+
+/* The theoretical maximum number of RX messages that can be fetched
+ * from the mbox interrupt handler in one loop is derived in the following
+ * way:
+ *
+ * Let's assume that each packet in a bundle of the maximum bundle size
+ * (HTC_HOST_MAX_MSG_PER_BUNDLE) has the HTC header bundle count set
+ * to the maximum value (HTC_HOST_MAX_MSG_PER_BUNDLE).
+ *
+ * in this case the driver must allocate
+ * (HTC_HOST_MAX_MSG_PER_BUNDLE * HTC_HOST_MAX_MSG_PER_BUNDLE) skb's.
+ */
+#define ATH10K_SDIO_MAX_RX_MSGS \
+ (HTC_HOST_MAX_MSG_PER_BUNDLE * HTC_HOST_MAX_MSG_PER_BUNDLE)
+
+#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL 0x00000868u
+#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF 0xFFFEFFFF
+#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_ON 0x10000
+
+struct ath10k_sdio_bus_request {
+ struct list_head list;
+
+ /* sdio address */
+ u32 address;
+
+ struct sk_buff *skb;
+ enum ath10k_htc_ep_id eid;
+ int status;
+ /* Specifies if the current request is an HTC message.
+ * If not, the eid is not applicable an the TX completion handler
+ * associated with the endpoint will not be invoked.
+ */
+ bool htc_msg;
+ /* Completion that (if set) will be invoked for non HTC requests
+ * (htc_msg == false) when the request has been processed.
+ */
+ struct completion *comp;
+};
+
+struct ath10k_sdio_rx_data {
+ struct sk_buff *skb;
+ size_t alloc_len;
+ size_t act_len;
+ enum ath10k_htc_ep_id eid;
+ bool part_of_bundle;
+ bool last_in_bundle;
+ bool trailer_only;
+ int status;
+};
+
+struct ath10k_sdio_irq_proc_regs {
+ u8 host_int_status;
+ u8 cpu_int_status;
+ u8 error_int_status;
+ u8 counter_int_status;
+ u8 mbox_frame;
+ u8 rx_lookahead_valid;
+ u8 host_int_status2;
+ u8 gmbox_rx_avail;
+ __le32 rx_lookahead[2];
+ __le32 rx_gmbox_lookahead_alias[2];
+};
+
+struct ath10k_sdio_irq_enable_regs {
+ u8 int_status_en;
+ u8 cpu_int_status_en;
+ u8 err_int_status_en;
+ u8 cntr_int_status_en;
+};
+
+struct ath10k_sdio_irq_data {
+ /* protects irq_proc_reg and irq_en_reg below.
+ * We use a mutex here and not a spinlock since we will have the
+ * mutex locked while calling the sdio_memcpy_ functions.
+ * These function require non atomic context, and hence, spinlocks
+ * can be held while calling these functions.
+ */
+ struct mutex mtx;
+ struct ath10k_sdio_irq_proc_regs *irq_proc_reg;
+ struct ath10k_sdio_irq_enable_regs *irq_en_reg;
+};
+
+struct ath10k_mbox_ext_info {
+ u32 htc_ext_addr;
+ u32 htc_ext_sz;
+};
+
+struct ath10k_mbox_info {
+ u32 htc_addr;
+ struct ath10k_mbox_ext_info ext_info[2];
+ u32 block_size;
+ u32 block_mask;
+ u32 gmbox_addr;
+ u32 gmbox_sz;
+};
+
+struct ath10k_sdio {
+ struct sdio_func *func;
+
+ struct ath10k_mbox_info mbox_info;
+ bool swap_mbox;
+ u32 mbox_addr[ATH10K_HTC_EP_COUNT];
+ u32 mbox_size[ATH10K_HTC_EP_COUNT];
+
+ /* available bus requests */
+ struct ath10k_sdio_bus_request bus_req[ATH10K_SDIO_BUS_REQUEST_MAX_NUM];
+ /* free list of bus requests */
+ struct list_head bus_req_freeq;
+ /* protects access to bus_req_freeq */
+ spinlock_t lock;
+
+ struct ath10k_sdio_rx_data rx_pkts[ATH10K_SDIO_MAX_RX_MSGS];
+ size_t n_rx_pkts;
+
+ struct ath10k *ar;
+ struct ath10k_sdio_irq_data irq_data;
+
+ /* temporary buffer for BMI requests */
+ u8 *bmi_buf;
+
+ wait_queue_head_t irq_wq;
+
+ bool is_disabled;
+
+ struct workqueue_struct *workqueue;
+ struct work_struct wr_async_work;
+ struct list_head wr_asyncq;
+ /* protects access to wr_asyncq */
+ spinlock_t wr_async_lock;
+};
+
+static inline struct ath10k_sdio *ath10k_sdio_priv(struct ath10k *ar)
+{
+ return (struct ath10k_sdio *)ar->drv_priv;
+}
+
+#endif
diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h
index cbac9e42..8bded5d 100644
--- a/drivers/net/wireless/ath/ath10k/targaddrs.h
+++ b/drivers/net/wireless/ath/ath10k/targaddrs.h
@@ -205,6 +205,24 @@ struct host_interest {
*/
/* Bit 1 - unused */
u32 hi_fw_swap; /* 0x104 */
+
+ /* global arenas pointer address, used by host driver debug */
+ u32 hi_dynamic_mem_arenas_addr; /* 0x108 */
+
+ /* allocated bytes of DRAM use by allocated */
+ u32 hi_dynamic_mem_allocated; /* 0x10C */
+
+ /* remaining bytes of DRAM */
+ u32 hi_dynamic_mem_remaining; /* 0x110 */
+
+ /* memory track count, configured by host */
+ u32 hi_dynamic_mem_track_max; /* 0x114 */
+
+ /* minidump buffer */
+ u32 hi_minidump; /* 0x118 */
+
+ /* bdata's sig and key addr */
+ u32 hi_bd_sig_key; /* 0x11c */
} __packed;
#define HI_ITEM(item) offsetof(struct host_interest, item)
@@ -319,6 +337,12 @@ struct host_interest {
#define HI_ACS_FLAGS_USE_WWAN (1 << 1)
/* Use test VAP */
#define HI_ACS_FLAGS_TEST_VAP (1 << 2)
+/* SDIO/mailbox ACS flag definitions */
+#define HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET (1 << 0)
+#define HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET (1 << 1)
+#define HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE (1 << 2)
+#define HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_FW_ACK (1 << 16)
+#define HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_FW_ACK (1 << 17)
/*
* CONSOLE FLAGS
diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c
index d856462..9d3eb25 100644
--- a/drivers/net/wireless/ath/ath10k/testmode.c
+++ b/drivers/net/wireless/ath/ath10k/testmode.c
@@ -137,6 +137,13 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[])
return ret;
}
+ ret = nla_put_u32(skb, ATH10K_TM_ATTR_WMI_OP_VERSION,
+ ar->normal_mode_fw.fw_file.wmi_op_version);
+ if (ret) {
+ kfree_skb(skb);
+ return ret;
+ }
+
return cfg80211_testmode_reply(skb);
}
diff --git a/drivers/net/wireless/ath/ath10k/testmode_i.h b/drivers/net/wireless/ath/ath10k/testmode_i.h
index ba81bf6..191a8f3 100644
--- a/drivers/net/wireless/ath/ath10k/testmode_i.h
+++ b/drivers/net/wireless/ath/ath10k/testmode_i.h
@@ -33,6 +33,7 @@ enum ath10k_tm_attr {
ATH10K_TM_ATTR_WMI_CMDID = 3,
ATH10K_TM_ATTR_VERSION_MAJOR = 4,
ATH10K_TM_ATTR_VERSION_MINOR = 5,
+ ATH10K_TM_ATTR_WMI_OP_VERSION = 6,
/* keep last */
__ATH10K_TM_ATTR_AFTER_LAST,
diff --git a/drivers/net/wireless/ath/ath10k/thermal.c b/drivers/net/wireless/ath/ath10k/thermal.c
index 87948af..ef717b6 100644
--- a/drivers/net/wireless/ath/ath10k/thermal.c
+++ b/drivers/net/wireless/ath/ath10k/thermal.c
@@ -63,7 +63,7 @@ ath10k_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev,
return 0;
}
-static struct thermal_cooling_device_ops ath10k_thermal_ops = {
+static const struct thermal_cooling_device_ops ath10k_thermal_ops = {
.get_max_state = ath10k_thermal_get_max_throttle_state,
.get_cur_state = ath10k_thermal_get_cur_throttle_state,
.set_cur_state = ath10k_thermal_set_cur_throttle_state,
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index f918802..7616c1c 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -2022,7 +2022,7 @@ ath10k_wmi_tlv_op_gen_sta_keepalive(struct ath10k *ar,
arp->dest_ip4_addr = arg->dest_ip4_addr;
ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr);
- ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv sta keepalive vdev %d enabled %d method %d inverval %d\n",
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv sta keepalive vdev %d enabled %d method %d interval %d\n",
arg->vdev_id, arg->enabled, arg->method, arg->interval);
return skb;
}
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 6afc8d2..3efb404 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -3304,9 +3304,8 @@ static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif,
if (arvif->u.ap.noa_data)
if (!pskb_expand_head(bcn, 0, arvif->u.ap.noa_len, GFP_ATOMIC))
- memcpy(skb_put(bcn, arvif->u.ap.noa_len),
- arvif->u.ap.noa_data,
- arvif->u.ap.noa_len);
+ skb_put_data(bcn, arvif->u.ap.noa_data,
+ arvif->u.ap.noa_len);
}
static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb,
@@ -4482,31 +4481,17 @@ static int ath10k_wmi_alloc_chunk(struct ath10k *ar, u32 req_id,
u32 num_units, u32 unit_len)
{
dma_addr_t paddr;
- u32 pool_size = 0;
+ u32 pool_size;
int idx = ar->wmi.num_mem_chunks;
- void *vaddr = NULL;
-
- if (ar->wmi.num_mem_chunks == ARRAY_SIZE(ar->wmi.mem_chunks))
- return -ENOMEM;
+ void *vaddr;
- while (!vaddr && num_units) {
- pool_size = num_units * round_up(unit_len, 4);
- if (!pool_size)
- return -EINVAL;
+ pool_size = num_units * round_up(unit_len, 4);
+ vaddr = dma_alloc_coherent(ar->dev, pool_size, &paddr, GFP_KERNEL);
- vaddr = kzalloc(pool_size, GFP_KERNEL | __GFP_NOWARN);
- if (!vaddr)
- num_units /= 2;
- }
-
- if (!num_units)
+ if (!vaddr)
return -ENOMEM;
- paddr = dma_map_single(ar->dev, vaddr, pool_size, DMA_BIDIRECTIONAL);
- if (dma_mapping_error(ar->dev, paddr)) {
- kfree(vaddr);
- return -ENOMEM;
- }
+ memset(vaddr, 0, pool_size);
ar->wmi.mem_chunks[idx].vaddr = vaddr;
ar->wmi.mem_chunks[idx].paddr = paddr;
@@ -5948,15 +5933,6 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar)
int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg)
{
- if (arg->ie_len && !arg->ie)
- return -EINVAL;
- if (arg->n_channels && !arg->channels)
- return -EINVAL;
- if (arg->n_ssids && !arg->ssids)
- return -EINVAL;
- if (arg->n_bssids && !arg->bssids)
- return -EINVAL;
-
if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN)
return -EINVAL;
if (arg->n_channels > ARRAY_SIZE(arg->channels))
@@ -6757,7 +6733,12 @@ ath10k_wmi_peer_assoc_fill_10_4(struct ath10k *ar, void *buf,
struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf;
ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg);
- cmd->peer_bw_rxnss_override = 0;
+ if (arg->peer_bw_rxnss_override)
+ cmd->peer_bw_rxnss_override =
+ __cpu_to_le32((arg->peer_bw_rxnss_override - 1) |
+ BIT(PEER_BW_RXNSS_OVERRIDE_OFFSET));
+ else
+ cmd->peer_bw_rxnss_override = 0;
}
static int
@@ -8290,11 +8271,10 @@ void ath10k_wmi_free_host_mem(struct ath10k *ar)
/* free the host memory chunks requested by firmware */
for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
- dma_unmap_single(ar->dev,
- ar->wmi.mem_chunks[i].paddr,
- ar->wmi.mem_chunks[i].len,
- DMA_BIDIRECTIONAL);
- kfree(ar->wmi.mem_chunks[i].vaddr);
+ dma_free_coherent(ar->dev,
+ ar->wmi.mem_chunks[i].len,
+ ar->wmi.mem_chunks[i].vaddr,
+ ar->wmi.mem_chunks[i].paddr);
}
ar->wmi.num_mem_chunks = 0;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 1b4865a..baa38c8 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -6028,6 +6028,8 @@ struct wmi_10_2_peer_assoc_complete_cmd {
__le32 info0; /* WMI_PEER_ASSOC_INFO0_ */
} __packed;
+#define PEER_BW_RXNSS_OVERRIDE_OFFSET 31
+
struct wmi_10_4_peer_assoc_complete_cmd {
struct wmi_10_2_peer_assoc_complete_cmd cmd;
__le32 peer_bw_rxnss_override;
@@ -6051,6 +6053,7 @@ struct wmi_peer_assoc_complete_arg {
u32 peer_vht_caps;
enum wmi_phy_mode peer_phymode;
struct wmi_vht_rate_set_arg peer_vht_rates;
+ u32 peer_bw_rxnss_override;
};
struct wmi_peer_add_wds_entry_cmd {
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index d068df5..bd7f6d7 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -938,7 +938,10 @@ static int open_file_eeprom(struct inode *inode, struct file *file)
}
for (i = 0; i < eesize; ++i) {
- AR5K_EEPROM_READ(i, val);
+ if (!ath5k_hw_nvram_read(ah, i, &val)) {
+ ret = -EIO;
+ goto freebuf;
+ }
buf[i] = val;
}
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index e2b7809..1eea6c2 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -348,7 +348,7 @@ void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len)
if (!skb)
return;
- slot = (struct ath6kl_fwlog_slot *) skb_put(skb, slot_len);
+ slot = skb_put(skb, slot_len);
slot->timestamp = cpu_to_le32(jiffies);
slot->length = cpu_to_le32(len);
memcpy(slot->payload, buf, len);
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
index d127a08..546243e 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
@@ -228,8 +228,7 @@ static int htc_issue_packets(struct htc_target *target,
payload_len = packet->act_len;
/* setup HTC frame header */
- htc_hdr = (struct htc_frame_hdr *) skb_push(skb,
- sizeof(*htc_hdr));
+ htc_hdr = skb_push(skb, sizeof(*htc_hdr));
if (!htc_hdr) {
WARN_ON_ONCE(1);
status = -EINVAL;
@@ -383,7 +382,7 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target,
list_for_each_entry_safe(packet, tmp_pkt,
txq, list) {
ath6kl_dbg(ATH6KL_DBG_HTC,
- "%s: Indicat overflowed TX pkts: %p\n",
+ "%s: Indicate overflowed TX pkts: %p\n",
__func__, packet);
action = ep->ep_cb.tx_full(ep->target, packet);
if (action == HTC_SEND_FULL_DROP) {
@@ -1274,8 +1273,7 @@ static int ath6kl_htc_pipe_conn_service(struct htc_target *target,
length = sizeof(struct htc_conn_service_msg);
/* assemble connect service message */
- conn_msg = (struct htc_conn_service_msg *) skb_put(skb,
- length);
+ conn_msg = skb_put(skb, length);
if (conn_msg == NULL) {
WARN_ON_ONCE(1);
status = -EINVAL;
@@ -1504,8 +1502,7 @@ static int ath6kl_htc_pipe_start(struct htc_target *target)
skb = packet->skb;
/* assemble setup complete message */
- setup = (struct htc_setup_comp_ext_msg *) skb_put(skb,
- sizeof(*setup));
+ setup = skb_put(skb, sizeof(*setup));
memset(setup, 0, sizeof(struct htc_setup_comp_ext_msg));
setup->msg_id = cpu_to_le16(HTC_MSG_SETUP_COMPLETE_EX_ID);
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
index a531e0c..e6b2517 100644
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -399,15 +399,10 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
csum_dest = skb->csum_offset + csum_start;
}
- if (skb_headroom(skb) < dev->needed_headroom) {
- struct sk_buff *tmp_skb = skb;
-
- skb = skb_realloc_headroom(skb, dev->needed_headroom);
- kfree_skb(tmp_skb);
- if (skb == NULL) {
- dev->stats.tx_dropped++;
- return 0;
- }
+ if (skb_cow_head(skb, dev->needed_headroom)) {
+ dev->stats.tx_dropped++;
+ kfree_skb(skb);
+ return 0;
}
if (ath6kl_wmi_dix_2_dot3(ar->wmi, skb)) {
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index ae304355..fe5102c 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -1821,8 +1821,6 @@ static void ar9003_hw_spectral_scan_wait(struct ath_hw *ah)
static void ar9003_hw_tx99_start(struct ath_hw *ah, u32 qnum)
{
REG_SET_BIT(ah, AR_PHY_TEST, PHY_AGC_CLR);
- REG_SET_BIT(ah, 0x9864, 0x7f000);
- REG_SET_BIT(ah, 0x9924, 0x7f00fe);
REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
REG_WRITE(ah, AR_CR, AR_CR_RXD);
REG_WRITE(ah, AR_DLCL_IFS(qnum), 0);
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index b84539d..f0439f2 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -1005,7 +1005,7 @@ static void ath_scan_send_probe(struct ath_softc *sc,
info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
if (req->ie_len)
- memcpy(skb_put(skb, req->ie_len), req->ie, req->ie_len);
+ skb_put_data(skb, req->ie, req->ie_len);
skb_set_queue_mapping(skb, IEEE80211_AC_VO);
@@ -1521,13 +1521,11 @@ void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *avp,
noa_desc = !!avp->offchannel_duration + !!avp->noa_duration;
noa_len = 2 + sizeof(struct ieee80211_p2p_noa_desc) * noa_desc;
- hdr = skb_put(skb, sizeof(noa_ie_hdr));
- memcpy(hdr, noa_ie_hdr, sizeof(noa_ie_hdr));
+ hdr = skb_put_data(skb, noa_ie_hdr, sizeof(noa_ie_hdr));
hdr[1] = sizeof(noa_ie_hdr) + noa_len - 2;
hdr[7] = noa_len;
- noa = (void *) skb_put(skb, noa_len);
- memset(noa, 0, noa_len);
+ noa = skb_put_zero(skb, noa_len);
noa->index = avp->noa_index;
noa->oppps_ctwindow = ath9k_get_ctwin(sc, avp);
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index c67d0e0..099f3d4 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -369,7 +369,7 @@ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
{
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
- if (reg->power_limit != new_txpow)
+ if (ah->curchan && reg->power_limit != new_txpow)
ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
/* read back in case value is clamped */
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
index 6ccf248..6fbd555 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -143,7 +143,7 @@ bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
if (ah->eeprom_blob)
ret = ath9k_hw_nvram_read_firmware(ah->eeprom_blob, off, data);
- else if (pdata && !pdata->use_eeprom && pdata->eeprom_data)
+ else if (pdata && !pdata->use_eeprom)
ret = ath9k_hw_nvram_read_pdata(pdata, off, data);
else
ret = common->bus_ops->eeprom_read(common, off, data);
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 12aa8ab..0d9687a 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -199,7 +199,7 @@ static int hif_usb_send_mgmt(struct hif_device_usb *hif_dev,
cmd->skb = skb;
cmd->hif_dev = hif_dev;
- hdr = (__le16 *) skb_push(skb, 4);
+ hdr = skb_push(skb, 4);
*hdr++ = cpu_to_le16(skb->len - 4);
*hdr++ = cpu_to_le16(ATH_USB_TX_STREAM_MODE_TAG);
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index 8e6dae2..1bf63a4 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -26,8 +26,7 @@ static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
struct htc_endpoint *endpoint = &target->endpoint[epid];
int status;
- hdr = (struct htc_frame_hdr *)
- skb_push(skb, sizeof(struct htc_frame_hdr));
+ hdr = skb_push(skb, sizeof(struct htc_frame_hdr));
hdr->endpoint_id = epid;
hdr->flags = flags;
hdr->payload_len = cpu_to_be16(len);
@@ -156,8 +155,7 @@ static int htc_config_pipe_credits(struct htc_target *target)
}
skb_reserve(skb, sizeof(struct htc_frame_hdr));
- cp_msg = (struct htc_config_pipe_msg *)
- skb_put(skb, sizeof(struct htc_config_pipe_msg));
+ cp_msg = skb_put(skb, sizeof(struct htc_config_pipe_msg));
cp_msg->message_id = cpu_to_be16(HTC_MSG_CONFIG_PIPE_ID);
cp_msg->pipe_id = USB_WLAN_TX_PIPE;
@@ -195,8 +193,7 @@ static int htc_setup_complete(struct htc_target *target)
}
skb_reserve(skb, sizeof(struct htc_frame_hdr));
- comp_msg = (struct htc_comp_msg *)
- skb_put(skb, sizeof(struct htc_comp_msg));
+ comp_msg = skb_put(skb, sizeof(struct htc_comp_msg));
comp_msg->msg_id = cpu_to_be16(HTC_MSG_SETUP_COMPLETE_ID);
target->htc_flags |= HTC_OP_START_WAIT;
@@ -265,8 +262,7 @@ int htc_connect_service(struct htc_target *target,
skb_reserve(skb, sizeof(struct htc_frame_hdr));
- conn_msg = (struct htc_conn_svc_msg *)
- skb_put(skb, sizeof(struct htc_conn_svc_msg));
+ conn_msg = skb_put(skb, sizeof(struct htc_conn_svc_msg));
conn_msg->service_id = cpu_to_be16(service_connreq->service_id);
conn_msg->msg_id = cpu_to_be16(HTC_MSG_CONNECT_SERVICE_ID);
conn_msg->con_flags = cpu_to_be16(service_connreq->con_flags);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 9e65d14..8b4ac7f 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -731,12 +731,12 @@ static int ath9k_start(struct ieee80211_hw *hw)
spin_unlock_bh(&sc->sc_pcu_lock);
+ ath9k_rng_start(sc);
+
mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
- ath9k_rng_start(sc);
-
return 0;
}
@@ -826,10 +826,10 @@ static void ath9k_stop(struct ieee80211_hw *hw)
ath9k_deinit_channel_context(sc);
- ath9k_rng_stop(sc);
-
mutex_lock(&sc->mutex);
+ ath9k_rng_stop(sc);
+
ath_cancel_work(sc);
if (test_bit(ATH_OP_INVALID, &common->op_flags)) {
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c
index 66596b9..cf23fd8 100644
--- a/drivers/net/wireless/ath/ath9k/mci.c
+++ b/drivers/net/wireless/ath/ath9k/mci.c
@@ -548,7 +548,7 @@ void ath_mci_intr(struct ath_softc *sc)
if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO) {
mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO;
- offset = ar9003_mci_state(ah, MCI_STATE_LAST_SCHD_MSG_OFFSET);
+ ar9003_mci_state(ah, MCI_STATE_LAST_SCHD_MSG_OFFSET);
}
if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_GPM) {
diff --git a/drivers/net/wireless/ath/ath9k/rng.c b/drivers/net/wireless/ath/ath9k/rng.c
index 568b1c6..f9d3d6e 100644
--- a/drivers/net/wireless/ath/ath9k/rng.c
+++ b/drivers/net/wireless/ath/ath9k/rng.c
@@ -24,6 +24,8 @@
#define ATH9K_RNG_BUF_SIZE 320
#define ATH9K_RNG_ENTROPY(x) (((x) * 8 * 10) >> 5) /* quality: 10/32 */
+static DECLARE_WAIT_QUEUE_HEAD(rng_queue);
+
static int ath9k_rng_data_read(struct ath_softc *sc, u32 *buf, u32 buf_size)
{
int i, j;
@@ -85,7 +87,9 @@ static int ath9k_rng_kthread(void *data)
ATH9K_RNG_BUF_SIZE);
if (unlikely(!bytes_read)) {
delay = ath9k_rng_delay_get(++fail_stats);
- msleep_interruptible(delay);
+ wait_event_interruptible_timeout(rng_queue,
+ kthread_should_stop(),
+ msecs_to_jiffies(delay));
continue;
}
@@ -120,6 +124,8 @@ void ath9k_rng_start(struct ath_softc *sc)
void ath9k_rng_stop(struct ath_softc *sc)
{
- if (sc->rng_task)
+ if (sc->rng_task) {
kthread_stop(sc->rng_task);
+ sc->rng_task = NULL;
+ }
}
diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c
index 16aca9e..49ed1af 100644
--- a/drivers/net/wireless/ath/ath9k/tx99.c
+++ b/drivers/net/wireless/ath/ath9k/tx99.c
@@ -153,7 +153,7 @@ static int ath9k_tx99_init(struct ath_softc *sc)
sc->tx99_power,
sc->tx99_power / 2);
- /* We leave the harware awake as it will be chugging on */
+ /* We leave the hardware awake as it will be chugging on */
return 0;
}
@@ -189,22 +189,27 @@ static ssize_t write_file_tx99(struct file *file, const char __user *user_buf,
if (strtobool(buf, &start))
return -EINVAL;
+ mutex_lock(&sc->mutex);
+
if (start == sc->tx99_state) {
if (!start)
- return count;
+ goto out;
ath_dbg(common, XMIT, "Resetting TX99\n");
ath9k_tx99_deinit(sc);
}
if (!start) {
ath9k_tx99_deinit(sc);
- return count;
+ goto out;
}
r = ath9k_tx99_init(sc);
- if (r)
+ if (r) {
+ mutex_unlock(&sc->mutex);
return r;
-
+ }
+out:
+ mutex_unlock(&sc->mutex);
return count;
}
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index 9c16e2a..64a354f 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -277,7 +277,7 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi,
struct wmi_cmd_hdr *hdr;
unsigned long flags;
- hdr = (struct wmi_cmd_hdr *) skb_push(skb, sizeof(struct wmi_cmd_hdr));
+ hdr = skb_push(skb, sizeof(struct wmi_cmd_hdr));
hdr->command_id = cpu_to_be16(cmd);
hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id);
@@ -298,7 +298,6 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
u16 headroom = sizeof(struct htc_frame_hdr) +
sizeof(struct wmi_cmd_hdr);
struct sk_buff *skb;
- u8 *data;
unsigned long time_left;
int ret = 0;
@@ -312,8 +311,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
skb_reserve(skb, headroom);
if (cmd_len != 0 && cmd_buf != NULL) {
- data = (u8 *) skb_put(skb, cmd_len);
- memcpy(data, cmd_buf, cmd_len);
+ skb_put_data(skb, cmd_buf, cmd_len);
}
mutex_lock(&wmi->op_mutex);
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index b216672..7050632 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -481,7 +481,7 @@ static struct sk_buff *carl9170_rx_copy_data(u8 *buf, int len)
skb = dev_alloc_skb(len + reserved);
if (likely(skb)) {
skb_reserve(skb, reserved);
- memcpy(skb_put(skb, len), buf, len);
+ skb_put_data(skb, buf, len);
}
return skb;
@@ -916,7 +916,7 @@ static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len)
}
}
- memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen);
+ skb_put_data(ar->rx_failover, tbuf, tlen);
ar->rx_failover_missing -= tlen;
if (ar->rx_failover_missing <= 0) {
@@ -958,7 +958,7 @@ static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len)
* the rx - descriptor comes round again.
*/
- memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen);
+ skb_put_data(ar->rx_failover, tbuf, tlen);
ar->rx_failover_missing = clen - tlen;
return;
}
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index 2bf04c9..0cb5b58 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -991,7 +991,7 @@ static int carl9170_tx_prepare(struct ar9170 *ar,
else
cvif = NULL;
- txc = (void *)skb_push(skb, sizeof(*txc));
+ txc = skb_push(skb, sizeof(*txc));
memset(txc, 0, sizeof(*txc));
SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, txc->s.misc, hw_queue);
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile
index 89bf2f9..4ae21da 100644
--- a/drivers/net/wireless/ath/wil6210/Makefile
+++ b/drivers/net/wireless/ath/wil6210/Makefile
@@ -10,7 +10,6 @@ wil6210-y += interrupt.o
wil6210-y += txrx.o
wil6210-y += debug.o
wil6210-y += rx_reorder.o
-wil6210-y += ioctl.o
wil6210-y += fw.o
wil6210-y += pm.o
wil6210-y += pmc.o
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index fdaa99c..0b5383a 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -16,6 +16,7 @@
#include <linux/etherdevice.h>
#include <linux/moduleparam.h>
+#include <net/netlink.h>
#include "wil6210.h"
#include "wmi.h"
@@ -41,6 +42,126 @@ static struct ieee80211_channel wil_60ghz_channels[] = {
/* channel 4 not supported yet */
};
+/* Vendor id to be used in vendor specific command and events
+ * to user space.
+ * NOTE: The authoritative place for definition of QCA_NL80211_VENDOR_ID,
+ * vendor subcmd definitions prefixed with QCA_NL80211_VENDOR_SUBCMD, and
+ * qca_wlan_vendor_attr is open source file src/common/qca-vendor.h in
+ * git://w1.fi/srv/git/hostap.git; the values here are just a copy of that
+ */
+
+#define QCA_NL80211_VENDOR_ID 0x001374
+
+#define WIL_MAX_RF_SECTORS (128)
+#define WIL_CID_ALL (0xff)
+
+enum qca_wlan_vendor_attr_rf_sector {
+ QCA_ATTR_MAC_ADDR = 6,
+ QCA_ATTR_PAD = 13,
+ QCA_ATTR_TSF = 29,
+ QCA_ATTR_DMG_RF_SECTOR_INDEX = 30,
+ QCA_ATTR_DMG_RF_SECTOR_TYPE = 31,
+ QCA_ATTR_DMG_RF_MODULE_MASK = 32,
+ QCA_ATTR_DMG_RF_SECTOR_CFG = 33,
+ QCA_ATTR_DMG_RF_SECTOR_MAX,
+};
+
+enum qca_wlan_vendor_attr_dmg_rf_sector_type {
+ QCA_ATTR_DMG_RF_SECTOR_TYPE_RX,
+ QCA_ATTR_DMG_RF_SECTOR_TYPE_TX,
+ QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX
+};
+
+enum qca_wlan_vendor_attr_dmg_rf_sector_cfg {
+ QCA_ATTR_DMG_RF_SECTOR_CFG_INVALID = 0,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16,
+
+ /* keep last */
+ QCA_ATTR_DMG_RF_SECTOR_CFG_AFTER_LAST,
+ QCA_ATTR_DMG_RF_SECTOR_CFG_MAX =
+ QCA_ATTR_DMG_RF_SECTOR_CFG_AFTER_LAST - 1
+};
+
+static const struct
+nla_policy wil_rf_sector_policy[QCA_ATTR_DMG_RF_SECTOR_MAX + 1] = {
+ [QCA_ATTR_MAC_ADDR] = { .len = ETH_ALEN },
+ [QCA_ATTR_DMG_RF_SECTOR_INDEX] = { .type = NLA_U16 },
+ [QCA_ATTR_DMG_RF_SECTOR_TYPE] = { .type = NLA_U8 },
+ [QCA_ATTR_DMG_RF_MODULE_MASK] = { .type = NLA_U32 },
+ [QCA_ATTR_DMG_RF_SECTOR_CFG] = { .type = NLA_NESTED },
+};
+
+static const struct
+nla_policy wil_rf_sector_cfg_policy[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1] = {
+ [QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX] = { .type = NLA_U8 },
+ [QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0] = { .type = NLA_U32 },
+ [QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1] = { .type = NLA_U32 },
+ [QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2] = { .type = NLA_U32 },
+ [QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI] = { .type = NLA_U32 },
+ [QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO] = { .type = NLA_U32 },
+ [QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16] = { .type = NLA_U32 },
+};
+
+enum qca_nl80211_vendor_subcmds {
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG = 139,
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG = 140,
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR = 141,
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR = 142,
+};
+
+static int wil_rf_sector_get_cfg(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len);
+static int wil_rf_sector_set_cfg(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len);
+static int wil_rf_sector_get_selected(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len);
+static int wil_rf_sector_set_selected(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len);
+
+/* vendor specific commands */
+static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wil_rf_sector_get_cfg
+ },
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wil_rf_sector_set_cfg
+ },
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd =
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wil_rf_sector_get_selected
+ },
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd =
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wil_rf_sector_set_selected
+ },
+};
+
static struct ieee80211_supported_band wil_band_60ghz = {
.channels = wil_60ghz_channels,
.n_channels = ARRAY_SIZE(wil_60ghz_channels),
@@ -1325,6 +1446,8 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
wil_set_recovery_state(wil, fw_recovery_idle);
+ set_bit(wil_status_resetting, wil->status);
+
mutex_lock(&wil->mutex);
wmi_pcp_stop(wil);
@@ -1571,6 +1694,42 @@ static int wil_cfg80211_set_power_mgmt(struct wiphy *wiphy,
return wil_ps_update(wil, ps_profile);
}
+static int wil_cfg80211_suspend(struct wiphy *wiphy,
+ struct cfg80211_wowlan *wow)
+{
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+ int rc;
+
+ /* Setting the wakeup trigger based on wow is TBD */
+
+ if (test_bit(wil_status_suspended, wil->status)) {
+ wil_dbg_pm(wil, "trying to suspend while suspended\n");
+ return 0;
+ }
+
+ rc = wil_can_suspend(wil, false);
+ if (rc)
+ goto out;
+
+ wil_dbg_pm(wil, "suspending\n");
+
+ wil_p2p_stop_discovery(wil);
+
+ wil_abort_scan(wil, true);
+
+out:
+ return rc;
+}
+
+static int wil_cfg80211_resume(struct wiphy *wiphy)
+{
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+ wil_dbg_pm(wil, "resuming\n");
+
+ return 0;
+}
+
static const struct cfg80211_ops wil_cfg80211_ops = {
.add_virtual_intf = wil_cfg80211_add_iface,
.del_virtual_intf = wil_cfg80211_del_iface,
@@ -1602,6 +1761,8 @@ static const struct cfg80211_ops wil_cfg80211_ops = {
.start_p2p_device = wil_cfg80211_start_p2p_device,
.stop_p2p_device = wil_cfg80211_stop_p2p_device,
.set_power_mgmt = wil_cfg80211_set_power_mgmt,
+ .suspend = wil_cfg80211_suspend,
+ .resume = wil_cfg80211_resume,
};
static void wil_wiphy_init(struct wiphy *wiphy)
@@ -1637,6 +1798,9 @@ static void wil_wiphy_init(struct wiphy *wiphy)
wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites);
wiphy->mgmt_stypes = wil_mgmt_stypes;
wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
+
+ wiphy->n_vendor_commands = ARRAY_SIZE(wil_nl80211_vendor_commands);
+ wiphy->vendor_commands = wil_nl80211_vendor_commands;
}
struct wireless_dev *wil_cfg80211_init(struct device *dev)
@@ -1695,3 +1859,452 @@ void wil_p2p_wdev_free(struct wil6210_priv *wil)
kfree(p2p_wdev);
}
}
+
+static int wil_rf_sector_status_to_rc(u8 status)
+{
+ switch (status) {
+ case WMI_RF_SECTOR_STATUS_SUCCESS:
+ return 0;
+ case WMI_RF_SECTOR_STATUS_BAD_PARAMETERS_ERROR:
+ return -EINVAL;
+ case WMI_RF_SECTOR_STATUS_BUSY_ERROR:
+ return -EAGAIN;
+ case WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR:
+ return -EOPNOTSUPP;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int wil_rf_sector_get_cfg(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ struct wil6210_priv *wil = wdev_to_wil(wdev);
+ int rc;
+ struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
+ u16 sector_index;
+ u8 sector_type;
+ u32 rf_modules_vec;
+ struct wmi_get_rf_sector_params_cmd cmd;
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_get_rf_sector_params_done_event evt;
+ } __packed reply;
+ struct sk_buff *msg;
+ struct nlattr *nl_cfgs, *nl_cfg;
+ u32 i;
+ struct wmi_rf_sector_info *si;
+
+ if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
+ return -EOPNOTSUPP;
+
+ rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
+ wil_rf_sector_policy, NULL);
+ if (rc) {
+ wil_err(wil, "Invalid rf sector ATTR\n");
+ return rc;
+ }
+
+ if (!tb[QCA_ATTR_DMG_RF_SECTOR_INDEX] ||
+ !tb[QCA_ATTR_DMG_RF_SECTOR_TYPE] ||
+ !tb[QCA_ATTR_DMG_RF_MODULE_MASK]) {
+ wil_err(wil, "Invalid rf sector spec\n");
+ return -EINVAL;
+ }
+
+ sector_index = nla_get_u16(
+ tb[QCA_ATTR_DMG_RF_SECTOR_INDEX]);
+ if (sector_index >= WIL_MAX_RF_SECTORS) {
+ wil_err(wil, "Invalid sector index %d\n", sector_index);
+ return -EINVAL;
+ }
+
+ sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
+ if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
+ wil_err(wil, "Invalid sector type %d\n", sector_type);
+ return -EINVAL;
+ }
+
+ rf_modules_vec = nla_get_u32(
+ tb[QCA_ATTR_DMG_RF_MODULE_MASK]);
+ if (rf_modules_vec >= BIT(WMI_MAX_RF_MODULES_NUM)) {
+ wil_err(wil, "Invalid rf module mask 0x%x\n", rf_modules_vec);
+ return -EINVAL;
+ }
+
+ cmd.sector_idx = cpu_to_le16(sector_index);
+ cmd.sector_type = sector_type;
+ cmd.rf_modules_vec = rf_modules_vec & 0xFF;
+ memset(&reply, 0, sizeof(reply));
+ rc = wmi_call(wil, WMI_GET_RF_SECTOR_PARAMS_CMDID, &cmd, sizeof(cmd),
+ WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID,
+ &reply, sizeof(reply),
+ 500);
+ if (rc)
+ return rc;
+ if (reply.evt.status) {
+ wil_err(wil, "get rf sector cfg failed with status %d\n",
+ reply.evt.status);
+ return wil_rf_sector_status_to_rc(reply.evt.status);
+ }
+
+ msg = cfg80211_vendor_cmd_alloc_reply_skb(
+ wiphy, 64 * WMI_MAX_RF_MODULES_NUM);
+ if (!msg)
+ return -ENOMEM;
+
+ if (nla_put_u64_64bit(msg, QCA_ATTR_TSF,
+ le64_to_cpu(reply.evt.tsf),
+ QCA_ATTR_PAD))
+ goto nla_put_failure;
+
+ nl_cfgs = nla_nest_start(msg, QCA_ATTR_DMG_RF_SECTOR_CFG);
+ if (!nl_cfgs)
+ goto nla_put_failure;
+ for (i = 0; i < WMI_MAX_RF_MODULES_NUM; i++) {
+ if (!(rf_modules_vec & BIT(i)))
+ continue;
+ nl_cfg = nla_nest_start(msg, i);
+ if (!nl_cfg)
+ goto nla_put_failure;
+ si = &reply.evt.sectors_info[i];
+ if (nla_put_u8(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX,
+ i) ||
+ nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0,
+ le32_to_cpu(si->etype0)) ||
+ nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1,
+ le32_to_cpu(si->etype1)) ||
+ nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2,
+ le32_to_cpu(si->etype2)) ||
+ nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI,
+ le32_to_cpu(si->psh_hi)) ||
+ nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO,
+ le32_to_cpu(si->psh_lo)) ||
+ nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16,
+ le32_to_cpu(si->dtype_swch_off)))
+ goto nla_put_failure;
+ nla_nest_end(msg, nl_cfg);
+ }
+
+ nla_nest_end(msg, nl_cfgs);
+ rc = cfg80211_vendor_cmd_reply(msg);
+ return rc;
+nla_put_failure:
+ kfree_skb(msg);
+ return -ENOBUFS;
+}
+
+static int wil_rf_sector_set_cfg(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ struct wil6210_priv *wil = wdev_to_wil(wdev);
+ int rc, tmp;
+ struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
+ struct nlattr *tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1];
+ u16 sector_index, rf_module_index;
+ u8 sector_type;
+ u32 rf_modules_vec = 0;
+ struct wmi_set_rf_sector_params_cmd cmd;
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_set_rf_sector_params_done_event evt;
+ } __packed reply;
+ struct nlattr *nl_cfg;
+ struct wmi_rf_sector_info *si;
+
+ if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
+ return -EOPNOTSUPP;
+
+ rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
+ wil_rf_sector_policy, NULL);
+ if (rc) {
+ wil_err(wil, "Invalid rf sector ATTR\n");
+ return rc;
+ }
+
+ if (!tb[QCA_ATTR_DMG_RF_SECTOR_INDEX] ||
+ !tb[QCA_ATTR_DMG_RF_SECTOR_TYPE] ||
+ !tb[QCA_ATTR_DMG_RF_SECTOR_CFG]) {
+ wil_err(wil, "Invalid rf sector spec\n");
+ return -EINVAL;
+ }
+
+ sector_index = nla_get_u16(
+ tb[QCA_ATTR_DMG_RF_SECTOR_INDEX]);
+ if (sector_index >= WIL_MAX_RF_SECTORS) {
+ wil_err(wil, "Invalid sector index %d\n", sector_index);
+ return -EINVAL;
+ }
+
+ sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
+ if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
+ wil_err(wil, "Invalid sector type %d\n", sector_type);
+ return -EINVAL;
+ }
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ cmd.sector_idx = cpu_to_le16(sector_index);
+ cmd.sector_type = sector_type;
+ nla_for_each_nested(nl_cfg, tb[QCA_ATTR_DMG_RF_SECTOR_CFG],
+ tmp) {
+ rc = nla_parse_nested(tb2, QCA_ATTR_DMG_RF_SECTOR_CFG_MAX,
+ nl_cfg, wil_rf_sector_cfg_policy,
+ NULL);
+ if (rc) {
+ wil_err(wil, "invalid sector cfg\n");
+ return -EINVAL;
+ }
+
+ if (!tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX] ||
+ !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0] ||
+ !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1] ||
+ !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2] ||
+ !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI] ||
+ !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO] ||
+ !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16]) {
+ wil_err(wil, "missing cfg params\n");
+ return -EINVAL;
+ }
+
+ rf_module_index = nla_get_u8(
+ tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX]);
+ if (rf_module_index >= WMI_MAX_RF_MODULES_NUM) {
+ wil_err(wil, "invalid RF module index %d\n",
+ rf_module_index);
+ return -EINVAL;
+ }
+ rf_modules_vec |= BIT(rf_module_index);
+ si = &cmd.sectors_info[rf_module_index];
+ si->etype0 = cpu_to_le32(nla_get_u32(
+ tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0]));
+ si->etype1 = cpu_to_le32(nla_get_u32(
+ tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1]));
+ si->etype2 = cpu_to_le32(nla_get_u32(
+ tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2]));
+ si->psh_hi = cpu_to_le32(nla_get_u32(
+ tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI]));
+ si->psh_lo = cpu_to_le32(nla_get_u32(
+ tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO]));
+ si->dtype_swch_off = cpu_to_le32(nla_get_u32(
+ tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16]));
+ }
+
+ cmd.rf_modules_vec = rf_modules_vec & 0xFF;
+ memset(&reply, 0, sizeof(reply));
+ rc = wmi_call(wil, WMI_SET_RF_SECTOR_PARAMS_CMDID, &cmd, sizeof(cmd),
+ WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID,
+ &reply, sizeof(reply),
+ 500);
+ if (rc)
+ return rc;
+ return wil_rf_sector_status_to_rc(reply.evt.status);
+}
+
+static int wil_rf_sector_get_selected(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ struct wil6210_priv *wil = wdev_to_wil(wdev);
+ int rc;
+ struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
+ u8 sector_type, mac_addr[ETH_ALEN];
+ int cid = 0;
+ struct wmi_get_selected_rf_sector_index_cmd cmd;
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_get_selected_rf_sector_index_done_event evt;
+ } __packed reply;
+ struct sk_buff *msg;
+
+ if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
+ return -EOPNOTSUPP;
+
+ rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
+ wil_rf_sector_policy, NULL);
+ if (rc) {
+ wil_err(wil, "Invalid rf sector ATTR\n");
+ return rc;
+ }
+
+ if (!tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]) {
+ wil_err(wil, "Invalid rf sector spec\n");
+ return -EINVAL;
+ }
+ sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
+ if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
+ wil_err(wil, "Invalid sector type %d\n", sector_type);
+ return -EINVAL;
+ }
+
+ if (tb[QCA_ATTR_MAC_ADDR]) {
+ ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR]));
+ cid = wil_find_cid(wil, mac_addr);
+ if (cid < 0) {
+ wil_err(wil, "invalid MAC address %pM\n", mac_addr);
+ return -ENOENT;
+ }
+ } else {
+ if (test_bit(wil_status_fwconnected, wil->status)) {
+ wil_err(wil, "must specify MAC address when connected\n");
+ return -EINVAL;
+ }
+ }
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cid = (u8)cid;
+ cmd.sector_type = sector_type;
+ memset(&reply, 0, sizeof(reply));
+ rc = wmi_call(wil, WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID,
+ &cmd, sizeof(cmd),
+ WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID,
+ &reply, sizeof(reply),
+ 500);
+ if (rc)
+ return rc;
+ if (reply.evt.status) {
+ wil_err(wil, "get rf selected sector cfg failed with status %d\n",
+ reply.evt.status);
+ return wil_rf_sector_status_to_rc(reply.evt.status);
+ }
+
+ msg = cfg80211_vendor_cmd_alloc_reply_skb(
+ wiphy, 64 * WMI_MAX_RF_MODULES_NUM);
+ if (!msg)
+ return -ENOMEM;
+
+ if (nla_put_u64_64bit(msg, QCA_ATTR_TSF,
+ le64_to_cpu(reply.evt.tsf),
+ QCA_ATTR_PAD) ||
+ nla_put_u16(msg, QCA_ATTR_DMG_RF_SECTOR_INDEX,
+ le16_to_cpu(reply.evt.sector_idx)))
+ goto nla_put_failure;
+
+ rc = cfg80211_vendor_cmd_reply(msg);
+ return rc;
+nla_put_failure:
+ kfree_skb(msg);
+ return -ENOBUFS;
+}
+
+static int wil_rf_sector_wmi_set_selected(struct wil6210_priv *wil,
+ u16 sector_index,
+ u8 sector_type, u8 cid)
+{
+ struct wmi_set_selected_rf_sector_index_cmd cmd;
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_set_selected_rf_sector_index_done_event evt;
+ } __packed reply;
+ int rc;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.sector_idx = cpu_to_le16(sector_index);
+ cmd.sector_type = sector_type;
+ cmd.cid = (u8)cid;
+ memset(&reply, 0, sizeof(reply));
+ rc = wmi_call(wil, WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID,
+ &cmd, sizeof(cmd),
+ WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID,
+ &reply, sizeof(reply),
+ 500);
+ if (rc)
+ return rc;
+ return wil_rf_sector_status_to_rc(reply.evt.status);
+}
+
+static int wil_rf_sector_set_selected(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ struct wil6210_priv *wil = wdev_to_wil(wdev);
+ int rc;
+ struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
+ u16 sector_index;
+ u8 sector_type, mac_addr[ETH_ALEN], i;
+ int cid = 0;
+
+ if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
+ return -EOPNOTSUPP;
+
+ rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
+ wil_rf_sector_policy, NULL);
+ if (rc) {
+ wil_err(wil, "Invalid rf sector ATTR\n");
+ return rc;
+ }
+
+ if (!tb[QCA_ATTR_DMG_RF_SECTOR_INDEX] ||
+ !tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]) {
+ wil_err(wil, "Invalid rf sector spec\n");
+ return -EINVAL;
+ }
+
+ sector_index = nla_get_u16(
+ tb[QCA_ATTR_DMG_RF_SECTOR_INDEX]);
+ if (sector_index >= WIL_MAX_RF_SECTORS &&
+ sector_index != WMI_INVALID_RF_SECTOR_INDEX) {
+ wil_err(wil, "Invalid sector index %d\n", sector_index);
+ return -EINVAL;
+ }
+
+ sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
+ if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
+ wil_err(wil, "Invalid sector type %d\n", sector_type);
+ return -EINVAL;
+ }
+
+ if (tb[QCA_ATTR_MAC_ADDR]) {
+ ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR]));
+ if (!is_broadcast_ether_addr(mac_addr)) {
+ cid = wil_find_cid(wil, mac_addr);
+ if (cid < 0) {
+ wil_err(wil, "invalid MAC address %pM\n",
+ mac_addr);
+ return -ENOENT;
+ }
+ } else {
+ if (sector_index != WMI_INVALID_RF_SECTOR_INDEX) {
+ wil_err(wil, "broadcast MAC valid only with unlocking\n");
+ return -EINVAL;
+ }
+ cid = -1;
+ }
+ } else {
+ if (test_bit(wil_status_fwconnected, wil->status)) {
+ wil_err(wil, "must specify MAC address when connected\n");
+ return -EINVAL;
+ }
+ /* otherwise, using cid=0 for unassociated station */
+ }
+
+ if (cid >= 0) {
+ rc = wil_rf_sector_wmi_set_selected(wil, sector_index,
+ sector_type, cid);
+ } else {
+ /* unlock all cids */
+ rc = wil_rf_sector_wmi_set_selected(
+ wil, WMI_INVALID_RF_SECTOR_INDEX, sector_type,
+ WIL_CID_ALL);
+ if (rc == -EINVAL) {
+ for (i = 0; i < WIL6210_MAX_CID; i++) {
+ rc = wil_rf_sector_wmi_set_selected(
+ wil, WMI_INVALID_RF_SECTOR_INDEX,
+ sector_type, i);
+ /* the FW will silently ignore and return
+ * success for unused cid, so abort the loop
+ * on any other error
+ */
+ if (rc) {
+ wil_err(wil, "unlock cid %d failed with status %d\n",
+ i, rc);
+ break;
+ }
+ }
+ }
+ }
+
+ return rc;
+}
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 5648ebb..f82506d 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -509,6 +509,10 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
void *buf;
size_t ret;
+ if (test_bit(wil_status_suspending, wil_blob->wil->status) ||
+ test_bit(wil_status_suspended, wil_blob->wil->status))
+ return 0;
+
if (pos < 0)
return -EINVAL;
@@ -795,15 +799,11 @@ static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf,
struct wireless_dev *wdev = wil_to_wdev(wil);
struct cfg80211_mgmt_tx_params params;
int rc;
- void *frame = kmalloc(len, GFP_KERNEL);
+ void *frame;
- if (!frame)
- return -ENOMEM;
-
- if (copy_from_user(frame, buf, len)) {
- kfree(frame);
- return -EIO;
- }
+ frame = memdup_user(buf, len);
+ if (IS_ERR(frame))
+ return PTR_ERR(frame);
params.buf = frame;
params.len = len;
@@ -1604,6 +1604,49 @@ static const struct file_operations fops_fw_version = {
.llseek = seq_lseek,
};
+/*---------suspend_stats---------*/
+static ssize_t wil_write_suspend_stats(struct file *file,
+ const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct wil6210_priv *wil = file->private_data;
+
+ memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats));
+
+ return len;
+}
+
+static ssize_t wil_read_suspend_stats(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wil6210_priv *wil = file->private_data;
+ static char text[400];
+ int n;
+
+ n = snprintf(text, sizeof(text),
+ "Suspend statistics:\n"
+ "successful suspends:%ld failed suspends:%ld\n"
+ "successful resumes:%ld failed resumes:%ld\n"
+ "rejected by host:%ld rejected by device:%ld\n",
+ wil->suspend_stats.successful_suspends,
+ wil->suspend_stats.failed_suspends,
+ wil->suspend_stats.successful_resumes,
+ wil->suspend_stats.failed_resumes,
+ wil->suspend_stats.rejected_by_host,
+ wil->suspend_stats.rejected_by_device);
+
+ n = min_t(int, n, sizeof(text));
+
+ return simple_read_from_buffer(user_buf, count, ppos, text, n);
+}
+
+static const struct file_operations fops_suspend_stats = {
+ .read = wil_read_suspend_stats,
+ .write = wil_write_suspend_stats,
+ .open = simple_open,
+};
+
/*----------------*/
static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
struct dentry *dbg)
@@ -1656,6 +1699,7 @@ static const struct {
{"led_blink_time", 0644, &fops_led_blink_time},
{"fw_capabilities", 0444, &fops_fw_capabilities},
{"fw_version", 0444, &fops_fw_version},
+ {"suspend_stats", 0644, &fops_suspend_stats},
};
static void wil6210_debugfs_init_files(struct wil6210_priv *wil,
@@ -1702,6 +1746,7 @@ static const struct dbg_off dbg_wil_off[] = {
WIL_FIELD(discovery_mode, 0644, doff_u8),
WIL_FIELD(chip_revision, 0444, doff_u8),
WIL_FIELD(abft_len, 0644, doff_u8),
+ WIL_FIELD(wakeup_trigger, 0644, doff_u8),
{},
};
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index cab1e5c..cad8a95 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -467,6 +467,12 @@ static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
wil6210_unmask_irq_pseudo(wil);
+ if (wil->suspend_resp_rcvd) {
+ wil_dbg_irq(wil, "set suspend_resp_comp to true\n");
+ wil->suspend_resp_comp = true;
+ wake_up_interruptible(&wil->wq);
+ }
+
return IRQ_HANDLED;
}
diff --git a/drivers/net/wireless/ath/wil6210/ioctl.c b/drivers/net/wireless/ath/wil6210/ioctl.c
deleted file mode 100644
index 6303800..0000000
--- a/drivers/net/wireless/ath/wil6210/ioctl.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (c) 2014 Qualcomm Atheros, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/uaccess.h>
-
-#include "wil6210.h"
-#include <uapi/linux/wil6210_uapi.h>
-
-#define wil_hex_dump_ioctl(prefix_str, buf, len) \
- print_hex_dump_debug("DBG[IOC ]" prefix_str, \
- DUMP_PREFIX_OFFSET, 16, 1, buf, len, true)
-#define wil_dbg_ioctl(wil, fmt, arg...) wil_dbg(wil, "DBG[IOC ]" fmt, ##arg)
-
-static void __iomem *wil_ioc_addr(struct wil6210_priv *wil, uint32_t addr,
- uint32_t size, enum wil_memio_op op)
-{
- void __iomem *a;
- u32 off;
-
- switch (op & wil_mmio_addr_mask) {
- case wil_mmio_addr_linker:
- a = wmi_buffer(wil, cpu_to_le32(addr));
- break;
- case wil_mmio_addr_ahb:
- a = wmi_addr(wil, addr);
- break;
- case wil_mmio_addr_bar:
- a = wmi_addr(wil, addr + WIL6210_FW_HOST_OFF);
- break;
- default:
- wil_err(wil, "Unsupported address mode, op = 0x%08x\n", op);
- return NULL;
- }
-
- off = a - wil->csr;
- if (size >= WIL6210_MEM_SIZE - off) {
- wil_err(wil, "Requested block does not fit into memory: "
- "off = 0x%08x size = 0x%08x\n", off, size);
- return NULL;
- }
-
- return a;
-}
-
-static int wil_ioc_memio_dword(struct wil6210_priv *wil, void __user *data)
-{
- struct wil_memio io;
- void __iomem *a;
- bool need_copy = false;
-
- if (copy_from_user(&io, data, sizeof(io)))
- return -EFAULT;
-
- wil_dbg_ioctl(wil, "IO: addr = 0x%08x val = 0x%08x op = 0x%08x\n",
- io.addr, io.val, io.op);
-
- a = wil_ioc_addr(wil, io.addr, sizeof(u32), io.op);
- if (!a) {
- wil_err(wil, "invalid address 0x%08x, op = 0x%08x\n", io.addr,
- io.op);
- return -EINVAL;
- }
- /* operation */
- switch (io.op & wil_mmio_op_mask) {
- case wil_mmio_read:
- io.val = readl(a);
- need_copy = true;
- break;
- case wil_mmio_write:
- writel(io.val, a);
- wmb(); /* make sure write propagated to HW */
- break;
- default:
- wil_err(wil, "Unsupported operation, op = 0x%08x\n", io.op);
- return -EINVAL;
- }
-
- if (need_copy) {
- wil_dbg_ioctl(wil, "IO done: addr = 0x%08x"
- " val = 0x%08x op = 0x%08x\n",
- io.addr, io.val, io.op);
- if (copy_to_user(data, &io, sizeof(io)))
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int wil_ioc_memio_block(struct wil6210_priv *wil, void __user *data)
-{
- struct wil_memio_block io;
- void *block;
- void __iomem *a;
- int rc = 0;
-
- if (copy_from_user(&io, data, sizeof(io)))
- return -EFAULT;
-
- wil_dbg_ioctl(wil, "IO: addr = 0x%08x size = 0x%08x op = 0x%08x\n",
- io.addr, io.size, io.op);
-
- /* size */
- if (io.size % 4) {
- wil_err(wil, "size is not multiple of 4: 0x%08x\n", io.size);
- return -EINVAL;
- }
-
- a = wil_ioc_addr(wil, io.addr, io.size, io.op);
- if (!a) {
- wil_err(wil, "invalid address 0x%08x, op = 0x%08x\n", io.addr,
- io.op);
- return -EINVAL;
- }
-
- block = kmalloc(io.size, GFP_USER);
- if (!block)
- return -ENOMEM;
-
- /* operation */
- switch (io.op & wil_mmio_op_mask) {
- case wil_mmio_read:
- wil_memcpy_fromio_32(block, a, io.size);
- wil_hex_dump_ioctl("Read ", block, io.size);
- if (copy_to_user(io.block, block, io.size)) {
- rc = -EFAULT;
- goto out_free;
- }
- break;
- case wil_mmio_write:
- if (copy_from_user(block, io.block, io.size)) {
- rc = -EFAULT;
- goto out_free;
- }
- wil_memcpy_toio_32(a, block, io.size);
- wmb(); /* make sure write propagated to HW */
- wil_hex_dump_ioctl("Write ", block, io.size);
- break;
- default:
- wil_err(wil, "Unsupported operation, op = 0x%08x\n", io.op);
- rc = -EINVAL;
- break;
- }
-
-out_free:
- kfree(block);
- return rc;
-}
-
-int wil_ioctl(struct wil6210_priv *wil, void __user *data, int cmd)
-{
- int ret;
-
- switch (cmd) {
- case WIL_IOCTL_MEMIO:
- ret = wil_ioc_memio_dword(wil, data);
- break;
- case WIL_IOCTL_MEMIO_BLOCK:
- ret = wil_ioc_memio_block(wil, data);
- break;
- default:
- wil_dbg_ioctl(wil, "Unsupported IOCTL 0x%04x\n", cmd);
- return -ENOIOCTLCMD;
- }
-
- wil_dbg_ioctl(wil, "ioctl(0x%04x) -> %d\n", cmd, ret);
- return ret;
-}
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 3208679..daf944a 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -576,6 +576,9 @@ int wil_priv_init(struct wil6210_priv *wil)
wil->ps_profile = WMI_PS_PROFILE_TYPE_DEFAULT;
+ wil->wakeup_trigger = WMI_WAKEUP_TRIGGER_UCAST |
+ WMI_WAKEUP_TRIGGER_BCAST;
+
return 0;
out_wmi_wq:
@@ -586,8 +589,10 @@ out_wmi_wq:
void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps)
{
- if (wil->platform_ops.bus_request)
+ if (wil->platform_ops.bus_request) {
+ wil->bus_request_kbps = kbps;
wil->platform_ops.bus_request(wil->platform_handle, kbps);
+ }
}
/**
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index 708facd..4a6ab2d 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -42,20 +42,12 @@ static int wil_stop(struct net_device *ndev)
return wil_down(wil);
}
-static int wil_do_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
-{
- struct wil6210_priv *wil = ndev_to_wil(ndev);
-
- return wil_ioctl(wil, ifr->ifr_data, cmd);
-}
-
static const struct net_device_ops wil_netdev_ops = {
.ndo_open = wil_open,
.ndo_stop = wil_stop,
.ndo_start_xmit = wil_start_xmit,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
- .ndo_do_ioctl = wil_do_ioctl,
};
static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget)
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index b38515f..d571feb 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -26,6 +26,10 @@ static bool use_msi = true;
module_param(use_msi, bool, 0444);
MODULE_PARM_DESC(use_msi, " Use MSI interrupt, default - true");
+static bool ftm_mode;
+module_param(ftm_mode, bool, 0444);
+MODULE_PARM_DESC(ftm_mode, " Set factory test mode, default - false");
+
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int wil6210_pm_notify(struct notifier_block *notify_block,
@@ -36,13 +40,15 @@ static int wil6210_pm_notify(struct notifier_block *notify_block,
static
void wil_set_capabilities(struct wil6210_priv *wil)
{
+ const char *wil_fw_name;
u32 jtag_id = wil_r(wil, RGF_USER_JTAG_DEV_ID);
u8 chip_revision = (wil_r(wil, RGF_USER_REVISION_ID) &
RGF_USER_REVISION_ID_MASK);
bitmap_zero(wil->hw_capabilities, hw_capability_last);
bitmap_zero(wil->fw_capabilities, WMI_FW_CAPABILITY_MAX);
- wil->wil_fw_name = WIL_FW_NAME_DEFAULT;
+ wil->wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_DEFAULT :
+ WIL_FW_NAME_DEFAULT;
wil->chip_revision = chip_revision;
switch (jtag_id) {
@@ -51,9 +57,11 @@ void wil_set_capabilities(struct wil6210_priv *wil)
case REVISION_ID_SPARROW_D0:
wil->hw_name = "Sparrow D0";
wil->hw_version = HW_VER_SPARROW_D0;
- if (wil_fw_verify_file_exists(wil,
- WIL_FW_NAME_SPARROW_PLUS))
- wil->wil_fw_name = WIL_FW_NAME_SPARROW_PLUS;
+ wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_SPARROW_PLUS :
+ WIL_FW_NAME_SPARROW_PLUS;
+
+ if (wil_fw_verify_file_exists(wil, wil_fw_name))
+ wil->wil_fw_name = wil_fw_name;
break;
case REVISION_ID_SPARROW_B0:
wil->hw_name = "Sparrow B0";
@@ -104,8 +112,6 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
wil_dbg_misc(wil, "if_pcie_enable, wmi_only %d\n", wmi_only);
- pdev->msi_enabled = 0;
-
pci_set_master(pdev);
wil_dbg_misc(wil, "Setup %s interrupt\n", use_msi ? "MSI" : "INTx");
@@ -183,6 +189,13 @@ static int wil_platform_rop_fw_recovery(void *wil_handle)
return 0;
}
+static void wil_platform_ops_uninit(struct wil6210_priv *wil)
+{
+ if (wil->platform_ops.uninit)
+ wil->platform_ops.uninit(wil->platform_handle);
+ memset(&wil->platform_ops, 0, sizeof(wil->platform_ops));
+}
+
static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct wil6210_priv *wil;
@@ -192,16 +205,18 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
.ramdump = wil_platform_rop_ramdump,
.fw_recovery = wil_platform_rop_fw_recovery,
};
+ u32 bar_size = pci_resource_len(pdev, 0);
/* check HW */
dev_info(&pdev->dev, WIL_NAME
- " device found [%04x:%04x] (rev %x)\n",
- (int)pdev->vendor, (int)pdev->device, (int)pdev->revision);
-
- if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) {
- dev_err(&pdev->dev, "Not " WIL_NAME "? "
- "BAR0 size is %lu while expecting %lu\n",
- (ulong)pci_resource_len(pdev, 0), WIL6210_MEM_SIZE);
+ " device found [%04x:%04x] (rev %x) bar size 0x%x\n",
+ (int)pdev->vendor, (int)pdev->device, (int)pdev->revision,
+ bar_size);
+
+ if ((bar_size < WIL6210_MIN_MEM_SIZE) ||
+ (bar_size > WIL6210_MAX_MEM_SIZE)) {
+ dev_err(&pdev->dev, "Unexpected BAR0 size 0x%x\n",
+ bar_size);
return -ENODEV;
}
@@ -214,6 +229,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
wil->pdev = pdev;
pci_set_drvdata(pdev, wil);
+ wil->bar_size = bar_size;
/* rollback to if_free */
wil->platform_handle =
@@ -241,7 +257,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
rc = pci_enable_device(pdev);
- if (rc) {
+ if (rc && pdev->msi_enabled == 0) {
wil_err(wil,
"pci_enable_device failed, retry with MSI only\n");
/* Work around for platforms that can't allocate IRQ:
@@ -256,6 +272,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_plat;
}
/* rollback to err_disable_pdev */
+ pci_set_power_state(pdev, PCI_D0);
rc = pci_request_region(pdev, 0, WIL_NAME);
if (rc) {
@@ -276,6 +293,15 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
wil_set_capabilities(wil);
wil6210_clear_irq(wil);
+ wil->keep_radio_on_during_sleep =
+ wil->platform_ops.keep_radio_on_during_sleep &&
+ wil->platform_ops.keep_radio_on_during_sleep(
+ wil->platform_handle) &&
+ test_bit(WMI_FW_CAPABILITY_D3_SUSPEND, wil->fw_capabilities);
+
+ wil_info(wil, "keep_radio_on_during_sleep (%d)\n",
+ wil->keep_radio_on_during_sleep);
+
/* FW should raise IRQ when ready */
rc = wil_if_pcie_enable(wil);
if (rc) {
@@ -316,8 +342,7 @@ err_release_reg:
err_disable_pdev:
pci_disable_device(pdev);
err_plat:
- if (wil->platform_ops.uninit)
- wil->platform_ops.uninit(wil->platform_handle);
+ wil_platform_ops_uninit(wil);
if_free:
wil_if_free(wil);
@@ -346,8 +371,7 @@ static void wil_pcie_remove(struct pci_dev *pdev)
pci_iounmap(pdev, csr);
pci_release_region(pdev, 0);
pci_disable_device(pdev);
- if (wil->platform_ops.uninit)
- wil->platform_ops.uninit(wil->platform_handle);
+ wil_platform_ops_uninit(wil);
wil_if_free(wil);
}
@@ -374,15 +398,16 @@ static int wil6210_suspend(struct device *dev, bool is_runtime)
goto out;
rc = wil_suspend(wil, is_runtime);
- if (rc)
- goto out;
-
- /* TODO: how do I bring card in low power state? */
-
- /* disable bus mastering */
- pci_clear_master(pdev);
- /* PCI will call pci_save_state(pdev) and pci_prepare_to_sleep(pdev) */
+ if (!rc) {
+ wil->suspend_stats.successful_suspends++;
+ /* If platform device supports keep_radio_on_during_sleep
+ * it will control PCIe master
+ */
+ if (!wil->keep_radio_on_during_sleep)
+ /* disable bus mastering */
+ pci_clear_master(pdev);
+ }
out:
return rc;
}
@@ -395,12 +420,21 @@ static int wil6210_resume(struct device *dev, bool is_runtime)
wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system");
- /* allow master */
- pci_set_master(pdev);
-
+ /* If platform device supports keep_radio_on_during_sleep it will
+ * control PCIe master
+ */
+ if (!wil->keep_radio_on_during_sleep)
+ /* allow master */
+ pci_set_master(pdev);
rc = wil_resume(wil, is_runtime);
- if (rc)
- pci_clear_master(pdev);
+ if (rc) {
+ wil_err(wil, "device failed to resume (%d)\n", rc);
+ wil->suspend_stats.failed_resumes++;
+ if (!wil->keep_radio_on_during_sleep)
+ pci_clear_master(pdev);
+ } else {
+ wil->suspend_stats.successful_resumes++;
+ }
return rc;
}
diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c
index 2ae4fe8..ce1f384 100644
--- a/drivers/net/wireless/ath/wil6210/pm.c
+++ b/drivers/net/wireless/ath/wil6210/pm.c
@@ -15,6 +15,7 @@
*/
#include "wil6210.h"
+#include <linux/jiffies.h>
int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime)
{
@@ -61,20 +62,170 @@ out:
wil_dbg_pm(wil, "can_suspend: %s => %s (%d)\n",
is_runtime ? "runtime" : "system", rc ? "No" : "Yes", rc);
+ if (rc)
+ wil->suspend_stats.rejected_by_host++;
+
return rc;
}
-int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
+static int wil_resume_keep_radio_on(struct wil6210_priv *wil)
{
int rc = 0;
- struct net_device *ndev = wil_to_ndev(wil);
- wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system");
+ /* wil_status_resuming will be cleared when getting
+ * WMI_TRAFFIC_RESUME_EVENTID
+ */
+ set_bit(wil_status_resuming, wil->status);
+ clear_bit(wil_status_suspended, wil->status);
+ wil_c(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
+ wil_unmask_irq(wil);
- if (test_bit(wil_status_suspended, wil->status)) {
- wil_dbg_pm(wil, "trying to suspend while suspended\n");
- return 0;
+ wil6210_bus_request(wil, wil->bus_request_kbps_pre_suspend);
+
+ /* Send WMI resume request to the device */
+ rc = wmi_resume(wil);
+ if (rc) {
+ wil_err(wil, "device failed to resume (%d), resetting\n", rc);
+ rc = wil_down(wil);
+ if (rc) {
+ wil_err(wil, "wil_down failed (%d)\n", rc);
+ goto out;
+ }
+ rc = wil_up(wil);
+ if (rc) {
+ wil_err(wil, "wil_up failed (%d)\n", rc);
+ goto out;
+ }
+ }
+
+ /* Wake all queues */
+ if (test_bit(wil_status_fwconnected, wil->status))
+ wil_update_net_queues_bh(wil, NULL, false);
+
+out:
+ if (rc)
+ set_bit(wil_status_suspended, wil->status);
+ return rc;
+}
+
+static int wil_suspend_keep_radio_on(struct wil6210_priv *wil)
+{
+ int rc = 0;
+ unsigned long start, data_comp_to;
+
+ wil_dbg_pm(wil, "suspend keep radio on\n");
+
+ /* Prevent handling of new tx and wmi commands */
+ set_bit(wil_status_suspending, wil->status);
+ wil_update_net_queues_bh(wil, NULL, true);
+
+ if (!wil_is_tx_idle(wil)) {
+ wil_dbg_pm(wil, "Pending TX data, reject suspend\n");
+ wil->suspend_stats.rejected_by_host++;
+ goto reject_suspend;
+ }
+
+ if (!wil_is_rx_idle(wil)) {
+ wil_dbg_pm(wil, "Pending RX data, reject suspend\n");
+ wil->suspend_stats.rejected_by_host++;
+ goto reject_suspend;
+ }
+
+ if (!wil_is_wmi_idle(wil)) {
+ wil_dbg_pm(wil, "Pending WMI events, reject suspend\n");
+ wil->suspend_stats.rejected_by_host++;
+ goto reject_suspend;
+ }
+
+ /* Send WMI suspend request to the device */
+ rc = wmi_suspend(wil);
+ if (rc) {
+ wil_dbg_pm(wil, "wmi_suspend failed, reject suspend (%d)\n",
+ rc);
+ goto reject_suspend;
+ }
+
+ /* Wait for completion of the pending RX packets */
+ start = jiffies;
+ data_comp_to = jiffies + msecs_to_jiffies(WIL_DATA_COMPLETION_TO_MS);
+ if (test_bit(wil_status_napi_en, wil->status)) {
+ while (!wil_is_rx_idle(wil)) {
+ if (time_after(jiffies, data_comp_to)) {
+ if (wil_is_rx_idle(wil))
+ break;
+ wil_err(wil,
+ "TO waiting for idle RX, suspend failed\n");
+ wil->suspend_stats.failed_suspends++;
+ goto resume_after_fail;
+ }
+ wil_dbg_ratelimited(wil, "rx vring is not empty -> NAPI\n");
+ napi_synchronize(&wil->napi_rx);
+ msleep(20);
+ }
+ }
+
+ /* In case of pending WMI events, reject the suspend
+ * and resume the device.
+ * This can happen if the device sent the WMI events before
+ * approving the suspend.
+ */
+ if (!wil_is_wmi_idle(wil)) {
+ wil_err(wil, "suspend failed due to pending WMI events\n");
+ wil->suspend_stats.failed_suspends++;
+ goto resume_after_fail;
+ }
+
+ wil_mask_irq(wil);
+
+ /* Disable device reset on PERST */
+ wil_s(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
+
+ if (wil->platform_ops.suspend) {
+ rc = wil->platform_ops.suspend(wil->platform_handle, true);
+ if (rc) {
+ wil_err(wil, "platform device failed to suspend (%d)\n",
+ rc);
+ wil->suspend_stats.failed_suspends++;
+ wil_c(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
+ wil_unmask_irq(wil);
+ goto resume_after_fail;
+ }
+ }
+
+ /* Save the current bus request to return to the same in resume */
+ wil->bus_request_kbps_pre_suspend = wil->bus_request_kbps;
+ wil6210_bus_request(wil, 0);
+
+ set_bit(wil_status_suspended, wil->status);
+ clear_bit(wil_status_suspending, wil->status);
+
+ return rc;
+
+resume_after_fail:
+ set_bit(wil_status_resuming, wil->status);
+ clear_bit(wil_status_suspending, wil->status);
+ rc = wmi_resume(wil);
+ /* if resume succeeded, reject the suspend */
+ if (!rc) {
+ rc = -EBUSY;
+ if (test_bit(wil_status_fwconnected, wil->status))
+ wil_update_net_queues_bh(wil, NULL, false);
}
+ return rc;
+
+reject_suspend:
+ clear_bit(wil_status_suspending, wil->status);
+ if (test_bit(wil_status_fwconnected, wil->status))
+ wil_update_net_queues_bh(wil, NULL, false);
+ return -EBUSY;
+}
+
+static int wil_suspend_radio_off(struct wil6210_priv *wil)
+{
+ int rc = 0;
+ struct net_device *ndev = wil_to_ndev(wil);
+
+ wil_dbg_pm(wil, "suspend radio off\n");
/* if netif up, hardware is alive, shut it down */
if (ndev->flags & IFF_UP) {
@@ -90,7 +241,7 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
wil_disable_irq(wil);
if (wil->platform_ops.suspend) {
- rc = wil->platform_ops.suspend(wil->platform_handle);
+ rc = wil->platform_ops.suspend(wil->platform_handle, false);
if (rc) {
wil_enable_irq(wil);
goto out;
@@ -100,6 +251,50 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
set_bit(wil_status_suspended, wil->status);
out:
+ wil_dbg_pm(wil, "suspend radio off: %d\n", rc);
+
+ return rc;
+}
+
+static int wil_resume_radio_off(struct wil6210_priv *wil)
+{
+ int rc = 0;
+ struct net_device *ndev = wil_to_ndev(wil);
+
+ wil_dbg_pm(wil, "Enabling PCIe IRQ\n");
+ wil_enable_irq(wil);
+ /* if netif up, bring hardware up
+ * During open(), IFF_UP set after actual device method
+ * invocation. This prevent recursive call to wil_up()
+ * wil_status_suspended will be cleared in wil_reset
+ */
+ if (ndev->flags & IFF_UP)
+ rc = wil_up(wil);
+ else
+ clear_bit(wil_status_suspended, wil->status);
+
+ return rc;
+}
+
+int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
+{
+ int rc = 0;
+ struct net_device *ndev = wil_to_ndev(wil);
+ bool keep_radio_on = ndev->flags & IFF_UP &&
+ wil->keep_radio_on_during_sleep;
+
+ wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system");
+
+ if (test_bit(wil_status_suspended, wil->status)) {
+ wil_dbg_pm(wil, "trying to suspend while suspended\n");
+ return 0;
+ }
+
+ if (!keep_radio_on)
+ rc = wil_suspend_radio_off(wil);
+ else
+ rc = wil_suspend_keep_radio_on(wil);
+
wil_dbg_pm(wil, "suspend: %s => %d\n",
is_runtime ? "runtime" : "system", rc);
@@ -110,29 +305,24 @@ int wil_resume(struct wil6210_priv *wil, bool is_runtime)
{
int rc = 0;
struct net_device *ndev = wil_to_ndev(wil);
+ bool keep_radio_on = ndev->flags & IFF_UP &&
+ wil->keep_radio_on_during_sleep;
wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system");
if (wil->platform_ops.resume) {
- rc = wil->platform_ops.resume(wil->platform_handle);
+ rc = wil->platform_ops.resume(wil->platform_handle,
+ keep_radio_on);
if (rc) {
wil_err(wil, "platform_ops.resume : %d\n", rc);
goto out;
}
}
- wil_dbg_pm(wil, "Enabling PCIe IRQ\n");
- wil_enable_irq(wil);
-
- /* if netif up, bring hardware up
- * During open(), IFF_UP set after actual device method
- * invocation. This prevent recursive call to wil_up().
- * wil_status_suspended will be cleared in wil_reset
- */
- if (ndev->flags & IFF_UP)
- rc = wil_up(wil);
+ if (keep_radio_on)
+ rc = wil_resume_keep_radio_on(wil);
else
- clear_bit(wil_status_suspended, wil->status);
+ rc = wil_resume_radio_off(wil);
out:
wil_dbg_pm(wil, "resume: %s => %d\n",
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index edab4c0..ec57bcc 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -104,6 +104,51 @@ static inline int wil_vring_avail_high(struct vring *vring)
return wil_vring_avail_tx(vring) > wil_vring_wmark_high(vring);
}
+/* returns true when all tx vrings are empty */
+bool wil_is_tx_idle(struct wil6210_priv *wil)
+{
+ int i;
+ unsigned long data_comp_to;
+
+ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
+ struct vring *vring = &wil->vring_tx[i];
+ int vring_index = vring - wil->vring_tx;
+ struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index];
+
+ spin_lock(&txdata->lock);
+
+ if (!vring->va || !txdata->enabled) {
+ spin_unlock(&txdata->lock);
+ continue;
+ }
+
+ data_comp_to = jiffies + msecs_to_jiffies(
+ WIL_DATA_COMPLETION_TO_MS);
+ if (test_bit(wil_status_napi_en, wil->status)) {
+ while (!wil_vring_is_empty(vring)) {
+ if (time_after(jiffies, data_comp_to)) {
+ wil_dbg_pm(wil,
+ "TO waiting for idle tx\n");
+ spin_unlock(&txdata->lock);
+ return false;
+ }
+ wil_dbg_ratelimited(wil,
+ "tx vring is not empty -> NAPI\n");
+ spin_unlock(&txdata->lock);
+ napi_synchronize(&wil->napi_tx);
+ msleep(20);
+ spin_lock(&txdata->lock);
+ if (!vring->va || !txdata->enabled)
+ break;
+ }
+ }
+
+ spin_unlock(&txdata->lock);
+ }
+
+ return true;
+}
+
/* wil_val_in_range - check if value in [min,max) */
static inline bool wil_val_in_range(int val, int min, int max)
{
@@ -363,7 +408,7 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil,
return;
}
- rtap_vendor = (void *)skb_push(skb, rtap_len);
+ rtap_vendor = skb_push(skb, rtap_len);
memset(rtap_vendor, 0, rtap_len);
rtap_vendor->rtap.rthdr.it_version = PKTHDR_RADIOTAP_VERSION;
@@ -406,6 +451,18 @@ static inline int wil_is_back_req(u8 fc)
(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ);
}
+bool wil_is_rx_idle(struct wil6210_priv *wil)
+{
+ struct vring_rx_desc *_d;
+ struct vring *vring = &wil->vring_rx;
+
+ _d = (struct vring_rx_desc *)&vring->va[vring->swhead].rx;
+ if (_d->dma.status & RX_DMA_STATUS_DU)
+ return false;
+
+ return true;
+}
+
/**
* reap 1 frame from @swhead
*
@@ -1812,6 +1869,15 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
spin_lock(&txdata->lock);
+ if (test_bit(wil_status_suspending, wil->status) ||
+ test_bit(wil_status_suspended, wil->status) ||
+ test_bit(wil_status_resuming, wil->status)) {
+ wil_dbg_txrx(wil,
+ "suspend/resume in progress. drop packet\n");
+ spin_unlock(&txdata->lock);
+ return -EINVAL;
+ }
+
rc = (skb_is_gso(skb) ? __wil_tx_vring_tso : __wil_tx_vring)
(wil, vring, skb);
@@ -1864,6 +1930,11 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil,
return;
}
+ /* Do not wake the queues in suspend flow */
+ if (test_bit(wil_status_suspending, wil->status) ||
+ test_bit(wil_status_suspended, wil->status))
+ return;
+
/* check wake */
for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
struct vring *cur_vring = &wil->vring_tx[i];
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index b00c803..d085ccf 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -37,8 +37,13 @@ extern bool debug_fw;
extern bool disable_ap_sme;
#define WIL_NAME "wil6210"
-#define WIL_FW_NAME_DEFAULT "wil6210.fw" /* code Sparrow B0 */
-#define WIL_FW_NAME_SPARROW_PLUS "wil6210_sparrow_plus.fw" /* code Sparrow D0 */
+
+#define WIL_FW_NAME_DEFAULT "wil6210.fw"
+#define WIL_FW_NAME_FTM_DEFAULT "wil6210_ftm.fw"
+
+#define WIL_FW_NAME_SPARROW_PLUS "wil6210_sparrow_plus.fw"
+#define WIL_FW_NAME_FTM_SPARROW_PLUS "wil6210_sparrow_plus_ftm.fw"
+
#define WIL_BOARD_FILE_NAME "wil6210.brd" /* board & radio parameters */
#define WIL_DEFAULT_BUS_REQUEST_KBPS 128000 /* ~1Gbps */
@@ -53,7 +58,8 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
return (x >> b0) & ((1 << (b1 - b0 + 1)) - 1);
}
-#define WIL6210_MEM_SIZE (2*1024*1024UL)
+#define WIL6210_MIN_MEM_SIZE (2 * 1024 * 1024UL)
+#define WIL6210_MAX_MEM_SIZE (4 * 1024 * 1024UL)
#define WIL_TX_Q_LEN_DEFAULT (4000)
#define WIL_RX_RING_SIZE_ORDER_DEFAULT (10)
@@ -77,6 +83,15 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
*/
#define WIL_MAX_MPDU_OVERHEAD (62)
+struct wil_suspend_stats {
+ unsigned long successful_suspends;
+ unsigned long failed_suspends;
+ unsigned long successful_resumes;
+ unsigned long failed_resumes;
+ unsigned long rejected_by_device;
+ unsigned long rejected_by_host;
+};
+
/* Calculate MAC buffer size for the firmware. It includes all overhead,
* as it will go over the air, and need to be 8 byte aligned
*/
@@ -284,6 +299,8 @@ enum {
#define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT(1)
#define ISR_MISC_FW_ERROR BIT_DMA_EP_MISC_ICR_FW_INT(3)
+#define WIL_DATA_COMPLETION_TO_MS 200
+
/* Hardware definitions end */
struct fw_map {
u32 from; /* linker address - from, inclusive */
@@ -412,7 +429,9 @@ enum { /* for wil6210_priv.status */
wil_status_irqen, /* FIXME: interrupts enabled - for debug */
wil_status_napi_en, /* NAPI enabled protected by wil->mutex */
wil_status_resetting, /* reset in progress */
+ wil_status_suspending, /* suspend in progress */
wil_status_suspended, /* suspend completed, device is suspended */
+ wil_status_resuming, /* resume in progress */
wil_status_last /* keep last */
};
@@ -594,6 +613,7 @@ extern u8 led_polarity;
struct wil6210_priv {
struct pci_dev *pdev;
+ u32 bar_size;
struct wireless_dev *wdev;
void __iomem *csr;
DECLARE_BITMAP(status, wil_status_last);
@@ -676,9 +696,12 @@ struct wil6210_priv {
struct wil_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)];
u8 discovery_mode;
u8 abft_len;
+ u8 wakeup_trigger;
+ struct wil_suspend_stats suspend_stats;
void *platform_handle;
struct wil_platform_ops platform_ops;
+ bool keep_radio_on_during_sleep;
struct pmc_ctx pmc;
@@ -701,6 +724,11 @@ struct wil6210_priv {
struct notifier_block pm_notify;
#endif /* CONFIG_PM_SLEEP */
#endif /* CONFIG_PM */
+
+ bool suspend_resp_rcvd;
+ bool suspend_resp_comp;
+ u32 bus_request_kbps;
+ u32 bus_request_kbps_pre_suspend;
};
#define wil_to_wiphy(i) (i->wdev->wiphy)
@@ -949,7 +977,6 @@ void wil6210_unmask_irq_rx(struct wil6210_priv *wil);
int wil_iftype_nl2wmi(enum nl80211_iftype type);
-int wil_ioctl(struct wil6210_priv *wil, void __user *data, int cmd);
int wil_request_firmware(struct wil6210_priv *wil, const char *name,
bool load);
bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name);
@@ -957,6 +984,11 @@ bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name);
int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime);
int wil_suspend(struct wil6210_priv *wil, bool is_runtime);
int wil_resume(struct wil6210_priv *wil, bool is_runtime);
+bool wil_is_wmi_idle(struct wil6210_priv *wil);
+int wmi_resume(struct wil6210_priv *wil);
+int wmi_suspend(struct wil6210_priv *wil);
+bool wil_is_tx_idle(struct wil6210_priv *wil);
+bool wil_is_rx_idle(struct wil6210_priv *wil);
int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size);
void wil_fw_core_dump(struct wil6210_priv *wil);
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.h b/drivers/net/wireless/ath/wil6210/wil_platform.h
index f8c4117..5d9e4bf 100644
--- a/drivers/net/wireless/ath/wil6210/wil_platform.h
+++ b/drivers/net/wireless/ath/wil6210/wil_platform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016 Qualcomm Atheros, Inc.
+ * Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -33,10 +33,11 @@ enum wil_platform_event {
*/
struct wil_platform_ops {
int (*bus_request)(void *handle, uint32_t kbps /* KBytes/Sec */);
- int (*suspend)(void *handle);
- int (*resume)(void *handle);
+ int (*suspend)(void *handle, bool keep_device_power);
+ int (*resume)(void *handle, bool device_powered_on);
void (*uninit)(void *handle);
int (*notify)(void *handle, enum wil_platform_event evt);
+ bool (*keep_radio_on_during_sleep)(void *handle);
};
/**
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 814c356..65ef673 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -37,6 +37,8 @@ module_param(led_id, byte, 0444);
MODULE_PARM_DESC(led_id,
" 60G device led enablement. Set the led ID (0-2) to enable");
+#define WIL_WAIT_FOR_SUSPEND_RESUME_COMP 200
+
/**
* WMI event receiving - theory of operations
*
@@ -157,7 +159,7 @@ void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_)
return NULL;
off = HOSTADDR(ptr);
- if (off > WIL6210_MEM_SIZE - 4)
+ if (off > wil->bar_size - 4)
return NULL;
return wil->csr + off;
@@ -177,7 +179,7 @@ void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr)
return NULL;
off = HOSTADDR(ptr);
- if (off > WIL6210_MEM_SIZE - 4)
+ if (off > wil->bar_size - 4)
return NULL;
return wil->csr + off;
@@ -233,6 +235,16 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
return -EAGAIN;
}
+ /* Allow sending only suspend / resume commands during susepnd flow */
+ if ((test_bit(wil_status_suspending, wil->status) ||
+ test_bit(wil_status_suspended, wil->status) ||
+ test_bit(wil_status_resuming, wil->status)) &&
+ ((cmdid != WMI_TRAFFIC_SUSPEND_CMDID) &&
+ (cmdid != WMI_TRAFFIC_RESUME_CMDID))) {
+ wil_err(wil, "WMI: reject send_command during suspend\n");
+ return -EINVAL;
+ }
+
if (!head) {
wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head);
return -EINVAL;
@@ -677,11 +689,11 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
return;
}
- eth = (struct ethhdr *)skb_put(skb, ETH_HLEN);
+ eth = skb_put(skb, ETH_HLEN);
ether_addr_copy(eth->h_dest, ndev->dev_addr);
ether_addr_copy(eth->h_source, evt->src_mac);
eth->h_proto = cpu_to_be16(ETH_P_PAE);
- memcpy(skb_put(skb, eapol_len), evt->eapol, eapol_len);
+ skb_put_data(skb, evt->eapol, eapol_len);
skb->protocol = eth_type_trans(skb, ndev);
if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) {
ndev->stats.rx_packets++;
@@ -862,6 +874,11 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
return;
}
+ if (test_bit(wil_status_suspended, wil->status)) {
+ wil_err(wil, "suspended. cannot handle WMI event\n");
+ return;
+ }
+
for (n = 0;; n++) {
u16 len;
bool q;
@@ -914,6 +931,15 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
struct wmi_cmd_hdr *wmi = &evt->event.wmi;
u16 id = le16_to_cpu(wmi->command_id);
u32 tstamp = le32_to_cpu(wmi->fw_timestamp);
+ if (test_bit(wil_status_resuming, wil->status)) {
+ if (id == WMI_TRAFFIC_RESUME_EVENTID)
+ clear_bit(wil_status_resuming,
+ wil->status);
+ else
+ wil_err(wil,
+ "WMI evt %d while resuming\n",
+ id);
+ }
spin_lock_irqsave(&wil->wmi_ev_lock, flags);
if (wil->reply_id && wil->reply_id == id) {
if (wil->reply_buf) {
@@ -921,6 +947,11 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
min(len, wil->reply_size));
immed_reply = true;
}
+ if (id == WMI_TRAFFIC_SUSPEND_EVENTID) {
+ wil_dbg_wmi(wil,
+ "set suspend_resp_rcvd\n");
+ wil->suspend_resp_rcvd = true;
+ }
}
spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
@@ -1762,6 +1793,85 @@ void wmi_event_flush(struct wil6210_priv *wil)
spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
}
+int wmi_suspend(struct wil6210_priv *wil)
+{
+ int rc;
+ struct wmi_traffic_suspend_cmd cmd = {
+ .wakeup_trigger = wil->wakeup_trigger,
+ };
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_traffic_suspend_event evt;
+ } __packed reply;
+ u32 suspend_to = WIL_WAIT_FOR_SUSPEND_RESUME_COMP;
+
+ wil->suspend_resp_rcvd = false;
+ wil->suspend_resp_comp = false;
+
+ reply.evt.status = WMI_TRAFFIC_SUSPEND_REJECTED;
+
+ rc = wmi_call(wil, WMI_TRAFFIC_SUSPEND_CMDID, &cmd, sizeof(cmd),
+ WMI_TRAFFIC_SUSPEND_EVENTID, &reply, sizeof(reply),
+ suspend_to);
+ if (rc) {
+ wil_err(wil, "wmi_call for suspend req failed, rc=%d\n", rc);
+ if (rc == -ETIME)
+ /* wmi_call TO */
+ wil->suspend_stats.rejected_by_device++;
+ else
+ wil->suspend_stats.rejected_by_host++;
+ goto out;
+ }
+
+ wil_dbg_wmi(wil, "waiting for suspend_response_completed\n");
+
+ rc = wait_event_interruptible_timeout(wil->wq,
+ wil->suspend_resp_comp,
+ msecs_to_jiffies(suspend_to));
+ if (rc == 0) {
+ wil_err(wil, "TO waiting for suspend_response_completed\n");
+ if (wil->suspend_resp_rcvd)
+ /* Device responded but we TO due to another reason */
+ wil->suspend_stats.rejected_by_host++;
+ else
+ wil->suspend_stats.rejected_by_device++;
+ rc = -EBUSY;
+ goto out;
+ }
+
+ wil_dbg_wmi(wil, "suspend_response_completed rcvd\n");
+ if (reply.evt.status == WMI_TRAFFIC_SUSPEND_REJECTED) {
+ wil_dbg_pm(wil, "device rejected the suspend\n");
+ wil->suspend_stats.rejected_by_device++;
+ }
+ rc = reply.evt.status;
+
+out:
+ wil->suspend_resp_rcvd = false;
+ wil->suspend_resp_comp = false;
+
+ return rc;
+}
+
+int wmi_resume(struct wil6210_priv *wil)
+{
+ int rc;
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_traffic_resume_event evt;
+ } __packed reply;
+
+ reply.evt.status = WMI_TRAFFIC_RESUME_FAILED;
+
+ rc = wmi_call(wil, WMI_TRAFFIC_RESUME_CMDID, NULL, 0,
+ WMI_TRAFFIC_RESUME_EVENTID, &reply, sizeof(reply),
+ WIL_WAIT_FOR_SUSPEND_RESUME_COMP);
+ if (rc)
+ return rc;
+
+ return reply.evt.status;
+}
+
static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id,
void *d, int len)
{
@@ -1851,3 +1961,36 @@ void wmi_event_worker(struct work_struct *work)
}
wil_dbg_wmi(wil, "event_worker: Finished\n");
}
+
+bool wil_is_wmi_idle(struct wil6210_priv *wil)
+{
+ ulong flags;
+ struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx;
+ bool rc = false;
+
+ spin_lock_irqsave(&wil->wmi_ev_lock, flags);
+
+ /* Check if there are pending WMI events in the events queue */
+ if (!list_empty(&wil->pending_wmi_ev)) {
+ wil_dbg_pm(wil, "Pending WMI events in queue\n");
+ goto out;
+ }
+
+ /* Check if there is a pending WMI call */
+ if (wil->reply_id) {
+ wil_dbg_pm(wil, "Pending WMI call\n");
+ goto out;
+ }
+
+ /* Check if there are pending RX events in mbox */
+ r->head = wil_r(wil, RGF_MBOX +
+ offsetof(struct wil6210_mbox_ctl, rx.head));
+ if (r->tail != r->head)
+ wil_dbg_pm(wil, "Pending WMI mbox events\n");
+ else
+ rc = true;
+
+out:
+ spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
+ return rc;
+}
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
index f7f5f4f..256f63c 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.h
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -59,6 +59,7 @@ enum wmi_fw_capability {
WMI_FW_CAPABILITY_DISABLE_AP_SME = 4,
WMI_FW_CAPABILITY_WMI_ONLY = 5,
WMI_FW_CAPABILITY_THERMAL_THROTTLING = 7,
+ WMI_FW_CAPABILITY_D3_SUSPEND = 8,
WMI_FW_CAPABILITY_MAX,
};
@@ -157,7 +158,7 @@ enum wmi_command_id {
WMI_FLASH_READ_CMDID = 0x902,
WMI_FLASH_WRITE_CMDID = 0x903,
/* Power management */
- WMI_TRAFFIC_DEFERRAL_CMDID = 0x904,
+ WMI_TRAFFIC_SUSPEND_CMDID = 0x904,
WMI_TRAFFIC_RESUME_CMDID = 0x905,
/* P2P */
WMI_P2P_CFG_CMDID = 0x910,
@@ -500,8 +501,14 @@ struct wmi_port_delete_cmd {
u8 reserved[3];
} __packed;
-/* WMI_TRAFFIC_DEFERRAL_CMDID */
-struct wmi_traffic_deferral_cmd {
+/* WMI_TRAFFIC_SUSPEND_CMD wakeup trigger bit mask values */
+enum wmi_wakeup_trigger {
+ WMI_WAKEUP_TRIGGER_UCAST = 0x01,
+ WMI_WAKEUP_TRIGGER_BCAST = 0x02,
+};
+
+/* WMI_TRAFFIC_SUSPEND_CMDID */
+struct wmi_traffic_suspend_cmd {
/* Bit vector: bit[0] - wake on Unicast, bit[1] - wake on Broadcast */
u8 wakeup_trigger;
} __packed;
@@ -1084,7 +1091,7 @@ enum wmi_event_id {
WMI_FLASH_READ_DONE_EVENTID = 0x1902,
WMI_FLASH_WRITE_DONE_EVENTID = 0x1903,
/* Power management */
- WMI_TRAFFIC_DEFERRAL_EVENTID = 0x1904,
+ WMI_TRAFFIC_SUSPEND_EVENTID = 0x1904,
WMI_TRAFFIC_RESUME_EVENTID = 0x1905,
/* P2P */
WMI_P2P_CFG_DONE_EVENTID = 0x1910,
@@ -1926,14 +1933,14 @@ struct wmi_link_maintain_cfg_read_done_event {
struct wmi_link_maintain_cfg lm_cfg;
} __packed;
-enum wmi_traffic_deferral_status {
- WMI_TRAFFIC_DEFERRAL_APPROVED = 0x0,
- WMI_TRAFFIC_DEFERRAL_REJECTED = 0x1,
+enum wmi_traffic_suspend_status {
+ WMI_TRAFFIC_SUSPEND_APPROVED = 0x0,
+ WMI_TRAFFIC_SUSPEND_REJECTED = 0x1,
};
-/* WMI_TRAFFIC_DEFERRAL_EVENTID */
-struct wmi_traffic_deferral_event {
- /* enum wmi_traffic_deferral_status_e */
+/* WMI_TRAFFIC_SUSPEND_EVENTID */
+struct wmi_traffic_suspend_event {
+ /* enum wmi_traffic_suspend_status_e */
u8 status;
} __packed;
diff --git a/drivers/net/wireless/atmel/atmel.c b/drivers/net/wireless/atmel/atmel.c
index 27b110d..b68436b 100644
--- a/drivers/net/wireless/atmel/atmel.c
+++ b/drivers/net/wireless/atmel/atmel.c
@@ -1036,9 +1036,8 @@ static void frag_rx_path(struct atmel_private *priv,
priv->dev->stats.rx_dropped++;
} else {
skb_reserve(skb, 2);
- memcpy(skb_put(skb, priv->frag_len + 12),
- priv->rx_buf,
- priv->frag_len + 12);
+ skb_put_data(skb, priv->rx_buf,
+ priv->frag_len + 12);
skb->protocol = eth_type_trans(skb, priv->dev);
skb->ip_summed = CHECKSUM_NONE;
netif_rx(skb);
diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
index d23aac7..b37e739 100644
--- a/drivers/net/wireless/broadcom/b43/main.c
+++ b/drivers/net/wireless/broadcom/b43/main.c
@@ -71,8 +71,18 @@ MODULE_FIRMWARE("b43/ucode11.fw");
MODULE_FIRMWARE("b43/ucode13.fw");
MODULE_FIRMWARE("b43/ucode14.fw");
MODULE_FIRMWARE("b43/ucode15.fw");
+MODULE_FIRMWARE("b43/ucode16_lp.fw");
MODULE_FIRMWARE("b43/ucode16_mimo.fw");
+MODULE_FIRMWARE("b43/ucode24_lcn.fw");
+MODULE_FIRMWARE("b43/ucode25_lcn.fw");
+MODULE_FIRMWARE("b43/ucode25_mimo.fw");
+MODULE_FIRMWARE("b43/ucode26_mimo.fw");
+MODULE_FIRMWARE("b43/ucode29_mimo.fw");
+MODULE_FIRMWARE("b43/ucode33_lcn40.fw");
+MODULE_FIRMWARE("b43/ucode30_mimo.fw");
MODULE_FIRMWARE("b43/ucode5.fw");
+MODULE_FIRMWARE("b43/ucode40.fw");
+MODULE_FIRMWARE("b43/ucode42.fw");
MODULE_FIRMWARE("b43/ucode9.fw");
static int modparam_bad_frames_preempt;
diff --git a/drivers/net/wireless/broadcom/b43legacy/dma.c b/drivers/net/wireless/broadcom/b43legacy/dma.c
index f9dd892..cfa617d 100644
--- a/drivers/net/wireless/broadcom/b43legacy/dma.c
+++ b/drivers/net/wireless/broadcom/b43legacy/dma.c
@@ -1072,7 +1072,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
goto out_unmap_hdr;
}
- memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
+ skb_put_data(bounce_skb, skb->data, skb->len);
memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb));
bounce_skb->dev = skb->dev;
skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb));
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 9b970dc..984c1d0 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -108,12 +108,14 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)
int ret = 0;
u8 data;
u32 addr, gpiocontrol;
- unsigned long flags;
pdata = &sdiodev->settings->bus.sdio;
if (pdata->oob_irq_supported) {
brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n",
pdata->oob_irq_nr);
+ spin_lock_init(&sdiodev->irq_en_lock);
+ sdiodev->irq_en = true;
+
ret = request_irq(pdata->oob_irq_nr, brcmf_sdiod_oob_irqhandler,
pdata->oob_irq_flags, "brcmf_oob_intr",
&sdiodev->func[1]->dev);
@@ -122,10 +124,6 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)
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(pdata->oob_irq_nr);
if (ret != 0) {
@@ -706,7 +704,7 @@ done:
int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
struct sk_buff_head *pktq, uint totlen)
{
- struct sk_buff *glom_skb;
+ struct sk_buff *glom_skb = NULL;
struct sk_buff *skb;
u32 addr = sdiodev->sbwad;
int err = 0;
@@ -727,10 +725,8 @@ int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
return -ENOMEM;
err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr,
glom_skb);
- if (err) {
- brcmu_pkt_buf_free_skb(glom_skb);
+ if (err)
goto done;
- }
skb_queue_walk(pktq, skb) {
memcpy(skb->data, glom_skb->data, skb->len);
@@ -741,6 +737,7 @@ int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
pktq);
done:
+ brcmu_pkt_buf_free_skb(glom_skb);
return err;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c
index 14a70d4..3559fb5 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c
@@ -380,9 +380,7 @@ int brcmf_btcoex_attach(struct brcmf_cfg80211_info *cfg)
/* 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;
+ setup_timer(&btci->timer, brcmf_btcoex_timerfunc, (ulong)btci);
btci->cfg = cfg;
btci->saved_regs_part1 = false;
btci->saved_regs_part2 = false;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
index b55c329..163ddc4 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
@@ -113,6 +113,17 @@ struct brcmf_bus_msgbuf {
/**
+ * struct brcmf_bus_stats - bus statistic counters.
+ *
+ * @pktcowed: packets cowed for extra headroom/unorphan.
+ * @pktcow_failed: packets dropped due to failed cow-ing.
+ */
+struct brcmf_bus_stats {
+ atomic_t pktcowed;
+ atomic_t pktcow_failed;
+};
+
+/**
* struct brcmf_bus - interface structure between common and bus layer
*
* @bus_priv: pointer to private bus device.
@@ -120,11 +131,10 @@ struct brcmf_bus_msgbuf {
* @dev: device pointer of bus device.
* @drvr: public driver information.
* @state: operational state of the bus interface.
+ * @stats: statistics shared between common and bus layer.
* @maxctl: maximum size for rxctl request message.
- * @tx_realloc: number of tx packets realloced for headroom.
- * @dstats: dongle-based statistical data.
- * @dcmd_list: bus/device specific dongle initialization commands.
* @chip: device identifier of the dongle chip.
+ * @always_use_fws_queue: bus wants use queue also when fwsignal is inactive.
* @wowl_supported: is wowl supported by bus driver.
* @chiprev: revision of the dongle chip.
*/
@@ -138,8 +148,8 @@ struct brcmf_bus {
struct device *dev;
struct brcmf_pub *drvr;
enum brcmf_bus_state state;
+ struct brcmf_bus_stats stats;
uint maxctl;
- unsigned long tx_realloc;
u32 chip;
u32 chiprev;
bool always_use_fws_queue;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 617199c..dcde596 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -625,6 +625,7 @@ struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name,
err = brcmf_net_attach(ifp, true);
if (err) {
brcmf_err("Registering netdevice failed\n");
+ free_netdev(ifp->ndev);
goto fail;
}
@@ -719,6 +720,8 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
{
struct brcmf_scan_params_le params_le;
struct cfg80211_scan_request *scan_request;
+ u64 reqid;
+ u32 bucket;
s32 err = 0;
brcmf_dbg(SCAN, "Enter\n");
@@ -749,7 +752,7 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
&params_le, sizeof(params_le));
if (err)
- brcmf_err("Scan abort failed\n");
+ brcmf_err("Scan abort failed\n");
}
brcmf_scan_config_mpc(ifp, 1);
@@ -758,11 +761,21 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
* e-scan can be initiated internally
* which takes precedence.
*/
- if (cfg->internal_escan) {
- brcmf_dbg(SCAN, "scheduled scan completed\n");
- cfg->internal_escan = false;
- if (!aborted)
- cfg80211_sched_scan_results(cfg_to_wiphy(cfg), 0);
+ if (cfg->int_escan_map) {
+ brcmf_dbg(SCAN, "scheduled scan completed (%x)\n",
+ cfg->int_escan_map);
+ while (cfg->int_escan_map) {
+ bucket = __ffs(cfg->int_escan_map);
+ cfg->int_escan_map &= ~BIT(bucket);
+ reqid = brcmf_pno_find_reqid_by_bucket(cfg->pno,
+ bucket);
+ if (!aborted) {
+ brcmf_dbg(SCAN, "report results: reqid=%llu\n",
+ reqid);
+ cfg80211_sched_scan_results(cfg_to_wiphy(cfg),
+ reqid);
+ }
+ }
} else if (scan_request) {
struct cfg80211_scan_info info = {
.aborted = aborted,
@@ -1011,7 +1024,7 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
if (!ssid_le.SSID_len)
brcmf_dbg(SCAN, "%d: Broadcast scan\n", i);
else
- brcmf_dbg(SCAN, "%d: scan for %s size =%d\n",
+ brcmf_dbg(SCAN, "%d: scan for %.32s size=%d\n",
i, ssid_le.SSID, ssid_le.SSID_len);
memcpy(ptr, &ssid_le, sizeof(ssid_le));
ptr += sizeof(ssid_le);
@@ -1344,6 +1357,27 @@ static u16 brcmf_map_fw_linkdown_reason(const struct brcmf_event_msg *e)
return reason;
}
+static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len)
+{
+ struct brcmf_wsec_pmk_le pmk;
+ int i, err;
+
+ /* convert to firmware key format */
+ pmk.key_len = cpu_to_le16(pmk_len << 1);
+ pmk.flags = cpu_to_le16(BRCMF_WSEC_PASSPHRASE);
+ for (i = 0; i < pmk_len; i++)
+ snprintf(&pmk.key[2 * i], 3, "%02x", pmk_data[i]);
+
+ /* store psk in firmware */
+ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_WSEC_PMK,
+ &pmk, sizeof(pmk));
+ if (err < 0)
+ brcmf_err("failed to change PSK in firmware (len=%u)\n",
+ pmk_len);
+
+ return err;
+}
+
static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy);
@@ -1366,6 +1400,10 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason)
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);
+ if (vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {
+ brcmf_set_pmk(vif->ifp, NULL, 0);
+ vif->profile.use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
+ }
brcmf_dbg(TRACE, "Exit\n");
}
@@ -1679,6 +1717,7 @@ static s32
brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
{
struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
s32 val;
s32 err;
const struct brcmf_tlv *rsn_ie;
@@ -1689,6 +1728,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
u32 mfp;
u16 count;
+ profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
+
if (!sme->crypto.n_akm_suites)
return 0;
@@ -1701,6 +1742,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
switch (sme->crypto.akm_suites[0]) {
case WLAN_AKM_SUITE_8021X:
val = WPA_AUTH_UNSPECIFIED;
+ if (sme->want_1x)
+ profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
break;
case WLAN_AKM_SUITE_PSK:
val = WPA_AUTH_PSK;
@@ -1714,9 +1757,13 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
switch (sme->crypto.akm_suites[0]) {
case WLAN_AKM_SUITE_8021X:
val = WPA2_AUTH_UNSPECIFIED;
+ if (sme->want_1x)
+ profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
break;
case WLAN_AKM_SUITE_8021X_SHA256:
val = WPA2_AUTH_1X_SHA256;
+ if (sme->want_1x)
+ profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
break;
case WLAN_AKM_SUITE_PSK_SHA256:
val = WPA2_AUTH_PSK_SHA256;
@@ -1731,6 +1778,9 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
}
}
+ if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X)
+ brcmf_dbg(INFO, "using 1X offload\n");
+
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))
goto skip_mfp_config;
/* The MFP mode (1 or 2) needs to be determined, parse IEs. The
@@ -1903,6 +1953,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct ieee80211_channel *chan = sme->channel;
struct brcmf_join_params join_params;
size_t join_params_size;
@@ -1999,6 +2050,31 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
goto done;
}
+ if (sme->crypto.psk) {
+ if (WARN_ON(profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE)) {
+ err = -EINVAL;
+ goto done;
+ }
+ brcmf_dbg(INFO, "using PSK offload\n");
+ profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK;
+ }
+
+ if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {
+ /* enable firmware supplicant for this interface */
+ err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1);
+ if (err < 0) {
+ brcmf_err("failed to enable fw supplicant\n");
+ goto done;
+ }
+ }
+
+ if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK) {
+ err = brcmf_set_pmk(ifp, sme->crypto.psk,
+ BRCMF_WSEC_MAX_PSK_LEN);
+ if (err)
+ goto done;
+ }
+
/* Join with specific BSSID and cached SSID
* If SSID is zero join based on BSSID only
*/
@@ -3011,7 +3087,7 @@ void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg)
struct escan_info *escan = &cfg->escan_info;
set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
- if (cfg->internal_escan || cfg->scan_request) {
+ if (cfg->int_escan_map || cfg->scan_request) {
escan->escan_state = WL_ESCAN_STATE_IDLE;
brcmf_notify_escan_complete(cfg, escan->ifp, true, true);
}
@@ -3034,7 +3110,7 @@ static void brcmf_escan_timeout(unsigned long data)
struct brcmf_cfg80211_info *cfg =
(struct brcmf_cfg80211_info *)data;
- if (cfg->internal_escan || cfg->scan_request) {
+ if (cfg->int_escan_map || cfg->scan_request) {
brcmf_err("timer expired\n");
schedule_work(&cfg->escan_timeout_work);
}
@@ -3120,7 +3196,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
if (brcmf_p2p_scan_finding_common_channel(cfg, bss_info_le))
goto exit;
- if (!cfg->internal_escan && !cfg->scan_request) {
+ if (!cfg->int_escan_map && !cfg->scan_request) {
brcmf_dbg(SCAN, "result without cfg80211 request\n");
goto exit;
}
@@ -3166,7 +3242,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
if (brcmf_p2p_scan_finding_common_channel(cfg, NULL))
goto exit;
- if (cfg->internal_escan || cfg->scan_request) {
+ if (cfg->int_escan_map || cfg->scan_request) {
brcmf_inform_bss(cfg);
aborted = status != BRCMF_E_STATUS_SUCCESS;
brcmf_notify_escan_complete(cfg, ifp, aborted, false);
@@ -3248,17 +3324,21 @@ static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req,
return 0;
}
-static int brcmf_start_internal_escan(struct brcmf_if *ifp,
+static int brcmf_start_internal_escan(struct brcmf_if *ifp, u32 fwmap,
struct cfg80211_scan_request *request)
{
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
int err;
if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
+ if (cfg->int_escan_map)
+ brcmf_dbg(SCAN, "aborting internal scan: map=%u\n",
+ cfg->int_escan_map);
/* Abort any on-going scan */
brcmf_abort_scanning(cfg);
}
+ brcmf_dbg(SCAN, "start internal scan: map=%u\n", fwmap);
set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
cfg->escan_info.run = brcmf_run_escan;
err = brcmf_do_escan(ifp, request);
@@ -3266,7 +3346,7 @@ static int brcmf_start_internal_escan(struct brcmf_if *ifp,
clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
return err;
}
- cfg->internal_escan = true;
+ cfg->int_escan_map = fwmap;
return 0;
}
@@ -3308,6 +3388,7 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
struct wiphy *wiphy = cfg_to_wiphy(cfg);
int i, err = 0;
struct brcmf_pno_scanresults_le *pfn_result;
+ u32 bucket_map;
u32 result_count;
u32 status;
u32 datalen;
@@ -3352,6 +3433,7 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
goto out_err;
}
+ bucket_map = 0;
for (i = 0; i < result_count; i++) {
netinfo = &netinfo_start[i];
@@ -3359,6 +3441,7 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
netinfo->SSID_len = IEEE80211_MAX_SSID_LEN;
brcmf_dbg(SCAN, "SSID:%.32s Channel:%d\n",
netinfo->SSID, netinfo->channel);
+ bucket_map |= brcmf_pno_get_bucket_map(cfg->pno, netinfo);
err = brcmf_internal_escan_add_info(request,
netinfo->SSID,
netinfo->SSID_len,
@@ -3367,7 +3450,10 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
goto out_err;
}
- err = brcmf_start_internal_escan(ifp, request);
+ if (!bucket_map)
+ goto free_req;
+
+ err = brcmf_start_internal_escan(ifp, bucket_map, request);
if (!err)
goto free_req;
@@ -3386,11 +3472,11 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
- brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n",
+ brcmf_dbg(SCAN, "Enter: n_match_sets=%d n_ssids=%d\n",
req->n_match_sets, req->n_ssids);
if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {
- brcmf_err("Scanning suppressed: status (%lu)\n",
+ brcmf_err("Scanning suppressed: status=%lu\n",
cfg->scan_status);
return -EAGAIN;
}
@@ -3411,8 +3497,8 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
struct brcmf_if *ifp = netdev_priv(ndev);
brcmf_dbg(SCAN, "enter\n");
- brcmf_pno_clean(ifp);
- if (cfg->internal_escan)
+ brcmf_pno_stop_sched_scan(ifp, reqid);
+ if (cfg->int_escan_map)
brcmf_notify_escan_complete(cfg, ifp, true, true);
return 0;
}
@@ -4674,9 +4760,6 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
if (err < 0)
brcmf_err("setting AP mode failed %d\n", err);
- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0);
- if (err < 0)
- brcmf_err("setting INFRA mode failed %d\n", err);
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS))
brcmf_fil_iovar_int_set(ifp, "mbss", 0);
brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,
@@ -5131,6 +5214,34 @@ brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev,
}
#endif
+static int brcmf_cfg80211_set_pmk(struct wiphy *wiphy, struct net_device *dev,
+ const struct cfg80211_pmk_conf *conf)
+{
+ struct brcmf_if *ifp;
+
+ brcmf_dbg(TRACE, "enter\n");
+
+ /* expect using firmware supplicant for 1X */
+ ifp = netdev_priv(dev);
+ if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))
+ return -EINVAL;
+
+ return brcmf_set_pmk(ifp, conf->pmk, conf->pmk_len);
+}
+
+static int brcmf_cfg80211_del_pmk(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *aa)
+{
+ struct brcmf_if *ifp;
+
+ brcmf_dbg(TRACE, "enter\n");
+ ifp = netdev_priv(dev);
+ if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))
+ return -EINVAL;
+
+ return brcmf_set_pmk(ifp, NULL, 0);
+}
+
static struct cfg80211_ops brcmf_cfg80211_ops = {
.add_virtual_intf = brcmf_cfg80211_add_iface,
.del_virtual_intf = brcmf_cfg80211_del_iface,
@@ -5174,6 +5285,8 @@ static struct cfg80211_ops brcmf_cfg80211_ops = {
.crit_proto_stop = brcmf_cfg80211_crit_proto_stop,
.tdls_oper = brcmf_cfg80211_tdls_oper,
.update_connect_params = brcmf_cfg80211_update_conn_params,
+ .set_pmk = brcmf_cfg80211_set_pmk,
+ .del_pmk = brcmf_cfg80211_del_pmk,
};
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
@@ -5227,16 +5340,31 @@ void brcmf_cfg80211_free_netdev(struct net_device *ndev)
brcmf_free_vif(vif);
}
-static bool brcmf_is_linkup(const struct brcmf_event_msg *e)
+static bool brcmf_is_linkup(struct brcmf_cfg80211_vif *vif,
+ const struct brcmf_event_msg *e)
{
u32 event = e->event_code;
u32 status = e->status;
+ if (vif->profile.use_fwsup == BRCMF_PROFILE_FWSUP_PSK &&
+ event == BRCMF_E_PSK_SUP &&
+ status == BRCMF_E_STATUS_FWSUP_COMPLETED)
+ set_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state);
if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
brcmf_dbg(CONN, "Processing set ssid\n");
- return true;
+ memcpy(vif->profile.bssid, e->addr, ETH_ALEN);
+ if (vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_PSK)
+ return true;
+
+ set_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state);
}
+ if (test_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state) &&
+ test_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state)) {
+ clear_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state);
+ clear_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state);
+ return true;
+ }
return false;
}
@@ -5271,6 +5399,13 @@ static bool brcmf_is_nonetwork(struct brcmf_cfg80211_info *cfg,
return true;
}
+ if (event == BRCMF_E_PSK_SUP &&
+ status != BRCMF_E_STATUS_FWSUP_COMPLETED) {
+ brcmf_dbg(CONN, "Processing failed supplicant state: %u\n",
+ status);
+ return true;
+ }
+
return false;
}
@@ -5421,27 +5556,28 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg,
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
+ struct cfg80211_connect_resp_params conn_params;
brcmf_dbg(TRACE, "Enter\n");
if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTING,
&ifp->vif->sme_state)) {
+ memset(&conn_params, 0, sizeof(conn_params));
if (completed) {
brcmf_get_assoc_ies(cfg, ifp);
- memcpy(profile->bssid, e->addr, ETH_ALEN);
brcmf_update_bss_info(cfg, ifp);
set_bit(BRCMF_VIF_STATUS_CONNECTED,
&ifp->vif->sme_state);
+ conn_params.status = WLAN_STATUS_SUCCESS;
+ } else {
+ conn_params.status = WLAN_STATUS_AUTH_TIMEOUT;
}
- cfg80211_connect_result(ndev,
- (u8 *)profile->bssid,
- conn_info->req_ie,
- conn_info->req_ie_len,
- conn_info->resp_ie,
- conn_info->resp_ie_len,
- completed ? WLAN_STATUS_SUCCESS :
- WLAN_STATUS_AUTH_TIMEOUT,
- GFP_KERNEL);
+ conn_params.bssid = profile->bssid;
+ conn_params.req_ie = conn_info->req_ie;
+ conn_params.req_ie_len = conn_info->req_ie_len;
+ conn_params.resp_ie = conn_info->resp_ie;
+ conn_params.resp_ie_len = conn_info->resp_ie_len;
+ cfg80211_connect_done(ndev, &conn_params, GFP_KERNEL);
brcmf_dbg(CONN, "Report connect result - connection %s\n",
completed ? "succeeded" : "failed");
}
@@ -5507,7 +5643,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
if (brcmf_is_apmode(ifp->vif)) {
err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);
- } else if (brcmf_is_linkup(e)) {
+ } else if (brcmf_is_linkup(ifp->vif, e)) {
brcmf_dbg(CONN, "Linkup\n");
if (brcmf_is_ibssmode(ifp->vif)) {
brcmf_inform_ibss(cfg, ndev, e->addr);
@@ -5675,6 +5811,8 @@ static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
brcmf_p2p_notify_action_tx_complete);
brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE,
brcmf_p2p_notify_action_tx_complete);
+ brcmf_fweh_register(cfg->pub, BRCMF_E_PSK_SUP,
+ brcmf_notify_connect_status);
}
static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
@@ -6377,16 +6515,6 @@ err:
return -ENOMEM;
}
-static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
-{
- /* scheduled scan settings */
- wiphy->max_sched_scan_reqs = 1;
- wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
- wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
- wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
- wiphy->max_sched_scan_plan_interval = BRCMF_PNO_SCHED_SCAN_MAX_PERIOD;
-}
-
#ifdef CONFIG_PM
static const struct wiphy_wowlan_support brcmf_wowlan_support = {
.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
@@ -6433,6 +6561,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
const struct ieee80211_iface_combination *combo;
struct ieee80211_supported_band *band;
u16 max_interfaces = 0;
+ bool gscan;
__le32 bandlist[3];
u32 n_bands;
int err, i;
@@ -6480,11 +6609,18 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
if (!ifp->drvr->settings->roamoff)
wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP)) {
+ wiphy_ext_feature_set(wiphy,
+ NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK);
+ wiphy_ext_feature_set(wiphy,
+ NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X);
+ }
wiphy->mgmt_stypes = brcmf_txrx_stypes;
wiphy->max_remain_on_channel_duration = 5000;
- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO))
- brcmf_wiphy_pno_params(wiphy);
-
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {
+ gscan = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_GSCAN);
+ brcmf_pno_wiphy_params(wiphy, gscan);
+ }
/* vendor commands/events support */
wiphy->vendor_commands = brcmf_vendor_cmds;
wiphy->n_vendor_commands = BRCMF_VNDR_CMDS_LAST - 1;
@@ -6766,7 +6902,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
/* ignore non-ISO3166 country codes */
for (i = 0; i < sizeof(req->alpha2); i++)
if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
- brcmf_err("not a ISO3166 code (0x%02x 0x%02x)\n",
+ brcmf_err("not an ISO3166 code (0x%02x 0x%02x)\n",
req->alpha2[0], req->alpha2[1]);
return;
}
@@ -6850,7 +6986,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
wiphy = wiphy_new(ops, sizeof(struct brcmf_cfg80211_info));
if (!wiphy) {
brcmf_err("Could not allocate wiphy device\n");
- return NULL;
+ goto ops_out;
}
memcpy(wiphy->perm_addr, drvr->mac, ETH_ALEN);
set_wiphy_dev(wiphy, busdev);
@@ -6951,6 +7087,13 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
brcmf_p2p_detach(&cfg->p2p);
goto wiphy_unreg_out;
}
+ err = brcmf_pno_attach(cfg);
+ if (err) {
+ brcmf_err("PNO initialisation failed (%d)\n", err);
+ brcmf_btcoex_detach(cfg);
+ brcmf_p2p_detach(&cfg->p2p);
+ goto wiphy_unreg_out;
+ }
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_TDLS)) {
err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
@@ -6983,6 +7126,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
return cfg;
detach:
+ brcmf_pno_detach(cfg);
brcmf_btcoex_detach(cfg);
brcmf_p2p_detach(&cfg->p2p);
wiphy_unreg_out:
@@ -6993,6 +7137,7 @@ priv_out:
ifp->vif = NULL;
wiphy_out:
brcmf_free_wiphy(wiphy);
+ops_out:
kfree(ops);
return NULL;
}
@@ -7002,6 +7147,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
if (!cfg)
return;
+ brcmf_pno_detach(cfg);
brcmf_btcoex_detach(cfg);
wiphy_unregister(cfg->wiphy);
kfree(cfg->ops);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
index 8f19d95..7b2835e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
@@ -24,6 +24,8 @@
#include "fwil_types.h"
#include "p2p.h"
+#define BRCMF_SCAN_IE_LEN_MAX 2048
+
#define WL_NUM_SCAN_MAX 10
#define WL_TLV_INFO_MAX 1024
#define WL_BSS_INFO_MAX 2048
@@ -113,6 +115,12 @@ struct brcmf_cfg80211_security {
u32 cipher_group;
};
+enum brcmf_profile_fwsup {
+ BRCMF_PROFILE_FWSUP_NONE,
+ BRCMF_PROFILE_FWSUP_PSK,
+ BRCMF_PROFILE_FWSUP_1X
+};
+
/**
* struct brcmf_cfg80211_profile - profile information.
*
@@ -124,6 +132,7 @@ struct brcmf_cfg80211_profile {
u8 bssid[ETH_ALEN];
struct brcmf_cfg80211_security sec;
struct brcmf_wsec_key key[BRCMF_MAX_DEFAULT_KEYS];
+ enum brcmf_profile_fwsup use_fwsup;
};
/**
@@ -131,16 +140,20 @@ struct brcmf_cfg80211_profile {
*
* @BRCMF_VIF_STATUS_READY: ready for operation.
* @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress.
- * @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully.
+ * @BRCMF_VIF_STATUS_CONNECTED: connected/joined successfully.
* @BRCMF_VIF_STATUS_DISCONNECTING: disconnect/disable in progress.
* @BRCMF_VIF_STATUS_AP_CREATED: AP operation started.
+ * @BRCMF_VIF_STATUS_EAP_SUCCUSS: EAPOL handshake successful.
+ * @BRCMF_VIF_STATUS_ASSOC_SUCCESS: successful SET_SSID received.
*/
enum brcmf_vif_status {
BRCMF_VIF_STATUS_READY,
BRCMF_VIF_STATUS_CONNECTING,
BRCMF_VIF_STATUS_CONNECTED,
BRCMF_VIF_STATUS_DISCONNECTING,
- BRCMF_VIF_STATUS_AP_CREATED
+ BRCMF_VIF_STATUS_AP_CREATED,
+ BRCMF_VIF_STATUS_EAP_SUCCESS,
+ BRCMF_VIF_STATUS_ASSOC_SUCCESS,
};
/**
@@ -271,7 +284,7 @@ struct brcmf_cfg80211_wowl {
* @pub: common driver information.
* @channel: current channel.
* @active_scan: current scan mode.
- * @internal_escan: indicates internally initiated e-scan is running.
+ * @int_escan_map: bucket map for which internal e-scan is done.
* @ibss_starter: indicates this sta is ibss starter.
* @pwr_save: indicate whether dongle to support power save mode.
* @dongle_up: indicate whether dongle up or not.
@@ -287,6 +300,7 @@ struct brcmf_cfg80211_wowl {
* @vif_cnt: number of vif instances.
* @vif_event: vif event signalling.
* @wowl: wowl related information.
+ * @pno: information of pno module.
*/
struct brcmf_cfg80211_info {
struct wiphy *wiphy;
@@ -303,7 +317,7 @@ struct brcmf_cfg80211_info {
struct brcmf_pub *pub;
u32 channel;
bool active_scan;
- bool internal_escan;
+ u32 int_escan_map;
bool ibss_starter;
bool pwr_save;
bool dongle_up;
@@ -320,6 +334,7 @@ struct brcmf_cfg80211_info {
struct brcmu_d11inf d11inf;
struct brcmf_assoclist_le assoclist;
struct brcmf_cfg80211_wowl wowl;
+ struct brcmf_pno_info *pno;
};
/**
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 511d190..2153e80 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -30,6 +30,7 @@
#include "debug.h"
#include "fwil_types.h"
#include "p2p.h"
+#include "pno.h"
#include "cfg80211.h"
#include "fwil.h"
#include "feature.h"
@@ -198,6 +199,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_pub *drvr = ifp->drvr;
struct ethhdr *eh;
+ int head_delta;
brcmf_dbg(DATA, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
@@ -210,13 +212,21 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
goto done;
}
- /* Make sure there's enough writable headroom*/
- ret = skb_cow_head(skb, drvr->hdrlen);
- if (ret < 0) {
- brcmf_err("%s: skb_cow_head failed\n",
- brcmf_ifname(ifp));
- dev_kfree_skb(skb);
- goto done;
+ /* Make sure there's enough writeable headroom */
+ if (skb_headroom(skb) < drvr->hdrlen || skb_header_cloned(skb)) {
+ head_delta = drvr->hdrlen - skb_headroom(skb);
+
+ brcmf_dbg(INFO, "%s: insufficient headroom (%d)\n",
+ brcmf_ifname(ifp), head_delta);
+ atomic_inc(&drvr->bus_if->stats.pktcowed);
+ ret = pskb_expand_head(skb, ALIGN(head_delta, NET_SKB_PAD), 0,
+ GFP_ATOMIC);
+ if (ret < 0) {
+ brcmf_err("%s: failed to expand headroom\n",
+ brcmf_ifname(ifp));
+ atomic_inc(&drvr->bus_if->stats.pktcow_failed);
+ goto done;
+ }
}
/* validate length for ether packet */
@@ -484,13 +494,13 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
goto fail;
}
+ ndev->priv_destructor = brcmf_cfg80211_free_netdev;
brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
return 0;
fail:
drvr->iflist[ifp->bsscfgidx] = NULL;
ndev->netdev_ops = NULL;
- free_netdev(ndev);
return -EBADE;
}
@@ -503,6 +513,7 @@ static void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked)
unregister_netdev(ndev);
} else {
brcmf_cfg80211_free_netdev(ndev);
+ free_netdev(ndev);
}
}
@@ -579,7 +590,6 @@ static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
fail:
ifp->drvr->iflist[ifp->bsscfgidx] = NULL;
ndev->netdev_ops = NULL;
- free_netdev(ndev);
return -EBADE;
}
@@ -625,7 +635,6 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
return ERR_PTR(-ENOMEM);
ndev->needs_free_netdev = true;
- ndev->priv_destructor = brcmf_cfg80211_free_netdev;
ifp = netdev_priv(ndev);
ifp->ndev = ndev;
/* store mapping ifidx to bsscfgidx */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
index fe264a5..35919d9 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
@@ -78,6 +78,7 @@ do { \
#define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL)
#define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL)
#define BRCMF_FWCON_ON() (brcmf_msg_level & BRCMF_FWCON_VAL)
+#define BRCMF_SCAN_ON() (brcmf_msg_level & BRCMF_SCAN_VAL)
#else /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */
@@ -96,6 +97,7 @@ do { \
#define BRCMF_EVENT_ON() 0
#define BRCMF_FIL_ON() 0
#define BRCMF_FWCON_ON() 0
+#define BRCMF_SCAN_ON() 0
#endif /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
index 62985f2..d21258d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
@@ -27,6 +27,7 @@
#include "feature.h"
#include "common.h"
+#define BRCMF_FW_UNSUPPORTED 23
/*
* expand feature list to array of feature strings.
@@ -113,6 +114,22 @@ static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp,
}
}
+static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp,
+ enum brcmf_feat_id id, char *name,
+ const void *data, size_t len)
+{
+ int err;
+
+ err = brcmf_fil_iovar_data_set(ifp, name, data, len);
+ if (err != -BRCMF_FW_UNSUPPORTED) {
+ brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
+ ifp->drvr->feat_flags |= BIT(id);
+ } else {
+ brcmf_dbg(TRACE, "%s feature check failed: %d\n",
+ brcmf_feat_names[id], err);
+ }
+}
+
static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp)
{
char caps[256];
@@ -136,11 +153,14 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
{
struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
struct brcmf_pno_macaddr_le pfn_mac;
+ struct brcmf_gscan_config gscan_cfg;
u32 wowl_cap;
s32 err;
brcmf_feat_firmware_capabilities(ifp);
-
+ memset(&gscan_cfg, 0, sizeof(gscan_cfg));
+ brcmf_feat_iovar_data_set(ifp, BRCMF_FEAT_GSCAN, "pfn_gscan_cfg",
+ &gscan_cfg, sizeof(gscan_cfg));
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn");
if (drvr->bus_if->wowl_supported)
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
@@ -175,6 +195,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
drvr->settings->feature_disable);
ifp->drvr->feat_flags &= ~drvr->settings->feature_disable;
}
+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa");
/* set chip related quirks */
switch (drvr->bus_if->chip) {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
index db4733a..1ab4f161 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
@@ -31,6 +31,8 @@
* WOWL_GTK: (WOWL) GTK rekeying offload
* WOWL_ARP_ND: ARP and Neighbor Discovery offload support during WOWL.
* MFP: 802.11w Management Frame Protection.
+ * GSCAN: enhanced scan offload feature.
+ * FWSUP: Firmware supplicant.
*/
#define BRCMF_FEAT_LIST \
BRCMF_FEAT_DEF(MBSS) \
@@ -44,7 +46,9 @@
BRCMF_FEAT_DEF(WOWL_ND) \
BRCMF_FEAT_DEF(WOWL_GTK) \
BRCMF_FEAT_DEF(WOWL_ARP_ND) \
- BRCMF_FEAT_DEF(MFP)
+ BRCMF_FEAT_DEF(MFP) \
+ BRCMF_FEAT_DEF(GSCAN) \
+ BRCMF_FEAT_DEF(FWSUP)
/*
* Quirks:
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
index 5fba4b4..816f80e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
@@ -142,6 +142,16 @@ enum brcmf_fweh_event_code {
#define BRCMF_E_STATUS_CS_ABORT 15
#define BRCMF_E_STATUS_ERROR 16
+/* status field values for PSK_SUP event */
+#define BRCMF_E_STATUS_FWSUP_WAIT_M1 4
+#define BRCMF_E_STATUS_FWSUP_PREP_M2 5
+#define BRCMF_E_STATUS_FWSUP_COMPLETED 6
+#define BRCMF_E_STATUS_FWSUP_TIMEOUT 7
+#define BRCMF_E_STATUS_FWSUP_WAIT_M3 8
+#define BRCMF_E_STATUS_FWSUP_PREP_M4 9
+#define BRCMF_E_STATUS_FWSUP_WAIT_G1 10
+#define BRCMF_E_STATUS_FWSUP_PREP_G2 11
+
/* reason field values in struct brcmf_event_msg */
#define BRCMF_E_REASON_INITIAL_ASSOC 0
#define BRCMF_E_REASON_LOW_RSSI 1
@@ -161,6 +171,26 @@ enum brcmf_fweh_event_code {
#define BRCMF_E_REASON_TDLS_PEER_CONNECTED 1
#define BRCMF_E_REASON_TDLS_PEER_DISCONNECTED 2
+/* reason field values for PSK_SUP event */
+#define BRCMF_E_REASON_FWSUP_OTHER 0
+#define BRCMF_E_REASON_FWSUP_DECRYPT_KEY_DATA 1
+#define BRCMF_E_REASON_FWSUP_BAD_UCAST_WEP128 2
+#define BRCMF_E_REASON_FWSUP_BAD_UCAST_WEP40 3
+#define BRCMF_E_REASON_FWSUP_UNSUP_KEY_LEN 4
+#define BRCMF_E_REASON_FWSUP_PW_KEY_CIPHER 5
+#define BRCMF_E_REASON_FWSUP_MSG3_TOO_MANY_IE 6
+#define BRCMF_E_REASON_FWSUP_MSG3_IE_MISMATCH 7
+#define BRCMF_E_REASON_FWSUP_NO_INSTALL_FLAG 8
+#define BRCMF_E_REASON_FWSUP_MSG3_NO_GTK 9
+#define BRCMF_E_REASON_FWSUP_GRP_KEY_CIPHER 10
+#define BRCMF_E_REASON_FWSUP_GRP_MSG1_NO_GTK 11
+#define BRCMF_E_REASON_FWSUP_GTK_DECRYPT_FAIL 12
+#define BRCMF_E_REASON_FWSUP_SEND_FAIL 13
+#define BRCMF_E_REASON_FWSUP_DEAUTH 14
+#define BRCMF_E_REASON_FWSUP_WPA_PSK_TMO 15
+#define BRCMF_E_REASON_FWSUP_WPA_PSK_M1_TMO 16
+#define BRCMF_E_REASON_FWSUP_WPA_PSK_M3_TMO 17
+
/* action field values for brcmf_ifevent */
#define BRCMF_E_IF_ADD 1
#define BRCMF_E_IF_DEL 2
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
index 3a9a76d..63b1287 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
@@ -85,6 +85,7 @@
#define BRCMF_C_SET_SCAN_PASSIVE_TIME 258
#define BRCMF_C_GET_VAR 262
#define BRCMF_C_SET_VAR 263
+#define BRCMF_C_SET_WSEC_PMK 268
s32 brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len);
s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
index 9a1eb5a..8391989 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -45,6 +45,9 @@
#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff
#define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16
+#define BRCMF_WSEC_MAX_PSK_LEN 32
+#define BRCMF_WSEC_PASSPHRASE BIT(0)
+
/* primary (ie tx) key */
#define BRCMF_PRIMARY_KEY (1 << 1)
#define DOT11_BSSTYPE_ANY 2
@@ -470,6 +473,19 @@ struct brcmf_wsec_key_le {
u8 ea[ETH_ALEN]; /* per station */
};
+/**
+ * struct brcmf_wsec_pmk_le - firmware pmk material.
+ *
+ * @key_len: number of octets in key material.
+ * @flags: key handling qualifiers.
+ * @key: PMK key material.
+ */
+struct brcmf_wsec_pmk_le {
+ __le16 key_len;
+ __le16 flags;
+ u8 key[2 * BRCMF_WSEC_MAX_PSK_LEN + 1];
+};
+
/* Used to get specific STA parameters */
struct brcmf_scb_val_le {
__le32 val;
@@ -806,6 +822,17 @@ struct brcmf_pno_macaddr_le {
};
/**
+ * struct brcmf_pno_bssid_le - bssid configuration for PNO scan.
+ *
+ * @bssid: BSS network identifier.
+ * @flags: flags for this BSSID.
+ */
+struct brcmf_pno_bssid_le {
+ u8 bssid[ETH_ALEN];
+ __le16 flags;
+};
+
+/**
* struct brcmf_pktcnt_le - packet counters.
*
* @rx_good_pkt: packets (MSDUs & MMPDUs) received from this station
@@ -835,4 +862,69 @@ struct brcmf_gtk_keyinfo_le {
u8 replay_counter[BRCMF_RSN_REPLAY_LEN];
};
+#define BRCMF_PNO_REPORT_NO_BATCH BIT(2)
+
+/**
+ * struct brcmf_gscan_bucket_config - configuration data for channel bucket.
+ *
+ * @bucket_end_index: last channel index in @channel_list in
+ * @struct brcmf_pno_config_le.
+ * @bucket_freq_multiple: scan interval expressed in N * @scan_freq.
+ * @flag: channel bucket report flags.
+ * @reserved: for future use.
+ * @repeat: number of scan at interval for exponential scan.
+ * @max_freq_multiple: maximum scan interval for exponential scan.
+ */
+struct brcmf_gscan_bucket_config {
+ u8 bucket_end_index;
+ u8 bucket_freq_multiple;
+ u8 flag;
+ u8 reserved;
+ __le16 repeat;
+ __le16 max_freq_multiple;
+};
+
+/* version supported which must match firmware */
+#define BRCMF_GSCAN_CFG_VERSION 2
+
+/**
+ * enum brcmf_gscan_cfg_flags - bit values for gscan flags.
+ *
+ * @BRCMF_GSCAN_CFG_FLAGS_ALL_RESULTS: send probe responses/beacons to host.
+ * @BRCMF_GSCAN_CFG_ALL_BUCKETS_IN_1ST_SCAN: all buckets will be included in
+ * first scan cycle.
+ * @BRCMF_GSCAN_CFG_FLAGS_CHANGE_ONLY: indicated only flags member is changed.
+ */
+enum brcmf_gscan_cfg_flags {
+ BRCMF_GSCAN_CFG_FLAGS_ALL_RESULTS = BIT(0),
+ BRCMF_GSCAN_CFG_ALL_BUCKETS_IN_1ST_SCAN = BIT(3),
+ BRCMF_GSCAN_CFG_FLAGS_CHANGE_ONLY = BIT(7),
+};
+
+/**
+ * struct brcmf_gscan_config - configuration data for gscan.
+ *
+ * @version: version of the api to match firmware.
+ * @flags: flags according %enum brcmf_gscan_cfg_flags.
+ * @buffer_threshold: percentage threshold of buffer to generate an event.
+ * @swc_nbssid_threshold: number of BSSIDs with significant change that
+ * will generate an event.
+ * @swc_rssi_window_size: size of rssi cache buffer (max=8).
+ * @count_of_channel_buckets: number of array members in @bucket.
+ * @retry_threshold: !unknown!
+ * @lost_ap_window: !unknown!
+ * @bucket: array of channel buckets.
+ */
+struct brcmf_gscan_config {
+ __le16 version;
+ u8 flags;
+ u8 buffer_threshold;
+ u8 swc_nbssid_threshold;
+ u8 swc_rssi_window_size;
+ u8 count_of_channel_buckets;
+ u8 retry_threshold;
+ __le16 lost_ap_window;
+ struct brcmf_gscan_bucket_config bucket[1];
+};
+
#endif /* FWIL_TYPES_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
index aa299c4..2ce675a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -2208,6 +2208,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
err = brcmf_net_attach(ifp, true);
if (err) {
brcmf_err("Registering netdevice failed\n");
+ free_netdev(ifp->ndev);
goto fail;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
index 6c3bde8..ffa243e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
@@ -14,6 +14,7 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/netdevice.h>
+#include <linux/gcd.h>
#include <net/cfg80211.h>
#include "core.h"
@@ -35,6 +36,67 @@
#define BRCMF_PNO_HIDDEN_BIT 2
#define BRCMF_PNO_SCHED_SCAN_PERIOD 30
+#define BRCMF_PNO_MAX_BUCKETS 16
+#define GSCAN_BATCH_NO_THR_SET 101
+#define GSCAN_RETRY_THRESHOLD 3
+
+struct brcmf_pno_info {
+ int n_reqs;
+ struct cfg80211_sched_scan_request *reqs[BRCMF_PNO_MAX_BUCKETS];
+ struct mutex req_lock;
+};
+
+#define ifp_to_pno(_ifp) ((_ifp)->drvr->config->pno)
+
+static int brcmf_pno_store_request(struct brcmf_pno_info *pi,
+ struct cfg80211_sched_scan_request *req)
+{
+ if (WARN(pi->n_reqs == BRCMF_PNO_MAX_BUCKETS,
+ "pno request storage full\n"))
+ return -ENOSPC;
+
+ brcmf_dbg(SCAN, "reqid=%llu\n", req->reqid);
+ mutex_lock(&pi->req_lock);
+ pi->reqs[pi->n_reqs++] = req;
+ mutex_unlock(&pi->req_lock);
+ return 0;
+}
+
+static int brcmf_pno_remove_request(struct brcmf_pno_info *pi, u64 reqid)
+{
+ int i, err = 0;
+
+ mutex_lock(&pi->req_lock);
+
+ /* find request */
+ for (i = 0; i < pi->n_reqs; i++) {
+ if (pi->reqs[i]->reqid == reqid)
+ break;
+ }
+ /* request not found */
+ if (WARN(i == pi->n_reqs, "reqid not found\n")) {
+ err = -ENOENT;
+ goto done;
+ }
+
+ brcmf_dbg(SCAN, "reqid=%llu\n", reqid);
+ pi->n_reqs--;
+
+ /* if last we are done */
+ if (!pi->n_reqs || i == pi->n_reqs)
+ goto done;
+
+ /* fill the gap with remaining requests */
+ while (i <= pi->n_reqs - 1) {
+ pi->reqs[i] = pi->reqs[i + 1];
+ i++;
+ }
+
+done:
+ mutex_unlock(&pi->req_lock);
+ return err;
+}
+
static int brcmf_pno_channel_config(struct brcmf_if *ifp,
struct brcmf_pno_config_le *cfg)
{
@@ -57,16 +119,11 @@ static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq,
/* set extra pno params */
flags = BIT(BRCMF_PNO_IMMEDIATE_SCAN_BIT) |
- BIT(BRCMF_PNO_REPORT_SEPARATELY_BIT) |
BIT(BRCMF_PNO_ENABLE_ADAPTSCAN_BIT);
pfn_param.repeat = BRCMF_PNO_REPEAT;
pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX;
/* set up pno scan fr */
- if (scan_freq < BRCMF_PNO_SCHED_SCAN_MIN_PERIOD) {
- brcmf_dbg(SCAN, "scan period too small, using minimum\n");
- scan_freq = BRCMF_PNO_SCHED_SCAN_MIN_PERIOD;
- }
pfn_param.scan_freq = cpu_to_le32(scan_freq);
if (mscan) {
@@ -101,12 +158,24 @@ exit:
return err;
}
-static int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr,
- u8 *mac_mask)
+static int brcmf_pno_set_random(struct brcmf_if *ifp, struct brcmf_pno_info *pi)
{
struct brcmf_pno_macaddr_le pfn_mac;
+ u8 *mac_addr = NULL;
+ u8 *mac_mask = NULL;
int err, i;
+ for (i = 0; i < pi->n_reqs; i++)
+ if (pi->reqs[i]->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
+ mac_addr = pi->reqs[i]->mac_addr;
+ mac_mask = pi->reqs[i]->mac_addr_mask;
+ break;
+ }
+
+ /* no random mac requested */
+ if (!mac_addr)
+ return 0;
+
pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC;
@@ -120,6 +189,8 @@ static int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr,
/* Set locally administered */
pfn_mac.mac[0] |= 0x02;
+ brcmf_dbg(SCAN, "enabling random mac: reqid=%llu mac=%pM\n",
+ pi->reqs[i]->reqid, pfn_mac.mac);
err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac,
sizeof(pfn_mac));
if (err)
@@ -132,6 +203,7 @@ static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
bool active)
{
struct brcmf_pno_net_param_le pfn;
+ int err;
pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
@@ -142,7 +214,28 @@ static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
pfn.ssid.SSID_len = cpu_to_le32(ssid->ssid_len);
memcpy(pfn.ssid.SSID, ssid->ssid, ssid->ssid_len);
- return brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn));
+
+ brcmf_dbg(SCAN, "adding ssid=%.32s (active=%d)\n", ssid->ssid, active);
+ err = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn));
+ if (err < 0)
+ brcmf_err("adding failed: err=%d\n", err);
+ return err;
+}
+
+static int brcmf_pno_add_bssid(struct brcmf_if *ifp, const u8 *bssid)
+{
+ struct brcmf_pno_bssid_le bssid_cfg;
+ int err;
+
+ memcpy(bssid_cfg.bssid, bssid, ETH_ALEN);
+ bssid_cfg.flags = 0;
+
+ brcmf_dbg(SCAN, "adding bssid=%pM\n", bssid);
+ err = brcmf_fil_iovar_data_set(ifp, "pfn_add_bssid", &bssid_cfg,
+ sizeof(bssid_cfg));
+ if (err < 0)
+ brcmf_err("adding failed: err=%d\n", err);
+ return err;
}
static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid,
@@ -163,7 +256,7 @@ static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid,
return false;
}
-int brcmf_pno_clean(struct brcmf_if *ifp)
+static int brcmf_pno_clean(struct brcmf_if *ifp)
{
int ret;
@@ -179,63 +272,320 @@ int brcmf_pno_clean(struct brcmf_if *ifp)
return ret;
}
-int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
- struct cfg80211_sched_scan_request *req)
+static int brcmf_pno_get_bucket_channels(struct cfg80211_sched_scan_request *r,
+ struct brcmf_pno_config_le *pno_cfg)
{
- struct brcmf_pno_config_le pno_cfg;
- struct cfg80211_ssid *ssid;
+ u32 n_chan = le32_to_cpu(pno_cfg->channel_num);
u16 chan;
- int i, ret;
+ int i, err = 0;
- /* clean up everything */
- ret = brcmf_pno_clean(ifp);
- if (ret < 0) {
- brcmf_err("failed error=%d\n", ret);
- return ret;
+ for (i = 0; i < r->n_channels; i++) {
+ if (n_chan >= BRCMF_NUMCHANNELS) {
+ err = -ENOSPC;
+ goto done;
+ }
+ chan = r->channels[i]->hw_value;
+ brcmf_dbg(SCAN, "[%d] Chan : %u\n", n_chan, chan);
+ pno_cfg->channel_list[n_chan++] = cpu_to_le16(chan);
}
+ /* return number of channels */
+ err = n_chan;
+done:
+ pno_cfg->channel_num = cpu_to_le32(n_chan);
+ return err;
+}
- /* configure pno */
- ret = brcmf_pno_config(ifp, req->scan_plans[0].interval, 0, 0);
- if (ret < 0)
- return ret;
-
- /* configure random mac */
- if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
- ret = brcmf_pno_set_random(ifp, req->mac_addr,
- req->mac_addr_mask);
- if (ret < 0)
- return ret;
+static int brcmf_pno_prep_fwconfig(struct brcmf_pno_info *pi,
+ struct brcmf_pno_config_le *pno_cfg,
+ struct brcmf_gscan_bucket_config **buckets,
+ u32 *scan_freq)
+{
+ struct cfg80211_sched_scan_request *sr;
+ struct brcmf_gscan_bucket_config *fw_buckets;
+ int i, err, chidx;
+
+ brcmf_dbg(SCAN, "n_reqs=%d\n", pi->n_reqs);
+ if (WARN_ON(!pi->n_reqs))
+ return -ENODATA;
+
+ /*
+ * actual scan period is determined using gcd() for each
+ * scheduled scan period.
+ */
+ *scan_freq = pi->reqs[0]->scan_plans[0].interval;
+ for (i = 1; i < pi->n_reqs; i++) {
+ sr = pi->reqs[i];
+ *scan_freq = gcd(sr->scan_plans[0].interval, *scan_freq);
+ }
+ if (*scan_freq < BRCMF_PNO_SCHED_SCAN_MIN_PERIOD) {
+ brcmf_dbg(SCAN, "scan period too small, using minimum\n");
+ *scan_freq = BRCMF_PNO_SCHED_SCAN_MIN_PERIOD;
}
- /* configure channels to use */
- for (i = 0; i < req->n_channels; i++) {
- chan = req->channels[i]->hw_value;
- pno_cfg.channel_list[i] = cpu_to_le16(chan);
+ *buckets = NULL;
+ fw_buckets = kcalloc(pi->n_reqs, sizeof(*fw_buckets), GFP_KERNEL);
+ if (!fw_buckets)
+ return -ENOMEM;
+
+ memset(pno_cfg, 0, sizeof(*pno_cfg));
+ for (i = 0; i < pi->n_reqs; i++) {
+ sr = pi->reqs[i];
+ chidx = brcmf_pno_get_bucket_channels(sr, pno_cfg);
+ if (chidx < 0) {
+ err = chidx;
+ goto fail;
+ }
+ fw_buckets[i].bucket_end_index = chidx - 1;
+ fw_buckets[i].bucket_freq_multiple =
+ sr->scan_plans[0].interval / *scan_freq;
+ /* assure period is non-zero */
+ if (!fw_buckets[i].bucket_freq_multiple)
+ fw_buckets[i].bucket_freq_multiple = 1;
+ fw_buckets[i].flag = BRCMF_PNO_REPORT_NO_BATCH;
}
- if (req->n_channels) {
- pno_cfg.channel_num = cpu_to_le32(req->n_channels);
- brcmf_pno_channel_config(ifp, &pno_cfg);
+
+ if (BRCMF_SCAN_ON()) {
+ brcmf_err("base period=%u\n", *scan_freq);
+ for (i = 0; i < pi->n_reqs; i++) {
+ brcmf_err("[%d] period %u max %u repeat %u flag %x idx %u\n",
+ i, fw_buckets[i].bucket_freq_multiple,
+ le16_to_cpu(fw_buckets[i].max_freq_multiple),
+ fw_buckets[i].repeat, fw_buckets[i].flag,
+ fw_buckets[i].bucket_end_index);
+ }
}
+ *buckets = fw_buckets;
+ return pi->n_reqs;
- /* configure each match set */
- for (i = 0; i < req->n_match_sets; i++) {
- ssid = &req->match_sets[i].ssid;
- if (!ssid->ssid_len) {
- brcmf_err("skip broadcast ssid\n");
- continue;
+fail:
+ kfree(fw_buckets);
+ return err;
+}
+
+static int brcmf_pno_config_networks(struct brcmf_if *ifp,
+ struct brcmf_pno_info *pi)
+{
+ struct cfg80211_sched_scan_request *r;
+ struct cfg80211_match_set *ms;
+ bool active;
+ int i, j, err = 0;
+
+ for (i = 0; i < pi->n_reqs; i++) {
+ r = pi->reqs[i];
+
+ for (j = 0; j < r->n_match_sets; j++) {
+ ms = &r->match_sets[j];
+ if (ms->ssid.ssid_len) {
+ active = brcmf_is_ssid_active(&ms->ssid, r);
+ err = brcmf_pno_add_ssid(ifp, &ms->ssid,
+ active);
+ }
+ if (!err && is_valid_ether_addr(ms->bssid))
+ err = brcmf_pno_add_bssid(ifp, ms->bssid);
+
+ if (err < 0)
+ return err;
}
+ }
+ return 0;
+}
+
+static int brcmf_pno_config_sched_scans(struct brcmf_if *ifp)
+{
+ struct brcmf_pno_info *pi;
+ struct brcmf_gscan_config *gscan_cfg;
+ struct brcmf_gscan_bucket_config *buckets;
+ struct brcmf_pno_config_le pno_cfg;
+ size_t gsz;
+ u32 scan_freq;
+ int err, n_buckets;
+
+ pi = ifp_to_pno(ifp);
+ n_buckets = brcmf_pno_prep_fwconfig(pi, &pno_cfg, &buckets,
+ &scan_freq);
+ if (n_buckets < 0)
+ return n_buckets;
+
+ gsz = sizeof(*gscan_cfg) + (n_buckets - 1) * sizeof(*buckets);
+ gscan_cfg = kzalloc(gsz, GFP_KERNEL);
+ if (!gscan_cfg) {
+ err = -ENOMEM;
+ goto free_buckets;
+ }
- ret = brcmf_pno_add_ssid(ifp, ssid,
- brcmf_is_ssid_active(ssid, req));
- if (ret < 0)
- brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n",
- ret == 0 ? "set" : "failed", ssid->ssid);
+ /* clean up everything */
+ err = brcmf_pno_clean(ifp);
+ if (err < 0) {
+ brcmf_err("failed error=%d\n", err);
+ goto free_gscan;
}
+
+ /* configure pno */
+ err = brcmf_pno_config(ifp, scan_freq, 0, 0);
+ if (err < 0)
+ goto free_gscan;
+
+ err = brcmf_pno_channel_config(ifp, &pno_cfg);
+ if (err < 0)
+ goto clean;
+
+ gscan_cfg->version = cpu_to_le16(BRCMF_GSCAN_CFG_VERSION);
+ gscan_cfg->retry_threshold = GSCAN_RETRY_THRESHOLD;
+ gscan_cfg->buffer_threshold = GSCAN_BATCH_NO_THR_SET;
+ gscan_cfg->flags = BRCMF_GSCAN_CFG_ALL_BUCKETS_IN_1ST_SCAN;
+
+ gscan_cfg->count_of_channel_buckets = n_buckets;
+ memcpy(&gscan_cfg->bucket[0], buckets,
+ n_buckets * sizeof(*buckets));
+
+ err = brcmf_fil_iovar_data_set(ifp, "pfn_gscan_cfg", gscan_cfg, gsz);
+
+ if (err < 0)
+ goto clean;
+
+ /* configure random mac */
+ err = brcmf_pno_set_random(ifp, pi);
+ if (err < 0)
+ goto clean;
+
+ err = brcmf_pno_config_networks(ifp, pi);
+ if (err < 0)
+ goto clean;
+
/* Enable the PNO */
- ret = brcmf_fil_iovar_int_set(ifp, "pfn", 1);
+ err = brcmf_fil_iovar_int_set(ifp, "pfn", 1);
+
+clean:
+ if (err < 0)
+ brcmf_pno_clean(ifp);
+free_gscan:
+ kfree(gscan_cfg);
+free_buckets:
+ kfree(buckets);
+ return err;
+}
+
+int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
+ struct cfg80211_sched_scan_request *req)
+{
+ struct brcmf_pno_info *pi;
+ int ret;
+
+ brcmf_dbg(TRACE, "reqid=%llu\n", req->reqid);
+
+ pi = ifp_to_pno(ifp);
+ ret = brcmf_pno_store_request(pi, req);
if (ret < 0)
- brcmf_err("PNO enable failed!! ret=%d\n", ret);
+ return ret;
- return ret;
+ ret = brcmf_pno_config_sched_scans(ifp);
+ if (ret < 0) {
+ brcmf_pno_remove_request(pi, req->reqid);
+ if (pi->n_reqs)
+ (void)brcmf_pno_config_sched_scans(ifp);
+ return ret;
+ }
+ return 0;
}
+int brcmf_pno_stop_sched_scan(struct brcmf_if *ifp, u64 reqid)
+{
+ struct brcmf_pno_info *pi;
+ int err;
+
+ brcmf_dbg(TRACE, "reqid=%llu\n", reqid);
+
+ pi = ifp_to_pno(ifp);
+ err = brcmf_pno_remove_request(pi, reqid);
+ if (err)
+ return err;
+
+ brcmf_pno_clean(ifp);
+
+ if (pi->n_reqs)
+ (void)brcmf_pno_config_sched_scans(ifp);
+
+ return 0;
+}
+
+int brcmf_pno_attach(struct brcmf_cfg80211_info *cfg)
+{
+ struct brcmf_pno_info *pi;
+
+ brcmf_dbg(TRACE, "enter\n");
+ pi = kzalloc(sizeof(*pi), GFP_KERNEL);
+ if (!pi)
+ return -ENOMEM;
+
+ cfg->pno = pi;
+ mutex_init(&pi->req_lock);
+ return 0;
+}
+
+void brcmf_pno_detach(struct brcmf_cfg80211_info *cfg)
+{
+ struct brcmf_pno_info *pi;
+
+ brcmf_dbg(TRACE, "enter\n");
+ pi = cfg->pno;
+ cfg->pno = NULL;
+
+ WARN_ON(pi->n_reqs);
+ mutex_destroy(&pi->req_lock);
+ kfree(pi);
+}
+
+void brcmf_pno_wiphy_params(struct wiphy *wiphy, bool gscan)
+{
+ /* scheduled scan settings */
+ wiphy->max_sched_scan_reqs = gscan ? BRCMF_PNO_MAX_BUCKETS : 1;
+ wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
+ wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
+ wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
+ wiphy->max_sched_scan_plan_interval = BRCMF_PNO_SCHED_SCAN_MAX_PERIOD;
+}
+
+u64 brcmf_pno_find_reqid_by_bucket(struct brcmf_pno_info *pi, u32 bucket)
+{
+ u64 reqid = 0;
+
+ mutex_lock(&pi->req_lock);
+
+ if (bucket < pi->n_reqs)
+ reqid = pi->reqs[bucket]->reqid;
+
+ mutex_unlock(&pi->req_lock);
+ return reqid;
+}
+
+u32 brcmf_pno_get_bucket_map(struct brcmf_pno_info *pi,
+ struct brcmf_pno_net_info_le *ni)
+{
+ struct cfg80211_sched_scan_request *req;
+ struct cfg80211_match_set *ms;
+ u32 bucket_map = 0;
+ int i, j;
+
+ mutex_lock(&pi->req_lock);
+ for (i = 0; i < pi->n_reqs; i++) {
+ req = pi->reqs[i];
+
+ if (!req->n_match_sets)
+ continue;
+ for (j = 0; j < req->n_match_sets; j++) {
+ ms = &req->match_sets[j];
+ if (ms->ssid.ssid_len == ni->SSID_len &&
+ !memcmp(ms->ssid.ssid, ni->SSID, ni->SSID_len)) {
+ bucket_map |= BIT(i);
+ break;
+ }
+ if (is_valid_ether_addr(ms->bssid) &&
+ !memcmp(ms->bssid, ni->bssid, ETH_ALEN)) {
+ bucket_map |= BIT(i);
+ break;
+ }
+ }
+ }
+ mutex_unlock(&pi->req_lock);
+ return bucket_map;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
index bae55b2..cd9e35a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
@@ -21,12 +21,8 @@
#define BRCMF_PNO_SCHED_SCAN_MIN_PERIOD 10
#define BRCMF_PNO_SCHED_SCAN_MAX_PERIOD 508
-/**
- * brcmf_pno_clean - disable and clear pno in firmware.
- *
- * @ifp: interface object used.
- */
-int brcmf_pno_clean(struct brcmf_if *ifp);
+/* forward declaration */
+struct brcmf_pno_info;
/**
* brcmf_pno_start_sched_scan - initiate scheduled scan on device.
@@ -37,4 +33,51 @@ int brcmf_pno_clean(struct brcmf_if *ifp);
int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
struct cfg80211_sched_scan_request *req);
+/**
+ * brcmf_pno_stop_sched_scan - terminate scheduled scan on device.
+ *
+ * @ifp: interface object used.
+ * @reqid: unique identifier of scan to be stopped.
+ */
+int brcmf_pno_stop_sched_scan(struct brcmf_if *ifp, u64 reqid);
+
+/**
+ * brcmf_pno_wiphy_params - fill scheduled scan parameters in wiphy instance.
+ *
+ * @wiphy: wiphy instance to be used.
+ * @gscan: indicates whether the device has support for g-scan feature.
+ */
+void brcmf_pno_wiphy_params(struct wiphy *wiphy, bool gscan);
+
+/**
+ * brcmf_pno_attach - allocate and attach module information.
+ *
+ * @cfg: cfg80211 context used.
+ */
+int brcmf_pno_attach(struct brcmf_cfg80211_info *cfg);
+
+/**
+ * brcmf_pno_detach - detach and free module information.
+ *
+ * @cfg: cfg80211 context used.
+ */
+void brcmf_pno_detach(struct brcmf_cfg80211_info *cfg);
+
+/**
+ * brcmf_pno_find_reqid_by_bucket - find request id for given bucket index.
+ *
+ * @pi: pno instance used.
+ * @bucket: index of firmware bucket.
+ */
+u64 brcmf_pno_find_reqid_by_bucket(struct brcmf_pno_info *pi, u32 bucket);
+
+/**
+ * brcmf_pno_get_bucket_map - determine bucket map for given netinfo.
+ *
+ * @pi: pno instance used.
+ * @netinfo: netinfo to compare with bucket configuration.
+ */
+u32 brcmf_pno_get_bucket_map(struct brcmf_pno_info *pi,
+ struct brcmf_pno_net_info_le *netinfo);
+
#endif /* _BRCMF_PNO_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 5653d6d..fbcbb43 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -612,7 +612,9 @@ BRCMF_FW_NVRAM_DEF(43340, "brcmfmac43340-sdio.bin", "brcmfmac43340-sdio.txt");
BRCMF_FW_NVRAM_DEF(4335, "brcmfmac4335-sdio.bin", "brcmfmac4335-sdio.txt");
BRCMF_FW_NVRAM_DEF(43362, "brcmfmac43362-sdio.bin", "brcmfmac43362-sdio.txt");
BRCMF_FW_NVRAM_DEF(4339, "brcmfmac4339-sdio.bin", "brcmfmac4339-sdio.txt");
-BRCMF_FW_NVRAM_DEF(43430, "brcmfmac43430-sdio.bin", "brcmfmac43430-sdio.txt");
+BRCMF_FW_NVRAM_DEF(43430A0, "brcmfmac43430a0-sdio.bin", "brcmfmac43430a0-sdio.txt");
+/* Note the names are not postfixed with a1 for backward compatibility */
+BRCMF_FW_NVRAM_DEF(43430A1, "brcmfmac43430-sdio.bin", "brcmfmac43430-sdio.txt");
BRCMF_FW_NVRAM_DEF(43455, "brcmfmac43455-sdio.bin", "brcmfmac43455-sdio.txt");
BRCMF_FW_NVRAM_DEF(4354, "brcmfmac4354-sdio.bin", "brcmfmac4354-sdio.txt");
BRCMF_FW_NVRAM_DEF(4356, "brcmfmac4356-sdio.bin", "brcmfmac4356-sdio.txt");
@@ -630,7 +632,8 @@ static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339),
- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFF, 43430),
+ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43430_CHIP_ID, 0x00000001, 43430A0),
+ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFE, 43430A1),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, 43455),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356)
@@ -2034,6 +2037,7 @@ brcmf_sdio_wait_event_wakeup(struct brcmf_sdio *bus)
static int brcmf_sdio_txpkt_hdalign(struct brcmf_sdio *bus, struct sk_buff *pkt)
{
+ struct brcmf_bus_stats *stats;
u16 head_pad;
u8 *dat_buf;
@@ -2043,16 +2047,18 @@ static int brcmf_sdio_txpkt_hdalign(struct brcmf_sdio *bus, struct sk_buff *pkt)
head_pad = ((unsigned long)dat_buf % bus->head_align);
if (head_pad) {
if (skb_headroom(pkt) < head_pad) {
- bus->sdiodev->bus_if->tx_realloc++;
- head_pad = 0;
- if (skb_cow(pkt, head_pad))
+ stats = &bus->sdiodev->bus_if->stats;
+ atomic_inc(&stats->pktcowed);
+ if (skb_cow_head(pkt, head_pad)) {
+ atomic_inc(&stats->pktcow_failed);
return -ENOMEM;
+ }
}
skb_push(pkt, head_pad);
dat_buf = (u8 *)(pkt->data);
- memset(dat_buf, 0, head_pad + bus->tx_hdrlen);
}
- return head_pad;
+ memset(dat_buf, 0, head_pad + bus->tx_hdrlen);
+ return 0;
}
/**
diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c
index 6a13303..84143a0 100644
--- a/drivers/net/wireless/cisco/airo.c
+++ b/drivers/net/wireless/cisco/airo.c
@@ -3330,7 +3330,7 @@ static void airo_handle_rx(struct airo_info *ai)
}
skb_reserve(skb, 2); /* This way the IP header is aligned */
- buffer = (__le16 *) skb_put(skb, len + hdrlen);
+ buffer = skb_put(skb, len + hdrlen);
if (test_bit(FLAG_802_11, &ai->flags)) {
buffer[0] = fc;
bap_read(ai, buffer + 1, hdrlen - 2, BAP0);
@@ -3734,7 +3734,7 @@ static void mpi_receive_802_11(struct airo_info *ai)
ai->dev->stats.rx_dropped++;
goto badrx;
}
- buffer = (u16*)skb_put (skb, len + hdrlen);
+ buffer = skb_put(skb, len + hdrlen);
memcpy ((char *)buffer, ptr, hdrlen);
ptr += hdrlen;
if (hdrlen == 24)
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
index 5b79e2e..9368abd 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
@@ -10272,8 +10272,9 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct libipw_txb *txb,
printk(KERN_INFO "Adding frag %d %d...\n",
j, size);
- memcpy(skb_put(skb, size),
- txb->fragments[j]->data + hdr_len, size);
+ skb_put_data(skb,
+ txb->fragments[j]->data + hdr_len,
+ size);
}
dev_kfree_skb_any(txb->fragments[i]);
txb->fragments[i] = skb;
@@ -10368,7 +10369,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv,
if (!dst)
continue;
- rt_hdr = (void *)skb_put(dst, sizeof(*rt_hdr));
+ rt_hdr = skb_put(dst, sizeof(*rt_hdr));
rt_hdr->it_version = PKTHDR_RADIOTAP_VERSION;
rt_hdr->it_pad = 0;
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_tx.c b/drivers/net/wireless/intel/ipw2x00/libipw_tx.c
index 048f1e3..84205aa 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_tx.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_tx.c
@@ -359,7 +359,7 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev)
goto failed;
skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);
- memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);
+ skb_put_data(skb_new, &header, hdr_len);
snapped = 1;
libipw_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)),
ether_type);
@@ -439,8 +439,7 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev)
if (rts_required) {
skb_frag = txb->fragments[0];
- frag_hdr =
- (struct libipw_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
+ frag_hdr = skb_put(skb_frag, hdr_len);
/*
* Set header frame_ctl to the RTS.
@@ -470,9 +469,7 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev)
skb_reserve(skb_frag,
crypt->ops->extra_mpdu_prefix_len);
- frag_hdr =
- (struct libipw_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
- memcpy(frag_hdr, &header, hdr_len);
+ frag_hdr = skb_put_data(skb_frag, &header, hdr_len);
/* If this is not the last fragment, then add the MOREFRAGS
* bit to the frame control */
diff --git a/drivers/net/wireless/intel/iwlegacy/3945.c b/drivers/net/wireless/intel/iwlegacy/3945.c
index 080ea81..dbf164d 100644
--- a/drivers/net/wireless/intel/iwlegacy/3945.c
+++ b/drivers/net/wireless/intel/iwlegacy/3945.c
@@ -520,7 +520,7 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
* and do not consume a full page
*/
if (len <= SMALL_PACKET_SIZE) {
- memcpy(skb_put(skb, len), rx_hdr->payload, len);
+ skb_put_data(skb, rx_hdr->payload, len);
} else {
skb_add_rx_frag(skb, 0, rxb->page,
(void *)rx_hdr->payload - (void *)pkt, len,
diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
index 49a2ff1..5b51fba 100644
--- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
@@ -606,7 +606,7 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr,
}
if (len <= SMALL_PACKET_SIZE) {
- memcpy(skb_put(skb, len), hdr, len);
+ skb_put_data(skb, hdr, len);
} else {
skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb),
len, PAGE_SIZE << il->hw_params.rx_page_order);
diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c
index 140b6ea..8d5acda 100644
--- a/drivers/net/wireless/intel/iwlegacy/common.c
+++ b/drivers/net/wireless/intel/iwlegacy/common.c
@@ -5147,6 +5147,8 @@ set_ch_out:
if (changed & (IEEE80211_CONF_CHANGE_PS | IEEE80211_CONF_CHANGE_IDLE)) {
il->power_data.ps_disabled = !(conf->flags & IEEE80211_CONF_PS);
+ if (!il->power_data.ps_disabled)
+ IL_WARN_ONCE("Enabling power save might cause firmware crashes\n");
ret = il_power_update_mode(il, false);
if (ret)
D_MAC80211("Error setting sleep level\n");
diff --git a/drivers/net/wireless/intel/iwlegacy/common.h b/drivers/net/wireless/intel/iwlegacy/common.h
index 3bba521..18c60c9 100644
--- a/drivers/net/wireless/intel/iwlegacy/common.h
+++ b/drivers/net/wireless/intel/iwlegacy/common.h
@@ -45,6 +45,7 @@ struct il_tx_queue;
#define IL_ERR(f, a...) dev_err(&il->pci_dev->dev, f, ## a)
#define IL_WARN(f, a...) dev_warn(&il->pci_dev->dev, f, ## a)
+#define IL_WARN_ONCE(f, a...) dev_warn_once(&il->pci_dev->dev, f, ## a)
#define IL_INFO(f, a...) dev_info(&il->pci_dev->dev, f, ## a)
#define RX_QUEUE_SIZE 256
diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile
index 411cb91..20bd261 100644
--- a/drivers/net/wireless/intel/iwlwifi/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/Makefile
@@ -3,14 +3,14 @@ obj-$(CONFIG_IWLWIFI) += iwlwifi.o
iwlwifi-objs += iwl-io.o
iwlwifi-objs += iwl-drv.o
iwlwifi-objs += iwl-debug.o
-iwlwifi-objs += iwl-notif-wait.o
iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o
iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o
iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
iwlwifi-objs += pcie/ctxt-info.o pcie/trans-gen2.o pcie/tx-gen2.o
-iwlwifi-$(CONFIG_IWLDVM) += iwl-1000.o iwl-2000.o iwl-5000.o iwl-6000.o
-iwlwifi-$(CONFIG_IWLMVM) += iwl-7000.o iwl-8000.o iwl-9000.o iwl-a000.o
+iwlwifi-$(CONFIG_IWLDVM) += cfg/1000.o cfg/2000.o cfg/5000.o cfg/6000.o
+iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o cfg/9000.o cfg/a000.o
iwlwifi-objs += iwl-trans.o
+iwlwifi-objs += fw/notif-wait.o
iwlwifi-objs += $(iwlwifi-m)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-1000.c b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
index b2573b1..b2573b1 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-2000.c b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
index 1b32ad4..1b32ad4 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-2000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-5000.c b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
index 4aa8f0a..4aa8f0a 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-6000.c b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
index 39335b7..39335b7 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c
index 45e2efc..45e2efc 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c
index 8913771..5081720 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c
@@ -70,8 +70,8 @@
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
-#define IWL8000_UCODE_API_MAX 30
-#define IWL8265_UCODE_API_MAX 30
+#define IWL8000_UCODE_API_MAX 33
+#define IWL8265_UCODE_API_MAX 33
/* Lowest firmware API version supported */
#define IWL8000_UCODE_API_MIN 22
@@ -98,7 +98,6 @@
IWL8265_FW_PRE __stringify(api) ".ucode"
#define NVM_HW_SECTION_NUM_FAMILY_8000 10
-#define DEFAULT_NVM_FILE_FAMILY_8000B "nvmData-8000B"
#define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C"
/* Max SDIO RX/TX aggregation sizes of the ADDBA request/response */
@@ -162,10 +161,11 @@ static const struct iwl_tt_params iwl8000_tt_params = {
.dccm2_len = IWL8260_DCCM2_LEN, \
.smem_offset = IWL8260_SMEM_OFFSET, \
.smem_len = IWL8260_SMEM_LEN, \
- .default_nvm_file_B_step = DEFAULT_NVM_FILE_FAMILY_8000B, \
.default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C, \
.thermal_params = &iwl8000_tt_params, \
- .apmg_not_supported = true
+ .apmg_not_supported = true, \
+ .ext_nvm = true, \
+ .dbgc_supported = true
#define IWL_DEVICE_8000 \
IWL_DEVICE_8000_COMMON, \
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
index 110ceef..b4ecd1f 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
@@ -55,7 +55,7 @@
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
-#define IWL9000_UCODE_API_MAX 30
+#define IWL9000_UCODE_API_MAX 33
/* Lowest firmware API version supported */
#define IWL9000_UCODE_API_MIN 30
@@ -73,10 +73,13 @@
#define IWL9000_SMEM_LEN 0x68000
#define IWL9000_FW_PRE "iwlwifi-9000-pu-a0-jf-a0-"
+#define IWL9000RFB_FW_PRE "iwlwifi-9000-pu-a0-jf-b0-"
#define IWL9260A_FW_PRE "iwlwifi-9260-th-a0-jf-a0-"
#define IWL9260B_FW_PRE "iwlwifi-9260-th-b0-jf-b0-"
#define IWL9000_MODULE_FIRMWARE(api) \
IWL9000_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL9000RFB_MODULE_FIRMWARE(api) \
+ IWL9000RFB_FW_PRE "-" __stringify(api) ".ucode"
#define IWL9260A_MODULE_FIRMWARE(api) \
IWL9260A_FW_PRE "-" __stringify(api) ".ucode"
#define IWL9260B_MODULE_FIRMWARE(api) \
@@ -125,7 +128,7 @@ static const struct iwl_tt_params iwl9000_tt_params = {
#define IWL_DEVICE_9000 \
.ucode_api_max = IWL9000_UCODE_API_MAX, \
.ucode_api_min = IWL9000_UCODE_API_MIN, \
- .device_family = IWL_DEVICE_FAMILY_8000, \
+ .device_family = IWL_DEVICE_FAMILY_9000, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.base_params = &iwl9000_base_params, \
@@ -144,7 +147,9 @@ static const struct iwl_tt_params iwl9000_tt_params = {
.mq_rx_supported = true, \
.vht_mu_mimo_supported = true, \
.mac_addr_from_csr = true, \
- .rf_id = true
+ .rf_id = true, \
+ .ext_nvm = true, \
+ .dbgc_supported = true
const struct iwl_cfg iwl9160_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 9160",
@@ -182,6 +187,7 @@ const struct iwl_cfg iwl9270_2ac_cfg = {
const struct iwl_cfg iwl9460_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 9460",
.fw_name_pre = IWL9000_FW_PRE,
+ .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
IWL_DEVICE_9000,
.ht_params = &iwl9000_ht_params,
.nvm_ver = IWL9000_NVM_VERSION,
@@ -193,6 +199,7 @@ const struct iwl_cfg iwl9460_2ac_cfg = {
const struct iwl_cfg iwl9560_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 9560",
.fw_name_pre = IWL9000_FW_PRE,
+ .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE,
IWL_DEVICE_9000,
.ht_params = &iwl9000_ht_params,
.nvm_ver = IWL9000_NVM_VERSION,
@@ -202,5 +209,6 @@ const struct iwl_cfg iwl9560_2ac_cfg = {
};
MODULE_FIRMWARE(IWL9000_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL9000RFB_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL9260A_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL9260B_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-a000.c b/drivers/net/wireless/intel/iwlwifi/cfg/a000.c
index c648cfb..98f24cd 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-a000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/a000.c
@@ -55,7 +55,7 @@
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
-#define IWL_A000_UCODE_API_MAX 30
+#define IWL_A000_UCODE_API_MAX 33
/* Lowest firmware API version supported */
#define IWL_A000_UCODE_API_MIN 24
@@ -74,7 +74,7 @@
#define IWL_A000_JF_FW_PRE "iwlwifi-Qu-a0-jf-b0-"
#define IWL_A000_HR_FW_PRE "iwlwifi-Qu-a0-hr-a0-"
-#define IWL_A000_HR_CDB_FW_PRE "iwlwifi-QuIcp-a0-hrcdb-a0-"
+#define IWL_A000_HR_CDB_FW_PRE "iwlwifi-QuIcp-z0-hrcdb-a0-"
#define IWL_A000_HR_MODULE_FIRMWARE(api) \
IWL_A000_HR_FW_PRE "-" __stringify(api) ".ucode"
@@ -103,7 +103,7 @@ static const struct iwl_ht_params iwl_a000_ht_params = {
#define IWL_DEVICE_A000 \
.ucode_api_max = IWL_A000_UCODE_API_MAX, \
.ucode_api_min = IWL_A000_UCODE_API_MIN, \
- .device_family = IWL_DEVICE_FAMILY_8000, \
+ .device_family = IWL_DEVICE_FAMILY_A000, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.base_params = &iwl_a000_base_params, \
@@ -123,7 +123,9 @@ static const struct iwl_ht_params iwl_a000_ht_params = {
.mac_addr_from_csr = true, \
.use_tfh = true, \
.rf_id = true, \
- .gen2 = true
+ .gen2 = true, \
+ .ext_nvm = true, \
+ .dbgc_supported = true
const struct iwl_cfg iwla000_2ac_cfg_hr = {
.name = "Intel(R) Dual Band Wireless AC a000",
@@ -156,5 +158,15 @@ const struct iwl_cfg iwla000_2ac_cfg_jf = {
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
};
+const struct iwl_cfg iwla000_2ax_cfg_hr = {
+ .name = "Intel(R) Dual Band Wireless AX a000",
+ .fw_name_pre = IWL_A000_HR_FW_PRE,
+ IWL_DEVICE_A000,
+ .ht_params = &iwl_a000_ht_params,
+ .nvm_ver = IWL_A000_NVM_VERSION,
+ .nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
+ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
+};
+
MODULE_FIRMWARE(IWL_A000_HR_MODULE_FIRMWARE(IWL_A000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_A000_JF_MODULE_FIRMWARE(IWL_A000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c
index 376c793..482ac8f 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c
@@ -681,11 +681,10 @@ DEBUGFS_READ_FILE_OPS(temperature);
DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
DEBUGFS_READ_FILE_OPS(current_sleep_command);
-static const char *fmt_value = " %-30s %10u\n";
-static const char *fmt_hex = " %-30s 0x%02X\n";
-static const char *fmt_table = " %-30s %10u %10u %10u %10u\n";
-static const char *fmt_header =
- "%-32s current cumulative delta max\n";
+#define fmt_value " %-30s %10u\n"
+#define fmt_hex " %-30s 0x%02X\n"
+#define fmt_table " %-30s %10u %10u %10u %10u\n"
+#define fmt_header "%-32s current cumulative delta max\n"
static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
{
@@ -2309,10 +2308,10 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
- bool restart_fw = iwlwifi_mod_params.restart_fw;
+ bool fw_restart = iwlwifi_mod_params.fw_restart;
int __maybe_unused ret;
- iwlwifi_mod_params.restart_fw = true;
+ iwlwifi_mod_params.fw_restart = true;
mutex_lock(&priv->mutex);
@@ -2321,7 +2320,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
mutex_unlock(&priv->mutex);
- iwlwifi_mod_params.restart_fw = restart_fw;
+ iwlwifi_mod_params.fw_restart = fw_restart;
return count;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h
index 8148df6..cceb4cd 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h
@@ -38,13 +38,13 @@
#include <linux/slab.h>
#include <linux/mutex.h>
-#include "iwl-fw.h"
+#include "fw/img.h"
#include "iwl-eeprom-parse.h"
#include "iwl-csr.h"
#include "iwl-debug.h"
#include "iwl-agn-hw.h"
#include "iwl-op-mode.h"
-#include "iwl-notif-wait.h"
+#include "fw/notif-wait.h"
#include "iwl-trans.h"
#include "led.h"
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c
index 74e52f7..2b6ffbc 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c
@@ -1157,7 +1157,7 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan)
if (ret)
goto out;
- if (!iwlwifi_mod_params.sw_crypto) {
+ if (!iwlwifi_mod_params.swcrypto) {
/* mark all keys clear */
priv->ucode_key_table = 0;
ctx->key_mapping_keys = 0;
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
index 444c743..82caae0 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
@@ -138,7 +138,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
* packets, so enabling it with software crypto isn't safe)
*/
if (priv->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_MFP &&
- !iwlwifi_mod_params.sw_crypto)
+ !iwlwifi_mod_params.swcrypto)
ieee80211_hw_set(hw, MFP_CAPABLE);
hw->sta_data_size = sizeof(struct iwl_station_priv);
@@ -171,7 +171,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
WIPHY_WOWLAN_DISCONNECT |
WIPHY_WOWLAN_EAP_IDENTITY_REQ |
WIPHY_WOWLAN_RFKILL_RELEASE;
- if (!iwlwifi_mod_params.sw_crypto)
+ if (!iwlwifi_mod_params.swcrypto)
priv->wowlan_support.flags |=
WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
WIPHY_WOWLAN_GTK_REKEY_FAILURE;
@@ -348,7 +348,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
- if (iwlwifi_mod_params.sw_crypto)
+ if (iwlwifi_mod_params.swcrypto)
return;
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -624,7 +624,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
IWL_DEBUG_MAC80211(priv, "enter\n");
- if (iwlwifi_mod_params.sw_crypto) {
+ if (iwlwifi_mod_params.swcrypto) {
IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
return -EOPNOTSUPP;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c
index b498486..2acd94d 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c
@@ -1371,7 +1371,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
/* is antenna coupling more than 35dB ? */
priv->bt_ant_couple_ok =
- (iwlwifi_mod_params.ant_coupling >
+ (iwlwifi_mod_params.antenna_coupling >
IWL_BT_ANTENNA_COUPLING_THRESHOLD) ?
true : false;
@@ -1513,7 +1513,7 @@ out_destroy_workqueue:
out_free_eeprom_blob:
kfree(priv->eeprom_blob);
out_free_eeprom:
- iwl_free_nvm_data(priv->nvm_data);
+ kfree(priv->nvm_data);
out_free_hw:
ieee80211_free_hw(priv->hw);
out:
@@ -1532,7 +1532,7 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
iwl_tt_exit(priv);
kfree(priv->eeprom_blob);
- iwl_free_nvm_data(priv->nvm_data);
+ kfree(priv->nvm_data);
/*netif_stop_queue(dev); */
flush_workqueue(priv->workqueue);
@@ -1958,7 +1958,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
}
if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
- if (iwlwifi_mod_params.restart_fw) {
+ if (iwlwifi_mod_params.fw_restart) {
IWL_DEBUG_FW_ERRORS(priv,
"Restarting adapter due to uCode error.\n");
queue_work(priv->workqueue, &priv->restart);
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c
index adfd630..c942830 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c
@@ -639,7 +639,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
}
/* In case of HW accelerated crypto and bad decryption, drop */
- if (!iwlwifi_mod_params.sw_crypto &&
+ if (!iwlwifi_mod_params.swcrypto &&
iwlagn_set_decrypted_flag(priv, hdr, ampdu_status, stats))
return;
@@ -657,7 +657,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
*/
hdrlen = (len <= skb_tailroom(skb)) ? len : sizeof(*hdr);
- memcpy(skb_put(skb, hdrlen), hdr, hdrlen);
+ skb_put_data(skb, hdr, hdrlen);
fraglen = len - hdrlen;
if (fraglen) {
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c b/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c
index 087e579..8f3e558 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c
@@ -1120,7 +1120,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
return 0;
}
- iwl_set_rxon_hwcrypto(priv, ctx, !iwlwifi_mod_params.sw_crypto);
+ iwl_set_rxon_hwcrypto(priv, ctx, !iwlwifi_mod_params.swcrypto);
IWL_DEBUG_INFO(priv,
"Going to commit RXON\n"
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
index 4b97371..adaa2f0 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
@@ -319,8 +319,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
if (noa_data &&
pskb_expand_head(skb, 0, noa_data->length,
GFP_ATOMIC) == 0) {
- memcpy(skb_put(skb, noa_data->length),
- noa_data->data, noa_data->length);
+ skb_put_data(skb, noa_data->data, noa_data->length);
hdr = (struct ieee80211_hdr *)skb->data;
}
}
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api.h b/drivers/net/wireless/intel/iwlwifi/fw/api.h
new file mode 100644
index 0000000..0e107f9
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api.h
@@ -0,0 +1,229 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <linuxwifi@intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifndef __iwl_fw_api_h__
+#define __iwl_fw_api_h__
+
+/**
+ * DOC: Host command section
+ *
+ * A host command is a command issued by the upper layer to the fw. There are
+ * several versions of fw that have several APIs. The transport layer is
+ * completely agnostic to these differences.
+ * The transport does provide helper functionality (i.e. SYNC / ASYNC mode),
+ */
+#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f)
+#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
+#define SEQ_TO_INDEX(s) ((s) & 0xff)
+#define INDEX_TO_SEQ(i) ((i) & 0xff)
+#define SEQ_RX_FRAME cpu_to_le16(0x8000)
+
+/*
+ * those functions retrieve specific information from
+ * the id field in the iwl_host_cmd struct which contains
+ * the command id, the group id and the version of the command
+ * and vice versa
+*/
+static inline u8 iwl_cmd_opcode(u32 cmdid)
+{
+ return cmdid & 0xFF;
+}
+
+static inline u8 iwl_cmd_groupid(u32 cmdid)
+{
+ return ((cmdid & 0xFF00) >> 8);
+}
+
+static inline u8 iwl_cmd_version(u32 cmdid)
+{
+ return ((cmdid & 0xFF0000) >> 16);
+}
+
+static inline u32 iwl_cmd_id(u8 opcode, u8 groupid, u8 version)
+{
+ return opcode + (groupid << 8) + (version << 16);
+}
+
+/* make u16 wide id out of u8 group and opcode */
+#define WIDE_ID(grp, opcode) (((grp) << 8) | (opcode))
+#define DEF_ID(opcode) ((1 << 8) | (opcode))
+
+/* due to the conversion, this group is special; new groups
+ * should be defined in the appropriate fw-api header files
+ */
+#define IWL_ALWAYS_LONG_GROUP 1
+
+/**
+ * struct iwl_cmd_header
+ *
+ * This header format appears in the beginning of each command sent from the
+ * driver, and each response/notification received from uCode.
+ */
+struct iwl_cmd_header {
+ u8 cmd; /* Command ID: REPLY_RXON, etc. */
+ u8 group_id;
+ /*
+ * The driver sets up the sequence number to values of its choosing.
+ * uCode does not use this value, but passes it back to the driver
+ * when sending the response to each driver-originated command, so
+ * the driver can match the response to the command. Since the values
+ * don't get used by uCode, the driver may set up an arbitrary format.
+ *
+ * There is one exception: uCode sets bit 15 when it originates
+ * the response/notification, i.e. when the response/notification
+ * is not a direct response to a command sent by the driver. For
+ * example, uCode issues REPLY_RX when it sends a received frame
+ * to the driver; it is not a direct response to any driver command.
+ *
+ * The Linux driver uses the following format:
+ *
+ * 0:7 tfd index - position within TX queue
+ * 8:12 TX queue id
+ * 13:14 reserved
+ * 15 unsolicited RX or uCode-originated notification
+ */
+ __le16 sequence;
+} __packed;
+
+/**
+ * struct iwl_cmd_header_wide
+ *
+ * This header format appears in the beginning of each command sent from the
+ * driver, and each response/notification received from uCode.
+ * this is the wide version that contains more information about the command
+ * like length, version and command type
+ */
+struct iwl_cmd_header_wide {
+ u8 cmd;
+ u8 group_id;
+ __le16 sequence;
+ __le16 length;
+ u8 reserved;
+ u8 version;
+} __packed;
+
+/**
+ * iwl_tx_queue_cfg_actions - TXQ config options
+ * @TX_QUEUE_CFG_ENABLE_QUEUE: enable a queue
+ * @TX_QUEUE_CFG_TFD_SHORT_FORMAT: use short TFD format
+ */
+enum iwl_tx_queue_cfg_actions {
+ TX_QUEUE_CFG_ENABLE_QUEUE = BIT(0),
+ TX_QUEUE_CFG_TFD_SHORT_FORMAT = BIT(1),
+};
+
+/**
+ * struct iwl_tx_queue_cfg_cmd - txq hw scheduler config command
+ * @sta_id: station id
+ * @tid: tid of the queue
+ * @flags: see &enum iwl_tx_queue_cfg_actions
+ * @cb_size: size of TFD cyclic buffer. Value is exponent - 3.
+ * Minimum value 0 (8 TFDs), maximum value 5 (256 TFDs)
+ * @byte_cnt_addr: address of byte count table
+ * @tfdq_addr: address of TFD circular buffer
+ */
+struct iwl_tx_queue_cfg_cmd {
+ u8 sta_id;
+ u8 tid;
+ __le16 flags;
+ __le32 cb_size;
+ __le64 byte_cnt_addr;
+ __le64 tfdq_addr;
+} __packed; /* TX_QUEUE_CFG_CMD_API_S_VER_2 */
+
+/**
+ * struct iwl_tx_queue_cfg_rsp - response to txq hw scheduler config
+ * @queue_number: queue number assigned to this RA -TID
+ * @flags: set on failure
+ * @write_pointer: initial value for write pointer
+ */
+struct iwl_tx_queue_cfg_rsp {
+ __le16 queue_number;
+ __le16 flags;
+ __le16 write_pointer;
+ __le16 reserved;
+} __packed; /* TX_QUEUE_CFG_RSP_API_S_VER_2 */
+
+/**
+ * struct iwl_calib_res_notif_phy_db - Receive phy db chunk after calibrations
+ * @type: type of the result - mostly ignored
+ * @length: length of the data
+ * @data: data, length in @length
+ */
+struct iwl_calib_res_notif_phy_db {
+ __le16 type;
+ __le16 length;
+ u8 data[];
+} __packed;
+
+/**
+ * struct iwl_phy_db_cmd - configure operational ucode
+ * @type: type of the data
+ * @length: length of the data
+ * @data: data, length in @length
+ */
+struct iwl_phy_db_cmd {
+ __le16 type;
+ __le16 length;
+ u8 data[];
+} __packed;
+
+#endif /* __iwl_fw_api_h__*/
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
index 420c31d..cfebde6 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
@@ -116,7 +116,7 @@ enum iwl_fw_error_dump_type {
/**
* struct iwl_fw_error_dump_data - data for one type
- * @type: %enum iwl_fw_error_dump_type
+ * @type: &enum iwl_fw_error_dump_type
* @len: the length starting from %data
* @data: the data itself
*/
@@ -130,7 +130,7 @@ struct iwl_fw_error_dump_data {
* struct iwl_fw_error_dump_file - the layout of the header of the file
* @barker: must be %IWL_FW_ERROR_DUMP_BARKER
* @file_len: the length of all the file starting from %barker
- * @data: array of %struct iwl_fw_error_dump_data
+ * @data: array of &struct iwl_fw_error_dump_data
*/
struct iwl_fw_error_dump_file {
__le32 barker;
@@ -225,7 +225,7 @@ enum iwl_fw_error_dump_mem_type {
/**
* struct iwl_fw_error_dump_mem - chunk of memory
- * @type: %enum iwl_fw_error_dump_mem_type
+ * @type: &enum iwl_fw_error_dump_mem_type
* @offset: the offset from which the memory was read
* @data: the content of the memory
*/
@@ -324,7 +324,7 @@ enum iwl_fw_dbg_trigger {
/**
* struct iwl_fw_error_dump_trigger_desc - describes the trigger condition
- * @type: %enum iwl_fw_dbg_trigger
+ * @type: &enum iwl_fw_dbg_trigger
* @data: raw data about what happened
*/
struct iwl_fw_error_dump_trigger_desc {
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h
index 44419e8..0fa8c47 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
@@ -244,10 +244,13 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
* @IWL_UCODE_TLV_API_TKIP_MIC_KEYS: This ucode supports version 2 of
* ADD_MODIFY_STA_KEY_API_S_VER_2.
* @IWL_UCODE_TLV_API_STA_TYPE: This ucode supports station type assignement.
+ * @IWL_UCODE_TLV_API_NAN2_VER2: This ucode supports NAN API version 2
+ * @IWL_UCODE_TLV_API_NEW_RX_STATS: should new RX STATISTICS API be used
*
* @NUM_IWL_UCODE_TLV_API: number of bits used
*/
enum iwl_ucode_tlv_api {
+ /* API Set 0 */
IWL_UCODE_TLV_API_FRAGMENTED_SCAN = (__force iwl_ucode_tlv_api_t)8,
IWL_UCODE_TLV_API_WIFI_MCC_UPDATE = (__force iwl_ucode_tlv_api_t)9,
IWL_UCODE_TLV_API_LQ_SS_PARAMS = (__force iwl_ucode_tlv_api_t)18,
@@ -255,6 +258,9 @@ enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_SCAN_TSF_REPORT = (__force iwl_ucode_tlv_api_t)28,
IWL_UCODE_TLV_API_TKIP_MIC_KEYS = (__force iwl_ucode_tlv_api_t)29,
IWL_UCODE_TLV_API_STA_TYPE = (__force iwl_ucode_tlv_api_t)30,
+ IWL_UCODE_TLV_API_NAN2_VER2 = (__force iwl_ucode_tlv_api_t)31,
+ /* API Set 1 */
+ IWL_UCODE_TLV_API_NEW_RX_STATS = (__force iwl_ucode_tlv_api_t)35,
NUM_IWL_UCODE_TLV_API
#ifdef __CHECKER__
@@ -351,6 +357,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38,
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)39,
IWL_UCODE_TLV_CAPA_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)40,
+ IWL_UCODE_TLV_CAPA_D0I3_END_FIRST = (__force iwl_ucode_tlv_capa_t)41,
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65,
IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67,
@@ -395,8 +402,8 @@ enum iwl_ucode_tlv_capa {
#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8)
#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF)
-/*
- * Calibration control struct.
+/**
+ * struct iwl_tlv_calib_ctrl - Calibration control struct.
* Sent as part of the phy configuration command.
* @flow_trigger: bitmap for which calibrations to perform according to
* flow triggers.
@@ -468,7 +475,7 @@ enum iwl_fw_dbg_reg_operator {
/**
* struct iwl_fw_dbg_reg_op - an operation on a register
*
- * @op: %enum iwl_fw_dbg_reg_operator
+ * @op: &enum iwl_fw_dbg_reg_operator
* @addr: offset of the register
* @val: value
*/
@@ -526,7 +533,7 @@ struct iwl_fw_dbg_mem_seg_tlv {
* struct iwl_fw_dbg_dest_tlv - configures the destination of the debug data
*
* @version: version of the TLV - currently 0
- * @monitor_mode: %enum iwl_fw_dbg_monitor_mode
+ * @monitor_mode: &enum iwl_fw_dbg_monitor_mode
* @size_power: buffer size will be 2^(size_power + 11)
* @base_reg: addr of the base addr register (PRPH)
* @end_reg: addr of the end addr register (PRPH)
@@ -595,15 +602,15 @@ enum iwl_fw_dbg_trigger_vif_type {
/**
* struct iwl_fw_dbg_trigger_tlv - a TLV that describes the trigger
- * @id: %enum iwl_fw_dbg_trigger
- * @vif_type: %enum iwl_fw_dbg_trigger_vif_type
+ * @id: &enum iwl_fw_dbg_trigger
+ * @vif_type: &enum iwl_fw_dbg_trigger_vif_type
* @stop_conf_ids: bitmap of configurations this trigger relates to.
* if the mode is %IWL_FW_DBG_TRIGGER_STOP, then if the bit corresponding
* to the currently running configuration is set, the data should be
* collected.
* @stop_delay: how many milliseconds to wait before collecting the data
* after the STOP trigger fires.
- * @mode: %enum iwl_fw_dbg_trigger_mode - can be stop / start of both
+ * @mode: &enum iwl_fw_dbg_trigger_mode - can be stop / start of both
* @start_conf_id: if mode is %IWL_FW_DBG_TRIGGER_START, this defines what
* configuration should be applied when the triggers kicks in.
* @occurrences: number of occurrences. 0 means the trigger will never fire.
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h
index d323b70..e6bc9cb 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h
@@ -64,12 +64,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
-#ifndef __iwl_fw_h__
-#define __iwl_fw_h__
+#ifndef __iwl_fw_img_h__
+#define __iwl_fw_img_h__
#include <linux/types.h>
-#include "iwl-fw-file.h"
-#include "iwl-fw-error-dump.h"
+#include "file.h"
+#include "error-dump.h"
/**
* enum iwl_ucode_type
@@ -339,4 +339,4 @@ iwl_get_ucode_image(const struct iwl_fw *fw, enum iwl_ucode_type ucode_type)
return &fw->img[ucode_type];
}
-#endif /* __iwl_fw_h__ */
+#endif /* __iwl_fw_img_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-notif-wait.c b/drivers/net/wireless/intel/iwlwifi/fw/notif-wait.c
index 68412ff..29bb92e 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-notif-wait.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/notif-wait.c
@@ -65,7 +65,7 @@
#include <linux/export.h>
#include "iwl-drv.h"
-#include "iwl-notif-wait.h"
+#include "notif-wait.h"
void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_wait)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-notif-wait.h b/drivers/net/wireless/intel/iwlwifi/fw/notif-wait.h
index 368884b..368884b 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-notif-wait.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/notif-wait.h
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index a12197e..c52623c 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -88,6 +88,8 @@ enum iwl_device_family {
IWL_DEVICE_FAMILY_6150,
IWL_DEVICE_FAMILY_7000,
IWL_DEVICE_FAMILY_8000,
+ IWL_DEVICE_FAMILY_9000,
+ IWL_DEVICE_FAMILY_A000,
};
/*
@@ -129,6 +131,7 @@ enum iwl_led_mode {
/* Antenna presence definitions */
#define ANT_NONE 0x0
+#define ANT_INVALID 0xff
#define ANT_A BIT(0)
#define ANT_B BIT(1)
#define ANT_C BIT(2)
@@ -275,6 +278,8 @@ struct iwl_pwr_tx_backoff {
* filename is constructed as fw_name_pre<api>.ucode.
* @fw_name_pre_next_step: same as @fw_name_pre, only for next step
* (if supported)
+ * @fw_name_pre_rf_next_step: same as @fw_name_pre_next_step, only for rf next
+ * step. Supported only in integrated solutions.
* @ucode_api_max: Highest version of uCode API supported by driver.
* @ucode_api_min: Lowest version of uCode API supported by driver.
* @max_inst_size: The maximal length of the fw inst section
@@ -315,6 +320,7 @@ struct iwl_pwr_tx_backoff {
* @integrated: discrete or integrated
* @gen2: a000 and on transport operation
* @cdb: CDB support
+ * @ext_nvm: extended NVM format
*
* We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs
@@ -325,13 +331,13 @@ struct iwl_cfg {
const char *name;
const char *fw_name_pre;
const char *fw_name_pre_next_step;
+ const char *fw_name_pre_rf_next_step;
/* params not likely to change within a device family */
const struct iwl_base_params *base_params;
/* params likely to change within a device family */
const struct iwl_ht_params *ht_params;
const struct iwl_eeprom_params *eeprom_params;
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
- const char *default_nvm_file_B_step;
const char *default_nvm_file_C_step;
const struct iwl_tt_params *thermal_params;
enum iwl_device_family device_family;
@@ -362,7 +368,9 @@ struct iwl_cfg {
integrated:1,
use_tfh:1,
gen2:1,
- cdb:1;
+ cdb:1,
+ ext_nvm:1,
+ dbgc_supported:1;
u8 valid_tx_ant;
u8 valid_rx_ant;
u8 non_shared_ant;
@@ -454,6 +462,7 @@ extern const struct iwl_cfg iwl9560_2ac_cfg;
extern const struct iwl_cfg iwla000_2ac_cfg_hr;
extern const struct iwl_cfg iwla000_2ac_cfg_hr_cdb;
extern const struct iwl_cfg iwla000_2ac_cfg_jf;
+extern const struct iwl_cfg iwla000_2ax_cfg_hr;
#endif /* CONFIG_IWLMVM */
#endif /* __IWL_CONFIG_H__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
index fa120fb..c6c1876 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
@@ -153,6 +153,10 @@
/* GIO Chicken Bits (PCI Express bus link power management) */
#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
+/* host chicken bits */
+#define CSR_HOST_CHICKEN (CSR_BASE + 0x204)
+#define CSR_HOST_CHICKEN_PM_IDLE_SRC_DIS_SB_PME BIT(19)
+
/* Analog phase-lock-loop configuration */
#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c)
@@ -308,7 +312,7 @@
#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001)
#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000)
-#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000)
+#define CSR_GP_CNTRL_REG_FLAG_RFKILL_WAKE_L1A_EN (0x04000000)
#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000)
@@ -316,6 +320,11 @@
#define CSR_HW_REV_DASH(_val) (((_val) & 0x0000003) >> 0)
#define CSR_HW_REV_STEP(_val) (((_val) & 0x000000C) >> 2)
+/* HW RFID */
+#define CSR_HW_RFID_FLAVOR(_val) (((_val) & 0x000000F) >> 0)
+#define CSR_HW_RFID_DASH(_val) (((_val) & 0x00000F0) >> 4)
+#define CSR_HW_RFID_STEP(_val) (((_val) & 0x0000F00) >> 8)
+#define CSR_HW_RFID_TYPE(_val) (((_val) & 0x0FFF000) >> 12)
/**
* hw_rev values
@@ -348,7 +357,8 @@ enum {
/* RF_ID value */
#define CSR_HW_RF_ID_TYPE_JF (0x00105000)
-#define CSR_HW_RF_ID_TYPE_HR (0x00109000)
+#define CSR_HW_RF_ID_TYPE_HR (0x0010A000)
+#define CSR_HW_RF_ID_TYPE_HRCDB (0x00109000)
/* EEPROM REG */
#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h
index d80312b..a80e420 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h
@@ -35,19 +35,20 @@
TRACE_EVENT(iwlwifi_dev_tx_data,
TP_PROTO(const struct device *dev,
- struct sk_buff *skb,
- u8 hdr_len, size_t data_len),
- TP_ARGS(dev, skb, hdr_len, data_len),
+ struct sk_buff *skb, u8 hdr_len),
+ TP_ARGS(dev, skb, hdr_len),
TP_STRUCT__entry(
DEV_ENTRY
- __dynamic_array(u8, data, iwl_trace_data(skb) ? data_len : 0)
+ __dynamic_array(u8, data,
+ iwl_trace_data(skb) ? skb->len - hdr_len : 0)
),
TP_fast_assign(
DEV_ASSIGN;
if (iwl_trace_data(skb))
skb_copy_bits(skb, hdr_len,
- __get_dynamic_array(data), data_len);
+ __get_dynamic_array(data),
+ skb->len - hdr_len);
),
TP_printk("[%s] TX frame data", __get_str(dev))
);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h
index 1dccae6..4164dc1 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016-2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -29,6 +29,7 @@
#define __IWLWIFI_DEVICE_TRACE_IO
#include <linux/tracepoint.h>
+#include <linux/pci.h>
#undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi_io
@@ -165,6 +166,29 @@ TRACE_EVENT(iwlwifi_dev_irq,
TP_printk("%d", 0)
);
+TRACE_EVENT(iwlwifi_dev_irq_msix,
+ TP_PROTO(const struct device *dev, struct msix_entry *msix_entry,
+ bool defirq, u32 inta_fh, u32 inta_hw),
+ TP_ARGS(dev, msix_entry, defirq, inta_fh, inta_hw),
+ TP_STRUCT__entry(
+ DEV_ENTRY
+ __field(u32, entry)
+ __field(u8, defirq)
+ __field(u32, inta_fh)
+ __field(u32, inta_hw)
+ ),
+ TP_fast_assign(
+ DEV_ASSIGN;
+ __entry->entry = msix_entry->entry;
+ __entry->defirq = defirq;
+ __entry->inta_fh = inta_fh;
+ __entry->inta_hw = inta_hw;
+ ),
+ TP_printk("entry:%d defirq:%d fh:0x%x, hw:0x%x",
+ __entry->entry, __entry->defirq,
+ __entry->inta_fh, __entry->inta_hw)
+);
+
TRACE_EVENT(iwlwifi_dev_ict_read,
TP_PROTO(const struct device *dev, u32 index, u32 value),
TP_ARGS(dev, index, value),
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h
index f02e2c8..7f16dcc 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h
@@ -2,7 +2,7 @@
*
* Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -91,8 +91,8 @@ TRACE_EVENT(iwlwifi_dev_tx,
TP_PROTO(const struct device *dev, struct sk_buff *skb,
void *tfd, size_t tfdlen,
void *buf0, size_t buf0_len,
- void *buf1, size_t buf1_len),
- TP_ARGS(dev, skb, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
+ int hdr_len),
+ TP_ARGS(dev, skb, tfd, tfdlen, buf0, buf0_len, hdr_len),
TP_STRUCT__entry(
DEV_ENTRY
@@ -105,15 +105,20 @@ TRACE_EVENT(iwlwifi_dev_tx,
* for the possible padding).
*/
__dynamic_array(u8, buf0, buf0_len)
- __dynamic_array(u8, buf1, iwl_trace_data(skb) ? 0 : buf1_len)
+ __dynamic_array(u8, buf1, hdr_len > 0 && iwl_trace_data(skb) ?
+ 0 : skb->len - hdr_len)
),
TP_fast_assign(
DEV_ASSIGN;
- __entry->framelen = buf0_len + buf1_len;
+ __entry->framelen = buf0_len;
+ if (hdr_len > 0)
+ __entry->framelen += skb->len - hdr_len;
memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
- if (!iwl_trace_data(skb))
- memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
+ if (hdr_len > 0 && !iwl_trace_data(skb))
+ skb_copy_bits(skb, hdr_len,
+ __get_dynamic_array(buf1),
+ skb->len - hdr_len);
),
TP_printk("[%s] TX %.2x (%zu bytes)",
__get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0],
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 5cfacb0..6fdb592 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -76,7 +76,7 @@
#include "iwl-trans.h"
#include "iwl-op-mode.h"
#include "iwl-agn-hw.h"
-#include "iwl-fw.h"
+#include "fw/img.h"
#include "iwl-config.h"
#include "iwl-modparams.h"
@@ -215,9 +215,13 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
char tag[8];
const char *fw_pre_name;
- if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
+ if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_B_STEP)
fw_pre_name = cfg->fw_name_pre_next_step;
+ else if (drv->trans->cfg->integrated &&
+ CSR_HW_RFID_STEP(drv->trans->hw_rf_id) == SILICON_B_STEP &&
+ cfg->fw_name_pre_rf_next_step)
+ fw_pre_name = cfg->fw_name_pre_rf_next_step;
else
fw_pre_name = cfg->fw_name_pre;
@@ -1611,11 +1615,11 @@ void iwl_drv_stop(struct iwl_drv *drv)
/* shared module parameters */
struct iwl_mod_params iwlwifi_mod_params = {
- .restart_fw = true,
+ .fw_restart = true,
.bt_coex_active = true,
.power_level = IWL_POWER_INDEX_1,
.d0i3_disable = true,
- .d0i3_entry_delay = 1000,
+ .d0i3_timeout = 1000,
.uapsd_disable = IWL_DISABLE_UAPSD_BSS | IWL_DISABLE_UAPSD_P2P_CLIENT,
/* the rest are 0 by default */
};
@@ -1707,7 +1711,7 @@ module_param_named(debug, iwlwifi_mod_params.debug_level, uint,
MODULE_PARM_DESC(debug, "debug output mask");
#endif
-module_param_named(swcrypto, iwlwifi_mod_params.sw_crypto, int, S_IRUGO);
+module_param_named(swcrypto, iwlwifi_mod_params.swcrypto, int, S_IRUGO);
MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
module_param_named(11n_disable, iwlwifi_mod_params.disable_11n, uint, S_IRUGO);
MODULE_PARM_DESC(11n_disable,
@@ -1716,10 +1720,10 @@ module_param_named(amsdu_size, iwlwifi_mod_params.amsdu_size,
int, S_IRUGO);
MODULE_PARM_DESC(amsdu_size,
"amsdu size 0: 12K for multi Rx queue devices, 4K for other devices 1:4K 2:8K 3:12K (default 0)");
-module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, bool, S_IRUGO);
+module_param_named(fw_restart, iwlwifi_mod_params.fw_restart, bool, S_IRUGO);
MODULE_PARM_DESC(fw_restart, "restart firmware in case of error (default true)");
-module_param_named(antenna_coupling, iwlwifi_mod_params.ant_coupling,
+module_param_named(antenna_coupling, iwlwifi_mod_params.antenna_coupling,
int, S_IRUGO);
MODULE_PARM_DESC(antenna_coupling,
"specify antenna coupling in dB (default: 0 dB)");
@@ -1778,7 +1782,7 @@ module_param_named(fw_monitor, iwlwifi_mod_params.fw_monitor, bool, S_IRUGO);
MODULE_PARM_DESC(fw_monitor,
"firmware monitor - to debug FW (default: false - needs lots of memory)");
-module_param_named(d0i3_timeout, iwlwifi_mod_params.d0i3_entry_delay,
+module_param_named(d0i3_timeout, iwlwifi_mod_params.d0i3_timeout,
uint, S_IRUGO);
MODULE_PARM_DESC(d0i3_timeout, "Timeout to D0i3 entry when idle (ms)");
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
index 6c537e0..1f8a2ee 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
@@ -79,12 +79,12 @@
#define NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
#define NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
-#define NVM_RF_CFG_FLAVOR_MSK_FAMILY_8000(x) (x & 0xF)
-#define NVM_RF_CFG_DASH_MSK_FAMILY_8000(x) ((x >> 4) & 0xF)
-#define NVM_RF_CFG_STEP_MSK_FAMILY_8000(x) ((x >> 8) & 0xF)
-#define NVM_RF_CFG_TYPE_MSK_FAMILY_8000(x) ((x >> 12) & 0xFFF)
-#define NVM_RF_CFG_TX_ANT_MSK_FAMILY_8000(x) ((x >> 24) & 0xF)
-#define NVM_RF_CFG_RX_ANT_MSK_FAMILY_8000(x) ((x >> 28) & 0xF)
+#define EXT_NVM_RF_CFG_FLAVOR_MSK(x) ((x) & 0xF)
+#define EXT_NVM_RF_CFG_DASH_MSK(x) (((x) >> 4) & 0xF)
+#define EXT_NVM_RF_CFG_STEP_MSK(x) (((x) >> 8) & 0xF)
+#define EXT_NVM_RF_CFG_TYPE_MSK(x) (((x) >> 12) & 0xFFF)
+#define EXT_NVM_RF_CFG_TX_ANT_MSK(x) (((x) >> 24) & 0xF)
+#define EXT_NVM_RF_CFG_RX_ANT_MSK(x) (((x) >> 28) & 0xF)
/**
* DOC: Driver system flows - drv component
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h
index e04a91d..b338889 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h
@@ -121,15 +121,6 @@ struct iwl_nvm_data *
iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg,
const u8 *eeprom, size_t eeprom_size);
-/**
- * iwl_free_nvm_data - free NVM data
- * @data: the data to free
- */
-static inline void iwl_free_nvm_data(struct iwl_nvm_data *data)
-{
- kfree(data);
-}
-
int iwl_nvm_check_version(struct iwl_nvm_data *data,
struct iwl_trans *trans);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
index 62f9fe9..66e5db41 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -32,7 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -66,6 +66,7 @@
#define __iwl_fh_h__
#include <linux/types.h>
+#include <linux/bitfield.h>
/****************************/
/* Flow Handler Definitions */
@@ -77,6 +78,8 @@
*/
#define FH_MEM_LOWER_BOUND (0x1000)
#define FH_MEM_UPPER_BOUND (0x2000)
+#define FH_MEM_LOWER_BOUND_GEN2 (0xa06000)
+#define FH_MEM_UPPER_BOUND_GEN2 (0xa08000)
/**
* Keep-Warm (KW) buffer base address.
@@ -476,13 +479,12 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
#define RFH_GEN_CFG 0xA09800
#define RFH_GEN_CFG_SERVICE_DMA_SNOOP BIT(0)
#define RFH_GEN_CFG_RFH_DMA_SNOOP BIT(1)
-#define RFH_GEN_CFG_RB_CHUNK_SIZE_POS 4
+#define RFH_GEN_CFG_RB_CHUNK_SIZE BIT(4)
#define RFH_GEN_CFG_RB_CHUNK_SIZE_128 1
#define RFH_GEN_CFG_RB_CHUNK_SIZE_64 0
-#define RFH_GEN_CFG_DEFAULT_RXQ_NUM_MASK 0xF00
-#define RFH_GEN_CFG_DEFAULT_RXQ_NUM_POS 8
-
-#define DEFAULT_RXQ_NUM 0
+/* the driver assumes everywhere that the default RXQ is 0 */
+#define RFH_GEN_CFG_DEFAULT_RXQ_NUM 0xF00
+#define RFH_GEN_CFG_VAL(_n, _v) FIELD_PREP(RFH_GEN_CFG_ ## _n, _v)
/* end of 9000 rx series registers */
@@ -653,6 +655,17 @@ static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr)
{
return (sizeof(addr) > sizeof(u32) ? upper_32_bits(addr) : 0) & 0xF;
}
+
+/**
+ * enum iwl_tfd_tb_hi_n_len - TB hi_n_len bits
+ * @TB_HI_N_LEN_ADDR_HI_MSK: high 4 bits (to make it 36) of DMA address
+ * @TB_HI_N_LEN_LEN_MSK: length of the TB
+ */
+enum iwl_tfd_tb_hi_n_len {
+ TB_HI_N_LEN_ADDR_HI_MSK = 0xf,
+ TB_HI_N_LEN_LEN_MSK = 0xfff0,
+};
+
/**
* struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor
*
@@ -660,8 +673,7 @@ static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr)
*
* @lo: low [31:0] portion of the dma address of TX buffer
* every even is unaligned on 16 bit boundary
- * @hi_n_len 0-3 [35:32] portion of dma
- * 4-15 length of the tx buffer
+ * @hi_n_len: &enum iwl_tfd_tb_hi_n_len
*/
struct iwl_tfd_tb {
__le32 lo;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
index 9c8b09c..c527b8c 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
@@ -241,12 +241,12 @@ IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
void iwl_force_nmi(struct iwl_trans *trans)
{
- if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ if (trans->cfg->device_family < IWL_DEVICE_FAMILY_8000) {
iwl_write_prph(trans, DEVICE_SET_NMI_REG,
DEVICE_SET_NMI_VAL_DRV);
iwl_write_prph(trans, DEVICE_SET_NMI_REG,
DEVICE_SET_NMI_VAL_HW);
- } else if (trans->cfg->gen2) {
+ } else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_A000) {
iwl_write_prph(trans, UREG_NIC_SET_NMI_DRIVER,
DEVICE_SET_NMI_8000_VAL);
} else {
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
index 4d32b10..a41c46e 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
@@ -102,32 +102,32 @@ enum iwl_uapsd_disable {
*
* Holds the module parameters
*
- * @sw_crypto: using hardware encryption, default = 0
+ * @swcrypto: using hardware encryption, default = 0
* @disable_11n: disable 11n capabilities, default = 0,
* use IWL_[DIS,EN]ABLE_HT_* constants
* @amsdu_size: See &enum iwl_amsdu_size.
- * @restart_fw: restart firmware, default = 1
+ * @fw_restart: restart firmware, default = 1
* @bt_coex_active: enable bt coex, default = true
* @led_mode: system default, default = 0
* @power_save: enable power save, default = false
* @power_level: power level, default = 1
* @debug_level: levels are IWL_DL_*
- * @ant_coupling: antenna coupling in dB, default = 0
+ * @antenna_coupling: antenna coupling in dB, default = 0
* @nvm_file: specifies a external NVM file
- * @uapsd_disable: disable U-APSD, see %enum iwl_uapsd_disable, default =
+ * @uapsd_disable: disable U-APSD, see &enum iwl_uapsd_disable, default =
* IWL_DISABLE_UAPSD_BSS | IWL_DISABLE_UAPSD_P2P_CLIENT
* @d0i3_disable: disable d0i3, default = 1,
- * @d0i3_entry_delay: time to wait after no refs are taken before
+ * @d0i3_timeout: time to wait after no refs are taken before
* entering D0i3 (in msecs)
* @lar_disable: disable LAR (regulatory), default = 0
* @fw_monitor: allow to use firmware monitor
* @disable_11ac: disable VHT capabilities, default = false.
*/
struct iwl_mod_params {
- int sw_crypto;
+ int swcrypto;
unsigned int disable_11n;
int amsdu_size;
- bool restart_fw;
+ bool fw_restart;
bool bt_coex_active;
int led_mode;
bool power_save;
@@ -135,11 +135,11 @@ struct iwl_mod_params {
#ifdef CONFIG_IWLWIFI_DEBUG
u32 debug_level;
#endif
- int ant_coupling;
+ int antenna_coupling;
char *nvm_file;
u32 uapsd_disable;
bool d0i3_disable;
- unsigned int d0i3_entry_delay;
+ unsigned int d0i3_timeout;
bool lar_disable;
bool fw_monitor;
bool disable_11ac;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index 721ae6b..5c08f4d 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -94,30 +94,21 @@ enum wkp_nvm_offsets {
XTAL_CALIB = 0x316 - NVM_CALIB_SECTION
};
-enum family_8000_nvm_offsets {
+enum ext_nvm_offsets {
/* NVM HW-Section offset (in words) definitions */
- HW_ADDR0_WFPM_FAMILY_8000 = 0x12,
- HW_ADDR1_WFPM_FAMILY_8000 = 0x16,
- HW_ADDR0_PCIE_FAMILY_8000 = 0x8A,
- HW_ADDR1_PCIE_FAMILY_8000 = 0x8E,
- MAC_ADDRESS_OVERRIDE_FAMILY_8000 = 1,
+ MAC_ADDRESS_OVERRIDE_EXT_NVM = 1,
/* NVM SW-Section offset (in words) definitions */
- NVM_SW_SECTION_FAMILY_8000 = 0x1C0,
- NVM_VERSION_FAMILY_8000 = 0,
- RADIO_CFG_FAMILY_8000 = 0,
+ NVM_VERSION_EXT_NVM = 0,
+ RADIO_CFG_FAMILY_EXT_NVM = 0,
SKU_FAMILY_8000 = 2,
N_HW_ADDRS_FAMILY_8000 = 3,
/* NVM REGULATORY -Section offset (in words) definitions */
- NVM_CHANNELS_FAMILY_8000 = 0,
- NVM_LAR_OFFSET_FAMILY_8000_OLD = 0x4C7,
- NVM_LAR_OFFSET_FAMILY_8000 = 0x507,
- NVM_LAR_ENABLED_FAMILY_8000 = 0x7,
-
- /* NVM calibration section offset (in words) definitions */
- NVM_CALIB_SECTION_FAMILY_8000 = 0x2B8,
- XTAL_CALIB_FAMILY_8000 = 0x316 - NVM_CALIB_SECTION_FAMILY_8000
+ NVM_CHANNELS_EXTENDED = 0,
+ NVM_LAR_OFFSET_OLD = 0x4C7,
+ NVM_LAR_OFFSET = 0x507,
+ NVM_LAR_ENABLED = 0x7,
};
/* SKU Capabilities (actual values from NVM definition) */
@@ -141,7 +132,7 @@ static const u8 iwl_nvm_channels[] = {
149, 153, 157, 161, 165
};
-static const u8 iwl_nvm_channels_family_8000[] = {
+static const u8 iwl_ext_nvm_channels[] = {
/* 2.4 GHz */
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 5 GHz */
@@ -151,9 +142,9 @@ static const u8 iwl_nvm_channels_family_8000[] = {
};
#define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels)
-#define IWL_NUM_CHANNELS_FAMILY_8000 ARRAY_SIZE(iwl_nvm_channels_family_8000)
+#define IWL_NUM_CHANNELS_EXT ARRAY_SIZE(iwl_ext_nvm_channels)
#define NUM_2GHZ_CHANNELS 14
-#define NUM_2GHZ_CHANNELS_FAMILY_8000 14
+#define NUM_2GHZ_CHANNELS_EXT 14
#define FIRST_2GHZ_HT_MINUS 5
#define LAST_2GHZ_HT_PLUS 9
#define LAST_5GHZ_HT 165
@@ -219,7 +210,7 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
u32 flags = IEEE80211_CHAN_NO_HT40;
u32 last_5ghz_ht = LAST_5GHZ_HT;
- if (cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ if (cfg->ext_nvm)
last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
if (!is_5ghz && (nvm_flags & NVM_CHANNEL_40MHZ)) {
@@ -273,14 +264,14 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
int num_of_ch, num_2ghz_channels;
const u8 *nvm_chan;
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ if (!cfg->ext_nvm) {
num_of_ch = IWL_NUM_CHANNELS;
nvm_chan = &iwl_nvm_channels[0];
num_2ghz_channels = NUM_2GHZ_CHANNELS;
} else {
- num_of_ch = IWL_NUM_CHANNELS_FAMILY_8000;
- nvm_chan = &iwl_nvm_channels_family_8000[0];
- num_2ghz_channels = NUM_2GHZ_CHANNELS_FAMILY_8000;
+ num_of_ch = IWL_NUM_CHANNELS_EXT;
+ nvm_chan = &iwl_ext_nvm_channels[0];
+ num_2ghz_channels = NUM_2GHZ_CHANNELS_EXT;
}
for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
@@ -479,7 +470,7 @@ IWL_EXPORT_SYMBOL(iwl_init_sbands);
static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
const __le16 *phy_sku)
{
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (!cfg->ext_nvm)
return le16_to_cpup(nvm_sw + SKU);
return le32_to_cpup((__le32 *)(phy_sku + SKU_FAMILY_8000));
@@ -487,20 +478,20 @@ static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
{
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (!cfg->ext_nvm)
return le16_to_cpup(nvm_sw + NVM_VERSION);
else
return le32_to_cpup((__le32 *)(nvm_sw +
- NVM_VERSION_FAMILY_8000));
+ NVM_VERSION_EXT_NVM));
}
static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
const __le16 *phy_sku)
{
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (!cfg->ext_nvm)
return le16_to_cpup(nvm_sw + RADIO_CFG);
- return le32_to_cpup((__le32 *)(phy_sku + RADIO_CFG_FAMILY_8000));
+ return le32_to_cpup((__le32 *)(phy_sku + RADIO_CFG_FAMILY_EXT_NVM));
}
@@ -508,7 +499,7 @@ static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
{
int n_hw_addr;
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (!cfg->ext_nvm)
return le16_to_cpup(nvm_sw + N_HW_ADDRS);
n_hw_addr = le32_to_cpup((__le32 *)(nvm_sw + N_HW_ADDRS_FAMILY_8000));
@@ -520,7 +511,7 @@ static void iwl_set_radio_cfg(const struct iwl_cfg *cfg,
struct iwl_nvm_data *data,
u32 radio_cfg)
{
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ if (!cfg->ext_nvm) {
data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg);
data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg);
data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg);
@@ -529,12 +520,12 @@ static void iwl_set_radio_cfg(const struct iwl_cfg *cfg,
}
/* set the radio configuration for family 8000 */
- data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK_FAMILY_8000(radio_cfg);
- data->radio_cfg_step = NVM_RF_CFG_STEP_MSK_FAMILY_8000(radio_cfg);
- data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK_FAMILY_8000(radio_cfg);
- data->radio_cfg_pnum = NVM_RF_CFG_FLAVOR_MSK_FAMILY_8000(radio_cfg);
- data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK_FAMILY_8000(radio_cfg);
- data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK_FAMILY_8000(radio_cfg);
+ data->radio_cfg_type = EXT_NVM_RF_CFG_TYPE_MSK(radio_cfg);
+ data->radio_cfg_step = EXT_NVM_RF_CFG_STEP_MSK(radio_cfg);
+ data->radio_cfg_dash = EXT_NVM_RF_CFG_DASH_MSK(radio_cfg);
+ data->radio_cfg_pnum = EXT_NVM_RF_CFG_FLAVOR_MSK(radio_cfg);
+ data->valid_tx_ant = EXT_NVM_RF_CFG_TX_ANT_MSK(radio_cfg);
+ data->valid_rx_ant = EXT_NVM_RF_CFG_RX_ANT_MSK(radio_cfg);
}
static void iwl_flip_hw_address(__le32 mac_addr0, __le32 mac_addr1, u8 *dest)
@@ -587,7 +578,7 @@ static void iwl_set_hw_address_family_8000(struct iwl_trans *trans,
};
hw_addr = (const u8 *)(mac_override +
- MAC_ADDRESS_OVERRIDE_FAMILY_8000);
+ MAC_ADDRESS_OVERRIDE_EXT_NVM);
/*
* Store the MAC address from MAO section.
@@ -629,7 +620,7 @@ static int iwl_set_hw_address(struct iwl_trans *trans,
{
if (cfg->mac_addr_from_csr) {
iwl_set_hw_address_from_csr(trans, data);
- } else if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ } else if (!cfg->ext_nvm) {
const u8 *hw_addr = (const u8 *)(nvm_hw + HW_ADDR);
/* The byte order is little endian 16 bit, meaning 214365 */
@@ -649,6 +640,8 @@ static int iwl_set_hw_address(struct iwl_trans *trans,
return -EINVAL;
}
+ IWL_INFO(trans, "base HW address: %pM\n", data->hw_addr);
+
return 0;
}
@@ -666,7 +659,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
u16 lar_config;
const __le16 *ch_section;
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (!cfg->ext_nvm)
data = kzalloc(sizeof(*data) +
sizeof(struct ieee80211_channel) *
IWL_NUM_CHANNELS,
@@ -674,7 +667,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
else
data = kzalloc(sizeof(*data) +
sizeof(struct ieee80211_channel) *
- IWL_NUM_CHANNELS_FAMILY_8000,
+ IWL_NUM_CHANNELS_EXT,
GFP_KERNEL);
if (!data)
return NULL;
@@ -700,7 +693,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw);
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ if (!cfg->ext_nvm) {
/* Checking for required sections */
if (!nvm_calib) {
IWL_ERR(trans,
@@ -715,14 +708,14 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
ch_section = &nvm_sw[NVM_CHANNELS];
} else {
u16 lar_offset = data->nvm_version < 0xE39 ?
- NVM_LAR_OFFSET_FAMILY_8000_OLD :
- NVM_LAR_OFFSET_FAMILY_8000;
+ NVM_LAR_OFFSET_OLD :
+ NVM_LAR_OFFSET;
lar_config = le16_to_cpup(regulatory + lar_offset);
data->lar_enabled = !!(lar_config &
- NVM_LAR_ENABLED_FAMILY_8000);
+ NVM_LAR_ENABLED);
lar_enabled = data->lar_enabled;
- ch_section = &regulatory[NVM_CHANNELS_FAMILY_8000];
+ ch_section = &regulatory[NVM_CHANNELS_EXTENDED];
}
/* If no valid mac address was found - bail out */
@@ -746,7 +739,7 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan,
u32 flags = NL80211_RRF_NO_HT40;
u32 last_5ghz_ht = LAST_5GHZ_HT;
- if (cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ if (cfg->ext_nvm)
last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
if (ch_idx < NUM_2GHZ_CHANNELS &&
@@ -793,8 +786,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
{
int ch_idx;
u16 ch_flags, prev_ch_flags = 0;
- const u8 *nvm_chan = cfg->device_family == IWL_DEVICE_FAMILY_8000 ?
- iwl_nvm_channels_family_8000 : iwl_nvm_channels;
+ const u8 *nvm_chan = cfg->ext_nvm ?
+ iwl_ext_nvm_channels : iwl_nvm_channels;
struct ieee80211_regdomain *regd;
int size_of_regd;
struct ieee80211_reg_rule *rule;
@@ -802,8 +795,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int center_freq, prev_center_freq = 0;
int valid_rules = 0;
bool new_rule;
- int max_num_ch = cfg->device_family == IWL_DEVICE_FAMILY_8000 ?
- IWL_NUM_CHANNELS_FAMILY_8000 : IWL_NUM_CHANNELS;
+ int max_num_ch = cfg->ext_nvm ?
+ IWL_NUM_CHANNELS_EXT : IWL_NUM_CHANNELS;
if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES))
return ERR_PTR(-EINVAL);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/intel/iwlwifi/iwl-phy-db.c
index 2893826..b7cd813 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-phy-db.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-phy-db.c
@@ -112,30 +112,12 @@ enum iwl_phy_db_section_type {
#define PHY_DB_CMD 0x6c
-/*
- * phy db - configure operational ucode
- */
-struct iwl_phy_db_cmd {
- __le16 type;
- __le16 length;
- u8 data[];
-} __packed;
-
/* for parsing of tx power channel group data that comes from the firmware*/
struct iwl_phy_db_chg_txp {
__le32 space;
__le16 max_channel_idx;
} __packed;
-/*
- * phy db - Receive phy db chunk after calibrations
- */
-struct iwl_calib_res_notif_phy_db {
- __le16 type;
- __le16 length;
- u8 data[];
-} __packed;
-
struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans)
{
struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db),
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
index 77efbb7..6772c59 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
@@ -66,6 +66,7 @@
#ifndef __iwl_prph_h__
#define __iwl_prph_h__
+#include <linux/bitfield.h>
/*
* Registers in this file are internal, not PCI bus memory mapped.
@@ -247,14 +248,14 @@
#define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19)
#define SCD_QUEUE_STTS_REG_MSK (0x017F0000)
-#define SCD_QUEUE_CTX_REG1_CREDIT_POS (8)
-#define SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00)
-#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24)
-#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000)
-#define SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0)
-#define SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F)
-#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16)
-#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000)
+#define SCD_QUEUE_CTX_REG1_CREDIT (0x00FFFF00)
+#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT (0xFF000000)
+#define SCD_QUEUE_CTX_REG1_VAL(_n, _v) FIELD_PREP(SCD_QUEUE_CTX_REG1_ ## _n, _v)
+
+#define SCD_QUEUE_CTX_REG2_WIN_SIZE (0x0000007F)
+#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT (0x007F0000)
+#define SCD_QUEUE_CTX_REG2_VAL(_n, _v) FIELD_PREP(SCD_QUEUE_CTX_REG2_ ## _n, _v)
+
#define SCD_GP_CTRL_ENABLE_31_QUEUES BIT(0)
#define SCD_GP_CTRL_AUTO_ACTIVE_MODE BIT(18)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
index 0bde26b..784bdd0 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
@@ -102,6 +102,8 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
if (!trans->dev_cmd_pool)
return NULL;
+ WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty);
+
return trans;
}
@@ -115,7 +117,7 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
int ret;
if (unlikely(!(cmd->flags & CMD_SEND_IN_RFKILL) &&
- test_bit(STATUS_RFKILL, &trans->status)))
+ test_bit(STATUS_RFKILL_OPMODE, &trans->status)))
return -ERFKILL;
if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
@@ -141,6 +143,9 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
if (!(cmd->flags & CMD_ASYNC))
lock_map_release(&trans->sync_cmd_lockdep_map);
+ if (WARN_ON((cmd->flags & CMD_WANT_SKB) && !ret && !cmd->resp_pkt))
+ return -EIO;
+
return ret;
}
IWL_EXPORT_SYMBOL(iwl_trans_send_cmd);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index 0ebfdbb..eb6842a 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -74,8 +74,9 @@
#include "iwl-debug.h"
#include "iwl-config.h"
-#include "iwl-fw.h"
+#include "fw/img.h"
#include "iwl-op-mode.h"
+#include "fw/api.h"
/**
* DOC: Transport layer - what is it ?
@@ -111,104 +112,6 @@
* 6) Eventually, the free function will be called.
*/
-/**
- * DOC: Host command section
- *
- * A host command is a command issued by the upper layer to the fw. There are
- * several versions of fw that have several APIs. The transport layer is
- * completely agnostic to these differences.
- * The transport does provide helper functionality (i.e. SYNC / ASYNC mode),
- */
-#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f)
-#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
-#define SEQ_TO_INDEX(s) ((s) & 0xff)
-#define INDEX_TO_SEQ(i) ((i) & 0xff)
-#define SEQ_RX_FRAME cpu_to_le16(0x8000)
-
-/*
- * those functions retrieve specific information from
- * the id field in the iwl_host_cmd struct which contains
- * the command id, the group id and the version of the command
- * and vice versa
-*/
-static inline u8 iwl_cmd_opcode(u32 cmdid)
-{
- return cmdid & 0xFF;
-}
-
-static inline u8 iwl_cmd_groupid(u32 cmdid)
-{
- return ((cmdid & 0xFF00) >> 8);
-}
-
-static inline u8 iwl_cmd_version(u32 cmdid)
-{
- return ((cmdid & 0xFF0000) >> 16);
-}
-
-static inline u32 iwl_cmd_id(u8 opcode, u8 groupid, u8 version)
-{
- return opcode + (groupid << 8) + (version << 16);
-}
-
-/* make u16 wide id out of u8 group and opcode */
-#define WIDE_ID(grp, opcode) ((grp << 8) | opcode)
-#define DEF_ID(opcode) ((1 << 8) | (opcode))
-
-/* due to the conversion, this group is special; new groups
- * should be defined in the appropriate fw-api header files
- */
-#define IWL_ALWAYS_LONG_GROUP 1
-
-/**
- * struct iwl_cmd_header
- *
- * This header format appears in the beginning of each command sent from the
- * driver, and each response/notification received from uCode.
- */
-struct iwl_cmd_header {
- u8 cmd; /* Command ID: REPLY_RXON, etc. */
- u8 group_id;
- /*
- * The driver sets up the sequence number to values of its choosing.
- * uCode does not use this value, but passes it back to the driver
- * when sending the response to each driver-originated command, so
- * the driver can match the response to the command. Since the values
- * don't get used by uCode, the driver may set up an arbitrary format.
- *
- * There is one exception: uCode sets bit 15 when it originates
- * the response/notification, i.e. when the response/notification
- * is not a direct response to a command sent by the driver. For
- * example, uCode issues REPLY_RX when it sends a received frame
- * to the driver; it is not a direct response to any driver command.
- *
- * The Linux driver uses the following format:
- *
- * 0:7 tfd index - position within TX queue
- * 8:12 TX queue id
- * 13:14 reserved
- * 15 unsolicited RX or uCode-originated notification
- */
- __le16 sequence;
-} __packed;
-
-/**
- * struct iwl_cmd_header_wide
- *
- * This header format appears in the beginning of each command sent from the
- * driver, and each response/notification received from uCode.
- * this is the wide version that contains more information about the command
- * like length, version and command type
- */
-struct iwl_cmd_header_wide {
- u8 cmd;
- u8 group_id;
- __le16 sequence;
- __le16 length;
- u8 reserved;
- u8 version;
-} __packed;
-
#define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */
#define FH_RSCSR_FRAME_INVALID 0x55550000
#define FH_RSCSR_FRAME_ALIGN 0x40
@@ -308,7 +211,7 @@ struct iwl_device_cmd {
#define IWL_MAX_CMD_TBS_PER_TFD 2
/**
- * struct iwl_hcmd_dataflag - flag for each one of the chunks of the command
+ * enum iwl_hcmd_dataflag - flag for each one of the chunks of the command
*
* @IWL_HCMD_DFL_NOCOPY: By default, the command is copied to the host command's
* ring. The transport layer doesn't map the command's buffer to DMA, but
@@ -419,7 +322,8 @@ enum iwl_d3_status {
* @STATUS_DEVICE_ENABLED: APM is enabled
* @STATUS_TPOWER_PMI: the device might be asleep (need to wake it up)
* @STATUS_INT_ENABLED: interrupts are enabled
- * @STATUS_RFKILL: the HW RFkill switch is in KILL position
+ * @STATUS_RFKILL_HW: the actual HW state of the RF-kill switch
+ * @STATUS_RFKILL_OPMODE: RF-kill state reported to opmode
* @STATUS_FW_ERROR: the fw is in error state
* @STATUS_TRANS_GOING_IDLE: shutting down the trans, only special commands
* are sent
@@ -431,7 +335,8 @@ enum iwl_trans_status {
STATUS_DEVICE_ENABLED,
STATUS_TPOWER_PMI,
STATUS_INT_ENABLED,
- STATUS_RFKILL,
+ STATUS_RFKILL_HW,
+ STATUS_RFKILL_OPMODE,
STATUS_FW_ERROR,
STATUS_TRANS_GOING_IDLE,
STATUS_TRANS_IDLE,
@@ -533,44 +438,6 @@ struct iwl_trans_txq_scd_cfg {
int frame_limit;
};
-/* Available options for &struct iwl_tx_queue_cfg_cmd */
-enum iwl_tx_queue_cfg_actions {
- TX_QUEUE_CFG_ENABLE_QUEUE = BIT(0),
- TX_QUEUE_CFG_TFD_SHORT_FORMAT = BIT(1),
-};
-
-/**
- * struct iwl_tx_queue_cfg_cmd - txq hw scheduler config command
- * @sta_id: station id
- * @tid: tid of the queue
- * @flags: Bit 0 - on enable, off - disable, Bit 1 - short TFD format
- * @cb_size: size of TFD cyclic buffer. Value is exponent - 3.
- * Minimum value 0 (8 TFDs), maximum value 5 (256 TFDs)
- * @byte_cnt_addr: address of byte count table
- * @tfdq_addr: address of TFD circular buffer
- */
-struct iwl_tx_queue_cfg_cmd {
- u8 sta_id;
- u8 tid;
- __le16 flags;
- __le32 cb_size;
- __le64 byte_cnt_addr;
- __le64 tfdq_addr;
-} __packed; /* TX_QUEUE_CFG_CMD_API_S_VER_2 */
-
-/**
- * struct iwl_tx_queue_cfg_rsp - response to txq hw scheduler config
- * @queue_number: queue number assigned to this RA -TID
- * @flags: set on failure
- * @write_pointer: initial value for write pointer
- */
-struct iwl_tx_queue_cfg_rsp {
- __le16 queue_number;
- __le16 flags;
- __le16 write_pointer;
- __le16 reserved;
-} __packed; /* TX_QUEUE_CFG_RSP_API_S_VER_2 */
-
/**
* struct iwl_trans_ops - transport specific operations
*
@@ -615,11 +482,14 @@ struct iwl_tx_queue_cfg_rsp {
* iwl_trans_ac_txq_enable wrapper. fw_alive must have been called before
* this one. The op_mode must not configure the HCMD queue. The scheduler
* configuration may be %NULL, in which case the hardware will not be
- * configured. May sleep.
+ * configured. If true is returned, the operation mode needs to increment
+ * the sequence number of the packets routed to this queue because of a
+ * hardware scheduler bug. May sleep.
* @txq_disable: de-configure a Tx queue to send AMPDUs
* Must be atomic
* @txq_set_shared_mode: change Tx queue shared/unshared marking
- * @wait_tx_queue_empty: wait until tx queues are empty. May sleep.
+ * @wait_tx_queues_empty: wait until tx queues are empty. May sleep.
+ * @wait_txq_empty: wait until specific tx queue is empty. May sleep.
* @freeze_txq_timer: prevents the timer of the queue from firing until the
* queue is set to awake. Must be atomic.
* @block_txq_ptrs: stop updating the write pointers of the Tx queues. Note
@@ -676,7 +546,7 @@ struct iwl_trans_ops {
void (*reclaim)(struct iwl_trans *trans, int queue, int ssn,
struct sk_buff_head *skbs);
- void (*txq_enable)(struct iwl_trans *trans, int queue, u16 ssn,
+ bool (*txq_enable)(struct iwl_trans *trans, int queue, u16 ssn,
const struct iwl_trans_txq_scd_cfg *cfg,
unsigned int queue_wdg_timeout);
void (*txq_disable)(struct iwl_trans *trans, int queue,
@@ -692,6 +562,7 @@ struct iwl_trans_ops {
bool shared);
int (*wait_tx_queues_empty)(struct iwl_trans *trans, u32 txq_bm);
+ int (*wait_txq_empty)(struct iwl_trans *trans, int queue);
void (*freeze_txq_timer)(struct iwl_trans *trans, unsigned long txqs,
bool freeze);
void (*block_txq_ptrs)(struct iwl_trans *trans, bool block);
@@ -1041,13 +912,7 @@ iwl_trans_dump_data(struct iwl_trans *trans,
static inline struct iwl_device_cmd *
iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)
{
- struct iwl_device_cmd *dev_cmd_ptr =
- kmem_cache_alloc(trans->dev_cmd_pool, GFP_ATOMIC);
-
- if (unlikely(dev_cmd_ptr == NULL))
- return NULL;
-
- return dev_cmd_ptr;
+ return kmem_cache_alloc(trans->dev_cmd_pool, GFP_ATOMIC);
}
int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
@@ -1089,7 +954,7 @@ static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue,
trans->ops->txq_disable(trans, queue, configure_scd);
}
-static inline void
+static inline bool
iwl_trans_txq_enable_cfg(struct iwl_trans *trans, int queue, u16 ssn,
const struct iwl_trans_txq_scd_cfg *cfg,
unsigned int queue_wdg_timeout)
@@ -1098,10 +963,11 @@ iwl_trans_txq_enable_cfg(struct iwl_trans *trans, int queue, u16 ssn,
if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
- return;
+ return false;
}
- trans->ops->txq_enable(trans, queue, ssn, cfg, queue_wdg_timeout);
+ return trans->ops->txq_enable(trans, queue, ssn,
+ cfg, queue_wdg_timeout);
}
static inline void
@@ -1198,6 +1064,9 @@ static inline void iwl_trans_block_txq_ptrs(struct iwl_trans *trans,
static inline int iwl_trans_wait_tx_queues_empty(struct iwl_trans *trans,
u32 txqs)
{
+ if (WARN_ON_ONCE(!trans->ops->wait_tx_queues_empty))
+ return -ENOTSUPP;
+
if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return -EIO;
@@ -1206,6 +1075,19 @@ static inline int iwl_trans_wait_tx_queues_empty(struct iwl_trans *trans,
return trans->ops->wait_tx_queues_empty(trans, txqs);
}
+static inline int iwl_trans_wait_txq_empty(struct iwl_trans *trans, int queue)
+{
+ if (WARN_ON_ONCE(!trans->ops->wait_txq_empty))
+ return -ENOTSUPP;
+
+ if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
+ IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
+ return -EIO;
+ }
+
+ return trans->ops->wait_txq_empty(trans, queue);
+}
+
static inline void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val)
{
trans->ops->write8(trans, ofs, val);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
index 49b4418..34dd5c4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
@@ -406,7 +406,7 @@ iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif)
return ret;
}
-int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
+int iwl_mvm_send_bt_init_conf(struct iwl_mvm *mvm)
{
struct iwl_bt_coex_cmd bt_cmd = {};
u32 mode;
@@ -914,7 +914,8 @@ void iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- u32 ant_isolation = le32_to_cpup((void *)pkt->data);
+ struct iwl_mvm_antenna_coupling_notif *notif = (void *)pkt->data;
+ u32 ant_isolation = le32_to_cpu(notif->isolation);
struct iwl_bt_coex_corun_lut_update_cmd cmd = {};
u8 __maybe_unused lower_bound, upper_bound;
u8 lut;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
index 4eeb6b7..6fda862 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
@@ -110,6 +110,7 @@
#define IWL_MVM_TOF_IS_RESPONDER 0
#define IWL_MVM_SW_TX_CSUM_OFFLOAD 0
#define IWL_MVM_HW_CSUM_DISABLE 0
+#define IWL_MVM_PARSE_NVM 0
#define IWL_MVM_COLLECT_FW_ERR_DUMP 1
#define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1
#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 119a3bd..5de19ea 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -34,7 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -83,7 +83,7 @@ void iwl_mvm_set_rekey_data(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- if (iwlwifi_mod_params.sw_crypto)
+ if (iwlwifi_mod_params.swcrypto)
return;
mutex_lock(&mvm->mutex);
@@ -1054,7 +1054,7 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
return ret;
}
- if (!iwlwifi_mod_params.sw_crypto) {
+ if (!iwlwifi_mod_params.swcrypto) {
/*
* This needs to be unlocked due to lock ordering
* constraints. Since we're in the suspend path
@@ -1280,8 +1280,8 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
if (!unified_image) {
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
- if (mvm->restart_fw > 0) {
- mvm->restart_fw--;
+ if (mvm->fw_restart > 0) {
+ mvm->fw_restart--;
ieee80211_restart_hw(mvm->hw);
}
}
@@ -1431,7 +1431,7 @@ static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm,
if (!pkt)
goto report;
- memcpy(skb_put(pkt, hdrlen), pktdata, hdrlen);
+ skb_put_data(pkt, pktdata, hdrlen);
pktdata += hdrlen;
pktsize -= hdrlen;
@@ -1463,7 +1463,7 @@ static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm,
pktsize -= ivlen + icvlen;
pktdata += ivlen;
- memcpy(skb_put(pkt, pktsize), pktdata, pktsize);
+ skb_put_data(pkt, pktdata, pktsize);
if (ieee80211_data_to_8023(pkt, vif->addr, vif->type))
goto report;
@@ -1795,12 +1795,6 @@ iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
return ERR_PTR(ret);
}
- /* RF-kill already asserted again... */
- if (!cmd.resp_pkt) {
- fw_status = ERR_PTR(-ERFKILL);
- goto out_free_resp;
- }
-
status_size = sizeof(*fw_status);
len = iwl_rx_packet_payload_len(cmd.resp_pkt);
@@ -1925,12 +1919,6 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
return ret;
}
- /* RF-kill already asserted again... */
- if (!cmd.resp_pkt) {
- ret = -ERFKILL;
- goto out_free_resp;
- }
-
len = iwl_rx_packet_payload_len(cmd.resp_pkt);
if (len < sizeof(*query)) {
IWL_ERR(mvm, "Invalid scan offload profiles query response!\n");
@@ -2087,9 +2075,8 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
bool keep = false;
bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
-
- u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE |
- CMD_WAKE_UP_TRANS;
+ bool d0i3_first = fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_D0I3_END_FIRST);
mutex_lock(&mvm->mutex);
@@ -2110,6 +2097,15 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
/* query SRAM first in case we want event logging */
iwl_mvm_read_d3_sram(mvm);
+ if (d0i3_first) {
+ ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, 0, 0, NULL);
+ if (ret < 0) {
+ IWL_ERR(mvm, "Failed to send D0I3_END_CMD first (%d)\n",
+ ret);
+ goto err;
+ }
+ }
+
/*
* Query the current location and source from the D3 firmware so we
* can play it back when we re-intiailize the D0 firmware
@@ -2155,9 +2151,14 @@ out_iterate:
iwl_mvm_d3_disconnect_iter, keep ? vif : NULL);
out:
+ /* no need to reset the device in unified images, if successful */
if (unified_image && !ret) {
- ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, flags, 0, NULL);
- if (!ret) /* D3 ended successfully - no need to reset device */
+ /* nothing else to do if we already sent D0I3_END_CMD */
+ if (d0i3_first)
+ return 0;
+
+ ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, 0, 0, NULL);
+ if (!ret)
return 0;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
index 5d475b4..a7ac281 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -34,7 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1304,11 +1304,11 @@ static ssize_t iwl_dbgfs_low_latency_read(struct file *file,
char buf[30] = {};
int len;
- len = snprintf(buf, sizeof(buf) - 1,
- "traffic=%d\ndbgfs=%d\nvcmd=%d\n",
- mvmvif->low_latency_traffic,
- mvmvif->low_latency_dbgfs,
- mvmvif->low_latency_vcmd);
+ len = scnprintf(buf, sizeof(buf) - 1,
+ "traffic=%d\ndbgfs=%d\nvcmd=%d\n",
+ mvmvif->low_latency_traffic,
+ mvmvif->low_latency_dbgfs,
+ mvmvif->low_latency_vcmd);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -1385,10 +1385,12 @@ static ssize_t iwl_dbgfs_rx_phyinfo_read(struct file *file,
struct ieee80211_vif *vif = file->private_data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
char buf[8];
+ int len;
- snprintf(buf, sizeof(buf), "0x%04x\n", mvmvif->mvm->dbgfs_rx_phyinfo);
+ len = scnprintf(buf, sizeof(buf), "0x%04x\n",
+ mvmvif->mvm->dbgfs_rx_phyinfo);
- return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf));
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static void iwl_dbgfs_quota_check(void *data, u8 *mac,
@@ -1439,7 +1441,7 @@ static ssize_t iwl_dbgfs_quota_min_read(struct file *file,
char buf[10];
int len;
- len = snprintf(buf, sizeof(buf), "%d\n", mvmvif->dbgfs_quota_min);
+ len = scnprintf(buf, sizeof(buf), "%d\n", mvmvif->dbgfs_quota_min);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 4028466..c1c9c48 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -34,6 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -72,7 +73,7 @@
#include "sta.h"
#include "iwl-io.h"
#include "debugfs.h"
-#include "iwl-fw-error-dump.h"
+#include "fw/error-dump.h"
static ssize_t iwl_dbgfs_ctdp_budget_read(struct file *file,
char __user *user_buf,
@@ -82,7 +83,8 @@ static ssize_t iwl_dbgfs_ctdp_budget_read(struct file *file,
char buf[16];
int pos, budget;
- if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
+ if (!iwl_mvm_firmware_running(mvm) ||
+ mvm->cur_ucode != IWL_UCODE_REGULAR)
return -EIO;
mutex_lock(&mvm->mutex);
@@ -102,7 +104,8 @@ static ssize_t iwl_dbgfs_stop_ctdp_write(struct iwl_mvm *mvm, char *buf,
{
int ret;
- if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
+ if (!iwl_mvm_firmware_running(mvm) ||
+ mvm->cur_ucode != IWL_UCODE_REGULAR)
return -EIO;
mutex_lock(&mvm->mutex);
@@ -116,18 +119,30 @@ static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
{
int ret;
- u32 scd_q_msk;
+ u32 flush_arg;
- if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
+ if (!iwl_mvm_firmware_running(mvm) ||
+ mvm->cur_ucode != IWL_UCODE_REGULAR)
return -EIO;
- if (sscanf(buf, "%x", &scd_q_msk) != 1)
+ if (kstrtou32(buf, 0, &flush_arg))
return -EINVAL;
- IWL_ERR(mvm, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk);
+ if (iwl_mvm_has_new_tx_api(mvm)) {
+ IWL_DEBUG_TX_QUEUES(mvm,
+ "FLUSHING all tids queues on sta_id = %d\n",
+ flush_arg);
+ mutex_lock(&mvm->mutex);
+ ret = iwl_mvm_flush_sta_tids(mvm, flush_arg, 0xFF, 0) ? : count;
+ mutex_unlock(&mvm->mutex);
+ return ret;
+ }
+
+ IWL_DEBUG_TX_QUEUES(mvm, "FLUSHING queues mask to flush = 0x%x\n",
+ flush_arg);
mutex_lock(&mvm->mutex);
- ret = iwl_mvm_flush_tx_path(mvm, scd_q_msk, 0) ? : count;
+ ret = iwl_mvm_flush_tx_path(mvm, flush_arg, 0) ? : count;
mutex_unlock(&mvm->mutex);
return ret;
@@ -139,7 +154,8 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
struct iwl_mvm_sta *mvmsta;
int sta_id, drain, ret;
- if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
+ if (!iwl_mvm_firmware_running(mvm) ||
+ mvm->cur_ucode != IWL_UCODE_REGULAR)
return -EIO;
if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
@@ -172,7 +188,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
size_t ret;
u8 *ptr;
- if (!mvm->ucode_loaded)
+ if (!iwl_mvm_firmware_running(mvm))
return -EINVAL;
/* default is to dump the entire data segment */
@@ -205,7 +221,7 @@ static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf,
u32 offset, len;
u32 img_offset, img_len;
- if (!mvm->ucode_loaded)
+ if (!iwl_mvm_firmware_running(mvm))
return -EINVAL;
img = &mvm->fw->img[mvm->cur_ucode];
@@ -258,7 +274,7 @@ static ssize_t iwl_dbgfs_set_nic_temperature_write(struct iwl_mvm *mvm,
{
int temperature;
- if (!mvm->ucode_loaded && !mvm->temperature_test)
+ if (!iwl_mvm_firmware_running(mvm) && !mvm->temperature_test)
return -EIO;
if (kstrtoint(buf, 10, &temperature))
@@ -305,7 +321,7 @@ static ssize_t iwl_dbgfs_nic_temp_read(struct file *file,
int pos, ret;
s32 temp;
- if (!mvm->ucode_loaded)
+ if (!iwl_mvm_firmware_running(mvm))
return -EIO;
mutex_lock(&mvm->mutex);
@@ -320,6 +336,49 @@ static ssize_t iwl_dbgfs_nic_temp_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
+#ifdef CONFIG_ACPI
+static ssize_t iwl_dbgfs_sar_geo_profile_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_mvm *mvm = file->private_data;
+ char buf[256];
+ int pos = 0;
+ int bufsz = sizeof(buf);
+ int tbl_idx;
+ u8 *value;
+
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
+ mutex_lock(&mvm->mutex);
+ tbl_idx = iwl_mvm_get_sar_geo_profile(mvm);
+ if (tbl_idx < 0) {
+ mutex_unlock(&mvm->mutex);
+ return tbl_idx;
+ }
+
+ if (!tbl_idx) {
+ pos = scnprintf(buf, bufsz,
+ "SAR geographic profile disabled\n");
+ } else {
+ value = &mvm->geo_profiles[tbl_idx - 1].values[0];
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Use geographic profile %d\n", tbl_idx);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "2.4GHz:\n\tChain A offset: %hhd dBm\n\tChain B offset: %hhd dBm\n\tmax tx power: %hhd dBm\n",
+ value[1], value[2], value[0]);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "5.2GHz:\n\tChain A offset: %hhd dBm\n\tChain B offset: %hhd dBm\n\tmax tx power: %hhd dBm\n",
+ value[4], value[5], value[3]);
+ }
+ mutex_unlock(&mvm->mutex);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+#endif
+
static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -371,7 +430,7 @@ static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
{
int ret, val;
- if (!mvm->ucode_loaded)
+ if (!iwl_mvm_firmware_running(mvm))
return -EIO;
if (!strncmp("disable_power_off_d0=", buf, 21)) {
@@ -583,7 +642,11 @@ iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf,
mvm->bt_force_ant_mode = bt_force_ant_mode;
IWL_DEBUG_COEX(mvm, "Force mode: %s\n",
modes_str[mvm->bt_force_ant_mode]);
- ret = iwl_send_bt_init_conf(mvm);
+
+ if (iwl_mvm_firmware_running(mvm))
+ ret = iwl_mvm_send_bt_init_conf(mvm);
+ else
+ ret = 0;
out:
mutex_unlock(&mvm->mutex);
@@ -605,15 +668,15 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
int pos = 0;
char *buf;
int ret;
- /* 43 is the size of each data line, 33 is the size of each header */
- size_t bufsz =
- ((sizeof(struct mvm_statistics_rx) / sizeof(__le32)) * 43) +
- (4 * 33) + 1;
+ size_t bufsz;
- struct mvm_statistics_rx_phy *ofdm;
- struct mvm_statistics_rx_phy *cck;
- struct mvm_statistics_rx_non_phy *general;
- struct mvm_statistics_rx_ht_phy *ht;
+ if (iwl_mvm_has_new_rx_stats_api(mvm))
+ bufsz = ((sizeof(struct mvm_statistics_rx) /
+ sizeof(__le32)) * 43) + (4 * 33) + 1;
+ else
+ /* 43 = size of each data line; 33 = size of each header */
+ bufsz = ((sizeof(struct mvm_statistics_rx_v3) /
+ sizeof(__le32)) * 43) + (4 * 33) + 1;
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf)
@@ -621,96 +684,157 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
mutex_lock(&mvm->mutex);
- ofdm = &mvm->rx_stats.ofdm;
- cck = &mvm->rx_stats.cck;
- general = &mvm->rx_stats.general;
- ht = &mvm->rx_stats.ofdm_ht;
-
pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
"Statistics_Rx - OFDM");
- PRINT_STATS_LE32(ofdm, ina_cnt);
- PRINT_STATS_LE32(ofdm, fina_cnt);
- PRINT_STATS_LE32(ofdm, plcp_err);
- PRINT_STATS_LE32(ofdm, crc32_err);
- PRINT_STATS_LE32(ofdm, overrun_err);
- PRINT_STATS_LE32(ofdm, early_overrun_err);
- PRINT_STATS_LE32(ofdm, crc32_good);
- PRINT_STATS_LE32(ofdm, false_alarm_cnt);
- PRINT_STATS_LE32(ofdm, fina_sync_err_cnt);
- PRINT_STATS_LE32(ofdm, sfd_timeout);
- PRINT_STATS_LE32(ofdm, fina_timeout);
- PRINT_STATS_LE32(ofdm, unresponded_rts);
- PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun);
- PRINT_STATS_LE32(ofdm, sent_ack_cnt);
- PRINT_STATS_LE32(ofdm, sent_cts_cnt);
- PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt);
- PRINT_STATS_LE32(ofdm, dsp_self_kill);
- PRINT_STATS_LE32(ofdm, mh_format_err);
- PRINT_STATS_LE32(ofdm, re_acq_main_rssi_sum);
- PRINT_STATS_LE32(ofdm, reserved);
+ if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
+ struct mvm_statistics_rx_phy_v2 *ofdm = &mvm->rx_stats_v3.ofdm;
+
+ PRINT_STATS_LE32(ofdm, ina_cnt);
+ PRINT_STATS_LE32(ofdm, fina_cnt);
+ PRINT_STATS_LE32(ofdm, plcp_err);
+ PRINT_STATS_LE32(ofdm, crc32_err);
+ PRINT_STATS_LE32(ofdm, overrun_err);
+ PRINT_STATS_LE32(ofdm, early_overrun_err);
+ PRINT_STATS_LE32(ofdm, crc32_good);
+ PRINT_STATS_LE32(ofdm, false_alarm_cnt);
+ PRINT_STATS_LE32(ofdm, fina_sync_err_cnt);
+ PRINT_STATS_LE32(ofdm, sfd_timeout);
+ PRINT_STATS_LE32(ofdm, fina_timeout);
+ PRINT_STATS_LE32(ofdm, unresponded_rts);
+ PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun);
+ PRINT_STATS_LE32(ofdm, sent_ack_cnt);
+ PRINT_STATS_LE32(ofdm, sent_cts_cnt);
+ PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt);
+ PRINT_STATS_LE32(ofdm, dsp_self_kill);
+ PRINT_STATS_LE32(ofdm, mh_format_err);
+ PRINT_STATS_LE32(ofdm, re_acq_main_rssi_sum);
+ PRINT_STATS_LE32(ofdm, reserved);
+ } else {
+ struct mvm_statistics_rx_phy *ofdm = &mvm->rx_stats.ofdm;
+
+ PRINT_STATS_LE32(ofdm, unresponded_rts);
+ PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun);
+ PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt);
+ PRINT_STATS_LE32(ofdm, dsp_self_kill);
+ PRINT_STATS_LE32(ofdm, reserved);
+ }
pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
"Statistics_Rx - CCK");
- PRINT_STATS_LE32(cck, ina_cnt);
- PRINT_STATS_LE32(cck, fina_cnt);
- PRINT_STATS_LE32(cck, plcp_err);
- PRINT_STATS_LE32(cck, crc32_err);
- PRINT_STATS_LE32(cck, overrun_err);
- PRINT_STATS_LE32(cck, early_overrun_err);
- PRINT_STATS_LE32(cck, crc32_good);
- PRINT_STATS_LE32(cck, false_alarm_cnt);
- PRINT_STATS_LE32(cck, fina_sync_err_cnt);
- PRINT_STATS_LE32(cck, sfd_timeout);
- PRINT_STATS_LE32(cck, fina_timeout);
- PRINT_STATS_LE32(cck, unresponded_rts);
- PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun);
- PRINT_STATS_LE32(cck, sent_ack_cnt);
- PRINT_STATS_LE32(cck, sent_cts_cnt);
- PRINT_STATS_LE32(cck, sent_ba_rsp_cnt);
- PRINT_STATS_LE32(cck, dsp_self_kill);
- PRINT_STATS_LE32(cck, mh_format_err);
- PRINT_STATS_LE32(cck, re_acq_main_rssi_sum);
- PRINT_STATS_LE32(cck, reserved);
+ if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
+ struct mvm_statistics_rx_phy_v2 *cck = &mvm->rx_stats_v3.cck;
+
+ PRINT_STATS_LE32(cck, ina_cnt);
+ PRINT_STATS_LE32(cck, fina_cnt);
+ PRINT_STATS_LE32(cck, plcp_err);
+ PRINT_STATS_LE32(cck, crc32_err);
+ PRINT_STATS_LE32(cck, overrun_err);
+ PRINT_STATS_LE32(cck, early_overrun_err);
+ PRINT_STATS_LE32(cck, crc32_good);
+ PRINT_STATS_LE32(cck, false_alarm_cnt);
+ PRINT_STATS_LE32(cck, fina_sync_err_cnt);
+ PRINT_STATS_LE32(cck, sfd_timeout);
+ PRINT_STATS_LE32(cck, fina_timeout);
+ PRINT_STATS_LE32(cck, unresponded_rts);
+ PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun);
+ PRINT_STATS_LE32(cck, sent_ack_cnt);
+ PRINT_STATS_LE32(cck, sent_cts_cnt);
+ PRINT_STATS_LE32(cck, sent_ba_rsp_cnt);
+ PRINT_STATS_LE32(cck, dsp_self_kill);
+ PRINT_STATS_LE32(cck, mh_format_err);
+ PRINT_STATS_LE32(cck, re_acq_main_rssi_sum);
+ PRINT_STATS_LE32(cck, reserved);
+ } else {
+ struct mvm_statistics_rx_phy *cck = &mvm->rx_stats.cck;
+
+ PRINT_STATS_LE32(cck, unresponded_rts);
+ PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun);
+ PRINT_STATS_LE32(cck, sent_ba_rsp_cnt);
+ PRINT_STATS_LE32(cck, dsp_self_kill);
+ PRINT_STATS_LE32(cck, reserved);
+ }
pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
"Statistics_Rx - GENERAL");
- PRINT_STATS_LE32(general, bogus_cts);
- PRINT_STATS_LE32(general, bogus_ack);
- PRINT_STATS_LE32(general, non_bssid_frames);
- PRINT_STATS_LE32(general, filtered_frames);
- PRINT_STATS_LE32(general, non_channel_beacons);
- PRINT_STATS_LE32(general, channel_beacons);
- PRINT_STATS_LE32(general, num_missed_bcon);
- PRINT_STATS_LE32(general, adc_rx_saturation_time);
- PRINT_STATS_LE32(general, ina_detection_search_time);
- PRINT_STATS_LE32(general, beacon_silence_rssi_a);
- PRINT_STATS_LE32(general, beacon_silence_rssi_b);
- PRINT_STATS_LE32(general, beacon_silence_rssi_c);
- PRINT_STATS_LE32(general, interference_data_flag);
- PRINT_STATS_LE32(general, channel_load);
- PRINT_STATS_LE32(general, dsp_false_alarms);
- PRINT_STATS_LE32(general, beacon_rssi_a);
- PRINT_STATS_LE32(general, beacon_rssi_b);
- PRINT_STATS_LE32(general, beacon_rssi_c);
- PRINT_STATS_LE32(general, beacon_energy_a);
- PRINT_STATS_LE32(general, beacon_energy_b);
- PRINT_STATS_LE32(general, beacon_energy_c);
- PRINT_STATS_LE32(general, num_bt_kills);
- PRINT_STATS_LE32(general, mac_id);
- PRINT_STATS_LE32(general, directed_data_mpdu);
+ if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
+ struct mvm_statistics_rx_non_phy_v3 *general =
+ &mvm->rx_stats_v3.general;
+
+ PRINT_STATS_LE32(general, bogus_cts);
+ PRINT_STATS_LE32(general, bogus_ack);
+ PRINT_STATS_LE32(general, non_bssid_frames);
+ PRINT_STATS_LE32(general, filtered_frames);
+ PRINT_STATS_LE32(general, non_channel_beacons);
+ PRINT_STATS_LE32(general, channel_beacons);
+ PRINT_STATS_LE32(general, num_missed_bcon);
+ PRINT_STATS_LE32(general, adc_rx_saturation_time);
+ PRINT_STATS_LE32(general, ina_detection_search_time);
+ PRINT_STATS_LE32(general, beacon_silence_rssi_a);
+ PRINT_STATS_LE32(general, beacon_silence_rssi_b);
+ PRINT_STATS_LE32(general, beacon_silence_rssi_c);
+ PRINT_STATS_LE32(general, interference_data_flag);
+ PRINT_STATS_LE32(general, channel_load);
+ PRINT_STATS_LE32(general, dsp_false_alarms);
+ PRINT_STATS_LE32(general, beacon_rssi_a);
+ PRINT_STATS_LE32(general, beacon_rssi_b);
+ PRINT_STATS_LE32(general, beacon_rssi_c);
+ PRINT_STATS_LE32(general, beacon_energy_a);
+ PRINT_STATS_LE32(general, beacon_energy_b);
+ PRINT_STATS_LE32(general, beacon_energy_c);
+ PRINT_STATS_LE32(general, num_bt_kills);
+ PRINT_STATS_LE32(general, mac_id);
+ PRINT_STATS_LE32(general, directed_data_mpdu);
+ } else {
+ struct mvm_statistics_rx_non_phy *general =
+ &mvm->rx_stats.general;
+
+ PRINT_STATS_LE32(general, bogus_cts);
+ PRINT_STATS_LE32(general, bogus_ack);
+ PRINT_STATS_LE32(general, non_channel_beacons);
+ PRINT_STATS_LE32(general, channel_beacons);
+ PRINT_STATS_LE32(general, num_missed_bcon);
+ PRINT_STATS_LE32(general, adc_rx_saturation_time);
+ PRINT_STATS_LE32(general, ina_detection_search_time);
+ PRINT_STATS_LE32(general, beacon_silence_rssi_a);
+ PRINT_STATS_LE32(general, beacon_silence_rssi_b);
+ PRINT_STATS_LE32(general, beacon_silence_rssi_c);
+ PRINT_STATS_LE32(general, interference_data_flag);
+ PRINT_STATS_LE32(general, channel_load);
+ PRINT_STATS_LE32(general, beacon_rssi_a);
+ PRINT_STATS_LE32(general, beacon_rssi_b);
+ PRINT_STATS_LE32(general, beacon_rssi_c);
+ PRINT_STATS_LE32(general, beacon_energy_a);
+ PRINT_STATS_LE32(general, beacon_energy_b);
+ PRINT_STATS_LE32(general, beacon_energy_c);
+ PRINT_STATS_LE32(general, num_bt_kills);
+ PRINT_STATS_LE32(general, mac_id);
+ }
pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
"Statistics_Rx - HT");
- PRINT_STATS_LE32(ht, plcp_err);
- PRINT_STATS_LE32(ht, overrun_err);
- PRINT_STATS_LE32(ht, early_overrun_err);
- PRINT_STATS_LE32(ht, crc32_good);
- PRINT_STATS_LE32(ht, crc32_err);
- PRINT_STATS_LE32(ht, mh_format_err);
- PRINT_STATS_LE32(ht, agg_crc32_good);
- PRINT_STATS_LE32(ht, agg_mpdu_cnt);
- PRINT_STATS_LE32(ht, agg_cnt);
- PRINT_STATS_LE32(ht, unsupport_mcs);
+ if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
+ struct mvm_statistics_rx_ht_phy_v1 *ht =
+ &mvm->rx_stats_v3.ofdm_ht;
+
+ PRINT_STATS_LE32(ht, plcp_err);
+ PRINT_STATS_LE32(ht, overrun_err);
+ PRINT_STATS_LE32(ht, early_overrun_err);
+ PRINT_STATS_LE32(ht, crc32_good);
+ PRINT_STATS_LE32(ht, crc32_err);
+ PRINT_STATS_LE32(ht, mh_format_err);
+ PRINT_STATS_LE32(ht, agg_crc32_good);
+ PRINT_STATS_LE32(ht, agg_mpdu_cnt);
+ PRINT_STATS_LE32(ht, agg_cnt);
+ PRINT_STATS_LE32(ht, unsupport_mcs);
+ } else {
+ struct mvm_statistics_rx_ht_phy *ht =
+ &mvm->rx_stats.ofdm_ht;
+
+ PRINT_STATS_LE32(ht, mh_format_err);
+ PRINT_STATS_LE32(ht, agg_mpdu_cnt);
+ PRINT_STATS_LE32(ht, agg_cnt);
+ PRINT_STATS_LE32(ht, unsupport_mcs);
+ }
mutex_unlock(&mvm->mutex);
@@ -800,11 +924,14 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
{
int __maybe_unused ret;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
mutex_lock(&mvm->mutex);
/* allow one more restart that we're provoking here */
- if (mvm->restart_fw >= 0)
- mvm->restart_fw++;
+ if (mvm->fw_restart >= 0)
+ mvm->fw_restart++;
/* take the return value to make compiler happy - it will fail anyway */
ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, 0, 0, NULL);
@@ -817,7 +944,12 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
{
- int ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_NMI);
+ int ret;
+
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
+ ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_NMI);
if (ret)
return ret;
@@ -857,6 +989,9 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
{
u8 scan_rx_ant;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
if (sscanf(buf, "%hhx", &scan_rx_ant) != 1)
return -EINVAL;
if (scan_rx_ant > ANT_ABC)
@@ -911,7 +1046,11 @@ static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm,
netdev_rss_key_fill(cmd.secret_key, sizeof(cmd.secret_key));
mutex_lock(&mvm->mutex);
- ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd);
+ if (iwl_mvm_firmware_running(mvm))
+ ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0,
+ sizeof(cmd), &cmd);
+ else
+ ret = 0;
mutex_unlock(&mvm->mutex);
return ret ?: count;
@@ -931,6 +1070,9 @@ static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
int bin_len = count / 2;
int ret = -EINVAL;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
/* supporting only 9000 descriptor */
if (!mvm->trans->cfg->mq_rx_supported)
return -ENOTSUPP;
@@ -1004,11 +1146,14 @@ static ssize_t iwl_dbgfs_cont_recording_write(struct iwl_mvm *mvm,
struct iwl_continuous_record_cmd cont_rec = {};
int ret, rec_mode;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
if (!dest)
return -EOPNOTSUPP;
if (dest->monitor_mode != SMEM_MODE ||
- trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ trans->cfg->device_family < IWL_DEVICE_FAMILY_8000)
return -EOPNOTSUPP;
ret = kstrtoint(buf, 0, &rec_mode);
@@ -1034,6 +1179,9 @@ static ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm,
unsigned int conf_id;
int ret;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
ret = kstrtouint(buf, 0, &conf_id);
if (ret)
return ret;
@@ -1052,8 +1200,12 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
char *buf, size_t count,
loff_t *ppos)
{
- int ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
+ int ret;
+
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+ ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
if (ret)
return ret;
if (count == 0)
@@ -1184,7 +1336,8 @@ static ssize_t iwl_dbgfs_bcast_filters_write(struct iwl_mvm *mvm, char *buf,
&filter, sizeof(filter));
/* send updated bcast filtering configuration */
- if (mvm->dbgfs_bcast_filtering.override &&
+ if (iwl_mvm_firmware_running(mvm) &&
+ mvm->dbgfs_bcast_filtering.override &&
iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0,
sizeof(cmd), &cmd);
@@ -1256,7 +1409,8 @@ static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm,
&mac, sizeof(mac));
/* send updated bcast filtering configuration */
- if (mvm->dbgfs_bcast_filtering.override &&
+ if (iwl_mvm_firmware_running(mvm) &&
+ mvm->dbgfs_bcast_filtering.override &&
iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0,
sizeof(cmd), &cmd);
@@ -1473,6 +1627,9 @@ iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf,
{
int ret;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
mutex_lock(&mvm->mutex);
ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL);
mutex_unlock(&mvm->mutex);
@@ -1519,6 +1676,9 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
#ifdef CONFIG_PM_SLEEP
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
#endif
+#ifdef CONFIG_ACPI
+MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
+#endif
static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -1534,6 +1694,9 @@ static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
size_t delta;
ssize_t ret, len;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
hcmd.id = iwl_cmd_id(*ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR,
DEBUG_GROUP, 0);
cmd.op = cpu_to_le32(DEBUG_MEM_OP_READ);
@@ -1586,6 +1749,9 @@ static ssize_t iwl_dbgfs_mem_write(struct file *file,
u32 op, len;
ssize_t ret;
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
hcmd.id = iwl_cmd_id(*ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR,
DEBUG_GROUP, 0);
@@ -1685,6 +1851,10 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
MVM_DEBUGFS_ADD_FILE(cont_recording, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, S_IWUSR);
+#ifdef CONFIG_ACPI
+ MVM_DEBUGFS_ADD_FILE(sar_geo_profile, dbgfs_dir, S_IRUSR);
+#endif
+
if (!debugfs_create_bool("enable_scan_iteration_notif",
S_IRUSR | S_IWUSR,
mvm->debugfs_dir,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-coex.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-coex.h
index 204c1b1..8cd06aa 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-coex.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-coex.h
@@ -7,6 +7,7 @@
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -33,6 +34,7 @@
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -99,8 +101,8 @@ enum iwl_bt_coex_enabled_modules {
/**
* struct iwl_bt_coex_cmd - bt coex configuration command
- * @mode: enum %iwl_bt_coex_mode
- * @enabled_modules: enum %iwl_bt_coex_enabled_modules
+ * @mode: &enum iwl_bt_coex_mode
+ * @enabled_modules: &enum iwl_bt_coex_enabled_modules
*
* The structure is used for the BT_COEX command.
*/
@@ -132,10 +134,10 @@ struct iwl_bt_coex_reduced_txp_update_cmd {
/**
* struct iwl_bt_coex_ci_cmd - bt coex channel inhibition command
- * @bt_primary_ci:
- * @primary_ch_phy_id:
- * @bt_secondary_ci:
- * @secondary_ch_phy_id:
+ * @bt_primary_ci: primary channel inhibition bitmap
+ * @primary_ch_phy_id: primary channel PHY ID
+ * @bt_secondary_ci: secondary channel inhibition bitmap
+ * @secondary_ch_phy_id: secondary channel PHY ID
*
* Used for BT_COEX_CI command
*/
@@ -234,10 +236,11 @@ enum iwl_bt_ci_compliance {
* @mbox_msg: message from BT to WiFi
* @msg_idx: the index of the message
* @bt_ci_compliance: enum %iwl_bt_ci_compliance
- * @primary_ch_lut: LUT used for primary channel enum %iwl_bt_coex_lut_type
- * @secondary_ch_lut: LUT used for secondary channel enume %iwl_bt_coex_lut_type
- * @bt_activity_grading: the activity of BT enum %iwl_bt_activity_grading
+ * @primary_ch_lut: LUT used for primary channel &enum iwl_bt_coex_lut_type
+ * @secondary_ch_lut: LUT used for secondary channel &enum iwl_bt_coex_lut_type
+ * @bt_activity_grading: the activity of BT &enum iwl_bt_activity_grading
* @ttc_rrc_status: is TTC or RRC enabled - one bit per PHY
+ * @reserved: reserved
*/
struct iwl_bt_coex_profile_notif {
__le32 mbox_msg[4];
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h
index 5f22cc7..d4a4c28 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
- * Copyright(c) 2015 Intel Deutschland GmbH
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -34,6 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -138,6 +139,7 @@ struct iwl_proto_offload_cmd_common {
* for each target address
* @target_ipv6_addr: our target addresses
* @ndp_mac_addr: neighbor solicitation response MAC address
+ * @reserved2: reserved
*/
struct iwl_proto_offload_cmd_v1 {
struct iwl_proto_offload_cmd_common common;
@@ -156,6 +158,8 @@ struct iwl_proto_offload_cmd_v1 {
* for each target address
* @target_ipv6_addr: our target addresses
* @ndp_mac_addr: neighbor solicitation response MAC address
+ * @num_valid_ipv6_addrs: number of valid IPv6 addresses
+ * @reserved2: reserved
*/
struct iwl_proto_offload_cmd_v2 {
struct iwl_proto_offload_cmd_common common;
@@ -163,7 +167,7 @@ struct iwl_proto_offload_cmd_v2 {
u8 solicited_node_ipv6_addr[16];
u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2][16];
u8 ndp_mac_addr[ETH_ALEN];
- u8 numValidIPv6Addresses;
+ u8 num_valid_ipv6_addrs;
u8 reserved2[3];
} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_2 */
@@ -182,7 +186,8 @@ struct iwl_targ_addr {
/**
* struct iwl_proto_offload_cmd_v3_small - ARP/NS offload configuration
* @common: common/IPv4 configuration
- * @target_ipv6_addr: target IPv6 addresses
+ * @num_valid_ipv6_addrs: number of valid IPv6 addresses
+ * @targ_addrs: target IPv6 addresses
* @ns_config: NS offload configurations
*/
struct iwl_proto_offload_cmd_v3_small {
@@ -195,7 +200,8 @@ struct iwl_proto_offload_cmd_v3_small {
/**
* struct iwl_proto_offload_cmd_v3_large - ARP/NS offload configuration
* @common: common/IPv4 configuration
- * @target_ipv6_addr: target IPv6 addresses
+ * @num_valid_ipv6_addrs: number of valid IPv6 addresses
+ * @targ_addrs: target IPv6 addresses
* @ns_config: NS offload configurations
*/
struct iwl_proto_offload_cmd_v3_large {
@@ -254,6 +260,17 @@ enum iwl_wowlan_flags {
ENABLE_STORE_BEACON = BIT(4),
};
+/**
+ * struct iwl_wowlan_config_cmd - WoWLAN configuration
+ * @wakeup_filter: filter from &enum iwl_wowlan_wakeup_filters
+ * @non_qos_seq: non-QoS sequence counter to use next
+ * @qos_seq: QoS sequence counters to use next
+ * @wowlan_ba_teardown_tids: bitmap of BA sessions to tear down
+ * @is_11n_connection: indicates HT connection
+ * @offloading_tid: TID reserved for firmware use
+ * @flags: extra flags, see &enum iwl_wowlan_flags
+ * @reserved: reserved
+ */
struct iwl_wowlan_config_cmd {
__le32 wakeup_filter;
__le16 non_qos_seq;
@@ -370,6 +387,21 @@ struct iwl_wowlan_gtk_status {
struct iwl_wowlan_rsc_tsc_params_cmd rsc;
} __packed; /* WOWLAN_GTK_MATERIAL_VER_1 */
+/**
+ * struct iwl_wowlan_status - WoWLAN status
+ * @gtk: GTK data
+ * @replay_ctr: GTK rekey replay counter
+ * @pattern_number: number of the matched pattern
+ * @non_qos_seq_ctr: non-QoS sequence counter to use next
+ * @qos_seq_ctr: QoS sequence counters to use next
+ * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
+ * @num_of_gtk_rekeys: number of GTK rekeys
+ * @transmitted_ndps: number of transmitted neighbor discovery packets
+ * @received_beacons: number of received beacons
+ * @wake_packet_length: wakeup packet length
+ * @wake_packet_bufsize: wakeup packet buffer size
+ * @wake_packet: wakeup packet
+ */
struct iwl_wowlan_status {
struct iwl_wowlan_gtk_status gtk;
__le64 replay_ctr;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-mac.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-mac.h
index 970b030..0c3350a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-mac.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-mac.h
@@ -199,6 +199,7 @@ struct iwl_mac_data_ibss {
* @dtim_reciprocal: 2^32 / dtim_interval , applicable only when associated
* @listen_interval: in beacon intervals, applicable only when associated
* @assoc_id: unique ID assigned by the AP during association
+ * @assoc_beacon_arrive_time: TSF of first beacon after association
*/
struct iwl_mac_data_sta {
__le32 is_assoc;
@@ -329,19 +330,20 @@ struct iwl_ac_qos {
* ( MAC_CONTEXT_CMD = 0x28 )
* @id_and_color: ID and color of the MAC
* @action: action to perform, one of FW_CTXT_ACTION_*
- * @mac_type: one of FW_MAC_TYPE_*
- * @tsd_id: TSF HW timer, one of TSF_ID_*
+ * @mac_type: one of &enum iwl_mac_types
+ * @tsf_id: TSF HW timer, one of &enum iwl_tsf_id
* @node_addr: MAC address
+ * @reserved_for_node_addr: reserved
* @bssid_addr: BSSID
+ * @reserved_for_bssid_addr: reserved
* @cck_rates: basic rates available for CCK
* @ofdm_rates: basic rates available for OFDM
- * @protection_flags: combination of MAC_PROT_FLG_FLAG_*
+ * @protection_flags: combination of &enum iwl_mac_protection_flags
* @cck_short_preamble: 0x20 for enabling short preamble, 0 otherwise
* @short_slot: 0x10 for enabling short slots, 0 otherwise
- * @filter_flags: combination of MAC_FILTER_*
- * @qos_flags: from MAC_QOS_FLG_*
+ * @filter_flags: combination of &enum iwl_mac_filter_flags
+ * @qos_flags: from &enum iwl_mac_qos_flags
* @ac: one iwl_mac_qos configuration for each AC
- * @mac_specific: one of struct iwl_mac_data_*, according to mac_type
*/
struct iwl_mac_ctx_cmd {
/* COMMON_INDEX_HDR_API_S_VER_1 */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-power.h
index 750510a..7da57ef 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-power.h
@@ -82,6 +82,8 @@
* @LTR_CFG_FLAG_SW_SET_SHORT: fixed static short LTR register
* @LTR_CFG_FLAG_SW_SET_LONG: fixed static short LONG register
* @LTR_CFG_FLAG_DENIE_C10_ON_PD: allow going into C10 on PD
+ * @LTR_CFG_FLAG_UPDATE_VALUES: update config values and short
+ * idle timeout
*/
enum iwl_ltr_config_flags {
LTR_CFG_FLAG_FEATURE_ENABLE = BIT(0),
@@ -91,11 +93,14 @@ enum iwl_ltr_config_flags {
LTR_CFG_FLAG_SW_SET_SHORT = BIT(4),
LTR_CFG_FLAG_SW_SET_LONG = BIT(5),
LTR_CFG_FLAG_DENIE_C10_ON_PD = BIT(6),
+ LTR_CFG_FLAG_UPDATE_VALUES = BIT(7),
};
/**
* struct iwl_ltr_config_cmd_v1 - configures the LTR
- * @flags: See %enum iwl_ltr_config_flags
+ * @flags: See &enum iwl_ltr_config_flags
+ * @static_long: static LTR Long register value.
+ * @static_short: static LTR Short register value.
*/
struct iwl_ltr_config_cmd_v1 {
__le32 flags;
@@ -107,11 +112,14 @@ struct iwl_ltr_config_cmd_v1 {
/**
* struct iwl_ltr_config_cmd - configures the LTR
- * @flags: See %enum iwl_ltr_config_flags
- * @static_long:
- * @static_short:
- * @ltr_cfg_values:
- * @ltr_short_idle_timeout:
+ * @flags: See &enum iwl_ltr_config_flags
+ * @static_long: static LTR Long register value.
+ * @static_short: static LTR Short register value.
+ * @ltr_cfg_values: LTR parameters table values (in usec) in folowing order:
+ * TX, RX, Short Idle, Long Idle. Used only if %LTR_CFG_FLAG_UPDATE_VALUES
+ * is set.
+ * @ltr_short_idle_timeout: LTR Short Idle timeout (in usec). Used only if
+ * %LTR_CFG_FLAG_UPDATE_VALUES is set.
*/
struct iwl_ltr_config_cmd {
__le32 flags;
@@ -140,7 +148,7 @@ struct iwl_ltr_config_cmd {
* PBW Snoozing enabled
* @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask
* @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
- * @POWER_FLAGS_AP_UAPSD_MISBEHAVING_ENA_MSK: AP/GO's uAPSD misbehaving
+ * @POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK: AP/GO's uAPSD misbehaving
* detection enablement
*/
enum iwl_power_flags {
@@ -166,6 +174,7 @@ enum iwl_power_flags {
* 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.
+ * @debug_flags: debug flags
* @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
@@ -191,7 +200,8 @@ struct iwl_powertable_cmd {
/**
* enum iwl_device_power_flags - masks for device power command flags
- * @DEVIC_POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
+ * @DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK:
+ * '1' Allow to save power by turning off
* receiver and transmitter. '0' - does not allow.
*/
enum iwl_device_power_flags {
@@ -202,7 +212,8 @@ enum iwl_device_power_flags {
* struct iwl_device_power_cmd - device wide power command.
* DEVICE_POWER_CMD = 0x77 (command, has simple generic response)
*
- * @flags: Power table command flags from DEVICE_POWER_FLAGS_*
+ * @flags: Power table command flags from &enum iwl_device_power_flags
+ * @reserved: reserved (padding)
*/
struct iwl_device_power_cmd {
/* PM_POWER_TABLE_CMD_API_S_VER_6 */
@@ -213,7 +224,7 @@ struct iwl_device_power_cmd {
/**
* struct iwl_mac_power_cmd - New power command containing uAPSD support
* MAC_PM_POWER_TABLE = 0xA9 (command, has simple generic response)
- * @id_and_color: MAC contex identifier
+ * @id_and_color: MAC contex identifier, &enum iwl_mvm_id_and_color
* @flags: Power table command flags from POWER_FLAGS_*
* @keep_alive_seconds: Keep alive period in seconds. Default - 25 sec.
* Minimum allowed:- 3 * DTIM. Keep alive period must be
@@ -223,7 +234,6 @@ struct iwl_device_power_cmd {
* PSM transition - legacy PM
* @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to
* PSM transition - legacy PM
- * @sleep_interval: not in use
* @skip_dtim_periods: Number of DTIM periods to skip if Skip over DTIM flag
* is set. For example, if it is required to skip over
* one DTIM, this value need to be set to 2 (DTIM periods).
@@ -233,7 +243,6 @@ struct iwl_device_power_cmd {
* PSM transition - uAPSD
* @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: Maximum time between attempts to retrieve buffered data
* from the AP [msec]
* @snooze_window: A window of time in which PBW snoozing insures that all
@@ -251,8 +260,9 @@ struct iwl_device_power_cmd {
* @heavy_rx_thld_packets: RX threshold measured in number of packets
* @heavy_tx_thld_percentage: TX threshold measured in load's percentage
* @heavy_rx_thld_percentage: RX threshold measured in load's percentage
- * @limited_ps_threshold:
-*/
+ * @limited_ps_threshold: (unused)
+ * @reserved: reserved (padding)
+ */
struct iwl_mac_power_cmd {
/* CONTEXT_DESC_API_T_VER_1 */
__le32 id_and_color;
@@ -343,6 +353,7 @@ struct iwl_dev_tx_power_cmd_v3 {
* @v3: version 3 of the command, embedded here for easier software handling
* @enable_ack_reduction: enable or disable close range ack TX power
* reduction.
+ * @reserved: reserved (padding)
*/
struct iwl_dev_tx_power_cmd {
/* v4 is just an extension of v3 - keep this here */
@@ -352,6 +363,7 @@ struct iwl_dev_tx_power_cmd {
} __packed; /* TX_REDUCED_POWER_API_S_VER_4 */
#define IWL_NUM_GEO_PROFILES 3
+#define IWL_GEO_PER_CHAIN_SIZE 3
/**
* enum iwl_geo_per_chain_offset_operation - type of operation
@@ -391,9 +403,16 @@ struct iwl_geo_tx_power_profiles_cmd {
} __packed; /* GEO_TX_POWER_LIMIT */
/**
+ * struct iwl_geo_tx_power_profiles_resp - response to GEO_TX_POWER_LIMIT cmd
+ * @profile_idx: current geo profile in use
+ */
+struct iwl_geo_tx_power_profiles_resp {
+ __le32 profile_idx;
+} __packed; /* GEO_TX_POWER_LIMIT_RESP */
+
+/**
* struct iwl_beacon_filter_cmd
* REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
- * @id_and_color: MAC contex identifier
* @bf_energy_delta: Used for RSSI filtering, if in 'normal' state. Send beacon
* to driver if delta in Energy values calculated for this and last
* passed beacon is greater than this threshold. Zero value means that
@@ -411,7 +430,7 @@ struct iwl_geo_tx_power_profiles_cmd {
* Threshold. Typical energy threshold is -72dBm.
* @bf_temp_threshold: This threshold determines the type of temperature
* filtering (Slow or Fast) that is selected (Units are in Celsuis):
- * If the current temperature is above this threshold - Fast filter
+ * If the current temperature is above this threshold - Fast filter
* will be used, If the current temperature is below this threshold -
* Slow filter will be used.
* @bf_temp_fast_filter: Send Beacon to driver if delta in temperature values
@@ -425,7 +444,8 @@ struct iwl_geo_tx_power_profiles_cmd {
* beacon filtering; beacons will not be forced to be sent to driver
* regardless of whether its temerature has been changed.
* @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled.
- * @bf_filter_escape_timer: Send beacons to to driver if no beacons were passed
+ * @bf_debug_flag: beacon filtering debug configuration
+ * @bf_escape_timer: Send beacons to to driver if no beacons were passed
* for a specific period of time. Units: Beacons.
* @ba_escape_timer: Fully receive and parse beacon if no beacons were passed
* for a longer period of time then this escape-timeout. Units: Beacons.
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h
index a10c6aa..bdf1228 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h
@@ -368,6 +368,7 @@ enum {
/**
* struct iwl_lq_cmd - link quality command
* @sta_id: station to update
+ * @reduced_tpc: reduced transmit power control value
* @control: not used
* @flags: combination of LQ_FLAG_*
* @mimo_delim: the first SISO index in rs_table, which separates MIMO
@@ -385,6 +386,7 @@ enum {
* 0: no limit
* 1: no aggregation (one frame per aggregation)
* 2 - 0x3f: maximal number of frames (up to 3f == 63)
+ * @reserved2: reserved
* @rs_table: array of rates for each TX try, each is rate_n_flags,
* meaning it is a combination of RATE_MCS_* and IWL_RATE_*_PLCP
* @ss_params: single stream features. declare whether STBC or BFER are allowed.
@@ -392,7 +394,7 @@ enum {
struct iwl_lq_cmd {
u8 sta_id;
u8 reduced_tpc;
- u16 control;
+ __le16 control;
/* LINK_QUAL_GENERAL_PARAMS_API_S_VER_1 */
u8 flags;
u8 mimo_delim;
@@ -407,4 +409,5 @@ struct iwl_lq_cmd {
__le32 rs_table[LQ_MAX_RETRY_NUM];
__le32 ss_params;
}; /* LINK_QUALITY_CMD_API_S_VER_1 */
+
#endif /* __fw_api_rs_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
index b530fa4..59038ad 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -34,7 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -90,13 +90,13 @@ enum iwl_mac_context_info {
* @non_cfg_phy_cnt: non configurable DSP phy data byte count
* @cfg_phy_cnt: configurable DSP phy data byte count
* @stat_id: configurable DSP phy data set ID
- * @reserved1:
+ * @reserved1: reserved
* @system_timestamp: GP2 at on air rise
* @timestamp: TSF at on air rise
* @beacon_time_stamp: beacon at on-air rise
* @phy_flags: general phy flags: band, modulation, ...
* @channel: channel number
- * @non_cfg_phy_buf: for various implementations of non_cfg_phy
+ * @non_cfg_phy: for various implementations of non_cfg_phy
* @rate_n_flags: RATE_MCS_*
* @byte_count: frame's byte-count
* @frame_time: frame's time on the air, based on byte count and frame rate
@@ -147,7 +147,8 @@ enum iwl_csum_rx_assist_info {
/**
* struct iwl_rx_mpdu_res_start - phy info
- * @assist: see CSUM_RX_ASSIST_ above
+ * @byte_count: byte count of the frame
+ * @assist: see &enum iwl_csum_rx_assist_info
*/
struct iwl_rx_mpdu_res_start {
__le16 byte_count;
@@ -157,10 +158,11 @@ struct iwl_rx_mpdu_res_start {
/**
* enum iwl_rx_phy_flags - to parse %iwl_rx_phy_info phy_flags
* @RX_RES_PHY_FLAGS_BAND_24: true if the packet was received on 2.4 band
- * @RX_RES_PHY_FLAGS_MOD_CCK:
+ * @RX_RES_PHY_FLAGS_MOD_CCK: modulation is CCK
* @RX_RES_PHY_FLAGS_SHORT_PREAMBLE: true if packet's preamble was short
- * @RX_RES_PHY_FLAGS_NARROW_BAND:
+ * @RX_RES_PHY_FLAGS_NARROW_BAND: narrow band (<20 MHz) receive
* @RX_RES_PHY_FLAGS_ANTENNA: antenna on which the packet was received
+ * @RX_RES_PHY_FLAGS_ANTENNA_POS: antenna bit position
* @RX_RES_PHY_FLAGS_AGG: set if the packet was part of an A-MPDU
* @RX_RES_PHY_FLAGS_OFDM_HT: The frame was an HT frame
* @RX_RES_PHY_FLAGS_OFDM_GF: The frame used GF preamble
@@ -183,9 +185,9 @@ enum iwl_rx_phy_flags {
* enum iwl_mvm_rx_status - written by fw for each Rx packet
* @RX_MPDU_RES_STATUS_CRC_OK: CRC is fine
* @RX_MPDU_RES_STATUS_OVERRUN_OK: there was no RXE overflow
- * @RX_MPDU_RES_STATUS_SRC_STA_FOUND:
- * @RX_MPDU_RES_STATUS_KEY_VALID:
- * @RX_MPDU_RES_STATUS_KEY_PARAM_OK:
+ * @RX_MPDU_RES_STATUS_SRC_STA_FOUND: station was found
+ * @RX_MPDU_RES_STATUS_KEY_VALID: key was valid
+ * @RX_MPDU_RES_STATUS_KEY_PARAM_OK: key parameters were usable
* @RX_MPDU_RES_STATUS_ICV_OK: ICV is fine, if not, the packet is destroyed
* @RX_MPDU_RES_STATUS_MIC_OK: used for CCM alg only. TKIP MIC is checked
* in the driver.
@@ -197,21 +199,21 @@ enum iwl_rx_phy_flags {
* @RX_MPDU_RES_STATUS_SEC_WEP_ENC: this frame is encrypted using WEP
* @RX_MPDU_RES_STATUS_SEC_CCM_ENC: this frame is encrypted using CCM
* @RX_MPDU_RES_STATUS_SEC_TKIP_ENC: this frame is encrypted using TKIP
+ * @RX_MPDU_RES_STATUS_SEC_EXT_ENC: this frame is encrypted using extension
+ * algorithm
* @RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC: this frame is encrypted using CCM_CMAC
* @RX_MPDU_RES_STATUS_SEC_ENC_ERR: this frame couldn't be decrypted
* @RX_MPDU_RES_STATUS_SEC_ENC_MSK: bitmask of the encryption algorithm
* @RX_MPDU_RES_STATUS_DEC_DONE: this frame has been successfully decrypted
- * @RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP:
- * @RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP:
- * @RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT:
+ * @RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP: extended IV (set with TKIP)
+ * @RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT: key ID comparison done
* @RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME: this frame is an 11w management frame
* @RX_MPDU_RES_STATUS_CSUM_DONE: checksum was done by the hw
* @RX_MPDU_RES_STATUS_CSUM_OK: checksum found no errors
- * @RX_MPDU_RES_STATUS_HASH_INDEX_MSK:
- * @RX_MPDU_RES_STATUS_STA_ID_MSK:
- * @RX_MPDU_RES_STATUS_RRF_KILL:
- * @RX_MPDU_RES_STATUS_FILTERING_MSK:
- * @RX_MPDU_RES_STATUS2_FILTERING_MSK:
+ * @RX_MPDU_RES_STATUS_STA_ID_MSK: station ID mask
+ * @RX_MDPU_RES_STATUS_STA_ID_SHIFT: station ID bit shift
+ * @RX_MPDU_RES_STATUS_FILTERING_MSK: filter status
+ * @RX_MPDU_RES_STATUS2_FILTERING_MSK: filter status 2
*/
enum iwl_mvm_rx_status {
RX_MPDU_RES_STATUS_CRC_OK = BIT(0),
@@ -232,16 +234,13 @@ enum iwl_mvm_rx_status {
RX_MPDU_RES_STATUS_SEC_ENC_ERR = (7 << 8),
RX_MPDU_RES_STATUS_SEC_ENC_MSK = (7 << 8),
RX_MPDU_RES_STATUS_DEC_DONE = BIT(11),
- RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP = BIT(12),
RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP = BIT(13),
RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT = BIT(14),
RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME = BIT(15),
RX_MPDU_RES_STATUS_CSUM_DONE = BIT(16),
RX_MPDU_RES_STATUS_CSUM_OK = BIT(17),
- RX_MPDU_RES_STATUS_HASH_INDEX_MSK = (0x3F0000),
RX_MDPU_RES_STATUS_STA_ID_SHIFT = 24,
RX_MPDU_RES_STATUS_STA_ID_MSK = 0x1f << RX_MDPU_RES_STATUS_STA_ID_SHIFT,
- RX_MPDU_RES_STATUS_RRF_KILL = BIT(29),
RX_MPDU_RES_STATUS_FILTERING_MSK = (0xc00000),
RX_MPDU_RES_STATUS2_FILTERING_MSK = (0xc0000000),
};
@@ -348,35 +347,106 @@ enum iwl_rx_mpdu_mac_info {
IWL_RX_MPDU_PHY_PHY_INDEX_MASK = 0xf0,
};
+/**
+ * struct iwl_rx_mpdu_desc - RX MPDU descriptor
+ */
struct iwl_rx_mpdu_desc {
/* DW2 */
+ /**
+ * @mpdu_len: MPDU length
+ */
__le16 mpdu_len;
+ /**
+ * @mac_flags1: &enum iwl_rx_mpdu_mac_flags1
+ */
u8 mac_flags1;
+ /**
+ * @mac_flags2: &enum iwl_rx_mpdu_mac_flags2
+ */
u8 mac_flags2;
/* DW3 */
+ /**
+ * @amsdu_info: &enum iwl_rx_mpdu_amsdu_info
+ */
u8 amsdu_info;
+ /**
+ * @phy_info: &enum iwl_rx_mpdu_phy_info
+ */
__le16 phy_info;
+ /**
+ * @mac_phy_idx: MAC/PHY index
+ */
u8 mac_phy_idx;
/* DW4 - carries csum data only when rpa_en == 1 */
- __le16 raw_csum; /* alledgedly unreliable */
+ /**
+ * @raw_csum: raw checksum (alledgedly unreliable)
+ */
+ __le16 raw_csum;
+ /**
+ * @l3l4_flags: &enum iwl_rx_l3l4_flags
+ */
__le16 l3l4_flags;
/* DW5 */
+ /**
+ * @status: &enum iwl_rx_mpdu_status
+ */
__le16 status;
+ /**
+ * @hash_filter: hash filter value
+ */
u8 hash_filter;
+ /**
+ * @sta_id_flags: &enum iwl_rx_mpdu_sta_id_flags
+ */
u8 sta_id_flags;
/* DW6 */
+ /**
+ * @reorder_data: &enum iwl_rx_mpdu_reorder_data
+ */
__le32 reorder_data;
/* DW7 - carries rss_hash only when rpa_en == 1 */
+ /**
+ * @rss_hash: RSS hash value
+ */
__le32 rss_hash;
/* DW8 - carries filter_match only when rpa_en == 1 */
+ /**
+ * @filter_match: filter match value
+ */
__le32 filter_match;
/* DW9 */
+ /**
+ * @rate_n_flags: RX rate/flags encoding
+ */
__le32 rate_n_flags;
/* DW10 */
- u8 energy_a, energy_b, channel, mac_context;
+ /**
+ * @energy_a: energy chain A
+ */
+ u8 energy_a;
+ /**
+ * @energy_b: energy chain B
+ */
+ u8 energy_b;
+ /**
+ * @channel: channel number
+ */
+ u8 channel;
+ /**
+ * @mac_context: MAC context mask
+ */
+ u8 mac_context;
/* DW11 */
+ /**
+ * @gp2_on_air_rise: GP2 timer value on air rise (INA)
+ */
__le32 gp2_on_air_rise;
- /* DW12 & DW13 - carries TSF only TSF_OVERLOAD bit == 0 */
+ /* DW12 & DW13 */
+ /**
+ * @tsf_on_air_rise:
+ * TSF value on air rise (INA), only valid if
+ * %IWL_RX_MPDU_PHY_TSF_OVERLOAD isn't set
+ */
__le64 tsf_on_air_rise;
} __packed;
@@ -404,6 +474,7 @@ enum iwl_rss_hash_func_en {
*
* @flags: 1 - enable, 0 - disable
* @hash_mask: Type of RSS to use. Values are from %iwl_rss_hash_func_en
+ * @reserved: reserved
* @secret_key: 320 bit input of random key configuration from driver
* @indirection_table: indirection table
*/
@@ -447,7 +518,7 @@ struct iwl_rxq_sync_notification {
} __packed; /* MULTI_QUEUE_DRV_SYNC_HDR_CMD_API_S_VER_1 */
/**
- * Internal message identifier
+ * enum iwl_mvm_rxq_notif_type - Internal message identifier
*
* @IWL_MVM_RXQ_EMPTY: empty sync notification
* @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA
@@ -491,13 +562,13 @@ enum iwl_mvm_pm_event {
/**
* struct iwl_mvm_pm_state_notification - station PM state notification
* @sta_id: station ID of the station changing state
- * @type: the new powersave state, see IWL_MVM_PM_EVENT_ above
+ * @type: the new powersave state, see &enum iwl_mvm_pm_event
*/
struct iwl_mvm_pm_state_notification {
u8 sta_id;
u8 type;
/* private: */
- u16 reserved;
+ __le16 reserved;
} __packed; /* PEER_PM_NTFY_API_S_VER_1 */
#endif /* __fw_api_rx_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-scan.h
index 3178eb9..1cd7cc0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-scan.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-scan.h
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -34,6 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -67,8 +68,6 @@
#ifndef __fw_api_scan_h__
#define __fw_api_scan_h__
-#include "fw-api.h"
-
/* Scan Commands, Responses, Notifications */
/* Max number of IEs for direct SSID scans in a command */
@@ -81,6 +80,10 @@
* selected by "type" bit field in struct iwl_scan_channel;
* each channel may select different ssids from among the 20 entries.
* SSID IEs get transmitted in reverse order of entry.
+ *
+ * @id: element ID
+ * @len: element length
+ * @ssid: element (SSID) data
*/
struct iwl_ssid_ie {
u8 id;
@@ -111,7 +114,7 @@ enum scan_framework_client {
};
/**
- * iwl_scan_offload_blacklist - SCAN_OFFLOAD_BLACKLIST_S
+ * struct iwl_scan_offload_blacklist - SCAN_OFFLOAD_BLACKLIST_S
* @ssid: MAC address to filter out
* @reported_rssi: AP rssi reported to the host
* @client_bitmap: clients ignore this entry - enum scan_framework_client
@@ -135,13 +138,14 @@ enum iwl_scan_offload_band_selection {
};
/**
- * iwl_scan_offload_profile - SCAN_OFFLOAD_PROFILE_S
+ * struct iwl_scan_offload_profile - SCAN_OFFLOAD_PROFILE_S
* @ssid_index: index to ssid list in fixed part
* @unicast_cipher: encryption algorithm to match - bitmap
- * @aut_alg: authentication algorithm to match - bitmap
+ * @auth_alg: authentication algorithm to match - bitmap
* @network_type: enum iwl_scan_offload_network_type
* @band_selection: enum iwl_scan_offload_band_selection
* @client_bitmap: clients waiting for match - enum scan_framework_client
+ * @reserved: reserved
*/
struct iwl_scan_offload_profile {
u8 ssid_index;
@@ -154,8 +158,7 @@ struct iwl_scan_offload_profile {
} __packed;
/**
- * iwl_scan_offload_profile_cfg - SCAN_OFFLOAD_PROFILES_CFG_API_S_VER_1
- * @blaclist: AP list to filter off from scan results
+ * struct iwl_scan_offload_profile_cfg - SCAN_OFFLOAD_PROFILES_CFG_API_S_VER_1
* @profiles: profiles to search for match
* @blacklist_len: length of blacklist
* @num_profiles: num of profiles in the list
@@ -163,6 +166,7 @@ struct iwl_scan_offload_profile {
* @pass_match: clients waiting for the results
* @active_clients: active clients bitmap - enum scan_framework_client
* @any_beacon_notify: clients waiting for match notification without match
+ * @reserved: reserved
*/
struct iwl_scan_offload_profile_cfg {
struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES];
@@ -176,7 +180,7 @@ struct iwl_scan_offload_profile_cfg {
} __packed;
/**
- * iwl_scan_schedule_lmac - schedule of scan offload
+ * struct iwl_scan_schedule_lmac - schedule of scan offload
* @delay: delay between iterations, in seconds.
* @iterations: num of scan iterations
* @full_scan_mul: number of partial scans before each full scan
@@ -200,7 +204,7 @@ enum iwl_scan_ebs_status {
};
/**
- * iwl_scan_req_tx_cmd - SCAN_REQ_TX_CMD_API_S
+ * struct iwl_scan_req_tx_cmd - SCAN_REQ_TX_CMD_API_S
* @tx_flags: combination of TX_CMD_FLG_*
* @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
* cleared. Combination of RATE_MCS_*
@@ -220,10 +224,10 @@ enum iwl_scan_channel_flags_lmac {
};
/**
- * iwl_scan_channel_cfg_lmac - SCAN_CHANNEL_CFG_S_VER2
+ * struct iwl_scan_channel_cfg_lmac - SCAN_CHANNEL_CFG_S_VER2
* @flags: bits 1-20: directed scan to i'th ssid
* other bits &enum iwl_scan_channel_flags_lmac
- * @channel_number: channel number 1-13 etc
+ * @channel_num: channel number 1-13 etc
* @iter_count: scan iteration on this channel
* @iter_interval: interval in seconds between iterations on one channel
*/
@@ -235,7 +239,7 @@ struct iwl_scan_channel_cfg_lmac {
} __packed;
/*
- * iwl_scan_probe_segment - PROBE_SEGMENT_API_S_VER_1
+ * struct iwl_scan_probe_segment - PROBE_SEGMENT_API_S_VER_1
* @offset: offset in the data block
* @len: length of the segment
*/
@@ -263,7 +267,7 @@ enum iwl_scan_channel_flags {
IWL_SCAN_CHANNEL_FLAG_CACHE_ADD = BIT(2),
};
-/* iwl_scan_channel_opt - CHANNEL_OPTIMIZATION_API_S
+/* struct iwl_scan_channel_opt - CHANNEL_OPTIMIZATION_API_S
* @flags: enum iwl_scan_channel_flags
* @non_ebs_ratio: defines the ratio of number of scan iterations where EBS is
* involved.
@@ -276,13 +280,13 @@ struct iwl_scan_channel_opt {
} __packed;
/**
- * iwl_mvm_lmac_scan_flags
+ * enum iwl_mvm_lmac_scan_flags - LMAC scan flags
* @IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL: pass all beacons and probe responses
* without filtering.
* @IWL_MVM_LMAC_SCAN_FLAG_PASSIVE: force passive scan on all channels
* @IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION: single channel scan
* @IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE: send iteration complete notification
- * @IWL_MVM_LMAC_SCAN_FLAG_MULTIPLE_SSIDS multiple SSID matching
+ * @IWL_MVM_LMAC_SCAN_FLAG_MULTIPLE_SSIDS: multiple SSID matching
* @IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED: all passive scans will be fragmented
* @IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED: insert WFA vendor-specific TPC report
* and DS parameter set IEs into probe requests.
@@ -320,15 +324,15 @@ enum iwl_scan_priority_ext {
};
/**
- * iwl_scan_req_lmac - SCAN_REQUEST_CMD_API_S_VER_1
+ * struct iwl_scan_req_lmac - SCAN_REQUEST_CMD_API_S_VER_1
* @reserved1: for alignment and future use
- * @channel_num: num of channels to scan
- * @active-dwell: dwell time for active channels
- * @passive-dwell: dwell time for passive channels
- * @fragmented-dwell: dwell time for fragmented passive scan
+ * @n_channels: num of channels to scan
+ * @active_dwell: dwell time for active channels
+ * @passive_dwell: dwell time for passive channels
+ * @fragmented_dwell: dwell time for fragmented passive scan
* @extended_dwell: dwell time for channels 1, 6 and 11 (in certain cases)
* @reserved2: for alignment and future use
- * @rx_chain_selct: PHY_RX_CHAIN_* flags
+ * @rx_chain_select: PHY_RX_CHAIN_* flags
* @scan_flags: &enum iwl_mvm_lmac_scan_flags
* @max_out_time: max time (in TU) to be out of associated channel
* @suspend_time: pause scan this long (TUs) when returning to service channel
@@ -410,12 +414,13 @@ struct iwl_lmac_scan_complete_notif {
} __packed;
/**
- * iwl_scan_offload_complete - PERIODIC_SCAN_COMPLETE_NTF_API_S_VER_2
+ * struct iwl_scan_offload_complete - PERIODIC_SCAN_COMPLETE_NTF_API_S_VER_2
* @last_schedule_line: last schedule line executed (fast or regular)
* @last_schedule_iteration: last scan iteration executed before scan abort
- * @status: enum iwl_scan_offload_complete_status
+ * @status: &enum iwl_scan_offload_complete_status
* @ebs_status: EBS success status &enum iwl_scan_ebs_status
- * @time_after_last_iter; time in seconds elapsed after last iteration
+ * @time_after_last_iter: time in seconds elapsed after last iteration
+ * @reserved: reserved
*/
struct iwl_periodic_scan_complete {
u8 last_schedule_line;
@@ -547,12 +552,12 @@ struct iwl_scan_config {
} __packed; /* SCAN_CONFIG_DB_CMD_API_S_3 */
/**
- * iwl_umac_scan_flags
- *@IWL_UMAC_SCAN_FLAG_PREEMPTIVE: scan process triggered by this scan request
+ * enum iwl_umac_scan_flags - UMAC scan flags
+ * @IWL_UMAC_SCAN_FLAG_PREEMPTIVE: scan process triggered by this scan request
* can be preempted by other scan requests with higher priority.
* The low priority scan will be resumed when the higher proirity scan is
* completed.
- *@IWL_UMAC_SCAN_FLAG_START_NOTIF: notification will be sent to the driver
+ * @IWL_UMAC_SCAN_FLAG_START_NOTIF: notification will be sent to the driver
* when scan starts.
*/
enum iwl_umac_scan_flags {
@@ -701,8 +706,8 @@ struct iwl_umac_scan_abort {
* struct iwl_umac_scan_complete
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
* @last_schedule: last scheduling line
- * @last_iter: last scan iteration number
- * @scan status: &enum iwl_scan_offload_complete_status
+ * @last_iter: last scan iteration number
+ * @status: &enum iwl_scan_offload_complete_status
* @ebs_status: &enum iwl_scan_ebs_status
* @time_from_last_iter: time elapsed from last iteration
* @reserved: for future use
@@ -721,9 +726,10 @@ struct iwl_umac_scan_complete {
/**
* struct iwl_scan_offload_profile_match - match information
* @bssid: matched bssid
+ * @reserved: reserved
* @channel: channel where the match occurred
- * @energy:
- * @matching_feature:
+ * @energy: energy
+ * @matching_feature: feature matches
* @matching_channels: bitmap of channels that matched, referencing
* the channels passed in tue scan offload request
*/
@@ -771,7 +777,7 @@ struct iwl_scan_offload_profiles_query {
* @last_channel: last channel that was scanned
* @start_tsf: TSF timer in usecs of the scan start time for the mac specified
* in &struct iwl_scan_req_umac.
- * @results: array of scan results, only "scanned_channels" of them are valid
+ * @results: array of scan results, length in @scanned_channels
*/
struct iwl_umac_scan_iter_complete_notif {
__le32 uid;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
index 421b9dd..81f0a34 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
@@ -69,8 +69,8 @@
/**
* enum iwl_sta_flags - flags for the ADD_STA host command
- * @STA_FLG_REDUCED_TX_PWR_CTRL:
- * @STA_FLG_REDUCED_TX_PWR_DATA:
+ * @STA_FLG_REDUCED_TX_PWR_CTRL: reduced TX power (control frames)
+ * @STA_FLG_REDUCED_TX_PWR_DATA: reduced TX power (data frames)
* @STA_FLG_DISABLE_TX: set if TX should be disabled
* @STA_FLG_PS: set if STA is in Power Save
* @STA_FLG_INVALID: set if STA is invalid
@@ -78,18 +78,40 @@
* @STA_FLG_SET_ALL_KEYS: the current key applies to all key IDs
* @STA_FLG_DRAIN_FLOW: drain flow
* @STA_FLG_PAN: STA is for PAN interface
- * @STA_FLG_CLASS_AUTH:
- * @STA_FLG_CLASS_ASSOC:
- * @STA_FLG_CLASS_MIMO_PROT:
- * @STA_FLG_MAX_AGG_SIZE_MSK: maximal size for A-MPDU
+ * @STA_FLG_CLASS_AUTH: station is authenticated
+ * @STA_FLG_CLASS_ASSOC: station is associated
+ * @STA_FLG_RTS_MIMO_PROT: station requires RTS MIMO protection (dynamic SMPS)
+ * @STA_FLG_MAX_AGG_SIZE_MSK: maximal size for A-MPDU (mask)
+ * @STA_FLG_MAX_AGG_SIZE_SHIFT: maximal size for A-MPDU (bit shift)
+ * @STA_FLG_MAX_AGG_SIZE_8K: maximal size for A-MPDU (8k supported)
+ * @STA_FLG_MAX_AGG_SIZE_16K: maximal size for A-MPDU (16k supported)
+ * @STA_FLG_MAX_AGG_SIZE_32K: maximal size for A-MPDU (32k supported)
+ * @STA_FLG_MAX_AGG_SIZE_64K: maximal size for A-MPDU (64k supported)
+ * @STA_FLG_MAX_AGG_SIZE_128K: maximal size for A-MPDU (128k supported)
+ * @STA_FLG_MAX_AGG_SIZE_256K: maximal size for A-MPDU (256k supported)
+ * @STA_FLG_MAX_AGG_SIZE_512K: maximal size for A-MPDU (512k supported)
+ * @STA_FLG_MAX_AGG_SIZE_1024K: maximal size for A-MPDU (1024k supported)
* @STA_FLG_AGG_MPDU_DENS_MSK: maximal MPDU density for Tx aggregation
* @STA_FLG_FAT_EN_MSK: support for channel width (for Tx). This flag is
* initialised by driver and can be updated by fw upon reception of
* action frames that can change the channel width. When cleared the fw
* will send all the frames in 20MHz even when FAT channel is requested.
+ * @STA_FLG_FAT_EN_20MHZ: no wide channels are supported, only 20 MHz
+ * @STA_FLG_FAT_EN_40MHZ: wide channels up to 40 MHz supported
+ * @STA_FLG_FAT_EN_80MHZ: wide channels up to 80 MHz supported
+ * @STA_FLG_FAT_EN_160MHZ: wide channels up to 160 MHz supported
* @STA_FLG_MIMO_EN_MSK: support for MIMO. This flag is initialised by the
* driver and can be updated by fw upon reception of action frames.
+ * @STA_FLG_MIMO_EN_SISO: no support for MIMO
+ * @STA_FLG_MIMO_EN_MIMO2: 2 streams supported
+ * @STA_FLG_MIMO_EN_MIMO3: 3 streams supported
* @STA_FLG_MFP_EN: Management Frame Protection
+ * @STA_FLG_AGG_MPDU_DENS_MSK: A-MPDU density (mask)
+ * @STA_FLG_AGG_MPDU_DENS_SHIFT: A-MPDU density (bit shift)
+ * @STA_FLG_AGG_MPDU_DENS_2US: A-MPDU density (2 usec gap)
+ * @STA_FLG_AGG_MPDU_DENS_4US: A-MPDU density (4 usec gap)
+ * @STA_FLG_AGG_MPDU_DENS_8US: A-MPDU density (8 usec gap)
+ * @STA_FLG_AGG_MPDU_DENS_16US: A-MPDU density (16 usec gap)
*/
enum iwl_sta_flags {
STA_FLG_REDUCED_TX_PWR_CTRL = BIT(3),
@@ -148,9 +170,10 @@ enum iwl_sta_flags {
* @STA_KEY_FLG_WEP_KEY_MAP: wep is either a group key (0 - legacy WEP) or from
* station info array (1 - n 1X mode)
* @STA_KEY_FLG_KEYID_MSK: the index of the key
+ * @STA_KEY_FLG_KEYID_POS: key index bit position
* @STA_KEY_NOT_VALID: key is invalid
* @STA_KEY_FLG_WEP_13BYTES: set for 13 bytes WEP key
- * @STA_KEY_FLG_KEY_32BYTES for non-wep key set for 32 bytes key
+ * @STA_KEY_FLG_KEY_32BYTES: for non-wep key set for 32 bytes key
* @STA_KEY_MULTICAST: set for multical key
* @STA_KEY_MFP: key is used for Management Frame Protection
*/
@@ -183,7 +206,7 @@ enum iwl_sta_key_flag {
* @STA_MODIFY_ADD_BA_TID: this command modifies %add_immediate_ba_tid
* @STA_MODIFY_REMOVE_BA_TID: this command modifies %remove_immediate_ba_tid
* @STA_MODIFY_SLEEPING_STA_TX_COUNT: this command modifies %sleep_tx_count
- * @STA_MODIFY_PROT_TH:
+ * @STA_MODIFY_PROT_TH: modify RTS threshold
* @STA_MODIFY_QUEUES: modify the queues used by this station
*/
enum iwl_sta_modify_flag {
@@ -197,13 +220,21 @@ enum iwl_sta_modify_flag {
STA_MODIFY_QUEUES = BIT(7),
};
-#define STA_MODE_MODIFY 1
+/**
+ * enum iwl_sta_mode - station command mode
+ * @STA_MODE_ADD: add new station
+ * @STA_MODE_MODIFY: modify the station
+ */
+enum iwl_sta_mode {
+ STA_MODE_ADD = 0,
+ STA_MODE_MODIFY = 1,
+};
/**
* enum iwl_sta_sleep_flag - type of sleep of the station
- * @STA_SLEEP_STATE_AWAKE:
- * @STA_SLEEP_STATE_PS_POLL:
- * @STA_SLEEP_STATE_UAPSD:
+ * @STA_SLEEP_STATE_AWAKE: station is awake
+ * @STA_SLEEP_STATE_PS_POLL: station is PS-polling
+ * @STA_SLEEP_STATE_UAPSD: station uses U-APSD
* @STA_SLEEP_STATE_MOREDATA: set more-data bit on
* (last) released frame
*/
@@ -223,10 +254,12 @@ enum iwl_sta_sleep_flag {
/**
* struct iwl_mvm_keyinfo - key information
- * @key_flags: type %iwl_sta_key_flag
+ * @key_flags: type &enum iwl_sta_key_flag
* @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection
+ * @reserved1: reserved
* @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx
* @key_offset: key offset in the fw's key table
+ * @reserved2: reserved
* @key: 16-byte unicast decryption key
* @tx_secur_seq_cnt: initial RSC / PN needed for replay check
* @hw_tkip_mic_rx_key: byte: MIC Rx Key - used for TKIP only
@@ -253,17 +286,21 @@ struct iwl_mvm_keyinfo {
/**
* struct iwl_mvm_add_sta_cmd_v7 - Add/modify a station in the fw's sta table.
* ( REPLY_ADD_STA = 0x18 )
- * @add_modify: 1: modify existing, 0: add new station
- * @awake_acs:
+ * @add_modify: see &enum iwl_sta_mode
+ * @awake_acs: ACs to transmit data on while station is sleeping (for U-APSD)
* @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable
* AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field.
- * @mac_id_n_color: the Mac context this station belongs to
- * @addr[ETH_ALEN]: station's MAC address
+ * @mac_id_n_color: the Mac context this station belongs to,
+ * see &enum iwl_mvm_id_and_color
+ * @addr: station's MAC address
+ * @reserved2: reserved
* @sta_id: index of station in uCode's station table
* @modify_mask: STA_MODIFY_*, selects which parameters to modify vs. leave
* alone. 1 - modify, 0 - don't change.
- * @station_flags: look at %iwl_sta_flags
- * @station_flags_msk: what of %station_flags have changed
+ * @reserved3: reserved
+ * @station_flags: look at &enum iwl_sta_flags
+ * @station_flags_msk: what of %station_flags have changed,
+ * also &enum iwl_sta_flags
* @add_immediate_ba_tid: tid for which to add block-ack support (Rx)
* Set %STA_MODIFY_ADD_BA_TID to use this field, and also set
* add_immediate_ba_ssn.
@@ -274,7 +311,7 @@ struct iwl_mvm_keyinfo {
* @sleep_tx_count: number of packets to transmit to station even though it is
* asleep. Used to synchronise PS-poll and u-APSD responses while ucode
* keeps track of STA sleep state.
- * @sleep_state_flags: Look at %iwl_sta_sleep_flag.
+ * @sleep_state_flags: Look at &enum iwl_sta_sleep_flag.
* @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP
* mac-addr.
* @beamform_flags: beam forming controls
@@ -330,17 +367,21 @@ enum iwl_sta_type {
/**
* struct iwl_mvm_add_sta_cmd - Add/modify a station in the fw's sta table.
* ( REPLY_ADD_STA = 0x18 )
- * @add_modify: 1: modify existing, 0: add new station
- * @awake_acs:
+ * @add_modify: see &enum iwl_sta_mode
+ * @awake_acs: ACs to transmit data on while station is sleeping (for U-APSD)
* @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable
* AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field.
- * @mac_id_n_color: the Mac context this station belongs to
- * @addr[ETH_ALEN]: station's MAC address
+ * @mac_id_n_color: the Mac context this station belongs to,
+ * see &enum iwl_mvm_id_and_color
+ * @addr: station's MAC address
+ * @reserved2: reserved
* @sta_id: index of station in uCode's station table
* @modify_mask: STA_MODIFY_*, selects which parameters to modify vs. leave
* alone. 1 - modify, 0 - don't change.
- * @station_flags: look at %iwl_sta_flags
- * @station_flags_msk: what of %station_flags have changed
+ * @reserved3: reserved
+ * @station_flags: look at &enum iwl_sta_flags
+ * @station_flags_msk: what of %station_flags have changed,
+ * also &enum iwl_sta_flags
* @add_immediate_ba_tid: tid for which to add block-ack support (Rx)
* Set %STA_MODIFY_ADD_BA_TID to use this field, and also set
* add_immediate_ba_ssn.
@@ -352,7 +393,7 @@ enum iwl_sta_type {
* asleep. Used to synchronise PS-poll and u-APSD responses while ucode
* keeps track of STA sleep state.
* @station_type: type of this station. See &enum iwl_sta_type.
- * @sleep_state_flags: Look at %iwl_sta_sleep_flag.
+ * @sleep_state_flags: Look at &enum iwl_sta_sleep_flag.
* @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP
* mac-addr.
* @beamform_flags: beam forming controls
@@ -401,7 +442,7 @@ struct iwl_mvm_add_sta_cmd {
* ( REPLY_ADD_STA_KEY = 0x17 )
* @sta_id: index of station in uCode's station table
* @key_offset: key offset in key storage
- * @key_flags: type %iwl_sta_key_flag
+ * @key_flags: type &enum iwl_sta_key_flag
* @key: key material data
* @rx_secur_seq_cnt: RX security sequence counter for the key
*/
@@ -417,6 +458,7 @@ struct iwl_mvm_add_sta_key_common {
* struct iwl_mvm_add_sta_key_cmd_v1 - add/modify sta key
* @common: see &struct iwl_mvm_add_sta_key_common
* @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection
+ * @reserved: reserved
* @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx
*/
struct iwl_mvm_add_sta_key_cmd_v1 {
@@ -459,6 +501,7 @@ enum iwl_mvm_add_sta_rsp_status {
* struct iwl_mvm_rm_sta_cmd - Add / modify a station in the fw's station table
* ( REMOVE_STA = 0x19 )
* @sta_id: the station id of the station to be removed
+ * @reserved: reserved
*/
struct iwl_mvm_rm_sta_cmd {
u8 sta_id;
@@ -468,12 +511,12 @@ struct iwl_mvm_rm_sta_cmd {
/**
* struct iwl_mvm_mgmt_mcast_key_cmd_v1
* ( MGMT_MCAST_KEY = 0x1f )
- * @ctrl_flags: %iwl_sta_key_flag
- * @igtk:
+ * @ctrl_flags: &enum iwl_sta_key_flag
+ * @igtk: IGTK key material
* @k1: unused
* @k2: unused
* @sta_id: station ID that support IGTK
- * @key_id:
+ * @key_id: key ID
* @receive_seq_cnt: initial RSC/PN needed for replay check
*/
struct iwl_mvm_mgmt_mcast_key_cmd_v1 {
@@ -489,10 +532,10 @@ struct iwl_mvm_mgmt_mcast_key_cmd_v1 {
/**
* struct iwl_mvm_mgmt_mcast_key_cmd
* ( MGMT_MCAST_KEY = 0x1f )
- * @ctrl_flags: %iwl_sta_key_flag
+ * @ctrl_flags: &enum iwl_sta_key_flag
* @igtk: IGTK master key
* @sta_id: station ID that support IGTK
- * @key_id:
+ * @key_id: key ID
* @receive_seq_cnt: initial RSC/PN needed for replay check
*/
struct iwl_mvm_mgmt_mcast_key_cmd {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-stats.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-stats.h
index 6371c34..c7531da 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-stats.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-stats.h
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -72,7 +72,7 @@ struct mvm_statistics_dbg {
__le32 burst_check;
__le32 burst_count;
__le32 wait_for_silence_timeout_cnt;
- __le32 reserved[3];
+ u8 reserved[12];
} __packed; /* STATISTICS_DEBUG_API_S_VER_2 */
struct mvm_statistics_div {
@@ -84,7 +84,55 @@ struct mvm_statistics_div {
__le32 reserved2;
} __packed; /* STATISTICS_SLOW_DIV_API_S_VER_2 */
+/**
+ * struct mvm_statistics_rx_non_phy
+ * @bogus_cts: CTS received when not expecting CTS
+ * @bogus_ack: ACK received when not expecting ACK
+ * @non_channel_beacons: beacons with our bss id but not on our serving channel
+ * @channel_beacons: beacons with our bss id and in our serving channel
+ * @num_missed_bcon: number of missed beacons
+ * @adc_rx_saturation_time: count in 0.8us units the time the ADC was in
+ * saturation
+ * @ina_detection_search_time: total time (in 0.8us) searched for INA
+ * @beacon_silence_rssi_a: RSSI silence after beacon frame
+ * @beacon_silence_rssi_b: RSSI silence after beacon frame
+ * @beacon_silence_rssi_c: RSSI silence after beacon frame
+ * @interference_data_flag: flag for interference data availability. 1 when data
+ * is available.
+ * @channel_load: counts RX Enable time in uSec
+ * @beacon_rssi_a: beacon RSSI on anntena A
+ * @beacon_rssi_b: beacon RSSI on antenna B
+ * @beacon_rssi_c: beacon RSSI on antenna C
+ * @beacon_energy_a: beacon energy on antenna A
+ * @beacon_energy_b: beacon energy on antenna B
+ * @beacon_energy_c: beacon energy on antenna C
+ * @num_bt_kills: number of BT "kills" (frame TX aborts)
+ * @mac_id: mac ID
+ */
struct mvm_statistics_rx_non_phy {
+ __le32 bogus_cts;
+ __le32 bogus_ack;
+ __le32 non_channel_beacons;
+ __le32 channel_beacons;
+ __le32 num_missed_bcon;
+ __le32 adc_rx_saturation_time;
+ __le32 ina_detection_search_time;
+ __le32 beacon_silence_rssi_a;
+ __le32 beacon_silence_rssi_b;
+ __le32 beacon_silence_rssi_c;
+ __le32 interference_data_flag;
+ __le32 channel_load;
+ __le32 beacon_rssi_a;
+ __le32 beacon_rssi_b;
+ __le32 beacon_rssi_c;
+ __le32 beacon_energy_a;
+ __le32 beacon_energy_b;
+ __le32 beacon_energy_c;
+ __le32 num_bt_kills;
+ __le32 mac_id;
+} __packed; /* STATISTICS_RX_NON_PHY_API_S_VER_4 */
+
+struct mvm_statistics_rx_non_phy_v3 {
__le32 bogus_cts; /* CTS received when not expecting CTS */
__le32 bogus_ack; /* ACK received when not expecting ACK */
__le32 non_bssid_frames; /* number of frames with BSSID that
@@ -121,6 +169,14 @@ struct mvm_statistics_rx_non_phy {
} __packed; /* STATISTICS_RX_NON_PHY_API_S_VER_3 */
struct mvm_statistics_rx_phy {
+ __le32 unresponded_rts;
+ __le32 rxe_frame_lmt_overrun;
+ __le32 sent_ba_rsp_cnt;
+ __le32 dsp_self_kill;
+ __le32 reserved;
+} __packed; /* STATISTICS_RX_PHY_API_S_VER_3 */
+
+struct mvm_statistics_rx_phy_v2 {
__le32 ina_cnt;
__le32 fina_cnt;
__le32 plcp_err;
@@ -143,7 +199,7 @@ struct mvm_statistics_rx_phy {
__le32 reserved;
} __packed; /* STATISTICS_RX_PHY_API_S_VER_2 */
-struct mvm_statistics_rx_ht_phy {
+struct mvm_statistics_rx_ht_phy_v1 {
__le32 plcp_err;
__le32 overrun_err;
__le32 early_overrun_err;
@@ -156,7 +212,14 @@ struct mvm_statistics_rx_ht_phy {
__le32 unsupport_mcs;
} __packed; /* STATISTICS_HT_RX_PHY_API_S_VER_1 */
-struct mvm_statistics_tx_non_phy {
+struct mvm_statistics_rx_ht_phy {
+ __le32 mh_format_err;
+ __le32 agg_mpdu_cnt;
+ __le32 agg_cnt;
+ __le32 unsupport_mcs;
+} __packed; /* STATISTICS_HT_RX_PHY_API_S_VER_2 */
+
+struct mvm_statistics_tx_non_phy_v3 {
__le32 preamble_cnt;
__le32 rx_detected_cnt;
__le32 bt_prio_defer_cnt;
@@ -173,6 +236,19 @@ struct mvm_statistics_tx_non_phy {
__le32 ack_or_ba_timeout_collision;
} __packed; /* STATISTICS_TX_NON_PHY_API_S_VER_3 */
+struct mvm_statistics_tx_non_phy {
+ __le32 bt_prio_defer_cnt;
+ __le32 bt_prio_kill_cnt;
+ __le32 few_bytes_cnt;
+ __le32 cts_timeout;
+ __le32 ack_timeout;
+ __le32 dump_msdu_cnt;
+ __le32 burst_abort_next_frame_mismatch_cnt;
+ __le32 burst_abort_missing_next_frame_cnt;
+ __le32 cts_timeout_collision;
+ __le32 ack_or_ba_timeout_collision;
+} __packed; /* STATISTICS_TX_NON_PHY_API_S_VER_4 */
+
#define MAX_CHAINS 3
struct mvm_statistics_tx_non_phy_agg {
@@ -202,11 +278,17 @@ struct mvm_statistics_tx_channel_width {
__le32 fail_per_ch_width[4];
}; /* STATISTICS_TX_CHANNEL_WIDTH_API_S_VER_1 */
+struct mvm_statistics_tx_v4 {
+ struct mvm_statistics_tx_non_phy_v3 general;
+ struct mvm_statistics_tx_non_phy_agg agg;
+ struct mvm_statistics_tx_channel_width channel_width;
+} __packed; /* STATISTICS_TX_API_S_VER_4 */
+
struct mvm_statistics_tx {
struct mvm_statistics_tx_non_phy general;
struct mvm_statistics_tx_non_phy_agg agg;
struct mvm_statistics_tx_channel_width channel_width;
-} __packed; /* STATISTICS_TX_API_S_VER_4 */
+} __packed; /* STATISTICS_TX_API_S_VER_5 */
struct mvm_statistics_bt_activity {
@@ -220,7 +302,7 @@ struct mvm_statistics_bt_activity {
__le32 lo_priority_rx_denied_cnt;
} __packed; /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */
-struct mvm_statistics_general_common {
+struct mvm_statistics_general_common_v19 {
__le32 radio_temperature;
__le32 radio_voltage;
struct mvm_statistics_dbg dbg;
@@ -250,20 +332,56 @@ struct mvm_statistics_general_common {
__le64 tx_time;
} __packed;
+struct mvm_statistics_general_common {
+ __le32 radio_temperature;
+ struct mvm_statistics_dbg dbg;
+ __le32 sleep_time;
+ __le32 slots_out;
+ __le32 slots_idle;
+ __le32 ttl_timestamp;
+ struct mvm_statistics_div slow_div;
+ __le32 rx_enable_counter;
+ /*
+ * num_of_sos_states:
+ * count the number of times we have to re-tune
+ * in order to get out of bad PHY status
+ */
+ __le32 num_of_sos_states;
+ __le32 beacon_filtered;
+ __le32 missed_beacons;
+ u8 beacon_filter_average_energy;
+ u8 beacon_filter_reason;
+ u8 beacon_filter_current_energy;
+ u8 beacon_filter_reserved;
+ __le32 beacon_filter_delta_time;
+ struct mvm_statistics_bt_activity bt_activity;
+ __le64 rx_time;
+ __le64 on_time_rf;
+ __le64 on_time_scan;
+ __le64 tx_time;
+} __packed; /* STATISTICS_GENERAL_API_S_VER_10 */
+
struct mvm_statistics_general_v8 {
- struct mvm_statistics_general_common common;
+ struct mvm_statistics_general_common_v19 common;
__le32 beacon_counter[NUM_MAC_INDEX];
u8 beacon_average_energy[NUM_MAC_INDEX];
u8 reserved[4 - (NUM_MAC_INDEX % 4)];
} __packed; /* STATISTICS_GENERAL_API_S_VER_8 */
-struct mvm_statistics_general_cdb {
- struct mvm_statistics_general_common common;
+struct mvm_statistics_general_cdb_v9 {
+ struct mvm_statistics_general_common_v19 common;
__le32 beacon_counter[NUM_MAC_INDEX_CDB];
u8 beacon_average_energy[NUM_MAC_INDEX_CDB];
u8 reserved[4 - (NUM_MAC_INDEX_CDB % 4)];
} __packed; /* STATISTICS_GENERAL_API_S_VER_9 */
+struct mvm_statistics_general_cdb {
+ struct mvm_statistics_general_common common;
+ __le32 beacon_counter[MAC_INDEX_AUX];
+ u8 beacon_average_energy[MAC_INDEX_AUX];
+ u8 reserved[8 - MAC_INDEX_AUX];
+} __packed; /* STATISTICS_GENERAL_API_S_VER_10 */
+
/**
* struct mvm_statistics_load - RX statistics for multi-queue devices
* @air_time: accumulated air time, per mac
@@ -272,24 +390,31 @@ struct mvm_statistics_general_cdb {
* @avg_energy: average RSSI, per station
*/
struct mvm_statistics_load {
+ __le32 air_time[MAC_INDEX_AUX];
+ __le32 byte_count[MAC_INDEX_AUX];
+ __le32 pkt_count[MAC_INDEX_AUX];
+ u8 avg_energy[IWL_MVM_STATION_COUNT];
+} __packed; /* STATISTICS_RX_MAC_STATION_S_VER_3 */
+
+struct mvm_statistics_load_v1 {
__le32 air_time[NUM_MAC_INDEX];
__le32 byte_count[NUM_MAC_INDEX];
__le32 pkt_count[NUM_MAC_INDEX];
u8 avg_energy[IWL_MVM_STATION_COUNT];
} __packed; /* STATISTICS_RX_MAC_STATION_S_VER_1 */
-struct mvm_statistics_load_cdb {
- __le32 air_time[NUM_MAC_INDEX_CDB];
- __le32 byte_count[NUM_MAC_INDEX_CDB];
- __le32 pkt_count[NUM_MAC_INDEX_CDB];
- u8 avg_energy[IWL_MVM_STATION_COUNT];
-} __packed; /* STATISTICS_RX_MAC_STATION_S_VER_2 */
-
struct mvm_statistics_rx {
struct mvm_statistics_rx_phy ofdm;
struct mvm_statistics_rx_phy cck;
struct mvm_statistics_rx_non_phy general;
struct mvm_statistics_rx_ht_phy ofdm_ht;
+} __packed; /* STATISTICS_RX_API_S_VER_4 */
+
+struct mvm_statistics_rx_v3 {
+ struct mvm_statistics_rx_phy_v2 ofdm;
+ struct mvm_statistics_rx_phy_v2 cck;
+ struct mvm_statistics_rx_non_phy_v3 general;
+ struct mvm_statistics_rx_ht_phy_v1 ofdm_ht;
} __packed; /* STATISTICS_RX_API_S_VER_3 */
/*
@@ -302,17 +427,17 @@ struct mvm_statistics_rx {
struct iwl_notif_statistics_v10 {
__le32 flag;
- struct mvm_statistics_rx rx;
- struct mvm_statistics_tx tx;
+ struct mvm_statistics_rx_v3 rx;
+ struct mvm_statistics_tx_v4 tx;
struct mvm_statistics_general_v8 general;
} __packed; /* STATISTICS_NTFY_API_S_VER_10 */
struct iwl_notif_statistics_v11 {
__le32 flag;
- struct mvm_statistics_rx rx;
- struct mvm_statistics_tx tx;
+ struct mvm_statistics_rx_v3 rx;
+ struct mvm_statistics_tx_v4 tx;
struct mvm_statistics_general_v8 general;
- struct mvm_statistics_load load_stats;
+ struct mvm_statistics_load_v1 load_stats;
} __packed; /* STATISTICS_NTFY_API_S_VER_11 */
struct iwl_notif_statistics_cdb {
@@ -320,12 +445,33 @@ struct iwl_notif_statistics_cdb {
struct mvm_statistics_rx rx;
struct mvm_statistics_tx tx;
struct mvm_statistics_general_cdb general;
- struct mvm_statistics_load_cdb load_stats;
-} __packed; /* STATISTICS_NTFY_API_S_VER_12 */
+ struct mvm_statistics_load load_stats;
+} __packed; /* STATISTICS_NTFY_API_S_VER_13 */
-#define IWL_STATISTICS_FLG_CLEAR 0x1
-#define IWL_STATISTICS_FLG_DISABLE_NOTIF 0x2
+/**
+ * enum iwl_statistics_notif_flags - flags used in statistics notification
+ * @IWL_STATISTICS_REPLY_FLG_CLEAR: statistics were cleared after this report
+ */
+enum iwl_statistics_notif_flags {
+ IWL_STATISTICS_REPLY_FLG_CLEAR = 0x1,
+};
+/**
+ * enum iwl_statistics_cmd_flags - flags used in statistics command
+ * @IWL_STATISTICS_FLG_CLEAR: request to clear statistics after the report
+ * that's sent after this command
+ * @IWL_STATISTICS_FLG_DISABLE_NOTIF: disable unilateral statistics
+ * notifications
+ */
+enum iwl_statistics_cmd_flags {
+ IWL_STATISTICS_FLG_CLEAR = 0x1,
+ IWL_STATISTICS_FLG_DISABLE_NOTIF = 0x2,
+};
+
+/**
+ * struct iwl_statistics_cmd - statistics config command
+ * @flags: flags from &enum iwl_statistics_cmd_flags
+ */
struct iwl_statistics_cmd {
__le32 flags;
} __packed; /* STATISTICS_CMD_API_S_VER_1 */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tof.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tof.h
index 86aa51b..8658a98 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tof.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tof.h
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2015 Intel Deutschland GmbH
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2015 Intel Deutschland GmbH
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -63,8 +63,6 @@
#ifndef __fw_api_tof_h__
#define __fw_api_tof_h__
-#include "fw-api.h"
-
/* ToF sub-group command IDs */
enum iwl_mvm_tof_sub_grp_ids {
TOF_RANGE_REQ_CMD = 0x1,
@@ -118,11 +116,17 @@ struct iwl_tof_config_cmd {
* @bandwidth: current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz
* @rate: current AP rate
* @ctrl_ch_position: coding of the control channel position relative to
- * the center frequency.
- * 40MHz 0 below center, 1 above center
- * 80MHz bits [0..1]: 0 the near 20MHz to the center,
- * 1 the far 20MHz to the center
- * bit[2] as above 40MHz
+ * the center frequency:
+ *
+ * 40 MHz
+ * 0 below center, 1 above center
+ *
+ * 80 MHz
+ * bits [0..1]
+ * * 0 the near 20MHz to the center,
+ * * 1 the far 20MHz to the center
+ * bit[2]
+ * as above 40MHz
* @ftm_per_burst: FTMs per Burst
* @ftm_resp_ts_avail: '0' - we don't measure over the Initial FTM Response,
* '1' - we measure over the Initial FTM Response
@@ -159,6 +163,7 @@ struct iwl_tof_responder_config_cmd {
/**
* struct iwl_tof_range_request_ext_cmd - extended range req for WLS
* @tsf_timer_offset_msec: the recommended time offset (mSec) from the AP's TSF
+ * @reserved: reserved
* @min_delta_ftm: Minimal time between two consecutive measurements,
* in units of 100us. 0 means no preference by station
* @ftm_format_and_bw20M: FTM Channel Spacing/Format for 20MHz: recommended
@@ -268,6 +273,7 @@ enum iwl_tof_response_mode {
* '1' Use MAC Address randomization according to the below
* @macaddr_mask: Bits set to 0 shall be copied from the MAC address template.
* Bits set to 1 shall be randomized by the UMAC
+ * @ap: per-AP request data
*/
struct iwl_tof_range_req_cmd {
__le32 sub_grp_cmd_id;
@@ -294,7 +300,9 @@ struct iwl_tof_gen_resp_cmd {
/**
* struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response)
- * @measure_status: current APs measurement status
+ * @bssid: BSSID of the AP
+ * @measure_status: current APs measurement status, one of
+ * &enum iwl_tof_entry_status.
* @measure_bw: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz
* @rtt: The Round Trip Time that took for the last measurement for
* current AP [nSec]
@@ -304,6 +312,7 @@ struct iwl_tof_gen_resp_cmd {
* @rssi: RSSI as uploaded in the Channel Estimation notification
* @rssi_spread: The Difference between the maximum and the minimum RSSI values
* measured for current AP in the current session
+ * @reserved: reserved
* @range: Measured range [cm]
* @range_variance: Measured range variance [cm]
* @timestamp: The GP2 Clock [usec] where Channel Estimation notification was
@@ -330,6 +339,7 @@ struct iwl_tof_range_rsp_ap_entry_ntfy {
* @request_status: status of current measurement session
* @last_in_batch: reprot policy (when not all responses are uploaded at once)
* @num_of_aps: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS)
+ * @ap: per-AP data
*/
struct iwl_tof_range_rsp_ntfy {
u8 request_id;
@@ -344,6 +354,7 @@ struct iwl_tof_range_rsp_ntfy {
* struct iwl_tof_mcsi_notif - used for debug
* @token: token ID for the current session
* @role: '0' - initiator, '1' - responder
+ * @reserved: reserved
* @initiator_bssid: initiator machine
* @responder_bssid: responder machine
* @mcsi_buffer: debug data
@@ -376,6 +387,7 @@ struct iwl_tof_neighbor_report {
/**
* struct iwl_tof_range_abort_cmd
* @request_id: corresponds to a range request
+ * @reserved: reserved
*/
struct iwl_tof_range_abort_cmd {
__le32 sub_grp_cmd_id;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
index 1360ebf..97d7eed 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
@@ -74,6 +74,7 @@
* Otherwise, use rate_n_flags from the TX command
* @TX_CMD_FLG_BAR: this frame is a BA request, immediate BAR is expected
* Must set TX_CMD_FLG_ACK with this flag.
+ * @TX_CMD_FLG_TXOP_PROT: TXOP protection requested
* @TX_CMD_FLG_VHT_NDPA: mark frame is NDPA for VHT beamformer sequence
* @TX_CMD_FLG_HT_NDPA: mark frame is NDPA for HT beamformer sequence
* @TX_CMD_FLG_CSI_FDBK2HOST: mark to send feedback to host (only if good CRC)
@@ -177,29 +178,6 @@ enum iwl_tx_cmd_sec_ctrl {
TX_CMD_SEC_KEY_FROM_TABLE = 0x10,
};
-/* TODO: how does these values are OK with only 16 bit variable??? */
-/*
- * TX command next frame info
- *
- * bits 0:2 - security control (TX_CMD_SEC_*)
- * bit 3 - immediate ACK required
- * bit 4 - rate is taken from STA table
- * bit 5 - frame belongs to BA stream
- * bit 6 - immediate BA response expected
- * bit 7 - unused
- * bits 8:15 - Station ID
- * bits 16:31 - rate
- */
-#define TX_CMD_NEXT_FRAME_ACK_MSK (0x8)
-#define TX_CMD_NEXT_FRAME_STA_RATE_MSK (0x10)
-#define TX_CMD_NEXT_FRAME_BA_MSK (0x20)
-#define TX_CMD_NEXT_FRAME_IMM_BA_RSP_MSK (0x40)
-#define TX_CMD_NEXT_FRAME_FLAGS_MSK (0xf8)
-#define TX_CMD_NEXT_FRAME_STA_ID_MSK (0xff00)
-#define TX_CMD_NEXT_FRAME_STA_ID_POS (8)
-#define TX_CMD_NEXT_FRAME_RATE_MSK (0xffff0000)
-#define TX_CMD_NEXT_FRAME_RATE_POS (16)
-
/*
* TX command Frame life time in us - to be written in pm_frame_timeout
*/
@@ -224,7 +202,7 @@ enum iwl_tx_cmd_sec_ctrl {
/**
* enum iwl_tx_offload_assist_flags_pos - set %iwl_tx_cmd offload_assist values
- * @TX_CMD_OFFLD_IP_HDR_OFFSET: offset to start of IP header (in words)
+ * @TX_CMD_OFFLD_IP_HDR: offset to start of IP header (in words)
* from mac header end. For normal case it is 4 words for SNAP.
* note: tx_cmd, mac header and pad are not counted in the offset.
* This is used to help the offload in case there is tunneling such as
@@ -258,22 +236,27 @@ enum iwl_tx_offload_assist_flags_pos {
* @len: in bytes of the payload, see below for details
* @offload_assist: TX offload configuration
* @tx_flags: combination of TX_CMD_FLG_*
+ * @scratch: scratch buffer used by the device
* @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
* cleared. Combination of RATE_MCS_*
* @sta_id: index of destination station in FW station table
* @sec_ctl: security control, TX_CMD_SEC_*
* @initial_rate_index: index into the the rate table for initial TX attempt.
* Applied if TX_CMD_FLG_STA_RATE_MSK is set, normally 0 for data frames.
+ * @reserved2: reserved
* @key: security key
- * @next_frame_flags: TX_CMD_SEC_* and TX_CMD_NEXT_FRAME_*
+ * @reserved3: reserved
* @life_time: frame life time (usecs??)
* @dram_lsb_ptr: Physical address of scratch area in the command (try_cnt +
* btkill_cnd + reserved), first 32 bits. "0" disables usage.
* @dram_msb_ptr: upper bits of the scratch physical address
* @rts_retry_limit: max attempts for RTS
* @data_retry_limit: max attempts to send the data packet
- * @tid_spec: TID/tspec
+ * @tid_tspec: TID/tspec
* @pm_frame_timeout: PM TX frame timeout
+ * @reserved4: reserved
+ * @payload: payload (same as @hdr)
+ * @hdr: 802.11 header (same as @payload)
*
* The byte count (both len and next_frame_len) includes MAC header
* (24/26/30/32 bytes)
@@ -327,10 +310,11 @@ struct iwl_dram_sec_info {
* ( TX_CMD = 0x1c )
* @len: in bytes of the payload, see below for details
* @offload_assist: TX offload configuration
- * @tx_flags: combination of &iwl_tx_cmd_flags
+ * @flags: combination of &enum iwl_tx_cmd_flags
* @dram_info: FW internal DRAM storage
* @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
* cleared. Combination of RATE_MCS_*
+ * @hdr: 802.11 header
*/
struct iwl_tx_cmd_gen2 {
__le16 len;
@@ -504,7 +488,7 @@ enum iwl_tx_agg_status {
/**
* struct agg_tx_status - per packet TX aggregation status
- * @status: enum iwl_tx_agg_status
+ * @status: See &enum iwl_tx_agg_status
* @sequence: Sequence # for this frame's Tx cmd (not SSN!)
*/
struct agg_tx_status {
@@ -529,6 +513,63 @@ struct agg_tx_status {
#define IWL_MVM_TX_RES_GET_RA(_ra_tid) ((_ra_tid) >> 4)
/**
+ * struct iwl_mvm_tx_resp_v3 - notifies that fw is TXing a packet
+ * ( REPLY_TX = 0x1c )
+ * @frame_count: 1 no aggregation, >1 aggregation
+ * @bt_kill_count: num of times blocked by bluetooth (unused for agg)
+ * @failure_rts: num of failures due to unsuccessful RTS
+ * @failure_frame: num failures due to no ACK (unused for agg)
+ * @initial_rate: for non-agg: rate of the successful Tx. For agg: rate of the
+ * Tx of all the batch. RATE_MCS_*
+ * @wireless_media_time: for non-agg: RTS + CTS + frame tx attempts time + ACK.
+ * for agg: RTS + CTS + aggregation tx time + block-ack time.
+ * in usec.
+ * @pa_status: tx power info
+ * @pa_integ_res_a: tx power info
+ * @pa_integ_res_b: tx power info
+ * @pa_integ_res_c: tx power info
+ * @measurement_req_id: tx power info
+ * @reduced_tpc: transmit power reduction used
+ * @reserved: reserved
+ * @tfd_info: TFD information set by the FH
+ * @seq_ctl: sequence control from the Tx cmd
+ * @byte_cnt: byte count from the Tx cmd
+ * @tlc_info: TLC rate info
+ * @ra_tid: bits [3:0] = ra, bits [7:4] = tid
+ * @frame_ctrl: frame control
+ * @status: for non-agg: frame status TX_STATUS_*
+ * for agg: status of 1st frame, AGG_TX_STATE_*; other frame status fields
+ * follow this one, up to frame_count. Length in @frame_count.
+ *
+ * After the array of statuses comes the SSN of the SCD. Look at
+ * %iwl_mvm_get_scd_ssn for more details.
+ */
+struct iwl_mvm_tx_resp_v3 {
+ u8 frame_count;
+ u8 bt_kill_count;
+ u8 failure_rts;
+ u8 failure_frame;
+ __le32 initial_rate;
+ __le16 wireless_media_time;
+
+ u8 pa_status;
+ u8 pa_integ_res_a[3];
+ u8 pa_integ_res_b[3];
+ u8 pa_integ_res_c[3];
+ __le16 measurement_req_id;
+ u8 reduced_tpc;
+ u8 reserved;
+
+ __le32 tfd_info;
+ __le16 seq_ctl;
+ __le16 byte_cnt;
+ u8 tlc_info;
+ u8 ra_tid;
+ __le16 frame_ctrl;
+ struct agg_tx_status status[];
+} __packed; /* TX_RSP_API_S_VER_3 */
+
+/**
* struct iwl_mvm_tx_resp - notifies that fw is TXing a packet
* ( REPLY_TX = 0x1c )
* @frame_count: 1 no aggregation, >1 aggregation
@@ -545,6 +586,8 @@ struct agg_tx_status {
* @pa_integ_res_b: tx power info
* @pa_integ_res_c: tx power info
* @measurement_req_id: tx power info
+ * @reduced_tpc: transmit power reduction used
+ * @reserved: reserved
* @tfd_info: TFD information set by the FH
* @seq_ctl: sequence control from the Tx cmd
* @byte_cnt: byte count from the Tx cmd
@@ -552,9 +595,8 @@ struct agg_tx_status {
* @ra_tid: bits [3:0] = ra, bits [7:4] = tid
* @frame_ctrl: frame control
* @tx_queue: TX queue for this response
+ * @reserved2: reserved for padding/alignment
* @status: for non-agg: frame status TX_STATUS_*
- * for agg: status of 1st frame, AGG_TX_STATE_*; other frame status fields
- * follow this one, up to frame_count.
* For version 6 TX response isn't received for aggregation at all.
*
* After the array of statuses comes the SSN of the SCD. Look at
@@ -582,26 +624,19 @@ struct iwl_mvm_tx_resp {
u8 tlc_info;
u8 ra_tid;
__le16 frame_ctrl;
- union {
- struct {
- struct agg_tx_status status;
- } v3;/* TX_RSP_API_S_VER_3 */
- struct {
- __le16 tx_queue;
- __le16 reserved2;
- struct agg_tx_status status;
- } v6;
- };
+ __le16 tx_queue;
+ __le16 reserved2;
+ struct agg_tx_status status;
} __packed; /* TX_RSP_API_S_VER_6 */
/**
* struct iwl_mvm_ba_notif - notifies about reception of BA
* ( BA_NOTIF = 0xc5 )
- * @sta_addr_lo32: lower 32 bits of the MAC address
- * @sta_addr_hi16: upper 16 bits of the MAC address
+ * @sta_addr: MAC address
+ * @reserved: reserved
* @sta_id: Index of recipient (BA-sending) station in fw's station table
* @tid: tid of the session
- * @seq_ctl:
+ * @seq_ctl: sequence control field
* @bitmap: the bitmap of the BA notification as seen in the air
* @scd_flow: the tx queue this BA relates to
* @scd_ssn: the index of the last contiguously sent packet
@@ -610,10 +645,10 @@ struct iwl_mvm_tx_resp {
* @reduced_txp: power reduced according to TPC. This is the actual value and
* not a copy from the LQ command. Thus, if not the first rate was used
* for Tx-ing then this value will be set to 0 by FW.
+ * @reserved1: reserved
*/
struct iwl_mvm_ba_notif {
- __le32 sta_addr_lo32;
- __le16 sta_addr_hi16;
+ u8 sta_addr[ETH_ALEN];
__le16 reserved;
u8 sta_id;
@@ -633,13 +668,15 @@ struct iwl_mvm_ba_notif {
* @q_num: TFD queue number
* @tfd_index: Index of first un-acked frame in the TFD queue
* @scd_queue: For debug only - the physical queue the TFD queue is bound to
+ * @tid: TID of the queue (0-7)
+ * @reserved: reserved for alignment
*/
struct iwl_mvm_compressed_ba_tfd {
__le16 q_num;
__le16 tfd_index;
u8 scd_queue;
- u8 reserved;
- __le16 reserved2;
+ u8 tid;
+ u8 reserved[2];
} __packed; /* COMPRESSED_BA_TFD_API_S_VER_1 */
/**
@@ -687,11 +724,12 @@ enum iwl_mvm_ba_resp_flags {
* @query_frame_cnt: SCD query frame count
* @txed: number of frames sent in the aggregation (all-TIDs)
* @done: number of frames that were Acked by the BA (all-TIDs)
+ * @reserved: reserved (for alignment)
* @wireless_time: Wireless-media time
* @tx_rate: the rate the aggregation was sent at
* @tfd_cnt: number of TFD-Q elements
* @ra_tid_cnt: number of RATID-Q elements
- * @ba_tfd: array of TFD queue status updates. See &iwl_mvm_compressed_ba_tfd
+ * @tfd: array of TFD queue status updates. See &iwl_mvm_compressed_ba_tfd
* for details.
* @ra_tid: array of RA-TID queue status updates. For debug purposes only. See
* &iwl_mvm_compressed_ba_ratid for more details.
@@ -765,6 +803,7 @@ struct iwl_mac_beacon_cmd_v7 {
* struct iwl_mac_beacon_cmd - beacon template command with offloaded CSA
* @byte_cnt: byte count of the beacon frame
* @flags: for future use
+ * @reserved: reserved
* @data: see &iwl_mac_beacon_cmd_data
*/
struct iwl_mac_beacon_cmd {
@@ -809,12 +848,24 @@ enum iwl_dump_control {
* @flush_ctl: control flags
* @reserved: reserved
*/
-struct iwl_tx_path_flush_cmd {
+struct iwl_tx_path_flush_cmd_v1 {
__le32 queues_ctl;
__le16 flush_ctl;
__le16 reserved;
} __packed; /* TX_PATH_FLUSH_CMD_API_S_VER_1 */
+/**
+ * struct iwl_tx_path_flush_cmd -- queue/FIFO flush command
+ * @sta_id: station ID to flush
+ * @tid_mask: TID mask to flush
+ * @reserved: reserved
+ */
+struct iwl_tx_path_flush_cmd {
+ __le32 sta_id;
+ __le16 tid_mask;
+ __le16 reserved;
+} __packed; /* TX_PATH_FLUSH_CMD_API_S_VER_2 */
+
/* Available options for the SCD_QUEUE_CFG HCMD */
enum iwl_scd_cfg_actions {
SCD_CFG_DISABLE_QUEUE = 0x0,
@@ -824,16 +875,17 @@ enum iwl_scd_cfg_actions {
/**
* struct iwl_scd_txq_cfg_cmd - New txq hw scheduler config command
- * @token:
+ * @token: unused
* @sta_id: station id
- * @tid:
+ * @tid: TID
* @scd_queue: scheduler queue to confiug
* @action: 1 queue enable, 0 queue disable, 2 change txq's tid owner
- * Value is one of %iwl_scd_cfg_actions options
+ * Value is one of &enum iwl_scd_cfg_actions options
* @aggregate: 1 aggregated queue, 0 otherwise
- * @tx_fifo: %enum iwl_mvm_tx_fifo
+ * @tx_fifo: &enum iwl_mvm_tx_fifo
* @window: BA window size
* @ssn: SSN for the BA agreement
+ * @reserved: reserved
*/
struct iwl_scd_txq_cfg_cmd {
u8 token;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
index f545c5f..aad265d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
@@ -130,181 +130,547 @@ enum iwl_mvm_tx_fifo {
};
-/* commands */
-enum {
+/**
+ * enum iwl_legacy_cmds - legacy group command IDs
+ */
+enum iwl_legacy_cmds {
+ /**
+ * @MVM_ALIVE:
+ * Alive data from the firmware, as described in
+ * &struct mvm_alive_resp_v3 or &struct mvm_alive_resp.
+ */
MVM_ALIVE = 0x1,
+
+ /**
+ * @REPLY_ERROR: Cause an error in the firmware, for testing purposes.
+ */
REPLY_ERROR = 0x2,
+
+ /**
+ * @ECHO_CMD: Send data to the device to have it returned immediately.
+ */
ECHO_CMD = 0x3,
+ /**
+ * @INIT_COMPLETE_NOTIF: Notification that initialization is complete.
+ */
INIT_COMPLETE_NOTIF = 0x4,
- /* PHY context commands */
+ /**
+ * @PHY_CONTEXT_CMD:
+ * Add/modify/remove a PHY context, using &struct iwl_phy_context_cmd.
+ */
PHY_CONTEXT_CMD = 0x8,
+
+ /**
+ * @DBG_CFG: Debug configuration command.
+ */
DBG_CFG = 0x9,
+
+ /**
+ * @ANTENNA_COUPLING_NOTIFICATION:
+ * Antenna coupling data, &struct iwl_mvm_antenna_coupling_notif
+ */
ANTENNA_COUPLING_NOTIFICATION = 0xa,
- /* UMAC scan commands */
+ /**
+ * @SCAN_ITERATION_COMPLETE_UMAC:
+ * Firmware indicates a scan iteration completed, using
+ * &struct iwl_umac_scan_iter_complete_notif.
+ */
SCAN_ITERATION_COMPLETE_UMAC = 0xb5,
+
+ /**
+ * @SCAN_CFG_CMD:
+ * uses &struct iwl_scan_config_v1 or &struct iwl_scan_config
+ */
SCAN_CFG_CMD = 0xc,
+
+ /**
+ * @SCAN_REQ_UMAC: uses &struct iwl_scan_req_umac
+ */
SCAN_REQ_UMAC = 0xd,
+
+ /**
+ * @SCAN_ABORT_UMAC: uses &struct iwl_umac_scan_abort
+ */
SCAN_ABORT_UMAC = 0xe,
+
+ /**
+ * @SCAN_COMPLETE_UMAC: uses &struct iwl_umac_scan_complete
+ */
SCAN_COMPLETE_UMAC = 0xf,
+ /**
+ * @BA_WINDOW_STATUS_NOTIFICATION_ID:
+ * uses &struct iwl_ba_window_status_notif
+ */
BA_WINDOW_STATUS_NOTIFICATION_ID = 0x13,
- /* station table */
+ /**
+ * @ADD_STA_KEY:
+ * &struct iwl_mvm_add_sta_key_cmd_v1 or
+ * &struct iwl_mvm_add_sta_key_cmd.
+ */
ADD_STA_KEY = 0x17,
+
+ /**
+ * @ADD_STA:
+ * &struct iwl_mvm_add_sta_cmd or &struct iwl_mvm_add_sta_cmd_v7.
+ */
ADD_STA = 0x18,
+
+ /**
+ * @REMOVE_STA: &struct iwl_mvm_rm_sta_cmd
+ */
REMOVE_STA = 0x19,
- /* paging get item */
+ /**
+ * @FW_GET_ITEM_CMD: uses &struct iwl_fw_get_item_cmd
+ */
FW_GET_ITEM_CMD = 0x1a,
- /* TX */
+ /**
+ * @TX_CMD: uses &struct iwl_tx_cmd or &struct iwl_tx_cmd_gen2,
+ * response in &struct iwl_mvm_tx_resp or
+ * &struct iwl_mvm_tx_resp_v3
+ */
TX_CMD = 0x1c,
+
+ /**
+ * @TXPATH_FLUSH: &struct iwl_tx_path_flush_cmd
+ */
TXPATH_FLUSH = 0x1e,
+
+ /**
+ * @MGMT_MCAST_KEY:
+ * &struct iwl_mvm_mgmt_mcast_key_cmd or
+ * &struct iwl_mvm_mgmt_mcast_key_cmd_v1
+ */
MGMT_MCAST_KEY = 0x1f,
/* scheduler config */
+ /**
+ * @SCD_QUEUE_CFG: &struct iwl_scd_txq_cfg_cmd for older hardware,
+ * &struct iwl_tx_queue_cfg_cmd with &struct iwl_tx_queue_cfg_rsp
+ * for newer (A000) hardware.
+ */
SCD_QUEUE_CFG = 0x1d,
- /* global key */
+ /**
+ * @WEP_KEY: uses &struct iwl_mvm_wep_key_cmd
+ */
WEP_KEY = 0x20,
- /* Memory */
+ /**
+ * @SHARED_MEM_CFG:
+ * retrieve shared memory configuration - response in
+ * &struct iwl_shared_mem_cfg
+ */
SHARED_MEM_CFG = 0x25,
- /* TDLS */
+ /**
+ * @TDLS_CHANNEL_SWITCH_CMD: uses &struct iwl_tdls_channel_switch_cmd
+ */
TDLS_CHANNEL_SWITCH_CMD = 0x27,
+
+ /**
+ * @TDLS_CHANNEL_SWITCH_NOTIFICATION:
+ * uses &struct iwl_tdls_channel_switch_notif
+ */
TDLS_CHANNEL_SWITCH_NOTIFICATION = 0xaa,
+
+ /**
+ * @TDLS_CONFIG_CMD:
+ * &struct iwl_tdls_config_cmd, response in &struct iwl_tdls_config_res
+ */
TDLS_CONFIG_CMD = 0xa7,
- /* MAC and Binding commands */
+ /**
+ * @MAC_CONTEXT_CMD: &struct iwl_mac_ctx_cmd
+ */
MAC_CONTEXT_CMD = 0x28,
+
+ /**
+ * @TIME_EVENT_CMD:
+ * &struct iwl_time_event_cmd, response in &struct iwl_time_event_resp
+ */
TIME_EVENT_CMD = 0x29, /* both CMD and response */
+
+ /**
+ * @TIME_EVENT_NOTIFICATION: &struct iwl_time_event_notif
+ */
TIME_EVENT_NOTIFICATION = 0x2a,
+
+ /**
+ * @BINDING_CONTEXT_CMD:
+ * &struct iwl_binding_cmd or &struct iwl_binding_cmd_v1
+ */
BINDING_CONTEXT_CMD = 0x2b,
+
+ /**
+ * @TIME_QUOTA_CMD: &struct iwl_time_quota_cmd
+ */
TIME_QUOTA_CMD = 0x2c,
+
+ /**
+ * @NON_QOS_TX_COUNTER_CMD:
+ * command is &struct iwl_nonqos_seq_query_cmd
+ */
NON_QOS_TX_COUNTER_CMD = 0x2d,
+ /**
+ * @LQ_CMD: using &struct iwl_lq_cmd
+ */
LQ_CMD = 0x4e,
- /* paging block to FW cpu2 */
+ /**
+ * @FW_PAGING_BLOCK_CMD:
+ * &struct iwl_fw_paging_cmd
+ */
FW_PAGING_BLOCK_CMD = 0x4f,
- /* Scan offload */
+ /**
+ * @SCAN_OFFLOAD_REQUEST_CMD: uses &struct iwl_scan_req_lmac
+ */
SCAN_OFFLOAD_REQUEST_CMD = 0x51,
+
+ /**
+ * @SCAN_OFFLOAD_ABORT_CMD: abort the scan - no further contents
+ */
SCAN_OFFLOAD_ABORT_CMD = 0x52,
+
+ /**
+ * @HOT_SPOT_CMD: uses &struct iwl_hs20_roc_req
+ */
HOT_SPOT_CMD = 0x53,
+
+ /**
+ * @SCAN_OFFLOAD_COMPLETE:
+ * notification, &struct iwl_periodic_scan_complete
+ */
SCAN_OFFLOAD_COMPLETE = 0x6D,
+
+ /**
+ * @SCAN_OFFLOAD_UPDATE_PROFILES_CMD:
+ * update scan offload (scheduled scan) profiles/blacklist/etc.
+ */
SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E,
- SCAN_OFFLOAD_CONFIG_CMD = 0x6f,
+
+ /**
+ * @MATCH_FOUND_NOTIFICATION: scan match found
+ */
MATCH_FOUND_NOTIFICATION = 0xd9,
+
+ /**
+ * @SCAN_ITERATION_COMPLETE:
+ * uses &struct iwl_lmac_scan_complete_notif
+ */
SCAN_ITERATION_COMPLETE = 0xe7,
/* Phy */
+ /**
+ * @PHY_CONFIGURATION_CMD: &struct iwl_phy_cfg_cmd
+ */
PHY_CONFIGURATION_CMD = 0x6a,
+
+ /**
+ * @CALIB_RES_NOTIF_PHY_DB: &struct iwl_calib_res_notif_phy_db
+ */
CALIB_RES_NOTIF_PHY_DB = 0x6b,
+
+ /**
+ * @PHY_DB_CMD: &struct iwl_phy_db_cmd
+ */
PHY_DB_CMD = 0x6c,
- /* ToF - 802.11mc FTM */
+ /**
+ * @TOF_CMD: &struct iwl_tof_config_cmd
+ */
TOF_CMD = 0x10,
+
+ /**
+ * @TOF_NOTIFICATION: &struct iwl_tof_gen_resp_cmd
+ */
TOF_NOTIFICATION = 0x11,
- /* Power - legacy power table command */
+ /**
+ * @POWER_TABLE_CMD: &struct iwl_device_power_cmd
+ */
POWER_TABLE_CMD = 0x77,
+
+ /**
+ * @PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION:
+ * &struct iwl_uapsd_misbehaving_ap_notif
+ */
PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78,
+
+ /**
+ * @LTR_CONFIG: &struct iwl_ltr_config_cmd
+ */
LTR_CONFIG = 0xee,
- /* Thermal Throttling*/
+ /**
+ * @REPLY_THERMAL_MNG_BACKOFF:
+ * Thermal throttling command
+ */
REPLY_THERMAL_MNG_BACKOFF = 0x7e,
- /* Set/Get DC2DC frequency tune */
+ /**
+ * @DC2DC_CONFIG_CMD:
+ * Set/Get DC2DC frequency tune
+ * Command is &struct iwl_dc2dc_config_cmd,
+ * response is &struct iwl_dc2dc_config_resp
+ */
DC2DC_CONFIG_CMD = 0x83,
- /* NVM */
+ /**
+ * @NVM_ACCESS_CMD: using &struct iwl_nvm_access_cmd
+ */
NVM_ACCESS_CMD = 0x88,
- SET_CALIB_DEFAULT_CMD = 0x8e,
-
+ /**
+ * @BEACON_NOTIFICATION: &struct iwl_extended_beacon_notif
+ */
BEACON_NOTIFICATION = 0x90,
+
+ /**
+ * @BEACON_TEMPLATE_CMD:
+ * Uses one of &struct iwl_mac_beacon_cmd_v6,
+ * &struct iwl_mac_beacon_cmd_v7 or &struct iwl_mac_beacon_cmd
+ * depending on the device version.
+ */
BEACON_TEMPLATE_CMD = 0x91,
+ /**
+ * @TX_ANT_CONFIGURATION_CMD: &struct iwl_tx_ant_cfg_cmd
+ */
TX_ANT_CONFIGURATION_CMD = 0x98,
+
+ /**
+ * @STATISTICS_CMD:
+ * one of &struct iwl_statistics_cmd,
+ * &struct iwl_notif_statistics_v11,
+ * &struct iwl_notif_statistics_v10,
+ * &struct iwl_notif_statistics_cdb
+ */
STATISTICS_CMD = 0x9c,
+
+ /**
+ * @STATISTICS_NOTIFICATION:
+ * one of &struct iwl_notif_statistics_v10,
+ * &struct iwl_notif_statistics_v11,
+ * &struct iwl_notif_statistics_cdb
+ */
STATISTICS_NOTIFICATION = 0x9d,
+
+ /**
+ * @EOSP_NOTIFICATION:
+ * Notify that a service period ended,
+ * &struct iwl_mvm_eosp_notification
+ */
EOSP_NOTIFICATION = 0x9e,
+
+ /**
+ * @REDUCE_TX_POWER_CMD:
+ * &struct iwl_dev_tx_power_cmd_v3 or &struct iwl_dev_tx_power_cmd
+ */
REDUCE_TX_POWER_CMD = 0x9f,
- /* RF-KILL commands and notifications */
- CARD_STATE_CMD = 0xa0,
+ /**
+ * @CARD_STATE_NOTIFICATION:
+ * Card state (RF/CT kill) notification,
+ * uses &struct iwl_card_state_notif
+ */
CARD_STATE_NOTIFICATION = 0xa1,
+ /**
+ * @MISSED_BEACONS_NOTIFICATION: &struct iwl_missed_beacons_notif
+ */
MISSED_BEACONS_NOTIFICATION = 0xa2,
- /* Power - new power table command */
+ /**
+ * @MAC_PM_POWER_TABLE: using &struct iwl_mac_power_cmd
+ */
MAC_PM_POWER_TABLE = 0xa9,
+ /**
+ * @MFUART_LOAD_NOTIFICATION: &struct iwl_mfuart_load_notif
+ */
MFUART_LOAD_NOTIFICATION = 0xb1,
+ /**
+ * @RSS_CONFIG_CMD: &struct iwl_rss_config_cmd
+ */
RSS_CONFIG_CMD = 0xb3,
+ /**
+ * @REPLY_RX_PHY_CMD: &struct iwl_rx_phy_info
+ */
REPLY_RX_PHY_CMD = 0xc0,
+
+ /**
+ * @REPLY_RX_MPDU_CMD:
+ * &struct iwl_rx_mpdu_res_start or &struct iwl_rx_mpdu_desc
+ */
REPLY_RX_MPDU_CMD = 0xc1,
+
+ /**
+ * @FRAME_RELEASE:
+ * Frame release (reorder helper) notification, uses
+ * &struct iwl_frame_release
+ */
FRAME_RELEASE = 0xc3,
+
+ /**
+ * @BA_NOTIF:
+ * BlockAck notification, uses &struct iwl_mvm_compressed_ba_notif
+ * or &struct iwl_mvm_ba_notif depending on the HW
+ */
BA_NOTIF = 0xc5,
/* Location Aware Regulatory */
+ /**
+ * @MCC_UPDATE_CMD: using &struct iwl_mcc_update_cmd
+ */
MCC_UPDATE_CMD = 0xc8,
+
+ /**
+ * @MCC_CHUB_UPDATE_CMD: using &struct iwl_mcc_chub_notif
+ */
MCC_CHUB_UPDATE_CMD = 0xc9,
+ /**
+ * @MARKER_CMD: trace marker command, uses &struct iwl_mvm_marker
+ */
MARKER_CMD = 0xcb,
- /* BT Coex */
- BT_COEX_PRIO_TABLE = 0xcc,
- BT_COEX_PROT_ENV = 0xcd,
+ /**
+ * @BT_PROFILE_NOTIFICATION: &struct iwl_bt_coex_profile_notif
+ */
BT_PROFILE_NOTIFICATION = 0xce,
+
+ /**
+ * @BT_CONFIG: &struct iwl_bt_coex_cmd
+ */
BT_CONFIG = 0x9b,
- BT_COEX_UPDATE_SW_BOOST = 0x5a,
+
+ /**
+ * @BT_COEX_UPDATE_CORUN_LUT:
+ * &struct iwl_bt_coex_corun_lut_update_cmd
+ */
BT_COEX_UPDATE_CORUN_LUT = 0x5b,
+
+ /**
+ * @BT_COEX_UPDATE_REDUCED_TXP:
+ * &struct iwl_bt_coex_reduced_txp_update_cmd
+ */
BT_COEX_UPDATE_REDUCED_TXP = 0x5c,
+
+ /**
+ * @BT_COEX_CI: &struct iwl_bt_coex_ci_cmd
+ */
BT_COEX_CI = 0x5d,
+ /**
+ * @REPLY_SF_CFG_CMD: &struct iwl_sf_cfg_cmd
+ */
REPLY_SF_CFG_CMD = 0xd1,
+ /**
+ * @REPLY_BEACON_FILTERING_CMD: &struct iwl_beacon_filter_cmd
+ */
REPLY_BEACON_FILTERING_CMD = 0xd2,
- /* DTS measurements */
- CMD_DTS_MEASUREMENT_TRIGGER = 0xdc,
+ /**
+ * @DTS_MEASUREMENT_NOTIFICATION:
+ * &struct iwl_dts_measurement_notif_v1 or
+ * &struct iwl_dts_measurement_notif_v2
+ */
DTS_MEASUREMENT_NOTIFICATION = 0xdd,
- REPLY_DEBUG_CMD = 0xf0,
+ /**
+ * @LDBG_CONFIG_CMD: configure continuous trace recording
+ */
LDBG_CONFIG_CMD = 0xf6,
+
+ /**
+ * @DEBUG_LOG_MSG: Debugging log data from firmware
+ */
DEBUG_LOG_MSG = 0xf7,
+ /**
+ * @BCAST_FILTER_CMD: &struct iwl_bcast_filter_cmd
+ */
BCAST_FILTER_CMD = 0xcf,
+
+ /**
+ * @MCAST_FILTER_CMD: &struct iwl_mcast_filter_cmd
+ */
MCAST_FILTER_CMD = 0xd0,
- /* D3 commands/notifications */
+ /**
+ * @D3_CONFIG_CMD: &struct iwl_d3_manager_config
+ */
D3_CONFIG_CMD = 0xd3,
+
+ /**
+ * @PROT_OFFLOAD_CONFIG_CMD: Depending on firmware, uses one of
+ * &struct iwl_proto_offload_cmd_v1, &struct iwl_proto_offload_cmd_v2,
+ * &struct iwl_proto_offload_cmd_v3_small,
+ * &struct iwl_proto_offload_cmd_v3_large
+ */
PROT_OFFLOAD_CONFIG_CMD = 0xd4,
+
+ /**
+ * @OFFLOADS_QUERY_CMD:
+ * No data in command, response in &struct iwl_wowlan_status
+ */
OFFLOADS_QUERY_CMD = 0xd5,
+
+ /**
+ * @REMOTE_WAKE_CONFIG_CMD: &struct iwl_wowlan_remote_wake_config
+ */
REMOTE_WAKE_CONFIG_CMD = 0xd6,
+
+ /**
+ * @D0I3_END_CMD: End D0i3/D3 state, no command data
+ */
D0I3_END_CMD = 0xed,
- /* for WoWLAN in particular */
+ /**
+ * @WOWLAN_PATTERNS: &struct iwl_wowlan_patterns_cmd
+ */
WOWLAN_PATTERNS = 0xe0,
+
+ /**
+ * @WOWLAN_CONFIGURATION: &struct iwl_wowlan_config_cmd
+ */
WOWLAN_CONFIGURATION = 0xe1,
+
+ /**
+ * @WOWLAN_TSC_RSC_PARAM: &struct iwl_wowlan_rsc_tsc_params_cmd
+ */
WOWLAN_TSC_RSC_PARAM = 0xe2,
+
+ /**
+ * @WOWLAN_TKIP_PARAM: &struct iwl_wowlan_tkip_params_cmd
+ */
WOWLAN_TKIP_PARAM = 0xe3,
+
+ /**
+ * @WOWLAN_KEK_KCK_MATERIAL: &struct iwl_wowlan_kek_kck_material_cmd
+ */
WOWLAN_KEK_KCK_MATERIAL = 0xe4,
+
+ /**
+ * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status
+ */
WOWLAN_GET_STATUSES = 0xe5,
- WOWLAN_TX_POWER_PER_DB = 0xe6,
- /* and for NetDetect */
+ /**
+ * @SCAN_OFFLOAD_PROFILES_QUERY_CMD:
+ * No command data, response is &struct iwl_scan_offload_profiles_query
+ */
SCAN_OFFLOAD_PROFILES_QUERY_CMD = 0x56,
- SCAN_OFFLOAD_HOTSPOTS_CONFIG_CMD = 0x58,
- SCAN_OFFLOAD_HOTSPOTS_QUERY_CMD = 0x59,
-
- REPLY_MAX = 0xff,
};
/* Please keep this enum *SORTED* by hex value.
@@ -316,45 +682,169 @@ enum iwl_mac_conf_subcmd_ids {
CHANNEL_SWITCH_NOA_NOTIF = 0xFF,
};
+/**
+ * enum iwl_phy_ops_subcmd_ids - PHY group commands
+ */
enum iwl_phy_ops_subcmd_ids {
+ /**
+ * @CMD_DTS_MEASUREMENT_TRIGGER_WIDE:
+ * Uses either &struct iwl_dts_measurement_cmd or
+ * &struct iwl_ext_dts_measurement_cmd
+ */
CMD_DTS_MEASUREMENT_TRIGGER_WIDE = 0x0,
+
+ /**
+ * @CTDP_CONFIG_CMD: &struct iwl_mvm_ctdp_cmd
+ */
CTDP_CONFIG_CMD = 0x03,
+
+ /**
+ * @TEMP_REPORTING_THRESHOLDS_CMD: &struct temp_report_ths_cmd
+ */
TEMP_REPORTING_THRESHOLDS_CMD = 0x04,
+
+ /**
+ * @GEO_TX_POWER_LIMIT: &struct iwl_geo_tx_power_profiles_cmd
+ */
GEO_TX_POWER_LIMIT = 0x05,
+
+ /**
+ * @CT_KILL_NOTIFICATION: &struct ct_kill_notif
+ */
CT_KILL_NOTIFICATION = 0xFE,
+
+ /**
+ * @DTS_MEASUREMENT_NOTIF_WIDE:
+ * &struct iwl_dts_measurement_notif_v1 or
+ * &struct iwl_dts_measurement_notif_v2
+ */
DTS_MEASUREMENT_NOTIF_WIDE = 0xFF,
};
+/**
+ * enum iwl_system_subcmd_ids - system group command IDs
+ */
enum iwl_system_subcmd_ids {
+ /**
+ * @SHARED_MEM_CFG_CMD:
+ * response in &struct iwl_shared_mem_cfg or
+ * &struct iwl_shared_mem_cfg_v2
+ */
SHARED_MEM_CFG_CMD = 0x0,
+
+ /**
+ * @INIT_EXTENDED_CFG_CMD: &struct iwl_init_extended_cfg_cmd
+ */
INIT_EXTENDED_CFG_CMD = 0x03,
};
+/**
+ * enum iwl_data_path_subcmd_ids - data path group commands
+ */
enum iwl_data_path_subcmd_ids {
+ /**
+ * @DQA_ENABLE_CMD: &struct iwl_dqa_enable_cmd
+ */
DQA_ENABLE_CMD = 0x0,
+
+ /**
+ * @UPDATE_MU_GROUPS_CMD: &struct iwl_mu_group_mgmt_cmd
+ */
UPDATE_MU_GROUPS_CMD = 0x1,
+
+ /**
+ * @TRIGGER_RX_QUEUES_NOTIF_CMD: &struct iwl_rxq_sync_cmd
+ */
TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2,
+
+ /**
+ * @STA_PM_NOTIF: &struct iwl_mvm_pm_state_notification
+ */
STA_PM_NOTIF = 0xFD,
+
+ /**
+ * @MU_GROUP_MGMT_NOTIF: &struct iwl_mu_group_mgmt_notif
+ */
MU_GROUP_MGMT_NOTIF = 0xFE,
+
+ /**
+ * @RX_QUEUES_NOTIFICATION: &struct iwl_rxq_sync_notification
+ */
RX_QUEUES_NOTIFICATION = 0xFF,
};
+/**
+ * enum iwl_prot_offload_subcmd_ids - protocol offload commands
+ */
enum iwl_prot_offload_subcmd_ids {
+ /**
+ * @STORED_BEACON_NTF: &struct iwl_stored_beacon_notif
+ */
STORED_BEACON_NTF = 0xFF,
};
+/**
+ * enum iwl_regulatory_and_nvm_subcmd_ids - regulatory/NVM commands
+ */
enum iwl_regulatory_and_nvm_subcmd_ids {
+ /**
+ * @NVM_ACCESS_COMPLETE: &struct iwl_nvm_access_complete_cmd
+ */
NVM_ACCESS_COMPLETE = 0x0,
+
+ /**
+ * @NVM_GET_INFO:
+ * Command is &struct iwl_nvm_get_info,
+ * response is &struct iwl_nvm_get_info_rsp
+ */
+ NVM_GET_INFO = 0x2,
};
+/**
+ * enum iwl_debug_cmds - debug commands
+ */
enum iwl_debug_cmds {
+ /**
+ * @LMAC_RD_WR:
+ * LMAC memory read/write, using &struct iwl_dbg_mem_access_cmd and
+ * &struct iwl_dbg_mem_access_rsp
+ */
LMAC_RD_WR = 0x0,
+ /**
+ * @UMAC_RD_WR:
+ * UMAC memory read/write, using &struct iwl_dbg_mem_access_cmd and
+ * &struct iwl_dbg_mem_access_rsp
+ */
UMAC_RD_WR = 0x1,
+ /**
+ * @MFU_ASSERT_DUMP_NTF:
+ * &struct iwl_mfu_assert_dump_notif
+ */
MFU_ASSERT_DUMP_NTF = 0xFE,
};
-/* command groups */
-enum {
+/**
+ * enum iwl_mvm_command_groups - command groups for the firmware
+ * @LEGACY_GROUP: legacy group, uses command IDs from &enum iwl_legacy_cmds
+ * @LONG_GROUP: legacy group with long header, also uses command IDs
+ * from &enum iwl_legacy_cmds
+ * @SYSTEM_GROUP: system group, uses command IDs from
+ * &enum iwl_system_subcmd_ids
+ * @MAC_CONF_GROUP: MAC configuration group, uses command IDs from
+ * &enum iwl_mac_conf_subcmd_ids
+ * @PHY_OPS_GROUP: PHY operations group, uses command IDs from
+ * &enum iwl_phy_ops_subcmd_ids
+ * @DATA_PATH_GROUP: data path group, uses command IDs from
+ * &enum iwl_data_path_subcmd_ids
+ * @NAN_GROUP: NAN group, uses command IDs from &enum iwl_nan_subcmd_ids
+ * @TOF_GROUP: TOF group, uses command IDs from &enum iwl_tof_subcmd_ids
+ * @PROT_OFFLOAD_GROUP: protocol offload group, uses command IDs from
+ * &enum iwl_prot_offload_subcmd_ids
+ * @REGULATORY_AND_NVM_GROUP: regulatory/NVM group, uses command IDs from
+ * &enum iwl_regulatory_and_nvm_subcmd_ids
+ * @DEBUG_GROUP: Debug group, uses command IDs from &enum iwl_debug_cmds
+ */
+enum iwl_mvm_command_groups {
LEGACY_GROUP = 0x0,
LONG_GROUP = 0x1,
SYSTEM_GROUP = 0x2,
@@ -390,13 +880,13 @@ struct iwl_tx_ant_cfg_cmd {
__le32 valid;
} __packed;
-/*
- * Calibration control struct.
+/**
+ * struct iwl_calib_ctrl - Calibration control struct.
* Sent as part of the phy configuration command.
* @flow_trigger: bitmap for which calibrations to perform according to
- * flow triggers.
+ * flow triggers, using &enum iwl_calib_cfg
* @event_trigger: bitmap for which calibrations to perform according to
- * event triggers.
+ * event triggers, using &enum iwl_calib_cfg
*/
struct iwl_calib_ctrl {
__le32 flow_trigger;
@@ -428,8 +918,10 @@ enum iwl_calib_cfg {
IWL_CALIB_CFG_AGC_IDX = BIT(18),
};
-/*
- * Phy configuration command.
+/**
+ * struct iwl_phy_cfg_cmd - Phy configuration command
+ * @phy_cfg: PHY configuration value, uses &enum iwl_fw_phy_cfg
+ * @calib_control: calibration control data
*/
struct iwl_phy_cfg_cmd {
__le32 phy_cfg;
@@ -448,15 +940,39 @@ struct iwl_phy_cfg_cmd {
#define PHY_CFG_RX_CHAIN_C BIT(14)
-/* Target of the NVM_ACCESS_CMD */
-enum {
+/**
+ * enum iwl_nvm_access_op - NVM access opcode
+ * @IWL_NVM_READ: read NVM
+ * @IWL_NVM_WRITE: write NVM
+ */
+enum iwl_nvm_access_op {
+ IWL_NVM_READ = 0,
+ IWL_NVM_WRITE = 1,
+};
+
+/**
+ * enum iwl_nvm_access_target - target of the NVM_ACCESS_CMD
+ * @NVM_ACCESS_TARGET_CACHE: access the cache
+ * @NVM_ACCESS_TARGET_OTP: access the OTP
+ * @NVM_ACCESS_TARGET_EEPROM: access the EEPROM
+ */
+enum iwl_nvm_access_target {
NVM_ACCESS_TARGET_CACHE = 0,
NVM_ACCESS_TARGET_OTP = 1,
NVM_ACCESS_TARGET_EEPROM = 2,
};
-/* Section types for NVM_ACCESS_CMD */
-enum {
+/**
+ * enum iwl_nvm_section_type - section types for NVM_ACCESS_CMD
+ * @NVM_SECTION_TYPE_SW: software section
+ * @NVM_SECTION_TYPE_REGULATORY: regulatory section
+ * @NVM_SECTION_TYPE_CALIBRATION: calibration section
+ * @NVM_SECTION_TYPE_PRODUCTION: production section
+ * @NVM_SECTION_TYPE_MAC_OVERRIDE: MAC override section
+ * @NVM_SECTION_TYPE_PHY_SKU: PHY SKU section
+ * @NVM_MAX_NUM_SECTIONS: number of sections
+ */
+enum iwl_nvm_section_type {
NVM_SECTION_TYPE_SW = 1,
NVM_SECTION_TYPE_REGULATORY = 3,
NVM_SECTION_TYPE_CALIBRATION = 4,
@@ -467,10 +983,10 @@ enum {
};
/**
- * struct iwl_nvm_access_cmd_ver2 - Request the device to send an NVM section
- * @op_code: 0 - read, 1 - write
- * @target: NVM_ACCESS_TARGET_*
- * @type: NVM_SECTION_TYPE_*
+ * struct iwl_nvm_access_cmd - Request the device to send an NVM section
+ * @op_code: &enum iwl_nvm_access_op
+ * @target: &enum iwl_nvm_access_target
+ * @type: &enum iwl_nvm_section_type
* @offset: offset in bytes into the section
* @length: in bytes, to read/write
* @data: if write operation, the data to write. On read its empty
@@ -486,7 +1002,7 @@ struct iwl_nvm_access_cmd {
#define NUM_OF_FW_PAGING_BLOCKS 33 /* 32 for data and 1 block for CSS */
-/*
+/**
* struct iwl_fw_paging_cmd - paging layout
*
* (FW_PAGING_BLOCK_CMD = 0x4f)
@@ -497,17 +1013,13 @@ struct iwl_nvm_access_cmd {
* @block_size: the block size in powers of 2
* @block_num: number of blocks specified in the command.
* @device_phy_addr: virtual addresses from device side
- * 32 bit address for API version 1, 64 bit address for API version 2.
-*/
+ */
struct iwl_fw_paging_cmd {
__le32 flags;
__le32 block_size;
__le32 block_num;
- union {
- __le32 addr32[NUM_OF_FW_PAGING_BLOCKS];
- __le64 addr64[NUM_OF_FW_PAGING_BLOCKS];
- } device_phy_addr;
-} __packed; /* FW_PAGING_BLOCK_CMD_API_S_VER_2 */
+ __le32 device_phy_addr[NUM_OF_FW_PAGING_BLOCKS];
+} __packed; /* FW_PAGING_BLOCK_CMD_API_S_VER_1 */
/*
* Fw items ID's
@@ -660,6 +1172,7 @@ enum {
* ( REPLY_ERROR = 0x2 )
* @error_type: one of FW_ERR_*
* @cmd_id: the command ID for which the error occured
+ * @reserved1: reserved
* @bad_cmd_seq_num: sequence number of the erroneous command
* @error_service: which service created the error, applicable only if
* error_type = 2, otherwise 0
@@ -679,12 +1192,21 @@ struct iwl_error_resp {
#define MAX_MACS_IN_BINDING (3)
#define MAX_BINDINGS (4)
-/* Used to extract ID and color from the context dword */
-#define FW_CTXT_ID_POS (0)
-#define FW_CTXT_ID_MSK (0xff << FW_CTXT_ID_POS)
-#define FW_CTXT_COLOR_POS (8)
-#define FW_CTXT_COLOR_MSK (0xff << FW_CTXT_COLOR_POS)
-#define FW_CTXT_INVALID (0xffffffff)
+/**
+ * enum iwl_mvm_id_and_color - ID and color fields in context dword
+ * @FW_CTXT_ID_POS: position of the ID
+ * @FW_CTXT_ID_MSK: mask of the ID
+ * @FW_CTXT_COLOR_POS: position of the color
+ * @FW_CTXT_COLOR_MSK: mask of the color
+ * @FW_CTXT_INVALID: value used to indicate unused/invalid
+ */
+enum iwl_mvm_id_and_color {
+ FW_CTXT_ID_POS = 0,
+ FW_CTXT_ID_MSK = 0xff << FW_CTXT_ID_POS,
+ FW_CTXT_COLOR_POS = 8,
+ FW_CTXT_COLOR_MSK = 0xff << FW_CTXT_COLOR_POS,
+ FW_CTXT_INVALID = 0xffffffff,
+};
#define FW_CMD_ID_AND_COLOR(_id, _color) ((_id << FW_CTXT_ID_POS) |\
(_color << FW_CTXT_COLOR_POS))
@@ -832,7 +1354,8 @@ enum {
#define TE_V2_PLACEMENT_POS 12
#define TE_V2_ABSENCE_POS 15
-/* Time event policy values
+/**
+ * enum iwl_time_event_policy - Time event policy values
* 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
@@ -847,12 +1370,13 @@ enum {
* @TE_V2_NOTIF_HOST_FRAG_END:request/receive notification on frag end
* @TE_V2_NOTIF_INTERNAL_FRAG_START: internal FW use.
* @TE_V2_NOTIF_INTERNAL_FRAG_END: internal FW use.
+ * @T2_V2_START_IMMEDIATELY: start time event immediately
* @TE_V2_DEP_OTHER: depends on another time event
* @TE_V2_DEP_TSF: depends on a specific time
* @TE_V2_EVENT_SOCIOPATHIC: can't co-exist with other events of tha same MAC
* @TE_V2_ABSENCE: are we present or absent during the Time Event.
*/
-enum {
+enum iwl_time_event_policy {
TE_V2_DEFAULT_POLICY = 0x0,
/* notifications (event start/stop, fragment start/stop) */
@@ -867,8 +1391,6 @@ enum {
TE_V2_NOTIF_INTERNAL_FRAG_END = BIT(7),
T2_V2_START_IMMEDIATELY = BIT(11),
- TE_V2_NOTIF_MSK = 0xff,
-
/* placement characteristics */
TE_V2_DEP_OTHER = BIT(TE_V2_PLACEMENT_POS),
TE_V2_DEP_TSF = BIT(TE_V2_PLACEMENT_POS + 1),
@@ -879,12 +1401,13 @@ enum {
};
/**
- * struct iwl_time_event_cmd_api - configuring Time Events
+ * struct iwl_time_event_cmd - configuring Time Events
* with struct MAC_TIME_EVENT_DATA_API_S_VER_2 (see also
* with version 1. determined by IWL_UCODE_TLV_FLAGS)
* ( TIME_EVENT_CMD = 0x29 )
- * @id_and_color: ID and color of the relevant MAC
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @id_and_color: ID and color of the relevant MAC,
+ * &enum iwl_mvm_id_and_color
+ * @action: action to perform, one of &enum iwl_phy_ctxt_action
* @id: this field has two meanings, depending on the action:
* If the action is ADD, then it means the type of event to add.
* For all other actions it is the unique event ID assigned when the
@@ -900,7 +1423,8 @@ enum {
* on event and/or fragment start and/or end
* using one of TE_INDEPENDENT, TE_DEP_OTHER, TE_DEP_TSF
* TE_EVENT_SOCIOPATHIC
- * using TE_ABSENCE and using TE_NOTIF_*
+ * using TE_ABSENCE and using TE_NOTIF_*,
+ * &enum iwl_time_event_policy
*/
struct iwl_time_event_cmd {
/* COMMON_INDEX_HDR_API_S_VER_1 */
@@ -923,7 +1447,8 @@ struct iwl_time_event_cmd {
* @status: bit 0 indicates success, all others specify errors
* @id: the Time Event type
* @unique_id: the unique ID assigned (in ADD) or given (others) to the TE
- * @id_and_color: ID and color of the relevant MAC
+ * @id_and_color: ID and color of the relevant MAC,
+ * &enum iwl_mvm_id_and_color
*/
struct iwl_time_event_resp {
__le32 status;
@@ -939,7 +1464,7 @@ struct iwl_time_event_resp {
* @session_id: session's unique id
* @unique_id: unique id of the Time Event itself
* @id_and_color: ID and color of the relevant MAC
- * @action: one of TE_NOTIF_START or TE_NOTIF_END
+ * @action: &enum iwl_time_event_policy
* @status: true if scheduled, false otherwise (not executed)
*/
struct iwl_time_event_notif {
@@ -955,12 +1480,35 @@ struct iwl_time_event_notif {
/* Bindings and Time Quota */
/**
+ * struct iwl_binding_cmd_v1 - configuring bindings
+ * ( BINDING_CONTEXT_CMD = 0x2b )
+ * @id_and_color: ID and color of the relevant Binding,
+ * &enum iwl_mvm_id_and_color
+ * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @macs: array of MAC id and colors which belong to the binding,
+ * &enum iwl_mvm_id_and_color
+ * @phy: PHY id and color which belongs to the binding,
+ * &enum iwl_mvm_id_and_color
+ */
+struct iwl_binding_cmd_v1 {
+ /* COMMON_INDEX_HDR_API_S_VER_1 */
+ __le32 id_and_color;
+ __le32 action;
+ /* BINDING_DATA_API_S_VER_1 */
+ __le32 macs[MAX_MACS_IN_BINDING];
+ __le32 phy;
+} __packed; /* BINDING_CMD_API_S_VER_1 */
+
+/**
* struct iwl_binding_cmd - configuring bindings
* ( BINDING_CONTEXT_CMD = 0x2b )
- * @id_and_color: ID and color of the relevant Binding
+ * @id_and_color: ID and color of the relevant Binding,
+ * &enum iwl_mvm_id_and_color
* @action: action to perform, one of FW_CTXT_ACTION_*
* @macs: array of MAC id and colors which belong to the binding
+ * &enum iwl_mvm_id_and_color
* @phy: PHY id and color which belongs to the binding
+ * &enum iwl_mvm_id_and_color
* @lmac_id: the lmac id the binding belongs to
*/
struct iwl_binding_cmd {
@@ -970,11 +1518,10 @@ struct iwl_binding_cmd {
/* BINDING_DATA_API_S_VER_1 */
__le32 macs[MAX_MACS_IN_BINDING];
__le32 phy;
- /* BINDING_CMD_API_S_VER_1 */
__le32 lmac_id;
} __packed; /* BINDING_CMD_API_S_VER_2 */
-#define IWL_BINDING_CMD_SIZE_V1 offsetof(struct iwl_binding_cmd, lmac_id)
+#define IWL_BINDING_CMD_SIZE_V1 sizeof(struct iwl_binding_cmd_v1)
#define IWL_LMAC_24G_INDEX 0
#define IWL_LMAC_5G_INDEX 1
@@ -983,7 +1530,8 @@ struct iwl_binding_cmd {
/**
* struct iwl_time_quota_data - configuration of time quota per binding
- * @id_and_color: ID and color of the relevant Binding
+ * @id_and_color: ID and color of the relevant Binding,
+ * &enum iwl_mvm_id_and_color
* @quota: absolute time quota in TU. The scheduler will try to divide the
* remainig quota (after Time Events) according to this quota.
* @max_duration: max uninterrupted context duration in TU
@@ -1087,7 +1635,7 @@ struct iwl_fw_channel_info {
* @apply_time: 0 means immediate apply and context switch.
* other value means apply new params after X usecs
* @tx_param_color: ???
- * @channel_info:
+ * @ci: channel info
* @txchain_info: ???
* @rxchain_info: ???
* @acquisition_data: ???
@@ -1176,9 +1724,9 @@ struct iwl_hs20_roc_res {
/**
* struct iwl_radio_version_notif - information on the radio version
* ( RADIO_VERSION_NOTIFICATION = 0x68 )
- * @radio_flavor:
- * @radio_step:
- * @radio_dash:
+ * @radio_flavor: radio flavor
+ * @radio_step: radio version step
+ * @radio_dash: radio version dash
*/
struct iwl_radio_version_notif {
__le32 radio_flavor;
@@ -1212,8 +1760,8 @@ struct iwl_card_state_notif {
* @consec_missed_beacons_since_last_rx: number of consecutive missed
* beacons since last RX.
* @consec_missed_beacons: number of consecutive missed beacons
- * @num_expected_beacons:
- * @num_recvd_beacons:
+ * @num_expected_beacons: number of expected beacons
+ * @num_recvd_beacons: number of received beacons
*/
struct iwl_missed_beacons_notif {
__le32 mac_id;
@@ -1260,19 +1808,6 @@ struct iwl_mfu_assert_dump_notif {
__le32 data[0];
} __packed; /*MFU_DUMP_ASSERT_API_S_VER_1*/
-/**
- * struct iwl_set_calib_default_cmd - set default value for calibration.
- * ( SET_CALIB_DEFAULT_CMD = 0x8e )
- * @calib_index: the calibration to set value for
- * @length: of data
- * @data: the value to set for the calibration result
- */
-struct iwl_set_calib_default_cmd {
- __le16 calib_index;
- __le16 length;
- u8 data[0];
-} __packed; /* PHY_CALIB_OVERRIDE_VALUES_S */
-
#define MAX_PORT_ID_NUM 2
#define MAX_MCAST_FILTERING_ADDRESSES 256
@@ -1286,6 +1821,7 @@ struct iwl_set_calib_default_cmd {
* @count: Number of MAC addresses in the array
* @pass_all: Set 1 to pass all multicast packets.
* @bssid: current association BSSID.
+ * @reserved: reserved
* @addr_list: Place holder for array of MAC addresses.
* IMPORTANT: add padding if necessary to ensure DWORD alignment.
*/
@@ -1317,7 +1853,8 @@ enum iwl_mvm_bcast_filter_attr_offset {
* struct iwl_fw_bcast_filter_attr - broadcast filter attribute
* @offset_type: &enum iwl_mvm_bcast_filter_attr_offset.
* @offset: starting offset of this pattern.
- * @val: value to match - big endian (MSB is the first
+ * @reserved1: reserved
+ * @val: value to match - big endian (MSB is the first
* byte to match from offset pos).
* @mask: mask to match (big endian).
*/
@@ -1343,6 +1880,7 @@ enum iwl_mvm_bcast_filter_frame_type {
* struct iwl_fw_bcast_filter - broadcast filter
* @discard: discard frame (1) or let it pass (0).
* @frame_type: &enum iwl_mvm_bcast_filter_frame_type.
+ * @reserved1: reserved
* @num_attrs: number of valid attributes in this filter.
* @attrs: attributes of this filter. a filter is considered matched
* only when all its attributes are matched (i.e. AND relationship)
@@ -1378,6 +1916,7 @@ struct iwl_ba_window_status_notif {
/**
* struct iwl_fw_bcast_mac - per-mac broadcast filtering configuration.
* @default_discard: default action for this mac (discard (1) / pass (0)).
+ * @reserved1: reserved
* @attached_filters: bitmap of relevant filters for this mac.
*/
struct iwl_fw_bcast_mac {
@@ -1391,6 +1930,7 @@ struct iwl_fw_bcast_mac {
* @disable: enable (0) / disable (1)
* @max_bcast_filters: max number of filters (MAX_BCAST_FILTERS)
* @max_macs: max number of macs (NUM_MAC_INDEX_DRIVER)
+ * @reserved1: reserved
* @filters: broadcast filters
* @macs: broadcast filtering configuration per-mac
*/
@@ -1428,8 +1968,8 @@ enum iwl_mvm_marker_id {
* @metadata: additional meta data that will be written to the unsiffer log
*/
struct iwl_mvm_marker {
- u8 dwLen;
- u8 markerId;
+ u8 dw_len;
+ u8 marker_id;
__le16 reserved;
__le64 timestamp;
__le32 metadata[0];
@@ -1539,8 +2079,8 @@ enum iwl_sf_scenario {
#define SF_CFG_DUMMY_NOTIF_OFF BIT(16)
/**
- * Smart Fifo configuration command.
- * @state: smart fifo state, types listed in enum %iwl_sf_sate.
+ * struct iwl_sf_cfg_cmd - Smart Fifo configuration command.
+ * @state: smart fifo state, types listed in &enum iwl_sf_state.
* @watermark: Minimum allowed availabe free space in RXF for transient state.
* @long_delay_timeouts: aging and idle timer values for each scenario
* in long delay state.
@@ -1590,11 +2130,11 @@ struct iwl_mcc_update_cmd {
u8 source_id;
u8 reserved;
__le32 key;
- __le32 reserved2[5];
+ u8 reserved2[20];
} __packed; /* LAR_UPDATE_MCC_CMD_API_S_VER_2 */
/**
- * iwl_mcc_update_resp_v1 - response to MCC_UPDATE_CMD.
+ * struct iwl_mcc_update_resp_v1 - response to MCC_UPDATE_CMD.
* Contains the new channel control profile map, if changed, and the new MCC
* (mobile country code).
* The new MCC may be different than what was requested in MCC_UPDATE_CMD.
@@ -1617,7 +2157,7 @@ struct iwl_mcc_update_resp_v1 {
} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_1 */
/**
- * iwl_mcc_update_resp - response to MCC_UPDATE_CMD.
+ * struct iwl_mcc_update_resp - response to MCC_UPDATE_CMD.
* Contains the new channel control profile map, if changed, and the new MCC
* (mobile country code).
* The new MCC may be different than what was requested in MCC_UPDATE_CMD.
@@ -1659,7 +2199,7 @@ struct iwl_mcc_update_resp {
* @reserved1: reserved for alignment
*/
struct iwl_mcc_chub_notif {
- u16 mcc;
+ __le16 mcc;
u8 source_id;
u8 reserved1;
} __packed; /* LAR_MCC_NOTIFY_S */
@@ -1699,10 +2239,10 @@ enum iwl_dts_measurement_flags {
};
/**
- * iwl_dts_measurement_cmd - request DTS temperature and/or voltage measurements
+ * struct iwl_dts_measurement_cmd - request DTS temp and/or voltage measurements
*
- * @flags: indicates which measurements we want as specified in &enum
- * iwl_dts_measurement_flags
+ * @flags: indicates which measurements we want as specified in
+ * &enum iwl_dts_measurement_flags
*/
struct iwl_dts_measurement_cmd {
__le32 flags;
@@ -1733,7 +2273,7 @@ enum iwl_dts_control_measurement_mode {
* @DTS_USE_CHAIN_A: chain A
* @DTS_USE_CHAIN_B: chain B
* @DTS_USE_CHAIN_C: chain C
-* @XTAL_TEMPERATURE - read temperature from xtal
+* @XTAL_TEMPERATURE: read temperature from xtal
*/
enum iwl_dts_used {
DTS_USE_TOP = 0,
@@ -1754,7 +2294,7 @@ enum iwl_dts_bit_mode {
};
/**
- * iwl_ext_dts_measurement_cmd - request extended DTS temperature measurements
+ * struct iwl_ext_dts_measurement_cmd - request extended DTS temp measurements
* @control_mode: see &enum iwl_dts_control_measurement_mode
* @temperature: used when over write DTS mode is selected
* @sensor: set temperature sensor to use. See &enum iwl_dts_used
@@ -1810,7 +2350,7 @@ struct ct_kill_notif {
* enum ctdp_cmd_operation - CTDP command operations
* @CTDP_CMD_OPERATION_START: update the current budget
* @CTDP_CMD_OPERATION_STOP: stop ctdp
-* @CTDP_CMD_OPERATION_REPORT: get the avgerage budget
+* @CTDP_CMD_OPERATION_REPORT: get the average budget
*/
enum iwl_mvm_ctdp_cmd_operation {
CTDP_CMD_OPERATION_START = 0x1,
@@ -1834,7 +2374,7 @@ struct iwl_mvm_ctdp_cmd {
#define IWL_MAX_DTS_TRIPS 8
/**
- * struct iwl_temp_report_ths_cmd - set temperature thresholds
+ * struct temp_report_ths_cmd - set temperature thresholds
*
* @num_temps: number of temperature thresholds passed
* @thresholds: array with the thresholds to be configured
@@ -1856,7 +2396,7 @@ enum iwl_tdls_channel_switch_type {
}; /* TDLS_STA_CHANNEL_SWITCH_CMD_TYPE_API_E_VER_1 */
/**
- * Switch timing sub-element in a TDLS channel-switch command
+ * struct iwl_tdls_channel_switch_timing - Switch timing in TDLS channel-switch
* @frame_timestamp: GP2 timestamp of channel-switch request/response packet
* received from peer
* @max_offchan_duration: What amount of microseconds out of a DTIM is given
@@ -1864,7 +2404,7 @@ enum iwl_tdls_channel_switch_type {
* 200TU and the TDLS peer is to be given 25% of the time, the value
* given will be 50TU, or 50 * 1024 if translated into microseconds.
* @switch_time: switch time the peer sent in its channel switch timing IE
- * @switch_timout: switch timeout the peer sent in its channel switch timing IE
+ * @switch_timeout: switch timeout the peer sent in its channel switch timing IE
*/
struct iwl_tdls_channel_switch_timing {
__le32 frame_timestamp; /* GP2 time of peer packet Rx */
@@ -1876,7 +2416,7 @@ struct iwl_tdls_channel_switch_timing {
#define IWL_TDLS_CH_SW_FRAME_MAX_SIZE 200
/**
- * TDLS channel switch frame template
+ * struct iwl_tdls_channel_switch_frame - TDLS channel switch frame template
*
* A template representing a TDLS channel-switch request or response frame
*
@@ -1891,7 +2431,7 @@ struct iwl_tdls_channel_switch_frame {
} __packed; /* TDLS_STA_CHANNEL_SWITCH_FRAME_API_S_VER_1 */
/**
- * TDLS channel switch command
+ * struct iwl_tdls_channel_switch_cmd - TDLS channel switch command
*
* The command is sent to initiate a channel switch and also in response to
* incoming TDLS channel-switch request/response packets from remote peers.
@@ -1911,7 +2451,7 @@ struct iwl_tdls_channel_switch_cmd {
} __packed; /* TDLS_STA_CHANNEL_SWITCH_CMD_API_S_VER_1 */
/**
- * TDLS channel switch start notification
+ * struct iwl_tdls_channel_switch_notif - TDLS channel switch start notification
*
* @status: non-zero on success
* @offchannel_duration: duration given in microseconds
@@ -1924,7 +2464,7 @@ struct iwl_tdls_channel_switch_notif {
} __packed; /* TDLS_STA_CHANNEL_SWITCH_NTFY_API_S_VER_1 */
/**
- * TDLS station info
+ * struct iwl_tdls_sta_info - TDLS station info
*
* @sta_id: station id of the TDLS peer
* @tx_to_peer_tid: TID reserved vs. the peer for FW based Tx
@@ -1939,7 +2479,7 @@ struct iwl_tdls_sta_info {
} __packed; /* TDLS_STA_INFO_VER_1 */
/**
- * TDLS basic config command
+ * struct iwl_tdls_config_cmd - TDLS basic config command
*
* @id_and_color: MAC id and color being configured
* @tdls_peer_count: amount of currently connected TDLS peers
@@ -1963,7 +2503,7 @@ struct iwl_tdls_config_cmd {
} __packed; /* TDLS_CONFIG_CMD_API_S_VER_1 */
/**
- * TDLS per-station config information from FW
+ * struct iwl_tdls_config_sta_info_res - TDLS per-station config information
*
* @sta_id: station id of the TDLS peer
* @tx_to_peer_last_seq: last sequence number used by FW during FW-based Tx to
@@ -1975,7 +2515,7 @@ struct iwl_tdls_config_sta_info_res {
} __packed; /* TDLS_STA_INFO_RSP_VER_1 */
/**
- * TDLS config information from FW
+ * struct iwl_tdls_config_res - TDLS config information from FW
*
* @tx_to_ap_last_seq: last sequence number used by FW during FW-based Tx to AP
* @sta_info: per-station TDLS config information
@@ -1991,7 +2531,7 @@ struct iwl_tdls_config_res {
#define TX_FIFO_INTERNAL_MAX_NUM 6
/**
- * Shared memory configuration information from the FW
+ * struct iwl_shared_mem_cfg_v2 - Shared memory configuration information
*
* @shared_mem_addr: shared memory addr (pre 8000 HW set to 0x0 as MARBH is not
* accessible)
@@ -2013,7 +2553,7 @@ struct iwl_tdls_config_res {
* NOTE: on firmware that don't have IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG
* set, the last 3 members don't exist.
*/
-struct iwl_shared_mem_cfg_v1 {
+struct iwl_shared_mem_cfg_v2 {
__le32 shared_mem_addr;
__le32 shared_mem_size;
__le32 sample_buff_addr;
@@ -2045,7 +2585,7 @@ struct iwl_shared_mem_lmac_cfg {
} __packed; /* SHARED_MEM_ALLOC_LMAC_API_S_VER_1 */
/**
- * Shared memory configuration information from the FW
+ * struct iwl_shared_mem_cfg - Shared memory configuration information
*
* @shared_mem_addr: shared memory address
* @shared_mem_size: shared memory size
@@ -2073,8 +2613,9 @@ struct iwl_shared_mem_cfg {
} __packed; /* SHARED_MEM_ALLOC_API_S_VER_3 */
/**
- * VHT MU-MIMO group configuration
+ * struct iwl_mu_group_mgmt_cmd - VHT MU-MIMO group configuration
*
+ * @reserved: reserved
* @membership_status: a bitmap of MU groups
* @user_position:the position of station in a group. If the station is in the
* group then bits (group * 2) is the position -1
@@ -2100,7 +2641,7 @@ struct iwl_mu_group_mgmt_notif {
#define MAX_STORED_BEACON_SIZE 600
/**
- * Stored beacon notification
+ * struct iwl_stored_beacon_notif - Stored beacon notification
*
* @system_time: system time on air rise
* @tsf: TSF on air rise
@@ -2109,6 +2650,7 @@ struct iwl_mu_group_mgmt_notif {
* @channel: channel this beacon was received on
* @rates: rate in ucode internal format
* @byte_count: frame's byte count
+ * @data: beacon data, length in @byte_count
*/
struct iwl_stored_beacon_notif {
__le32 system_time;
@@ -2135,8 +2677,8 @@ enum iwl_lqm_status {
};
/**
- * Link Quality Measurement command
- * @cmd_operatrion: command operation to be performed (start or stop)
+ * struct iwl_link_qual_msrmnt_cmd - Link Quality Measurement command
+ * @cmd_operation: command operation to be performed (start or stop)
* as defined above.
* @mac_id: MAC ID the measurement applies to.
* @measurement_time: time of the total measurement to be performed, in uSec.
@@ -2150,7 +2692,7 @@ struct iwl_link_qual_msrmnt_cmd {
} __packed /* LQM_CMD_API_S_VER_1 */;
/**
- * Link Quality Measurement notification
+ * struct iwl_link_qual_msrmnt_notif - Link Quality Measurement notification
*
* @frequent_stations_air_time: an array containing the total air time
* (in uSec) used by the most frequently transmitting stations.
@@ -2174,11 +2716,11 @@ struct iwl_link_qual_msrmnt_notif {
__le32 tx_frame_dropped;
__le32 mac_id;
__le32 status;
- __le32 reserved[3];
+ u8 reserved[12];
} __packed; /* LQM_MEASUREMENT_COMPLETE_NTF_API_S_VER1 */
/**
- * Channel switch NOA notification
+ * struct iwl_channel_switch_noa_notif - Channel switch NOA notification
*
* @id_and_color: ID and color of the MAC
*/
@@ -2232,6 +2774,7 @@ struct iwl_dbg_mem_access_rsp {
/**
* struct iwl_nvm_access_complete_cmd - NVM_ACCESS commands are completed
+ * @reserved: reserved
*/
struct iwl_nvm_access_complete_cmd {
__le32 reserved;
@@ -2259,4 +2802,89 @@ struct iwl_init_extended_cfg_cmd {
__le32 init_flags;
} __packed; /* INIT_EXTENDED_CFG_CMD_API_S_VER_1 */
+/*
+ * struct iwl_nvm_get_info - request to get NVM data
+ */
+struct iwl_nvm_get_info {
+ __le32 reserved;
+} __packed; /* GRP_REGULATORY_NVM_GET_INFO_CMD_S_VER_1 */
+
+/**
+ * struct iwl_nvm_get_info_general - general NVM data
+ * @flags: 1 - empty, 0 - valid
+ * @nvm_version: nvm version
+ * @board_type: board type
+ * @reserved: reserved
+ */
+struct iwl_nvm_get_info_general {
+ __le32 flags;
+ __le16 nvm_version;
+ u8 board_type;
+ u8 reserved;
+} __packed; /* GRP_REGULATORY_NVM_GET_INFO_GENERAL_S_VER_1 */
+
+/**
+ * struct iwl_nvm_get_info_sku - mac information
+ * @enable_24g: band 2.4G enabled
+ * @enable_5g: band 5G enabled
+ * @enable_11n: 11n enabled
+ * @enable_11ac: 11ac enabled
+ * @mimo_disable: MIMO enabled
+ * @ext_crypto: Extended crypto enabled
+ */
+struct iwl_nvm_get_info_sku {
+ __le32 enable_24g;
+ __le32 enable_5g;
+ __le32 enable_11n;
+ __le32 enable_11ac;
+ __le32 mimo_disable;
+ __le32 ext_crypto;
+} __packed; /* GRP_REGULATORY_NVM_GET_INFO_MAC_SKU_SECTION_S_VER_1 */
+
+/**
+ * struct iwl_nvm_get_info_phy - phy information
+ * @tx_chains: BIT 0 chain A, BIT 1 chain B
+ * @rx_chains: BIT 0 chain A, BIT 1 chain B
+ */
+struct iwl_nvm_get_info_phy {
+ __le32 tx_chains;
+ __le32 rx_chains;
+} __packed; /* GRP_REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */
+
+#define IWL_NUM_CHANNELS (51)
+
+/**
+ * struct iwl_nvm_get_info_regulatory - regulatory information
+ * @lar_enabled: is LAR enabled
+ * @channel_profile: regulatory data of this channel
+ * @reserved: reserved
+ */
+struct iwl_nvm_get_info_regulatory {
+ __le32 lar_enabled;
+ __le16 channel_profile[IWL_NUM_CHANNELS];
+ __le16 reserved;
+} __packed; /* GRP_REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_1 */
+
+/**
+ * struct iwl_nvm_get_info_rsp - response to get NVM data
+ * @general: general NVM data
+ * @mac_sku: data relating to MAC sku
+ * @phy_sku: data relating to PHY sku
+ * @regulatory: regulatory data
+ */
+struct iwl_nvm_get_info_rsp {
+ struct iwl_nvm_get_info_general general;
+ struct iwl_nvm_get_info_sku mac_sku;
+ struct iwl_nvm_get_info_phy phy_sku;
+ struct iwl_nvm_get_info_regulatory regulatory;
+} __packed; /* GRP_REGULATORY_NVM_GET_INFO_CMD_RSP_S_VER_1 */
+
+/**
+ * struct iwl_mvm_antenna_coupling_notif - antenna coupling notification
+ * @isolation: antenna isolation value
+ */
+struct iwl_mvm_antenna_coupling_notif {
+ __le32 isolation;
+} __packed;
+
#endif /* __fw_api_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
index c8712e6..1602b36 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
@@ -319,10 +319,8 @@ static void iwl_mvm_dump_fifos(struct iwl_mvm *mvm,
void iwl_mvm_free_fw_dump_desc(struct iwl_mvm *mvm)
{
- if (mvm->fw_dump_desc == &iwl_mvm_dump_desc_assert)
- return;
-
- kfree(mvm->fw_dump_desc);
+ if (mvm->fw_dump_desc != &iwl_mvm_dump_desc_assert)
+ kfree(mvm->fw_dump_desc);
mvm->fw_dump_desc = NULL;
}
@@ -640,18 +638,21 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
}
/* Make room for PRPH registers */
- for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr_comm); i++) {
- /* The range includes both boundaries */
- int num_bytes_in_chunk =
- iwl_prph_dump_addr_comm[i].end -
- iwl_prph_dump_addr_comm[i].start + 4;
-
- prph_len += sizeof(*dump_data) +
- sizeof(struct iwl_fw_error_dump_prph) +
- num_bytes_in_chunk;
+ if (!mvm->trans->cfg->gen2) {
+ for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr_comm);
+ i++) {
+ /* The range includes both boundaries */
+ int num_bytes_in_chunk =
+ iwl_prph_dump_addr_comm[i].end -
+ iwl_prph_dump_addr_comm[i].start + 4;
+
+ prph_len += sizeof(*dump_data) +
+ sizeof(struct iwl_fw_error_dump_prph) +
+ num_bytes_in_chunk;
+ }
}
- if (mvm->cfg->mq_rx_supported) {
+ if (!mvm->trans->cfg->gen2 && mvm->cfg->mq_rx_supported) {
for (i = 0; i <
ARRAY_SIZE(iwl_prph_dump_addr_9000); i++) {
/* The range includes both boundaries */
@@ -691,7 +692,8 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
}
/* Make room for fw's virtual image pages, if it exists */
- if (mvm->fw->img[mvm->cur_ucode].paging_mem_size &&
+ if (!mvm->trans->cfg->gen2 &&
+ mvm->fw->img[mvm->cur_ucode].paging_mem_size &&
mvm->fw_paging_db[0].fw_paging_block)
file_len += mvm->num_of_paging_blk *
(sizeof(*dump_data) +
@@ -704,14 +706,6 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
sizeof(*dump_info);
}
- /*
- * In 8000 HW family B-step include the ICCM (which resides separately)
- */
- if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
- CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP)
- file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
- IWL8260_ICCM_LEN;
-
if (mvm->fw_dump_desc)
file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
mvm->fw_dump_desc->len;
@@ -836,21 +830,9 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
dump_data = iwl_fw_error_next_data(dump_data);
}
- if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
- CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP) {
- dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
- dump_data->len = cpu_to_le32(IWL8260_ICCM_LEN +
- sizeof(*dump_mem));
- dump_mem = (void *)dump_data->data;
- dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM);
- dump_mem->offset = cpu_to_le32(IWL8260_ICCM_OFFSET);
- iwl_trans_read_mem_bytes(mvm->trans, IWL8260_ICCM_OFFSET,
- dump_mem->data, IWL8260_ICCM_LEN);
- dump_data = iwl_fw_error_next_data(dump_data);
- }
-
/* Dump fw's virtual image */
- if (mvm->fw->img[mvm->cur_ucode].paging_mem_size &&
+ if (!mvm->trans->cfg->gen2 &&
+ mvm->fw->img[mvm->cur_ucode].paging_mem_size &&
mvm->fw_paging_db[0].fw_paging_block) {
for (i = 1; i < mvm->num_of_paging_blk + 1; i++) {
struct iwl_fw_error_dump_paging *paging;
@@ -931,6 +913,10 @@ int iwl_mvm_fw_dbg_collect_desc(struct iwl_mvm *mvm,
if (trigger)
delay = msecs_to_jiffies(le32_to_cpu(trigger->stop_delay));
+ if (WARN(mvm->trans->state == IWL_TRANS_NO_FW,
+ "Can't collect dbg data when FW isn't alive\n"))
+ return -EIO;
+
if (test_and_set_bit(IWL_MVM_STATUS_DUMPING_FW_LOG, &mvm->status))
return -EBUSY;
@@ -943,7 +929,7 @@ int iwl_mvm_fw_dbg_collect_desc(struct iwl_mvm *mvm,
mvm->fw_dump_desc = desc;
mvm->fw_dump_trig = trigger;
- queue_delayed_work(system_wq, &mvm->fw_dump_wk, delay);
+ schedule_delayed_work(&mvm->fw_dump_wk, delay);
return 0;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.h
index e9f1be9..4a5287a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.h
@@ -65,8 +65,8 @@
#ifndef __mvm_fw_dbg_h__
#define __mvm_fw_dbg_h__
-#include "iwl-fw-file.h"
-#include "iwl-fw-error-dump.h"
+#include "fw/file.h"
+#include "fw/error-dump.h"
#include "mvm.h"
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index e6c9528..79e7a7a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -70,7 +70,7 @@
#include "iwl-trans.h"
#include "iwl-op-mode.h"
-#include "iwl-fw.h"
+#include "fw/img.h"
#include "iwl-debug.h"
#include "iwl-csr.h" /* for iwl_mvm_rx_card_state_notif */
#include "iwl-io.h" /* for iwl_mvm_rx_card_state_notif */
@@ -385,40 +385,28 @@ static int iwl_save_fw_paging(struct iwl_mvm *mvm,
static int iwl_send_paging_cmd(struct iwl_mvm *mvm, const struct fw_img *fw)
{
struct iwl_fw_paging_cmd paging_cmd = {
- .flags =
- cpu_to_le32(PAGING_CMD_IS_SECURED |
- PAGING_CMD_IS_ENABLED |
- (mvm->num_of_pages_in_last_blk <<
- PAGING_CMD_NUM_OF_PAGES_IN_LAST_GRP_POS)),
+ .flags = cpu_to_le32(PAGING_CMD_IS_SECURED |
+ PAGING_CMD_IS_ENABLED |
+ (mvm->num_of_pages_in_last_blk <<
+ PAGING_CMD_NUM_OF_PAGES_IN_LAST_GRP_POS)),
.block_size = cpu_to_le32(BLOCK_2_EXP_SIZE),
.block_num = cpu_to_le32(mvm->num_of_paging_blk),
};
- int blk_idx, size = sizeof(paging_cmd);
-
- /* A bit hard coded - but this is the old API and will be deprecated */
- if (!iwl_mvm_has_new_tx_api(mvm))
- size -= NUM_OF_FW_PAGING_BLOCKS * 4;
+ int blk_idx;
/* loop for for all paging blocks + CSS block */
for (blk_idx = 0; blk_idx < mvm->num_of_paging_blk + 1; blk_idx++) {
dma_addr_t addr = mvm->fw_paging_db[blk_idx].fw_paging_phys;
+ __le32 phy_addr;
addr = addr >> PAGE_2_EXP_SIZE;
-
- if (iwl_mvm_has_new_tx_api(mvm)) {
- __le64 phy_addr = cpu_to_le64(addr);
-
- paging_cmd.device_phy_addr.addr64[blk_idx] = phy_addr;
- } else {
- __le32 phy_addr = cpu_to_le32(addr);
-
- paging_cmd.device_phy_addr.addr32[blk_idx] = phy_addr;
- }
+ phy_addr = cpu_to_le32(addr);
+ paging_cmd.device_phy_addr[blk_idx] = phy_addr;
}
return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(FW_PAGING_BLOCK_CMD,
IWL_ALWAYS_LONG_GROUP, 0),
- 0, size, &paging_cmd);
+ 0, sizeof(paging_cmd), &paging_cmd);
}
/*
@@ -619,7 +607,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
if (WARN_ON(!fw))
return -EINVAL;
mvm->cur_ucode = ucode_type;
- mvm->ucode_loaded = false;
+ clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
iwl_init_notification_wait(&mvm->notif_wait, &alive_wait,
alive_cmd, ARRAY_SIZE(alive_cmd),
@@ -641,12 +629,12 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
if (ret) {
struct iwl_trans *trans = mvm->trans;
- if (trans->cfg->gen2)
+ if (trans->cfg->device_family == IWL_DEVICE_FAMILY_A000)
IWL_ERR(mvm,
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
iwl_read_prph(trans, UMAG_SB_CPU_1_STATUS),
iwl_read_prph(trans, UMAG_SB_CPU_2_STATUS));
- else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ else if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
IWL_ERR(mvm,
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
iwl_read_prph(trans, SB_CPU_1_STATUS),
@@ -693,7 +681,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
for (i = 0; i < IEEE80211_MAX_QUEUES; i++)
atomic_set(&mvm->mac80211_queue_stop_count[i], 0);
- mvm->ucode_loaded = true;
+ set_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
return 0;
}
@@ -738,9 +726,13 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
goto error;
}
- /* Read the NVM only at driver load time, no need to do this twice */
- if (read_nvm) {
- /* Read nvm */
+ /* Load NVM to NIC if needed */
+ if (mvm->nvm_file_name) {
+ iwl_mvm_read_external_nvm(mvm);
+ iwl_mvm_load_nvm_to_nic(mvm);
+ }
+
+ if (IWL_MVM_PARSE_NVM && read_nvm) {
ret = iwl_nvm_init(mvm, true);
if (ret) {
IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
@@ -748,14 +740,6 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
}
}
- /* In case we read the NVM from external file, load it to the NIC */
- if (mvm->nvm_file_name)
- iwl_mvm_load_nvm_to_nic(mvm);
-
- ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans);
- if (WARN_ON(ret))
- goto error;
-
ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP,
NVM_ACCESS_COMPLETE), 0,
sizeof(nvm_complete), &nvm_complete);
@@ -766,8 +750,21 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
}
/* We wait for the INIT complete notification */
- return iwl_wait_notification(&mvm->notif_wait, &init_wait,
- MVM_UCODE_ALIVE_TIMEOUT);
+ ret = iwl_wait_notification(&mvm->notif_wait, &init_wait,
+ MVM_UCODE_ALIVE_TIMEOUT);
+ if (ret)
+ return ret;
+
+ /* Read the NVM only at driver load time, no need to do this twice */
+ if (!IWL_MVM_PARSE_NVM && read_nvm) {
+ ret = iwl_mvm_nvm_get_from_fw(mvm);
+ if (ret) {
+ IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
error:
iwl_remove_notification(&mvm->notif_wait, &init_wait);
@@ -824,9 +821,11 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
goto error;
}
- ret = iwl_send_bt_init_conf(mvm);
- if (ret)
- goto error;
+ if (mvm->cfg->device_family < IWL_DEVICE_FAMILY_8000) {
+ ret = iwl_mvm_send_bt_init_conf(mvm);
+ if (ret)
+ goto error;
+ }
/* Read the NVM only at driver load time, no need to do this twice */
if (read_nvm) {
@@ -941,7 +940,7 @@ static void iwl_mvm_parse_shared_mem_a000(struct iwl_mvm *mvm,
static void iwl_mvm_parse_shared_mem(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt)
{
- struct iwl_shared_mem_cfg_v1 *mem_cfg = (void *)pkt->data;
+ struct iwl_shared_mem_cfg_v2 *mem_cfg = (void *)pkt->data;
int i;
mvm->smem_cfg.num_lmacs = 1;
@@ -1231,15 +1230,15 @@ out_free:
return ret;
}
-static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm,
- struct iwl_mvm_geo_table *geo_table)
+static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
{
union acpi_object *wifi_pkg;
acpi_handle root_handle;
acpi_handle handle;
struct acpi_buffer wgds = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status;
- int i, ret;
+ int i, j, ret;
+ int idx = 1;
root_handle = ACPI_HANDLE(mvm->dev);
if (!root_handle) {
@@ -1270,15 +1269,17 @@ static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm,
goto out_free;
}
- for (i = 0; i < ACPI_WGDS_WIFI_DATA_SIZE; i++) {
- union acpi_object *entry;
+ for (i = 0; i < IWL_NUM_GEO_PROFILES; i++) {
+ for (j = 0; j < IWL_MVM_GEO_TABLE_SIZE; j++) {
+ union acpi_object *entry;
- entry = &wifi_pkg->package.elements[i + 1];
- if ((entry->type != ACPI_TYPE_INTEGER) ||
- (entry->integer.value > U8_MAX))
- return -EINVAL;
+ entry = &wifi_pkg->package.elements[idx++];
+ if ((entry->type != ACPI_TYPE_INTEGER) ||
+ (entry->integer.value > U8_MAX))
+ return -EINVAL;
- geo_table->values[i] = entry->integer.value;
+ mvm->geo_profiles[i].values[j] = entry->integer.value;
+ }
}
ret = 0;
out_free:
@@ -1339,16 +1340,47 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
}
+int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
+{
+ struct iwl_geo_tx_power_profiles_resp *resp;
+ int ret;
+
+ struct iwl_geo_tx_power_profiles_cmd geo_cmd = {
+ .ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE),
+ };
+ struct iwl_host_cmd cmd = {
+ .id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
+ .len = { sizeof(geo_cmd), },
+ .flags = CMD_WANT_SKB,
+ .data = { &geo_cmd },
+ };
+
+ ret = iwl_mvm_send_cmd(mvm, &cmd);
+ if (ret) {
+ IWL_ERR(mvm, "Failed to get geographic profile info %d\n", ret);
+ return ret;
+ }
+
+ resp = (void *)cmd.resp_pkt->data;
+ ret = le32_to_cpu(resp->profile_idx);
+ if (WARN_ON(ret > IWL_NUM_GEO_PROFILES)) {
+ ret = -EIO;
+ IWL_WARN(mvm, "Invalid geographic profile idx (%d)\n", ret);
+ }
+
+ iwl_free_resp(&cmd);
+ return ret;
+}
+
static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
{
- struct iwl_mvm_geo_table geo_table;
struct iwl_geo_tx_power_profiles_cmd cmd = {
.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES),
};
- int ret, i, j, idx;
+ int ret, i, j;
u16 cmd_wide_id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT);
- ret = iwl_mvm_sar_get_wgds_table(mvm, &geo_table);
+ ret = iwl_mvm_sar_get_wgds_table(mvm);
if (ret < 0) {
IWL_DEBUG_RADIO(mvm,
"Geo SAR BIOS table invalid or unavailable. (%d)\n",
@@ -1369,9 +1401,8 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
for (j = 0; j < ACPI_WGDS_NUM_BANDS; j++) {
u8 *value;
- idx = i * ACPI_WGDS_NUM_BANDS * ACPI_WGDS_TABLE_SIZE +
- j * ACPI_WGDS_TABLE_SIZE;
- value = &geo_table.values[idx];
+ value = &mvm->geo_profiles[i].values[j *
+ IWL_GEO_PER_CHAIN_SIZE];
chain[j].max_tx_power = cpu_to_le16(value[0]);
chain[j].chain_a = value[1];
chain[j].chain_b = value[2];
@@ -1501,10 +1532,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (ret)
goto error;
- ret = iwl_send_bt_init_conf(mvm);
- if (ret)
- goto error;
-
/* Send phy db control command and then phy db calibration*/
if (!iwl_mvm_has_new_tx_api(mvm)) {
ret = iwl_send_phy_db_data(mvm->phy_db);
@@ -1516,6 +1543,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error;
}
+ ret = iwl_mvm_send_bt_init_conf(mvm);
+ if (ret)
+ goto error;
+
/* Init RSS configuration */
/* TODO - remove a000 disablement when we have RXQ config API */
if (iwl_mvm_has_new_rx_api(mvm) && !iwl_mvm_has_new_tx_api(mvm)) {
@@ -1627,7 +1658,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
return 0;
error:
- iwl_mvm_stop_device(mvm);
+ if (!iwlmvm_mod_params.init_dbg)
+ iwl_mvm_stop_device(mvm);
return ret;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/led.c b/drivers/net/wireless/intel/iwlwifi/mvm/led.c
index 1e51fbe..3cac427 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/led.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/led.c
@@ -123,14 +123,17 @@ int iwl_mvm_leds_init(struct iwl_mvm *mvm)
return ret;
}
+ mvm->init_status |= IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE;
return 0;
}
void iwl_mvm_leds_exit(struct iwl_mvm *mvm)
{
- if (iwlwifi_mod_params.led_mode == IWL_LED_DISABLE)
+ if (iwlwifi_mod_params.led_mode == IWL_LED_DISABLE ||
+ !(mvm->init_status & IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE))
return;
led_classdev_unregister(&mvm->led);
kfree(mvm->led.name);
+ mvm->init_status &= ~IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index fd2fc46..dc631b2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -257,7 +257,7 @@ unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm,
};
if (iwl_mvm_is_dqa_supported(mvm))
- data.used_hw_queues |= BIT(IWL_MVM_DQA_CMD_QUEUE);
+ data.used_hw_queues |= BIT(IWL_MVM_DQA_GCAST_QUEUE);
else
data.used_hw_queues |= BIT(IWL_MVM_CMD_QUEUE);
@@ -268,6 +268,14 @@ unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm,
mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
iwl_mvm_iface_hw_queues_iter, &data);
+ /*
+ * for DQA, the hw_queue in mac80211 is never really used for
+ * real traffic (only the few queue IDs covered above), so
+ * we can reuse the real HW queue IDs the stations use
+ */
+ if (iwl_mvm_is_dqa_supported(mvm))
+ return data.used_hw_queues;
+
/* don't assign the same hw queues as TDLS stations */
ieee80211_iterate_stations_atomic(mvm->hw,
iwl_mvm_mac_sta_hw_queues_iter,
@@ -344,7 +352,7 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
.found_vif = false,
};
u32 ac;
- int ret, i;
+ int ret, i, queue_limit;
unsigned long used_hw_queues;
/*
@@ -430,17 +438,29 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
return 0;
}
+ if (iwl_mvm_is_dqa_supported(mvm)) {
+ /*
+ * queues in mac80211 almost entirely independent of
+ * the ones here - no real limit
+ */
+ queue_limit = IEEE80211_MAX_QUEUES;
+ BUILD_BUG_ON(IEEE80211_MAX_QUEUES >
+ BITS_PER_BYTE *
+ sizeof(mvm->hw_queue_to_mac80211[0]));
+ } else {
+ /* need to not use too many in this case */
+ queue_limit = mvm->first_agg_queue;
+ }
+
/*
* Find available queues, and allocate them to the ACs. When in
* DQA-mode they aren't really used, and this is done only so the
* mac80211 ieee80211_check_queues() function won't fail
*/
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
- u8 queue = find_first_zero_bit(&used_hw_queues,
- mvm->first_agg_queue);
+ u8 queue = find_first_zero_bit(&used_hw_queues, queue_limit);
- if (!iwl_mvm_is_dqa_supported(mvm) &&
- queue >= mvm->first_agg_queue) {
+ if (queue >= queue_limit) {
IWL_ERR(mvm, "Failed to allocate queue\n");
ret = -EIO;
goto exit_fail;
@@ -846,6 +866,8 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
cpu_to_le64(vif->bss_conf.sync_tsf + dtim_offs);
ctxt_sta->dtim_time =
cpu_to_le32(vif->bss_conf.sync_device_ts + dtim_offs);
+ ctxt_sta->assoc_beacon_arrive_time =
+ cpu_to_le32(vif->bss_conf.sync_device_ts);
IWL_DEBUG_INFO(mvm, "DTIM TBTT is 0x%llx/0x%x, offset %d\n",
le64_to_cpu(ctxt_sta->dtim_tsf),
@@ -1457,6 +1479,7 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
beacon_notify_hdr = &beacon->beacon_notify_hdr;
mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2);
+ mvm->ibss_manager = beacon->ibss_mgr_status != 0;
agg_status = iwl_mvm_get_agg_status(mvm, beacon_notify_hdr);
status = le16_to_cpu(agg_status->status) & TX_STATUS_MSK;
@@ -1596,7 +1619,7 @@ void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
rx_status.band);
/* copy the data */
- memcpy(skb_put(skb, size), sb->data, size);
+ skb_put_data(skb, sb->data, size);
memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
/* pass it as regular rx to mac80211 */
@@ -1632,9 +1655,9 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n");
- queue_delayed_work(system_wq, &mvm->cs_tx_unblock_dwork,
- msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT *
- csa_vif->bss_conf.beacon_int));
+ schedule_delayed_work(&mvm->cs_tx_unblock_dwork,
+ msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT *
+ csa_vif->bss_conf.beacon_int));
ieee80211_csa_finish(csa_vif);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index a67aa1f..bcde1ba 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -84,7 +84,7 @@
#include "iwl-eeprom-parse.h"
#include "iwl-phy-db.h"
#include "testmode.h"
-#include "iwl-fw-error-dump.h"
+#include "fw/error-dump.h"
#include "iwl-prph.h"
#include "iwl-nvm-parse.h"
#include "fw-dbg.h"
@@ -493,7 +493,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
* firmware will interpret some mgmt packets, so enabling it
* with software crypto isn't safe).
*/
- if (!iwlwifi_mod_params.sw_crypto) {
+ if (!iwlwifi_mod_params.swcrypto) {
ieee80211_hw_set(hw, MFP_CAPABLE);
mvm->ciphers[hw->wiphy->n_cipher_suites] =
WLAN_CIPHER_SUITE_AES_CMAC;
@@ -687,7 +687,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
WIPHY_WOWLAN_EAP_IDENTITY_REQ |
WIPHY_WOWLAN_RFKILL_RELEASE |
WIPHY_WOWLAN_NET_DETECT;
- if (!iwlwifi_mod_params.sw_crypto)
+ if (!iwlwifi_mod_params.swcrypto)
mvm->wowlan.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
WIPHY_WOWLAN_GTK_REKEY_FAILURE |
WIPHY_WOWLAN_4WAY_HANDSHAKE;
@@ -735,6 +735,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
ret = ieee80211_register_hw(mvm->hw);
if (ret)
iwl_mvm_leds_exit(mvm);
+ mvm->init_status |= IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE;
if (mvm->cfg->vht_mu_mimo_supported)
wiphy_ext_feature_set(hw->wiphy,
@@ -1243,6 +1244,17 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
flush_work(&mvm->d0i3_exit_work);
flush_work(&mvm->async_handlers_wk);
flush_work(&mvm->add_stream_wk);
+
+ /*
+ * Lock and clear the firmware running bit here already, so that
+ * new commands coming in elsewhere, e.g. from debugfs, will not
+ * be able to proceed. This is important here because one of those
+ * debugfs files causes the fw_dump_wk to be triggered, and if we
+ * don't stop debugfs accesses before canceling that it could be
+ * retriggered after we flush it but before we've cleared the bit.
+ */
+ clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
+
cancel_delayed_work_sync(&mvm->fw_dump_wk);
cancel_delayed_work_sync(&mvm->cs_tx_unblock_dwork);
cancel_delayed_work_sync(&mvm->scan_timeout_dwork);
@@ -1451,7 +1463,7 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
{
u32 tfd_msk = iwl_mvm_mac_get_queues_mask(vif);
- if (tfd_msk) {
+ if (tfd_msk && !iwl_mvm_is_dqa_supported(mvm)) {
/*
* mac80211 first removes all the stations of the vif and
* then removes the vif. When it removes a station it also
@@ -1460,6 +1472,8 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
* of these AMPDU sessions are properly closed.
* We still need to take care of the shared queues of the vif.
* Flush them here.
+ * For DQA mode there is no need - broacast and multicast queue
+ * are flushed separately.
*/
mutex_lock(&mvm->mutex);
iwl_mvm_flush_tx_path(mvm, tfd_msk, 0);
@@ -1974,14 +1988,32 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
WARN_ONCE(iwl_mvm_sf_update(mvm, vif, false),
"Failed to update SF upon disassociation\n");
- /* remove AP station now that the MAC is unassoc */
- ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id);
- if (ret)
- IWL_ERR(mvm, "failed to remove AP station\n");
+ /*
+ * If we get an assert during the connection (after the
+ * station has been added, but before the vif is set
+ * to associated), mac80211 will re-add the station and
+ * then configure the vif. Since the vif is not
+ * associated, we would remove the station here and
+ * this would fail the recovery.
+ */
+ if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
+ &mvm->status)) {
+ /*
+ * Remove AP station now that
+ * the MAC is unassoc
+ */
+ ret = iwl_mvm_rm_sta_id(mvm, vif,
+ mvmvif->ap_sta_id);
+ if (ret)
+ IWL_ERR(mvm,
+ "failed to remove AP station\n");
+
+ if (mvm->d0i3_ap_sta_id == mvmvif->ap_sta_id)
+ mvm->d0i3_ap_sta_id =
+ IWL_MVM_INVALID_STA;
+ mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
+ }
- if (mvm->d0i3_ap_sta_id == mvmvif->ap_sta_id)
- mvm->d0i3_ap_sta_id = IWL_MVM_INVALID_STA;
- mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
/* remove quota for this interface */
ret = iwl_mvm_update_quotas(mvm, false, NULL);
if (ret)
@@ -2381,7 +2413,7 @@ static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
__set_bit(tid_data->txq_id, &txqs);
- if (iwl_mvm_tid_queued(tid_data) == 0)
+ if (iwl_mvm_tid_queued(mvm, tid_data) == 0)
continue;
__set_bit(tid, &tids);
@@ -2856,7 +2888,7 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
int ret;
u8 key_offset;
- if (iwlwifi_mod_params.sw_crypto) {
+ if (iwlwifi_mod_params.swcrypto) {
IWL_DEBUG_MAC80211(mvm, "leave - hwcrypto disabled\n");
return -EOPNOTSUPP;
}
@@ -2869,7 +2901,8 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
- key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
+ if (!iwl_mvm_has_new_tx_api(mvm))
+ key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
@@ -2915,8 +2948,13 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
ret = -EOPNOTSUPP;
else
ret = 0;
- key->hw_key_idx = STA_KEY_IDX_INVALID;
- break;
+
+ if (key->cipher != WLAN_CIPHER_SUITE_GCMP &&
+ key->cipher != WLAN_CIPHER_SUITE_GCMP_256 &&
+ !iwl_mvm_has_new_tx_api(mvm)) {
+ key->hw_key_idx = STA_KEY_IDX_INVALID;
+ break;
+ }
}
/* During FW restart, in order to restore the state as it was,
@@ -3717,6 +3755,13 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
return ret;
}
+static int iwl_mvm_tx_last_beacon(struct ieee80211_hw *hw)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+ return mvm->ibss_manager;
+}
+
static int iwl_mvm_set_tim(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
bool set)
@@ -3988,21 +4033,23 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
/* make sure only TDLS peers or the AP are flushed */
WARN_ON(i != mvmvif->ap_sta_id && !sta->tdls);
- msk |= mvmsta->tfd_queue_msk;
+ if (drop) {
+ if (iwl_mvm_flush_sta(mvm, mvmsta, false, 0))
+ IWL_ERR(mvm, "flush request fail\n");
+ } else {
+ msk |= mvmsta->tfd_queue_msk;
+ if (iwl_mvm_has_new_tx_api(mvm))
+ iwl_mvm_wait_sta_queues_empty(mvm, mvmsta);
+ }
}
- if (drop) {
- if (iwl_mvm_flush_tx_path(mvm, msk, 0))
- IWL_ERR(mvm, "flush request fail\n");
- mutex_unlock(&mvm->mutex);
- } else {
- mutex_unlock(&mvm->mutex);
+ mutex_unlock(&mvm->mutex);
- /* this can take a while, and we may need/want other operations
- * to succeed while doing this, so do it without the mutex held
- */
+ /* this can take a while, and we may need/want other operations
+ * to succeed while doing this, so do it without the mutex held
+ */
+ if (!drop && !iwl_mvm_has_new_tx_api(mvm))
iwl_trans_wait_tx_queues_empty(mvm->trans, msk);
- }
}
static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
@@ -4023,7 +4070,7 @@ static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
mutex_lock(&mvm->mutex);
- if (mvm->ucode_loaded) {
+ if (iwl_mvm_firmware_running(mvm)) {
ret = iwl_mvm_request_statistics(mvm, false);
if (ret)
goto out;
@@ -4104,11 +4151,11 @@ static void iwl_mvm_event_mlme_callback(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
const struct ieee80211_event *event)
{
-#define CHECK_MLME_TRIGGER(_mvm, _trig, _buf, _cnt, _fmt...) \
+#define CHECK_MLME_TRIGGER(_cnt, _fmt...) \
do { \
- if ((_cnt) && --(_cnt)) \
+ if ((trig_mlme->_cnt) && --(trig_mlme->_cnt)) \
break; \
- iwl_mvm_fw_dbg_collect_trig(_mvm, _trig, _fmt);\
+ iwl_mvm_fw_dbg_collect_trig(mvm, trig, _fmt); \
} while (0)
struct iwl_fw_dbg_trigger_tlv *trig;
@@ -4124,31 +4171,25 @@ static void iwl_mvm_event_mlme_callback(struct iwl_mvm *mvm,
if (event->u.mlme.data == ASSOC_EVENT) {
if (event->u.mlme.status == MLME_DENIED)
- CHECK_MLME_TRIGGER(mvm, trig, buf,
- trig_mlme->stop_assoc_denied,
+ CHECK_MLME_TRIGGER(stop_assoc_denied,
"DENIED ASSOC: reason %d",
event->u.mlme.reason);
else if (event->u.mlme.status == MLME_TIMEOUT)
- CHECK_MLME_TRIGGER(mvm, trig, buf,
- trig_mlme->stop_assoc_timeout,
+ CHECK_MLME_TRIGGER(stop_assoc_timeout,
"ASSOC TIMEOUT");
} else if (event->u.mlme.data == AUTH_EVENT) {
if (event->u.mlme.status == MLME_DENIED)
- CHECK_MLME_TRIGGER(mvm, trig, buf,
- trig_mlme->stop_auth_denied,
+ CHECK_MLME_TRIGGER(stop_auth_denied,
"DENIED AUTH: reason %d",
event->u.mlme.reason);
else if (event->u.mlme.status == MLME_TIMEOUT)
- CHECK_MLME_TRIGGER(mvm, trig, buf,
- trig_mlme->stop_auth_timeout,
+ CHECK_MLME_TRIGGER(stop_auth_timeout,
"AUTH TIMEOUT");
} else if (event->u.mlme.data == DEAUTH_RX_EVENT) {
- CHECK_MLME_TRIGGER(mvm, trig, buf,
- trig_mlme->stop_rx_deauth,
+ CHECK_MLME_TRIGGER(stop_rx_deauth,
"DEAUTH RX %d", event->u.mlme.reason);
} else if (event->u.mlme.data == DEAUTH_TX_EVENT) {
- CHECK_MLME_TRIGGER(mvm, trig, buf,
- trig_mlme->stop_tx_deauth,
+ CHECK_MLME_TRIGGER(stop_tx_deauth,
"DEAUTH TX %d", event->u.mlme.reason);
}
#undef CHECK_MLME_TRIGGER
@@ -4248,11 +4289,13 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
goto out;
}
- if (notif->sync)
+ if (notif->sync) {
ret = wait_event_timeout(mvm->rx_sync_waitq,
- atomic_read(&mvm->queue_sync_counter) == 0,
+ atomic_read(&mvm->queue_sync_counter) == 0 ||
+ iwl_mvm_is_radio_killed(mvm),
HZ);
- WARN_ON_ONCE(!ret);
+ WARN_ON_ONCE(!ret && !iwl_mvm_is_radio_killed(mvm));
+ }
out:
atomic_set(&mvm->queue_sync_counter, 0);
@@ -4316,6 +4359,8 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.join_ibss = iwl_mvm_start_ap_ibss,
.leave_ibss = iwl_mvm_stop_ap_ibss,
+ .tx_last_beacon = iwl_mvm_tx_last_beacon,
+
.set_tim = iwl_mvm_set_tim,
.channel_switch = iwl_mvm_channel_switch,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 52f8d7a..eaacfaf 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -79,9 +79,9 @@
#include "iwl-op-mode.h"
#include "iwl-trans.h"
-#include "iwl-notif-wait.h"
+#include "fw/notif-wait.h"
#include "iwl-eeprom-parse.h"
-#include "iwl-fw-file.h"
+#include "fw/file.h"
#include "iwl-config.h"
#include "sta.h"
#include "fw-api.h"
@@ -724,14 +724,14 @@ enum iwl_mvm_queue_status {
#ifdef CONFIG_ACPI
#define IWL_MVM_SAR_TABLE_SIZE 10
#define IWL_MVM_SAR_PROFILE_NUM 4
-#define IWL_MVM_GEO_TABLE_SIZE 18
+#define IWL_MVM_GEO_TABLE_SIZE 6
struct iwl_mvm_sar_profile {
bool enabled;
u8 table[IWL_MVM_SAR_TABLE_SIZE];
};
-struct iwl_mvm_geo_table {
+struct iwl_mvm_geo_profile {
u8 values[IWL_MVM_GEO_TABLE_SIZE];
};
#endif
@@ -754,6 +754,8 @@ struct iwl_mvm {
struct work_struct roc_done_wk;
+ unsigned long init_status;
+
unsigned long status;
u32 queue_sync_cookie;
@@ -765,7 +767,6 @@ struct iwl_mvm {
struct iwl_mvm_vif *bf_allowed_vif;
enum iwl_ucode_type cur_ucode;
- bool ucode_loaded;
bool hw_registered;
bool calibrating;
u32 error_event_table[2];
@@ -779,7 +780,10 @@ struct iwl_mvm {
struct iwl_notif_wait_data notif_wait;
- struct mvm_statistics_rx rx_stats;
+ union {
+ struct mvm_statistics_rx_v3 rx_stats_v3;
+ struct mvm_statistics_rx rx_stats;
+ };
struct {
u64 rx_time;
@@ -788,7 +792,7 @@ struct iwl_mvm {
u64 on_time_scan;
} radio_stats, accu_radio_stats;
- u8 hw_queue_to_mac80211[IWL_MAX_TVQM_QUEUES];
+ u16 hw_queue_to_mac80211[IWL_MAX_TVQM_QUEUES];
struct {
u8 hw_queue_refcount;
@@ -920,7 +924,7 @@ struct iwl_mvm {
u8 vif_count;
/* -1 for always, 0 for never, >0 for that many times */
- s8 restart_fw;
+ s8 fw_restart;
u8 fw_dbg_conf;
struct delayed_work fw_dump_wk;
const struct iwl_mvm_dump_desc *fw_dump_desc;
@@ -1020,6 +1024,9 @@ struct iwl_mvm {
/* system time of last beacon (for AP/GO interface) */
u32 ap_last_beacon_gp2;
+ /* indicates that we transmitted the last beacon */
+ bool ibss_manager;
+
bool lar_regdom_set;
enum iwl_mcc_source mcc_src;
@@ -1067,6 +1074,7 @@ struct iwl_mvm {
struct delayed_work cs_tx_unblock_dwork;
#ifdef CONFIG_ACPI
struct iwl_mvm_sar_profile sar_profiles[IWL_MVM_SAR_PROFILE_NUM];
+ struct iwl_mvm_geo_profile geo_profiles[IWL_NUM_GEO_PROFILES];
#endif
};
@@ -1077,6 +1085,18 @@ struct iwl_mvm {
#define IWL_MAC80211_GET_MVM(_hw) \
IWL_OP_MODE_GET_MVM((struct iwl_op_mode *)((_hw)->priv))
+/**
+ * enum iwl_mvm_status - MVM status bits
+ * @IWL_MVM_STATUS_HW_RFKILL: HW RF-kill is asserted
+ * @IWL_MVM_STATUS_HW_CTKILL: CT-kill is active
+ * @IWL_MVM_STATUS_ROC_RUNNING: remain-on-channel is running
+ * @IWL_MVM_STATUS_IN_HW_RESTART: HW restart is active
+ * @IWL_MVM_STATUS_IN_D0I3: NIC is in D0i3
+ * @IWL_MVM_STATUS_ROC_AUX_RUNNING: AUX remain-on-channel is running
+ * @IWL_MVM_STATUS_D3_RECONFIG: D3 reconfiguration is being done
+ * @IWL_MVM_STATUS_DUMPING_FW_LOG: FW log is being dumped
+ * @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running
+ */
enum iwl_mvm_status {
IWL_MVM_STATUS_HW_RFKILL,
IWL_MVM_STATUS_HW_CTKILL,
@@ -1086,6 +1106,15 @@ enum iwl_mvm_status {
IWL_MVM_STATUS_ROC_AUX_RUNNING,
IWL_MVM_STATUS_D3_RECONFIG,
IWL_MVM_STATUS_DUMPING_FW_LOG,
+ IWL_MVM_STATUS_FIRMWARE_RUNNING,
+};
+
+/* Keep track of completed init configuration */
+enum iwl_mvm_init_status {
+ IWL_MVM_INIT_STATUS_THERMAL_INIT_COMPLETE = BIT(0),
+ IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE = BIT(1),
+ IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE = BIT(2),
+ IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE = BIT(3),
};
static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
@@ -1099,6 +1128,11 @@ static inline bool iwl_mvm_is_radio_hw_killed(struct iwl_mvm *mvm)
return test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
}
+static inline bool iwl_mvm_firmware_running(struct iwl_mvm *mvm)
+{
+ return test_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
+}
+
/* Must be called with rcu_read_lock() held and it can only be
* released when mvmsta is not needed anymore.
*/
@@ -1188,7 +1222,7 @@ static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm)
* Enable LAR only if it is supported by the FW (TLV) &&
* enabled in the NVM
*/
- if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ if (mvm->cfg->ext_nvm)
return nvm_lar && tlv_lar;
else
return tlv_lar;
@@ -1266,14 +1300,19 @@ static inline bool iwl_mvm_is_cdb_supported(struct iwl_mvm *mvm)
IWL_UCODE_TLV_CAPA_CDB_SUPPORT);
}
-static inline struct agg_tx_status*
-iwl_mvm_get_agg_status(struct iwl_mvm *mvm,
- struct iwl_mvm_tx_resp *tx_resp)
+static inline bool iwl_mvm_has_new_rx_stats_api(struct iwl_mvm *mvm)
+{
+ return fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_NEW_RX_STATS);
+}
+
+static inline struct agg_tx_status *
+iwl_mvm_get_agg_status(struct iwl_mvm *mvm, void *tx_resp)
{
if (iwl_mvm_has_new_tx_api(mvm))
- return &tx_resp->v6.status;
+ return &((struct iwl_mvm_tx_resp *)tx_resp)->status;
else
- return &tx_resp->v3.status;
+ return ((struct iwl_mvm_tx_resp_v3 *)tx_resp)->status;
}
static inline bool iwl_mvm_is_tt_in_fw(struct iwl_mvm *mvm)
@@ -1355,6 +1394,10 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status);
static inline const char *iwl_mvm_get_tx_fail_reason(u32 status) { return ""; }
#endif
int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, u32 flags);
+int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal, u32 flags);
+int iwl_mvm_flush_sta_tids(struct iwl_mvm *mvm, u32 sta_id,
+ u16 tids, u32 flags);
+
void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm);
static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_tx_info *info,
@@ -1381,7 +1424,9 @@ void iwl_mvm_accu_radio_stats(struct iwl_mvm *mvm);
/* NVM */
int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic);
+int iwl_mvm_nvm_get_from_fw(struct iwl_mvm *mvm);
int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm);
+int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm);
static inline u8 iwl_mvm_get_valid_tx_ant(struct iwl_mvm *mvm)
{
@@ -1644,7 +1689,7 @@ int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode);
int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm);
/* BT Coex */
-int iwl_send_bt_init_conf(struct iwl_mvm *mvm);
+int iwl_mvm_send_bt_init_conf(struct iwl_mvm *mvm);
void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -1711,7 +1756,7 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif)
}
/* hw scheduler queue config */
-void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
+bool iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
u16 ssn, const struct iwl_trans_txq_scd_cfg *cfg,
unsigned int wdg_timeout);
int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, int mac80211_queue,
@@ -1755,7 +1800,7 @@ static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
{
if (!iwl_mvm_has_new_tx_api(mvm))
iwl_free_fw_paging(mvm);
- mvm->ucode_loaded = false;
+ clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
mvm->fw_dbg_conf = FW_DBG_INVALID;
iwl_trans_stop_device(mvm->trans);
}
@@ -1854,12 +1899,19 @@ bool iwl_mvm_lqm_active(struct iwl_mvm *mvm);
#ifdef CONFIG_ACPI
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b);
+int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm);
#else
static inline
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
{
return -ENOENT;
}
+
+static inline
+int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
+{
+ return -ENOENT;
+}
#endif /* CONFIG_ACPI */
#endif /* __IWL_MVM_H__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
index 283c41d..dac7e54 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
@@ -77,7 +77,7 @@
/* Default NVM size to read */
#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024)
#define IWL_MAX_NVM_SECTION_SIZE 0x1b58
-#define IWL_MAX_NVM_8000_SECTION_SIZE 0x1ffc
+#define IWL_MAX_EXT_NVM_SECTION_SIZE 0x1ffc
#define NVM_WRITE_OPCODE 1
#define NVM_READ_OPCODE 0
@@ -118,10 +118,6 @@ static int iwl_nvm_write_chunk(struct iwl_mvm *mvm, u16 section,
return ret;
pkt = cmd.resp_pkt;
- if (!pkt) {
- IWL_ERR(mvm, "Error in NVM_ACCESS response\n");
- return -EINVAL;
- }
/* Extract & check NVM write response */
nvm_resp = (void *)pkt->data;
if (le16_to_cpu(nvm_resp->status) != READ_NVM_CHUNK_SUCCEED) {
@@ -300,7 +296,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
bool lar_enabled;
/* Checking for required sections */
- if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ if (!mvm->trans->cfg->ext_nvm) {
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
!mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n");
@@ -374,7 +370,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
*
* 4. save as "iNVM_xxx.bin" under /lib/firmware
*/
-static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
+int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
{
int ret, section_size;
u16 section_id;
@@ -391,19 +387,19 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
#define NVM_WORD1_LEN(x) (8 * (x & 0x03FF))
#define NVM_WORD2_ID(x) (x >> 12)
-#define NVM_WORD2_LEN_FAMILY_8000(x) (2 * ((x & 0xFF) << 8 | x >> 8))
-#define NVM_WORD1_ID_FAMILY_8000(x) (x >> 4)
+#define EXT_NVM_WORD2_LEN(x) (2 * (((x) & 0xFF) << 8 | (x) >> 8))
+#define EXT_NVM_WORD1_ID(x) ((x) >> 4)
#define NVM_HEADER_0 (0x2A504C54)
#define NVM_HEADER_1 (0x4E564D2A)
#define NVM_HEADER_SIZE (4 * sizeof(u32))
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n");
- /* Maximal size depends on HW family and step */
- if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ /* Maximal size depends on NVM version */
+ if (!mvm->trans->cfg->ext_nvm)
max_section_size = IWL_MAX_NVM_SECTION_SIZE;
else
- max_section_size = IWL_MAX_NVM_8000_SECTION_SIZE;
+ max_section_size = IWL_MAX_EXT_NVM_SECTION_SIZE;
/*
* Obtain NVM image via request_firmware. Since we already used
@@ -447,10 +443,9 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
le32_to_cpu(dword_buff[3]));
/* nvm file validation, dword_buff[2] holds the file version */
- if ((CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_C_STEP &&
- le32_to_cpu(dword_buff[2]) < 0xE4A) ||
- (CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP &&
- le32_to_cpu(dword_buff[2]) >= 0xE4A)) {
+ if (mvm->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
+ CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_C_STEP &&
+ le32_to_cpu(dword_buff[2]) < 0xE4A) {
ret = -EFAULT;
goto out;
}
@@ -472,14 +467,14 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
break;
}
- if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ if (!mvm->trans->cfg->ext_nvm) {
section_size =
2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1));
section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2));
} else {
- section_size = 2 * NVM_WORD2_LEN_FAMILY_8000(
+ section_size = 2 * EXT_NVM_WORD2_LEN(
le16_to_cpu(file_sec->word2));
- section_id = NVM_WORD1_ID_FAMILY_8000(
+ section_id = EXT_NVM_WORD1_ID(
le16_to_cpu(file_sec->word1));
}
@@ -551,12 +546,105 @@ int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm)
return ret;
}
+int iwl_mvm_nvm_get_from_fw(struct iwl_mvm *mvm)
+{
+ struct iwl_nvm_get_info cmd = {};
+ struct iwl_nvm_get_info_rsp *rsp;
+ struct iwl_trans *trans = mvm->trans;
+ struct iwl_host_cmd hcmd = {
+ .flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
+ .data = { &cmd, },
+ .len = { sizeof(cmd) },
+ .id = WIDE_ID(REGULATORY_AND_NVM_GROUP, NVM_GET_INFO)
+ };
+ int ret;
+ bool lar_fw_supported = !iwlwifi_mod_params.lar_disable &&
+ fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
+
+ lockdep_assert_held(&mvm->mutex);
+
+ ret = iwl_mvm_send_cmd(mvm, &hcmd);
+ if (ret)
+ return ret;
+
+ if (WARN(iwl_rx_packet_payload_len(hcmd.resp_pkt) != sizeof(*rsp),
+ "Invalid payload len in NVM response from FW %d",
+ iwl_rx_packet_payload_len(hcmd.resp_pkt))) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ rsp = (void *)hcmd.resp_pkt->data;
+ if (le32_to_cpu(rsp->general.flags)) {
+ IWL_ERR(mvm, "Invalid NVM data from FW\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ mvm->nvm_data = kzalloc(sizeof(*mvm->nvm_data) +
+ sizeof(struct ieee80211_channel) *
+ IWL_NUM_CHANNELS, GFP_KERNEL);
+ if (!mvm->nvm_data) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ iwl_set_hw_address_from_csr(trans, mvm->nvm_data);
+ /* TODO: if platform NVM has MAC address - override it here */
+
+ if (!is_valid_ether_addr(mvm->nvm_data->hw_addr)) {
+ IWL_ERR(trans, "no valid mac address was found\n");
+ ret = -EINVAL;
+ goto err_free;
+ }
+
+ IWL_INFO(trans, "base HW address: %pM\n", mvm->nvm_data->hw_addr);
+
+ /* Initialize general data */
+ mvm->nvm_data->nvm_version = le16_to_cpu(rsp->general.nvm_version);
+
+ /* Initialize MAC sku data */
+ mvm->nvm_data->sku_cap_11ac_enable =
+ le32_to_cpu(rsp->mac_sku.enable_11ac);
+ mvm->nvm_data->sku_cap_11n_enable =
+ le32_to_cpu(rsp->mac_sku.enable_11n);
+ mvm->nvm_data->sku_cap_band_24GHz_enable =
+ le32_to_cpu(rsp->mac_sku.enable_24g);
+ mvm->nvm_data->sku_cap_band_52GHz_enable =
+ le32_to_cpu(rsp->mac_sku.enable_5g);
+ mvm->nvm_data->sku_cap_mimo_disabled =
+ le32_to_cpu(rsp->mac_sku.mimo_disable);
+
+ /* Initialize PHY sku data */
+ mvm->nvm_data->valid_tx_ant = (u8)le32_to_cpu(rsp->phy_sku.tx_chains);
+ mvm->nvm_data->valid_rx_ant = (u8)le32_to_cpu(rsp->phy_sku.rx_chains);
+
+ /* Initialize regulatory data */
+ mvm->nvm_data->lar_enabled =
+ le32_to_cpu(rsp->regulatory.lar_enabled) && lar_fw_supported;
+
+ iwl_init_sbands(trans->dev, trans->cfg, mvm->nvm_data,
+ rsp->regulatory.channel_profile,
+ mvm->nvm_data->valid_tx_ant & mvm->fw->valid_tx_ant,
+ mvm->nvm_data->valid_rx_ant & mvm->fw->valid_rx_ant,
+ rsp->regulatory.lar_enabled && lar_fw_supported);
+
+ iwl_free_resp(&hcmd);
+ return 0;
+
+err_free:
+ kfree(mvm->nvm_data);
+out:
+ iwl_free_resp(&hcmd);
+ return ret;
+}
+
int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
{
int ret, section;
u32 size_read = 0;
u8 *nvm_buffer, *temp;
- const char *nvm_file_B = mvm->cfg->default_nvm_file_B_step;
const char *nvm_file_C = mvm->cfg->default_nvm_file_C_step;
if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))
@@ -626,14 +714,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
/* read External NVM file from the mod param */
ret = iwl_mvm_read_external_nvm(mvm);
if (ret) {
- /* choose the nvm_file name according to the
- * HW step
- */
- if (CSR_HW_REV_STEP(mvm->trans->hw_rev) ==
- SILICON_B_STEP)
- mvm->nvm_file_name = nvm_file_B;
- else
- mvm->nvm_file_name = nvm_file_C;
+ mvm->nvm_file_name = nvm_file_C;
if ((ret == -EFAULT || ret == -ENOENT) &&
mvm->nvm_file_name) {
@@ -704,6 +785,10 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
resp_len = sizeof(struct iwl_mcc_update_resp) +
n_channels * sizeof(__le32);
resp_cp = kmemdup(mcc_resp, resp_len, GFP_KERNEL);
+ if (!resp_cp) {
+ resp_cp = ERR_PTR(-ENOMEM);
+ goto exit;
+ }
} else {
struct iwl_mcc_update_resp_v1 *mcc_resp_v1 = (void *)pkt->data;
@@ -711,21 +796,18 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
resp_len = sizeof(struct iwl_mcc_update_resp) +
n_channels * sizeof(__le32);
resp_cp = kzalloc(resp_len, GFP_KERNEL);
-
- if (resp_cp) {
- resp_cp->status = mcc_resp_v1->status;
- resp_cp->mcc = mcc_resp_v1->mcc;
- resp_cp->cap = mcc_resp_v1->cap;
- resp_cp->source_id = mcc_resp_v1->source_id;
- resp_cp->n_channels = mcc_resp_v1->n_channels;
- memcpy(resp_cp->channels, mcc_resp_v1->channels,
- n_channels * sizeof(__le32));
+ if (!resp_cp) {
+ resp_cp = ERR_PTR(-ENOMEM);
+ goto exit;
}
- }
- if (!resp_cp) {
- ret = -ENOMEM;
- goto exit;
+ resp_cp->status = mcc_resp_v1->status;
+ resp_cp->mcc = mcc_resp_v1->mcc;
+ resp_cp->cap = mcc_resp_v1->cap;
+ resp_cp->source_id = mcc_resp_v1->source_id;
+ resp_cp->n_channels = mcc_resp_v1->n_channels;
+ memcpy(resp_cp->channels, mcc_resp_v1->channels,
+ n_channels * sizeof(__le32));
}
status = le32_to_cpu(resp_cp->status);
@@ -745,8 +827,6 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
exit:
iwl_free_resp(&cmd);
- if (ret)
- return ERR_PTR(ret);
return resp_cp;
}
@@ -758,7 +838,7 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
struct ieee80211_regdomain *regd;
char mcc[3];
- if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
+ if (mvm->cfg->ext_nvm) {
tlv_lar = fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
nvm_lar = mvm->nvm_data->lar_enabled;
@@ -825,8 +905,8 @@ void iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm,
if (WARN_ON_ONCE(!iwl_mvm_is_lar_supported(mvm)))
return;
- mcc[0] = notif->mcc >> 8;
- mcc[1] = notif->mcc & 0xff;
+ mcc[0] = le16_to_cpu(notif->mcc) >> 8;
+ mcc[1] = le16_to_cpu(notif->mcc) & 0xff;
mcc[2] = '\0';
src = notif->source_id;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 3da5ec4..4d1188b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -7,6 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -33,7 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -67,10 +68,10 @@
#include <linux/vmalloc.h>
#include <net/mac80211.h>
-#include "iwl-notif-wait.h"
+#include "fw/notif-wait.h"
#include "iwl-trans.h"
#include "iwl-op-mode.h"
-#include "iwl-fw.h"
+#include "fw/img.h"
#include "iwl-debug.h"
#include "iwl-drv.h"
#include "iwl-modparams.h"
@@ -172,13 +173,14 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
~CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE);
/*
- * TODO: Bits 7-8 of CSR in 8000 HW family set the ADC sampling, and
- * shouldn't be set to any non-zero value. The same is supposed to be
- * true of the other HW, but unsetting them (such as the 7260) causes
- * automatic tests to fail on seemingly unrelated errors. Need to
- * further investigate this, but for now we'll separate cases.
+ * TODO: Bits 7-8 of CSR in 8000 HW family and higher set the ADC
+ * sampling, and shouldn't be set to any non-zero value.
+ * The same is supposed to be true of the other HW, but unsetting
+ * them (such as the 7260) causes automatic tests to fail on seemingly
+ * unrelated errors. Need to further investigate this, but for now
+ * we'll separate cases.
*/
- if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (mvm->trans->cfg->device_family < IWL_DEVICE_FAMILY_8000)
reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI;
iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG,
@@ -355,9 +357,6 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(SCAN_OFFLOAD_ABORT_CMD),
HCMD_NAME(HOT_SPOT_CMD),
HCMD_NAME(SCAN_OFFLOAD_PROFILES_QUERY_CMD),
- HCMD_NAME(SCAN_OFFLOAD_HOTSPOTS_CONFIG_CMD),
- HCMD_NAME(SCAN_OFFLOAD_HOTSPOTS_QUERY_CMD),
- HCMD_NAME(BT_COEX_UPDATE_SW_BOOST),
HCMD_NAME(BT_COEX_UPDATE_CORUN_LUT),
HCMD_NAME(BT_COEX_UPDATE_REDUCED_TXP),
HCMD_NAME(BT_COEX_CI),
@@ -366,13 +365,11 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(PHY_DB_CMD),
HCMD_NAME(SCAN_OFFLOAD_COMPLETE),
HCMD_NAME(SCAN_OFFLOAD_UPDATE_PROFILES_CMD),
- HCMD_NAME(SCAN_OFFLOAD_CONFIG_CMD),
HCMD_NAME(POWER_TABLE_CMD),
HCMD_NAME(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION),
HCMD_NAME(REPLY_THERMAL_MNG_BACKOFF),
HCMD_NAME(DC2DC_CONFIG_CMD),
HCMD_NAME(NVM_ACCESS_CMD),
- HCMD_NAME(SET_CALIB_DEFAULT_CMD),
HCMD_NAME(BEACON_NOTIFICATION),
HCMD_NAME(BEACON_TEMPLATE_CMD),
HCMD_NAME(TX_ANT_CONFIGURATION_CMD),
@@ -381,7 +378,6 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(STATISTICS_NOTIFICATION),
HCMD_NAME(EOSP_NOTIFICATION),
HCMD_NAME(REDUCE_TX_POWER_CMD),
- HCMD_NAME(CARD_STATE_CMD),
HCMD_NAME(CARD_STATE_NOTIFICATION),
HCMD_NAME(MISSED_BEACONS_NOTIFICATION),
HCMD_NAME(TDLS_CONFIG_CMD),
@@ -396,8 +392,6 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(MCC_UPDATE_CMD),
HCMD_NAME(MCC_CHUB_UPDATE_CMD),
HCMD_NAME(MARKER_CMD),
- HCMD_NAME(BT_COEX_PRIO_TABLE),
- HCMD_NAME(BT_COEX_PROT_ENV),
HCMD_NAME(BT_PROFILE_NOTIFICATION),
HCMD_NAME(BCAST_FILTER_CMD),
HCMD_NAME(MCAST_FILTER_CMD),
@@ -408,7 +402,6 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(OFFLOADS_QUERY_CMD),
HCMD_NAME(REMOTE_WAKE_CONFIG_CMD),
HCMD_NAME(MATCH_FOUND_NOTIFICATION),
- HCMD_NAME(CMD_DTS_MEASUREMENT_TRIGGER),
HCMD_NAME(DTS_MEASUREMENT_NOTIFICATION),
HCMD_NAME(WOWLAN_PATTERNS),
HCMD_NAME(WOWLAN_CONFIGURATION),
@@ -416,11 +409,9 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(WOWLAN_TKIP_PARAM),
HCMD_NAME(WOWLAN_KEK_KCK_MATERIAL),
HCMD_NAME(WOWLAN_GET_STATUSES),
- HCMD_NAME(WOWLAN_TX_POWER_PER_DB),
HCMD_NAME(SCAN_ITERATION_COMPLETE),
HCMD_NAME(D0I3_END_CMD),
HCMD_NAME(LTR_CONFIG),
- HCMD_NAME(REPLY_DEBUG_CMD),
};
/* Please keep this array *SORTED* by hex value.
@@ -483,6 +474,7 @@ static const struct iwl_hcmd_names iwl_mvm_prot_offload_names[] = {
*/
static const struct iwl_hcmd_names iwl_mvm_regulatory_and_nvm_names[] = {
HCMD_NAME(NVM_ACCESS_COMPLETE),
+ HCMD_NAME(NVM_GET_INFO),
};
static const struct iwl_hcmd_arr iwl_mvm_groups[] = {
@@ -588,6 +580,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->fw = fw;
mvm->hw = hw;
+ mvm->init_status = 0;
+
if (iwl_mvm_has_new_rx_api(mvm)) {
op_mode->ops = &iwl_mvm_ops_mq;
trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_desc);
@@ -600,7 +594,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
goto out_free;
}
- mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0;
+ mvm->fw_restart = iwlwifi_mod_params.fw_restart ? -1 : 0;
if (!iwl_mvm_is_dqa_supported(mvm)) {
mvm->last_agg_queue = mvm->cfg->base_params->num_of_queues - 1;
@@ -608,9 +602,13 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
if (mvm->cfg->base_params->num_of_queues == 16) {
mvm->aux_queue = 11;
mvm->first_agg_queue = 12;
+ BUILD_BUG_ON(BITS_PER_BYTE *
+ sizeof(mvm->hw_queue_to_mac80211[0]) < 12);
} else {
mvm->aux_queue = 15;
mvm->first_agg_queue = 16;
+ BUILD_BUG_ON(BITS_PER_BYTE *
+ sizeof(mvm->hw_queue_to_mac80211[0]) < 16);
}
} else {
mvm->aux_queue = IWL_MVM_DQA_AUX_QUEUE;
@@ -747,12 +745,12 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mutex_lock(&mvm->mutex);
iwl_mvm_ref(mvm, IWL_MVM_REF_INIT_UCODE);
err = iwl_run_init_mvm_ucode(mvm, true);
- if (!err || !iwlmvm_mod_params.init_dbg)
+ if (!iwlmvm_mod_params.init_dbg)
iwl_mvm_stop_device(mvm);
iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE);
mutex_unlock(&mvm->mutex);
/* returns 0 if successful, 1 if success but in rfkill */
- if (err < 0 && !iwlmvm_mod_params.init_dbg) {
+ if (err < 0) {
IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err);
goto out_free;
}
@@ -778,7 +776,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
if (err)
goto out_unregister;
- memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx));
+ if (!iwl_mvm_has_new_rx_stats_api(mvm))
+ memset(&mvm->rx_stats_v3, 0,
+ sizeof(struct mvm_statistics_rx_v3));
+ else
+ memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx));
/* The transport always starts with a taken reference, we can
* release it now if d0i3 is supported */
@@ -790,12 +792,18 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
return op_mode;
out_unregister:
+ if (iwlmvm_mod_params.init_dbg)
+ return op_mode;
+
ieee80211_unregister_hw(mvm->hw);
mvm->hw_registered = false;
iwl_mvm_leds_exit(mvm);
iwl_mvm_thermal_exit(mvm);
out_free:
flush_delayed_work(&mvm->fw_dump_wk);
+
+ if (iwlmvm_mod_params.init_dbg)
+ return op_mode;
iwl_phy_db_free(mvm->phy_db);
kfree(mvm->scan_cmd);
iwl_trans_op_mode_leave(trans);
@@ -820,7 +828,10 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
iwl_mvm_thermal_exit(mvm);
- ieee80211_unregister_hw(mvm->hw);
+ if (mvm->init_status & IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE) {
+ ieee80211_unregister_hw(mvm->hw);
+ mvm->init_status &= ~IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE;
+ }
kfree(mvm->scan_cmd);
kfree(mvm->mcast_filter_cmd);
@@ -835,7 +846,7 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
iwl_phy_db_free(mvm->phy_db);
mvm->phy_db = NULL;
- iwl_free_nvm_data(mvm->nvm_data);
+ kfree(mvm->nvm_data);
for (i = 0; i < NVM_MAX_NUM_SECTIONS; i++)
kfree(mvm->nvm_sections[i].data);
@@ -1080,6 +1091,16 @@ static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int hw_queue)
iwl_mvm_start_mac_queues(mvm, mq);
}
+static void iwl_mvm_set_rfkill_state(struct iwl_mvm *mvm)
+{
+ bool state = iwl_mvm_is_radio_killed(mvm);
+
+ if (state)
+ wake_up(&mvm->rx_sync_waitq);
+
+ wiphy_rfkill_set_hw_state(mvm->hw->wiphy, state);
+}
+
void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state)
{
if (state)
@@ -1087,7 +1108,7 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state)
else
clear_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status);
- wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm));
+ iwl_mvm_set_rfkill_state(mvm);
}
static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
@@ -1100,7 +1121,7 @@ static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
else
clear_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
- wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm));
+ iwl_mvm_set_rfkill_state(mvm);
/* iwl_run_init_mvm_ucode is waiting for results, abort it */
if (calibrating)
@@ -1157,9 +1178,13 @@ static void iwl_mvm_fw_error_dump_wk(struct work_struct *work)
/* start recording again if the firmware is not crashed */
if (!test_bit(STATUS_FW_ERROR, &mvm->trans->status) &&
- mvm->fw->dbg_dest_tlv)
+ mvm->fw->dbg_dest_tlv) {
iwl_clear_bits_prph(mvm->trans,
MON_BUFF_SAMPLE_CTL, 0x100);
+ iwl_clear_bits_prph(mvm->trans,
+ MON_BUFF_SAMPLE_CTL, 0x1);
+ iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x1);
+ }
} else {
u32 in_sample = iwl_read_prph(mvm->trans, DBGC_IN_SAMPLE);
u32 out_ctrl = iwl_read_prph(mvm->trans, DBGC_OUT_CTRL);
@@ -1208,7 +1233,7 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
* If WoWLAN fw asserted, don't restart either, mac80211
* can't recover this since we're already half suspended.
*/
- if (!mvm->restart_fw && fw_error) {
+ if (!mvm->fw_restart && fw_error) {
iwl_mvm_fw_dbg_collect_desc(mvm, &iwl_mvm_dump_desc_assert,
NULL);
} else if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART,
@@ -1241,8 +1266,8 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
/* don't let the transport/FW power down */
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
- if (fw_error && mvm->restart_fw > 0)
- mvm->restart_fw--;
+ if (fw_error && mvm->fw_restart > 0)
+ mvm->fw_restart--;
ieee80211_restart_hw(mvm->hw);
}
}
@@ -1299,7 +1324,7 @@ static bool iwl_mvm_disallow_offloading(struct iwl_mvm *mvm,
* for offloading in order to prevent reuse of the same
* qos seq counters.
*/
- if (iwl_mvm_tid_queued(tid_data))
+ if (iwl_mvm_tid_queued(mvm, tid_data))
continue;
if (tid_data->state != IWL_AGG_OFF)
@@ -1449,9 +1474,15 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
synchronize_net();
/* Flush the hw queues, in case something got queued during entry */
- ret = iwl_mvm_flush_tx_path(mvm, iwl_mvm_flushable_queues(mvm), flags);
- if (ret)
- return ret;
+ /* TODO new tx api */
+ if (iwl_mvm_has_new_tx_api(mvm)) {
+ WARN_ONCE(1, "d0i3: Need to implement flush TX queue\n");
+ } else {
+ ret = iwl_mvm_flush_tx_path(mvm, iwl_mvm_flushable_queues(mvm),
+ flags);
+ if (ret)
+ return ret;
+ }
/* configure wowlan configuration only if needed */
if (mvm->d0i3_ap_sta_id != IWL_MVM_INVALID_STA) {
@@ -1597,9 +1628,6 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk)
if (ret)
goto out;
- if (!get_status_cmd.resp_pkt)
- goto out;
-
status = (void *)get_status_cmd.resp_pkt->data;
wakeup_reasons = le32_to_cpu(status->wakeup_reasons);
qos_seq = status->qos_seq_ctr;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
index d59efe8..fb9eaf0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
@@ -255,8 +255,8 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
lockdep_assert_held(&mvm->mutex);
- /* In CDB mode we cannot modify PHY context between bands so... */
- if (iwl_mvm_has_new_tx_api(mvm) &&
+ if (fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT) &&
ctxt->channel->band != chandef->chan->band) {
int ret;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
index aa785cf..65beca3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -2836,7 +2836,11 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
rs_get_initial_rate(mvm, sta, lq_sta, band, rate);
rs_init_optimal_rate(mvm, sta, lq_sta);
- WARN_ON_ONCE(rate->ant != ANT_A && rate->ant != ANT_B);
+ WARN_ONCE(rate->ant != ANT_A && rate->ant != ANT_B,
+ "ant: 0x%x, chains 0x%x, fw tx ant: 0x%x, nvm tx ant: 0x%x\n",
+ rate->ant, lq_sta->pers.chains, mvm->fw->valid_tx_ant,
+ mvm->nvm_data ? mvm->nvm_data->valid_tx_ant : ANT_INVALID);
+
tbl->column = rs_get_column_from_rate(rate);
rs_set_expected_tpt_table(lq_sta, tbl);
@@ -3229,7 +3233,11 @@ static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm,
if (num_of_ant(ant) == 1)
lq_cmd->single_stream_ant_msk = ant;
- lq_cmd->agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+ if (!mvm->trans->cfg->gen2)
+ lq_cmd->agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+ else
+ lq_cmd->agg_frame_cnt_limit =
+ LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF;
}
#endif /* CONFIG_MAC80211_DEBUGFS */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
index 3abde1c..32b4d66 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
@@ -145,6 +145,8 @@ enum {
#define LINK_QUAL_AGG_FRAME_LIMIT_DEF (63)
#define LINK_QUAL_AGG_FRAME_LIMIT_MAX (63)
+#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF (64)
+#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_MAX (64)
#define LINK_QUAL_AGG_FRAME_LIMIT_MIN (0)
#define LQ_SIZE 2 /* 2 mode tables: "Active" and "Search" */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index fd1dd06..622d543 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -133,7 +133,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
*/
hdrlen = (len <= skb_tailroom(skb)) ? len : hdrlen + crypt_len + 8;
- memcpy(skb_put(skb, hdrlen), hdr, hdrlen);
+ skb_put_data(skb, hdr, hdrlen);
fraglen = len - hdrlen;
if (fraglen) {
@@ -504,14 +504,6 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
iwl_mvm_unref(mvm, IWL_MVM_REF_RX);
}
-static void iwl_mvm_update_rx_statistics(struct iwl_mvm *mvm,
- struct mvm_statistics_rx *rx_stats)
-{
- lockdep_assert_held(&mvm->mutex);
-
- mvm->rx_stats = *rx_stats;
-}
-
struct iwl_mvm_stat_data {
struct iwl_mvm *mvm;
__le32 mac_id;
@@ -555,7 +547,6 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
mvmvif->beacon_stats.avg_signal =
-general->beacon_average_energy[vif_id];
}
-
}
if (mvmvif->id != id)
@@ -651,7 +642,6 @@ iwl_mvm_rx_stats_check_trigger(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt)
void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt)
{
- struct iwl_notif_statistics_cdb *stats = (void *)&pkt->data;
struct iwl_mvm_stat_data data = {
.mvm = mvm,
};
@@ -659,13 +649,16 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
int i;
u8 *energy;
__le32 *bytes, *air_time;
+ __le32 flags;
- if (iwl_mvm_is_cdb_supported(mvm))
- expected_size = sizeof(*stats);
- else if (iwl_mvm_has_new_rx_api(mvm))
- expected_size = sizeof(struct iwl_notif_statistics_v11);
- else
- expected_size = sizeof(struct iwl_notif_statistics_v10);
+ if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
+ if (iwl_mvm_has_new_rx_api(mvm))
+ expected_size = sizeof(struct iwl_notif_statistics_v11);
+ else
+ expected_size = sizeof(struct iwl_notif_statistics_v10);
+ } else {
+ expected_size = sizeof(struct iwl_notif_statistics_cdb);
+ }
if (iwl_rx_packet_payload_len(pkt) != expected_size) {
IWL_ERR(mvm, "received invalid statistics size (%d)!\n",
@@ -673,20 +666,49 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
return;
}
- data.mac_id = stats->rx.general.mac_id;
- data.beacon_filter_average_energy =
- stats->general.common.beacon_filter_average_energy;
+ if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
+ struct iwl_notif_statistics_v11 *stats = (void *)&pkt->data;
- iwl_mvm_update_rx_statistics(mvm, &stats->rx);
+ data.mac_id = stats->rx.general.mac_id;
+ data.beacon_filter_average_energy =
+ stats->general.common.beacon_filter_average_energy;
- mvm->radio_stats.rx_time = le64_to_cpu(stats->general.common.rx_time);
- mvm->radio_stats.tx_time = le64_to_cpu(stats->general.common.tx_time);
- mvm->radio_stats.on_time_rf =
- le64_to_cpu(stats->general.common.on_time_rf);
- mvm->radio_stats.on_time_scan =
- le64_to_cpu(stats->general.common.on_time_scan);
+ mvm->rx_stats_v3 = stats->rx;
- data.general = &stats->general;
+ mvm->radio_stats.rx_time =
+ le64_to_cpu(stats->general.common.rx_time);
+ mvm->radio_stats.tx_time =
+ le64_to_cpu(stats->general.common.tx_time);
+ mvm->radio_stats.on_time_rf =
+ le64_to_cpu(stats->general.common.on_time_rf);
+ mvm->radio_stats.on_time_scan =
+ le64_to_cpu(stats->general.common.on_time_scan);
+
+ data.general = &stats->general;
+
+ flags = stats->flag;
+ } else {
+ struct iwl_notif_statistics_cdb *stats = (void *)&pkt->data;
+
+ data.mac_id = stats->rx.general.mac_id;
+ data.beacon_filter_average_energy =
+ stats->general.common.beacon_filter_average_energy;
+
+ mvm->rx_stats = stats->rx;
+
+ mvm->radio_stats.rx_time =
+ le64_to_cpu(stats->general.common.rx_time);
+ mvm->radio_stats.tx_time =
+ le64_to_cpu(stats->general.common.tx_time);
+ mvm->radio_stats.on_time_rf =
+ le64_to_cpu(stats->general.common.on_time_rf);
+ mvm->radio_stats.on_time_scan =
+ le64_to_cpu(stats->general.common.on_time_scan);
+
+ data.general = &stats->general;
+
+ flags = stats->flag;
+ }
iwl_mvm_rx_stats_check_trigger(mvm, pkt);
@@ -698,14 +720,15 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
if (!iwl_mvm_has_new_rx_api(mvm))
return;
- if (!iwl_mvm_is_cdb_supported(mvm)) {
- struct iwl_notif_statistics_v11 *v11 =
- (void *)&pkt->data;
+ if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
+ struct iwl_notif_statistics_v11 *v11 = (void *)&pkt->data;
energy = (void *)&v11->load_stats.avg_energy;
bytes = (void *)&v11->load_stats.byte_count;
air_time = (void *)&v11->load_stats.air_time;
} else {
+ struct iwl_notif_statistics_cdb *stats = (void *)&pkt->data;
+
energy = (void *)&stats->load_stats.avg_energy;
bytes = (void *)&stats->load_stats.byte_count;
air_time = (void *)&stats->load_stats.air_time;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index 966cd75..f3e6081 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -183,9 +183,8 @@ static void iwl_mvm_create_skb(struct sk_buff *skb, struct ieee80211_hdr *hdr,
* present before copying packet data.
*/
hdrlen += crypt_len;
- memcpy(skb_put(skb, hdrlen), hdr, hdrlen);
- memcpy(skb_put(skb, headlen - hdrlen), (u8 *)hdr + hdrlen + pad_len,
- headlen - hdrlen);
+ skb_put_data(skb, hdr, hdrlen);
+ skb_put_data(skb, (u8 *)hdr + hdrlen + pad_len, headlen - hdrlen);
fraglen = len - headlen;
@@ -503,7 +502,7 @@ void iwl_mvm_reorder_timer_expired(unsigned long data)
buf->sta_id, sn);
iwl_mvm_release_frames(buf->mvm, sta, NULL, buf, sn);
rcu_read_unlock();
- } else if (buf->num_stored) {
+ } else {
/*
* If no frame expired and there are stored frames, index is now
* pointing to the first unexpired frame - modify timer
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index 8d1b994..35e813b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -1421,8 +1421,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif);
iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
- queue_delayed_work(system_wq, &mvm->scan_timeout_dwork,
- msecs_to_jiffies(SCAN_TIMEOUT));
+ schedule_delayed_work(&mvm->scan_timeout_dwork,
+ msecs_to_jiffies(SCAN_TIMEOUT));
return 0;
}
@@ -1695,7 +1695,7 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
mvm->scan_uid_status[uid] = 0;
}
uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_SCHED);
- if (uid >= 0 && !mvm->restart_fw) {
+ if (uid >= 0 && !mvm->fw_restart) {
ieee80211_sched_scan_stopped(mvm->hw);
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
mvm->scan_uid_status[uid] = 0;
@@ -1725,7 +1725,7 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
* restarted.
*/
if ((mvm->scan_status & IWL_MVM_SCAN_SCHED) &&
- !mvm->restart_fw) {
+ !mvm->fw_restart) {
ieee80211_sched_scan_stopped(mvm->hw);
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 614d678..4df5f13 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -398,7 +398,7 @@ static int iwl_mvm_get_queue_agg_tids(struct iwl_mvm *mvm, int queue)
struct iwl_mvm_sta *mvmsta;
unsigned long tid_bitmap;
unsigned long agg_tids = 0;
- s8 sta_id;
+ u8 sta_id;
int tid;
lockdep_assert_held(&mvm->mutex);
@@ -734,7 +734,6 @@ static int iwl_mvm_sta_alloc_queue_tvqm(struct iwl_mvm *mvm,
spin_lock_bh(&mvmsta->lock);
mvmsta->tid_data[tid].txq_id = queue;
mvmsta->tid_data[tid].is_tid_active = true;
- mvmsta->tfd_queue_msk |= BIT(queue);
spin_unlock_bh(&mvmsta->lock);
return 0;
@@ -758,7 +757,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
bool using_inactive_queue = false, same_sta = false;
unsigned long disable_agg_tids = 0;
enum iwl_mvm_agg_state queue_state;
- bool shared_queue = false;
+ bool shared_queue = false, inc_ssn;
int ssn;
unsigned long tfd_queue_mask;
int ret;
@@ -885,8 +884,12 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
}
ssn = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
- iwl_mvm_enable_txq(mvm, queue, mac_queue, ssn, &cfg,
- wdg_timeout);
+ inc_ssn = iwl_mvm_enable_txq(mvm, queue, mac_queue,
+ ssn, &cfg, wdg_timeout);
+ if (inc_ssn) {
+ ssn = (ssn + 1) & IEEE80211_SCTL_SEQ;
+ le16_add_cpu(&hdr->seq_ctrl, 0x10);
+ }
/*
* Mark queue as shared in transport if shared
@@ -898,6 +901,13 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
iwl_trans_txq_set_shared_mode(mvm->trans, queue, true);
spin_lock_bh(&mvmsta->lock);
+ /*
+ * This looks racy, but it is not. We have only one packet for
+ * this ra/tid in our Tx path since we stop the Qdisc when we
+ * need to allocate a new TFD queue.
+ */
+ if (inc_ssn)
+ mvmsta->tid_data[tid].seq_number += 0x10;
mvmsta->tid_data[tid].txq_id = queue;
mvmsta->tid_data[tid].is_tid_active = true;
mvmsta->tfd_queue_msk |= BIT(queue);
@@ -979,7 +989,7 @@ static void iwl_mvm_unshare_queue(struct iwl_mvm *mvm, int queue)
{
struct ieee80211_sta *sta;
struct iwl_mvm_sta *mvmsta;
- s8 sta_id;
+ u8 sta_id;
int tid = -1;
unsigned long tid_bitmap;
unsigned int wdg_timeout;
@@ -1344,7 +1354,10 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id,
mvmvif->color);
mvm_sta->vif = vif;
- mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+ if (!mvm->trans->cfg->gen2)
+ mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+ else
+ mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF;
mvm_sta->tx_protection = 0;
mvm_sta->tt_tx_protection = false;
mvm_sta->sta_type = sta->tdls ? IWL_STA_TDLS_LINK : IWL_STA_LINK;
@@ -1389,11 +1402,24 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
if (iwl_mvm_has_new_rx_api(mvm) &&
!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
+ int q;
+
dup_data = kcalloc(mvm->trans->num_rx_queues,
- sizeof(*dup_data),
- GFP_KERNEL);
+ sizeof(*dup_data), GFP_KERNEL);
if (!dup_data)
return -ENOMEM;
+ /*
+ * Initialize all the last_seq values to 0xffff which can never
+ * compare equal to the frame's seq_ctrl in the check in
+ * iwl_mvm_is_dup() since the lower 4 bits are the fragment
+ * number and fragmented packets don't reach that function.
+ *
+ * This thus allows receiving a packet with seqno 0 and the
+ * retry bit set as the very first packet on a new TID.
+ */
+ for (q = 0; q < mvm->trans->num_rx_queues; q++)
+ memset(dup_data[q].last_seq, 0xff,
+ sizeof(dup_data[q].last_seq));
mvm_sta->dup_data = dup_data;
}
@@ -1590,6 +1616,29 @@ static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm,
}
}
+int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm,
+ struct iwl_mvm_sta *mvm_sta)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(mvm_sta->tid_data); i++) {
+ u16 txq_id;
+
+ spin_lock_bh(&mvm_sta->lock);
+ txq_id = mvm_sta->tid_data[i].txq_id;
+ spin_unlock_bh(&mvm_sta->lock);
+
+ if (txq_id == IWL_MVM_INVALID_QUEUE)
+ continue;
+
+ ret = iwl_trans_wait_txq_empty(mvm->trans, txq_id);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
@@ -1611,11 +1660,17 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
if (ret)
return ret;
/* flush its queues here since we are freeing mvm_sta */
- ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, 0);
+ ret = iwl_mvm_flush_sta(mvm, mvm_sta, false, 0);
if (ret)
return ret;
- ret = iwl_trans_wait_tx_queues_empty(mvm->trans,
- mvm_sta->tfd_queue_msk);
+ if (iwl_mvm_has_new_tx_api(mvm)) {
+ ret = iwl_mvm_wait_sta_queues_empty(mvm, mvm_sta);
+ } else {
+ u32 q_mask = mvm_sta->tfd_queue_msk;
+
+ ret = iwl_trans_wait_tx_queues_empty(mvm->trans,
+ q_mask);
+ }
if (ret)
return ret;
ret = iwl_mvm_drain_sta(mvm, mvm_sta, false);
@@ -1964,8 +2019,6 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvm->probe_queue = queue;
else if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
mvm->p2p_dev_queue = queue;
-
- bsta->tfd_queue_msk |= BIT(queue);
}
return 0;
@@ -1975,27 +2028,32 @@ static void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ int queue;
lockdep_assert_held(&mvm->mutex);
- if (vif->type == NL80211_IFTYPE_AP ||
- vif->type == NL80211_IFTYPE_ADHOC)
- iwl_mvm_disable_txq(mvm, vif->cab_queue, vif->cab_queue,
- IWL_MAX_TID_COUNT, 0);
+ iwl_mvm_flush_sta(mvm, &mvmvif->bcast_sta, true, 0);
- if (mvmvif->bcast_sta.tfd_queue_msk & BIT(mvm->probe_queue)) {
- iwl_mvm_disable_txq(mvm, mvm->probe_queue,
- vif->hw_queue[0], IWL_MAX_TID_COUNT,
- 0);
- mvmvif->bcast_sta.tfd_queue_msk &= ~BIT(mvm->probe_queue);
+ switch (vif->type) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_ADHOC:
+ queue = mvm->probe_queue;
+ break;
+ case NL80211_IFTYPE_P2P_DEVICE:
+ queue = mvm->p2p_dev_queue;
+ break;
+ default:
+ WARN(1, "Can't free bcast queue on vif type %d\n",
+ vif->type);
+ return;
}
- if (mvmvif->bcast_sta.tfd_queue_msk & BIT(mvm->p2p_dev_queue)) {
- iwl_mvm_disable_txq(mvm, mvm->p2p_dev_queue,
- vif->hw_queue[0], IWL_MAX_TID_COUNT,
- 0);
- mvmvif->bcast_sta.tfd_queue_msk &= ~BIT(mvm->p2p_dev_queue);
- }
+ iwl_mvm_disable_txq(mvm, queue, vif->hw_queue[0], IWL_MAX_TID_COUNT, 0);
+ if (iwl_mvm_has_new_tx_api(mvm))
+ return;
+
+ WARN_ON(!(mvmvif->bcast_sta.tfd_queue_msk & BIT(queue)));
+ mvmvif->bcast_sta.tfd_queue_msk &= ~BIT(queue);
}
/* Send the FW a request to remove the station from it's internal data
@@ -2187,6 +2245,8 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (!iwl_mvm_is_dqa_supported(mvm))
return 0;
+ iwl_mvm_flush_sta(mvm, &mvmvif->mcast_sta, true, 0);
+
iwl_mvm_disable_txq(mvm, mvmvif->cab_queue, vif->cab_queue,
IWL_MAX_TID_COUNT, 0);
@@ -2496,6 +2556,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_tid_data *tid_data;
+ u16 normalized_ssn;
int txq_id;
int ret;
@@ -2583,7 +2644,15 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvmsta->sta_id, tid, txq_id, tid_data->ssn,
tid_data->next_reclaimed);
- if (tid_data->ssn == tid_data->next_reclaimed) {
+ /*
+ * In A000 HW, the next_reclaimed index is only 8 bit, so we'll need
+ * to align the wrap around of ssn so we compare relevant values.
+ */
+ normalized_ssn = tid_data->ssn;
+ if (mvm->trans->cfg->gen2)
+ normalized_ssn &= 0xff;
+
+ if (normalized_ssn == tid_data->next_reclaimed) {
tid_data->state = IWL_AGG_STARTING;
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
} else {
@@ -2624,7 +2693,11 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
BUILD_BUG_ON((sizeof(mvmsta->agg_tids) * BITS_PER_BYTE)
!= IWL_MAX_TID_COUNT);
- buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
+ if (!mvm->trans->cfg->gen2)
+ buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
+ else
+ buf_size = min_t(int, buf_size,
+ LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF);
spin_lock_bh(&mvmsta->lock);
ssn = tid_data->ssn;
@@ -2781,8 +2854,13 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
"ssn = %d, next_recl = %d\n",
tid_data->ssn, tid_data->next_reclaimed);
- /* There are still packets for this RA / TID in the HW */
- if (tid_data->ssn != tid_data->next_reclaimed) {
+ /*
+ * There are still packets for this RA / TID in the HW.
+ * Not relevant for DQA mode, since there is no need to disable
+ * the queue.
+ */
+ if (!iwl_mvm_is_dqa_supported(mvm) &&
+ tid_data->ssn != tid_data->next_reclaimed) {
tid_data->state = IWL_EMPTYING_HW_QUEUE_DELBA;
err = 0;
break;
@@ -2855,10 +2933,18 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (old_state >= IWL_AGG_ON) {
iwl_mvm_drain_sta(mvm, mvmsta, true);
- if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), 0))
- IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
- iwl_trans_wait_tx_queues_empty(mvm->trans,
- mvmsta->tfd_queue_msk);
+
+ if (iwl_mvm_has_new_tx_api(mvm)) {
+ if (iwl_mvm_flush_sta_tids(mvm, mvmsta->sta_id,
+ BIT(tid), 0))
+ IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
+ iwl_trans_wait_txq_empty(mvm->trans, txq_id);
+ } else {
+ if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), 0))
+ IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
+ iwl_trans_wait_tx_queues_empty(mvm->trans, BIT(txq_id));
+ }
+
iwl_mvm_drain_sta(mvm, mvmsta, false);
iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false);
@@ -2937,7 +3023,7 @@ static struct iwl_mvm_sta *iwl_mvm_get_key_sta(struct iwl_mvm *mvm,
}
static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
- struct iwl_mvm_sta *mvm_sta,
+ u32 sta_id,
struct ieee80211_key_conf *key, bool mcast,
u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags,
u8 key_offset)
@@ -2955,6 +3041,9 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
bool new_api = fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_TKIP_MIC_KEYS);
+ if (sta_id == IWL_MVM_INVALID_STA)
+ return -EINVAL;
+
keyidx = (key->keyidx << STA_KEY_FLG_KEYID_POS) &
STA_KEY_FLG_KEYID_MSK;
key_flags = cpu_to_le16(keyidx);
@@ -3013,7 +3102,7 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
u.cmd.common.key_offset = key_offset;
u.cmd.common.key_flags = key_flags;
- u.cmd.common.sta_id = mvm_sta->sta_id;
+ u.cmd.common.sta_id = sta_id;
if (new_api) {
u.cmd.transmit_seq_cnt = cpu_to_le64(pn);
@@ -3146,19 +3235,37 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
u8 key_offset,
bool mcast)
{
- struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
int ret;
const u8 *addr;
struct ieee80211_key_seq seq;
u16 p1k[5];
+ u32 sta_id;
+
+ if (sta) {
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+
+ sta_id = mvm_sta->sta_id;
+ } else if (vif->type == NL80211_IFTYPE_AP &&
+ !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ sta_id = mvmvif->mcast_sta.sta_id;
+ } else {
+ IWL_ERR(mvm, "Failed to find station id\n");
+ return -EINVAL;
+ }
switch (keyconf->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
+ if (vif->type == NL80211_IFTYPE_AP) {
+ ret = -EINVAL;
+ break;
+ }
addr = iwl_mvm_get_mac_addr(mvm, vif, sta);
/* get phase 1 key from mac80211 */
ieee80211_get_key_rx_seq(keyconf, 0, &seq);
ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
- ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
+ ret = iwl_mvm_send_sta_key(mvm, sta_id, keyconf, mcast,
seq.tkip.iv32, p1k, 0, key_offset);
break;
case WLAN_CIPHER_SUITE_CCMP:
@@ -3166,11 +3273,11 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
case WLAN_CIPHER_SUITE_WEP104:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
- ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
+ ret = iwl_mvm_send_sta_key(mvm, sta_id, keyconf, mcast,
0, NULL, 0, key_offset);
break;
default:
- ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
+ ret = iwl_mvm_send_sta_key(mvm, sta_id, keyconf, mcast,
0, NULL, 0, key_offset);
}
@@ -3191,6 +3298,9 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
int ret, size;
u32 status;
+ if (sta_id == IWL_MVM_INVALID_STA)
+ return -EINVAL;
+
key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
STA_KEY_FLG_KEYID_MSK);
key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
@@ -3234,42 +3344,48 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
{
bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
struct iwl_mvm_sta *mvm_sta;
- u8 sta_id;
+ u8 sta_id = IWL_MVM_INVALID_STA;
int ret;
static const u8 __maybe_unused zero_addr[ETH_ALEN] = {0};
lockdep_assert_held(&mvm->mutex);
- /* Get the station id from the mvm local station table */
- mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
- if (!mvm_sta) {
- IWL_ERR(mvm, "Failed to find station\n");
- return -EINVAL;
- }
- sta_id = mvm_sta->sta_id;
+ if (vif->type != NL80211_IFTYPE_AP ||
+ keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
+ /* Get the station id from the mvm local station table */
+ mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
+ if (!mvm_sta) {
+ IWL_ERR(mvm, "Failed to find station\n");
+ return -EINVAL;
+ }
+ sta_id = mvm_sta->sta_id;
- if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
- keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
- keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256) {
- ret = iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, false);
- goto end;
- }
+ if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
+ keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
+ keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256) {
+ ret = iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id,
+ false);
+ goto end;
+ }
- /*
- * It is possible that the 'sta' parameter is NULL, and thus
- * there is a need to retrieve the sta from the local station table.
- */
- if (!sta) {
- sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
- lockdep_is_held(&mvm->mutex));
- if (IS_ERR_OR_NULL(sta)) {
- IWL_ERR(mvm, "Invalid station id\n");
- return -EINVAL;
+ /*
+ * It is possible that the 'sta' parameter is NULL, and thus
+ * there is a need to retrieve the sta from the local station
+ * table.
+ */
+ if (!sta) {
+ sta = rcu_dereference_protected(
+ mvm->fw_id_to_mac_id[sta_id],
+ lockdep_is_held(&mvm->mutex));
+ if (IS_ERR_OR_NULL(sta)) {
+ IWL_ERR(mvm, "Invalid station id\n");
+ return -EINVAL;
+ }
}
- }
- if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
- return -EINVAL;
+ if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
+ return -EINVAL;
+ }
/* If the key_offset is not pre-assigned, we need to find a
* new offset to use. In normal cases, the offset is not
@@ -3299,8 +3415,9 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
* to the same key slot (offset).
* If this fails, remove the original as well.
*/
- if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
- keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
+ if ((keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+ keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) &&
+ sta) {
ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf,
key_offset, !mcast);
if (ret) {
@@ -3334,6 +3451,9 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
if (mvm_sta)
sta_id = mvm_sta->sta_id;
+ else if (!sta && vif->type == NL80211_IFTYPE_AP && mcast)
+ sta_id = iwl_mvm_vif_from_mac80211(vif)->mcast_sta.sta_id;
+
IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n",
keyconf->keyidx, sta_id);
@@ -3356,7 +3476,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
}
mvm->fw_key_deleted[keyconf->hw_key_idx] = 0;
- if (!mvm_sta) {
+ if (sta && !mvm_sta) {
IWL_DEBUG_WEP(mvm, "station non-existent, early return.\n");
return 0;
}
@@ -3387,7 +3507,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
if (WARN_ON_ONCE(!mvm_sta))
goto unlock;
- iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
+ iwl_mvm_send_sta_key(mvm, mvm_sta->sta_id, keyconf, mcast,
iv32, phase1key, CMD_ASYNC, keyconf->hw_key_idx);
unlock:
@@ -3463,7 +3583,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
return;
}
- n_queued = iwl_mvm_tid_queued(tid_data);
+ n_queued = iwl_mvm_tid_queued(mvm, tid_data);
if (n_queued > remaining) {
more_data = true;
remaining = 0;
@@ -3645,3 +3765,17 @@ void iwl_mvm_csa_client_absent(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
rcu_read_unlock();
}
+
+u16 iwl_mvm_tid_queued(struct iwl_mvm *mvm, struct iwl_mvm_tid_data *tid_data)
+{
+ u16 sn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
+
+ /*
+ * In A000 HW, the next_reclaimed index is only 8 bit, so we'll need
+ * to align the wrap around of ssn so we compare relevant values.
+ */
+ if (mvm->trans->cfg->gen2)
+ sn &= 0xff;
+
+ return ieee80211_sn_sub(sn, tid_data->next_reclaimed);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index ad62b67..05fecbe 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -341,12 +341,6 @@ struct iwl_mvm_tid_data {
bool is_tid_active;
};
-static inline u16 iwl_mvm_tid_queued(struct iwl_mvm_tid_data *tid_data)
-{
- return ieee80211_sn_sub(IEEE80211_SEQ_TO_SN(tid_data->seq_number),
- tid_data->next_reclaimed);
-}
-
struct iwl_mvm_key_pn {
struct rcu_head rcu_head;
struct {
@@ -447,6 +441,8 @@ struct iwl_mvm_sta {
u8 avg_energy;
};
+u16 iwl_mvm_tid_queued(struct iwl_mvm *mvm, struct iwl_mvm_tid_data *tid_data);
+
static inline struct iwl_mvm_sta *
iwl_mvm_sta_from_mac80211(struct ieee80211_sta *sta)
{
@@ -489,6 +485,8 @@ static inline int iwl_mvm_update_sta(struct iwl_mvm *mvm,
return iwl_mvm_sta_send_to_fw(mvm, sta, true, 0);
}
+int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm,
+ struct iwl_mvm_sta *mvm_sta);
int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
index df7cd87..3d97436 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
@@ -551,8 +551,7 @@ void iwl_mvm_tdls_ch_switch_work(struct work_struct *work)
/* retry after a DTIM if we failed sending now */
delay = TU_TO_MS(vif->bss_conf.dtim_period * vif->bss_conf.beacon_int);
- queue_delayed_work(system_wq, &mvm->tdls_cs.dwork,
- msecs_to_jiffies(delay));
+ schedule_delayed_work(&mvm->tdls_cs.dwork, msecs_to_jiffies(delay));
out:
mutex_unlock(&mvm->mutex);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
index 2c12789..5a68272 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
@@ -66,7 +66,7 @@
#include <linux/jiffies.h>
#include <net/mac80211.h>
-#include "iwl-notif-wait.h"
+#include "fw/notif-wait.h"
#include "iwl-trans.h"
#include "fw-api.h"
#include "time-event.h"
@@ -130,7 +130,10 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
* issue as it will have to complete before the next command is
* executed, and a new time event means a new command.
*/
- iwl_mvm_flush_tx_path(mvm, queues, CMD_ASYNC);
+ if (iwl_mvm_is_dqa_supported(mvm))
+ iwl_mvm_flush_sta(mvm, &mvm->aux_sta, true, CMD_ASYNC);
+ else
+ iwl_mvm_flush_tx_path(mvm, queues, CMD_ASYNC);
}
static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tof.c b/drivers/net/wireless/intel/iwlwifi/mvm/tof.c
index 16ce8a5..634175b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tof.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tof.c
@@ -93,17 +93,21 @@ void iwl_mvm_tof_init(struct iwl_mvm *mvm)
cpu_to_le32(TOF_RANGE_REQ_EXT_CMD);
mvm->tof_data.active_range_request = IWL_MVM_TOF_RANGE_REQ_MAX_ID;
+ mvm->init_status |= IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE;
}
void iwl_mvm_tof_clean(struct iwl_mvm *mvm)
{
struct iwl_mvm_tof_data *tof_data = &mvm->tof_data;
- if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT))
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_TOF_SUPPORT) ||
+ !(mvm->init_status & IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE))
return;
memset(tof_data, 0, sizeof(*tof_data));
mvm->tof_data.active_range_request = IWL_MVM_TOF_RANGE_REQ_MAX_ID;
+ mvm->init_status &= ~IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE;
}
static void iwl_tof_iterator(void *_data, u8 *mac,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
index 506d581..453a785 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
@@ -628,7 +628,8 @@ static int iwl_mvm_tzone_get_temp(struct thermal_zone_device *device,
mutex_lock(&mvm->mutex);
- if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) {
+ if (!iwl_mvm_firmware_running(mvm) ||
+ mvm->cur_ucode != IWL_UCODE_REGULAR) {
ret = -EIO;
goto out;
}
@@ -678,7 +679,8 @@ static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device,
mutex_lock(&mvm->mutex);
- if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) {
+ if (!iwl_mvm_firmware_running(mvm) ||
+ mvm->cur_ucode != IWL_UCODE_REGULAR) {
ret = -EIO;
goto out;
}
@@ -792,7 +794,8 @@ static int iwl_mvm_tcool_set_cur_state(struct thermal_cooling_device *cdev,
mutex_lock(&mvm->mutex);
- if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) {
+ if (!iwl_mvm_firmware_running(mvm) ||
+ mvm->cur_ucode != IWL_UCODE_REGULAR) {
ret = -EIO;
goto unlock;
}
@@ -884,10 +887,14 @@ void iwl_mvm_thermal_initialize(struct iwl_mvm *mvm, u32 min_backoff)
iwl_mvm_cooling_device_register(mvm);
iwl_mvm_thermal_zone_register(mvm);
#endif
+ mvm->init_status |= IWL_MVM_INIT_STATUS_THERMAL_INIT_COMPLETE;
}
void iwl_mvm_thermal_exit(struct iwl_mvm *mvm)
{
+ if (!(mvm->init_status & IWL_MVM_INIT_STATUS_THERMAL_INIT_COMPLETE))
+ return;
+
cancel_delayed_work_sync(&mvm->thermal_throttle.ct_kill_exit);
IWL_DEBUG_TEMP(mvm, "Exit Thermal Throttling\n");
@@ -895,4 +902,5 @@ void iwl_mvm_thermal_exit(struct iwl_mvm *mvm)
iwl_mvm_cooling_device_unregister(mvm);
iwl_mvm_thermal_zone_unregister(mvm);
#endif
+ mvm->init_status &= ~IWL_MVM_INIT_STATUS_THERMAL_INIT_COMPLETE;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index f21901c..60360ed 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -105,9 +105,9 @@ iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 *addr,
static u16 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_hdr *hdr,
- struct ieee80211_tx_info *info)
+ struct ieee80211_tx_info *info,
+ u16 offload_assist)
{
- u16 offload_assist = 0;
#if IS_ENABLED(CONFIG_INET)
u16 mh_len = ieee80211_hdrlen(hdr->frame_control);
u8 protocol = 0;
@@ -207,6 +207,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
__le16 fc = hdr->frame_control;
u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags);
u32 len = skb->len + FCS_LEN;
+ u16 offload_assist = 0;
u8 ac;
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
@@ -225,8 +226,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
tx_cmd->tid_tspec = qc[0] & 0xf;
tx_flags &= ~TX_CMD_FLG_SEQ_CTL;
if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)
- tx_cmd->offload_assist |=
- cpu_to_le16(BIT(TX_CMD_OFFLD_AMSDU));
+ offload_assist |= BIT(TX_CMD_OFFLD_AMSDU);
} else if (ieee80211_is_back_req(fc)) {
struct ieee80211_bar *bar = (void *)skb->data;
u16 control = le16_to_cpu(bar->control);
@@ -291,11 +291,12 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
/* padding is inserted later in transport */
if (ieee80211_hdrlen(fc) % 4 &&
- !(tx_cmd->offload_assist & cpu_to_le16(BIT(TX_CMD_OFFLD_AMSDU))))
- tx_cmd->offload_assist |= cpu_to_le16(BIT(TX_CMD_OFFLD_PAD));
+ !(offload_assist & BIT(TX_CMD_OFFLD_AMSDU)))
+ offload_assist |= BIT(TX_CMD_OFFLD_PAD);
tx_cmd->offload_assist |=
- cpu_to_le16(iwl_mvm_tx_csum(mvm, skb, hdr, info));
+ cpu_to_le16(iwl_mvm_tx_csum(mvm, skb, hdr, info,
+ offload_assist));
}
static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
@@ -473,15 +474,27 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
if (unlikely(!dev_cmd))
return NULL;
- memset(dev_cmd, 0, sizeof(*dev_cmd));
+ /* Make sure we zero enough of dev_cmd */
+ BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen2) > sizeof(*tx_cmd));
+
+ memset(dev_cmd, 0, sizeof(dev_cmd->hdr) + sizeof(*tx_cmd));
dev_cmd->hdr.cmd = TX_CMD;
if (iwl_mvm_has_new_tx_api(mvm)) {
struct iwl_tx_cmd_gen2 *cmd = (void *)dev_cmd->payload;
- u16 offload_assist = iwl_mvm_tx_csum(mvm, skb, hdr, info);
+ u16 offload_assist = 0;
+
+ if (ieee80211_is_data_qos(hdr->frame_control)) {
+ u8 *qc = ieee80211_get_qos_ctl(hdr);
+
+ if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)
+ offload_assist |= BIT(TX_CMD_OFFLD_AMSDU);
+ }
+
+ offload_assist = iwl_mvm_tx_csum(mvm, skb, hdr, info,
+ offload_assist);
/* padding is inserted later in transport */
- /* FIXME - check for AMSDU may need to be removed */
if (ieee80211_hdrlen(hdr->frame_control) % 4 &&
!(offload_assist & BIT(TX_CMD_OFFLD_AMSDU)))
offload_assist |= BIT(TX_CMD_OFFLD_PAD);
@@ -538,22 +551,32 @@ static void iwl_mvm_skb_prepare_status(struct sk_buff *skb,
static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
struct ieee80211_tx_info *info, __le16 fc)
{
+ struct iwl_mvm_vif *mvmvif;
+
if (!iwl_mvm_is_dqa_supported(mvm))
return info->hw_queue;
+ mvmvif = iwl_mvm_vif_from_mac80211(info->control.vif);
+
switch (info->control.vif->type) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_ADHOC:
/*
- * Handle legacy hostapd as well, where station may be added
- * only after assoc. Take care of the case where we send a
- * deauth to a station that we don't have.
+ * Handle legacy hostapd as well, where station will be added
+ * only just before sending the association response.
+ * Also take care of the case where we send a deauth to a
+ * station that we don't have, or similarly an association
+ * response (with non-success status) for a station we can't
+ * accept.
+ * Also, disassociate frames might happen, particular with
+ * reason 7 ("Class 3 frame received from nonassociated STA").
*/
if (ieee80211_is_probe_resp(fc) || ieee80211_is_auth(fc) ||
- ieee80211_is_deauth(fc))
+ ieee80211_is_deauth(fc) || ieee80211_is_assoc_resp(fc) ||
+ ieee80211_is_disassoc(fc))
return mvm->probe_queue;
if (info->hw_queue == info->control.vif->cab_queue)
- return info->hw_queue;
+ return mvmvif->cab_queue;
WARN_ONCE(info->control.vif->type != NL80211_IFTYPE_ADHOC,
"fc=0x%02x", le16_to_cpu(fc));
@@ -562,7 +585,7 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
if (ieee80211_is_mgmt(fc))
return mvm->p2p_dev_queue;
if (info->hw_queue == info->control.vif->cab_queue)
- return info->hw_queue;
+ return mvmvif->cab_queue;
WARN_ON_ONCE(1);
return mvm->p2p_dev_queue;
@@ -611,10 +634,6 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
* (this is not possible for unicast packets as a TLDS discovery
* response are sent without a station entry); otherwise use the
* AUX station.
- * In DQA mode, if vif is of type STATION and frames are not multicast
- * or offchannel, they should be sent from the BSS queue.
- * For example, TDLS setup frames should be sent on this queue,
- * as they go through the AP.
*/
sta_id = mvm->aux_sta.sta_id;
if (info.control.vif) {
@@ -629,9 +648,6 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
hdr->frame_control);
if (queue < 0)
return -1;
-
- if (queue == info.control.vif->cab_queue)
- queue = mvmvif->cab_queue;
} else if (info.control.vif->type == NL80211_IFTYPE_STATION &&
is_multicast_ether_addr(hdr->addr1)) {
u8 ap_sta_id = ACCESS_ONCE(mvmvif->ap_sta_id);
@@ -639,9 +655,8 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
if (ap_sta_id != IWL_MVM_INVALID_STA)
sta_id = ap_sta_id;
} else if (iwl_mvm_is_dqa_supported(mvm) &&
- info.control.vif->type == NL80211_IFTYPE_STATION &&
- queue != mvm->aux_queue) {
- queue = IWL_MVM_DQA_BSS_CLIENT_QUEUE;
+ info.control.vif->type == NL80211_IFTYPE_MONITOR) {
+ queue = mvm->aux_queue;
}
}
@@ -695,11 +710,6 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
snap_ip_tcp = 8 + skb_transport_header(skb) - skb_network_header(skb) +
tcp_hdrlen(skb);
- qc = ieee80211_get_qos_ctl(hdr);
- tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
- if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
- return -EINVAL;
-
dbg_max_amsdu_len = ACCESS_ONCE(mvm->max_amsdu_len);
if (!sta->max_amsdu_len ||
@@ -710,6 +720,11 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
goto segment;
}
+ qc = ieee80211_get_qos_ctl(hdr);
+ tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
+ if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
+ return -EINVAL;
+
/*
* Do not build AMSDU for IPv6 with extension headers.
* ask stack to segment and checkum the generated MPDUs for us.
@@ -829,11 +844,13 @@ segment:
if (tcp_payload_len > mss) {
skb_shinfo(tmp)->gso_size = mss;
} else {
- qc = ieee80211_get_qos_ctl((void *)tmp->data);
+ if (ieee80211_is_data_qos(hdr->frame_control)) {
+ qc = ieee80211_get_qos_ctl((void *)tmp->data);
- if (ipv4)
- ip_send_check(ip_hdr(tmp));
- *qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
+ if (ipv4)
+ ip_send_check(ip_hdr(tmp));
+ *qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
+ }
skb_shinfo(tmp)->gso_size = 0;
}
@@ -1120,13 +1137,14 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
struct ieee80211_vif *vif = mvmsta->vif;
+ u16 normalized_ssn;
lockdep_assert_held(&mvmsta->lock);
if ((tid_data->state == IWL_AGG_ON ||
tid_data->state == IWL_EMPTYING_HW_QUEUE_DELBA ||
iwl_mvm_is_dqa_supported(mvm)) &&
- iwl_mvm_tid_queued(tid_data) == 0) {
+ iwl_mvm_tid_queued(mvm, tid_data) == 0) {
/*
* Now that this aggregation or DQA queue is empty tell
* mac80211 so it knows we no longer have frames buffered for
@@ -1135,7 +1153,15 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
ieee80211_sta_set_buffered(sta, tid, false);
}
- if (tid_data->ssn != tid_data->next_reclaimed)
+ /*
+ * In A000 HW, the next_reclaimed index is only 8 bit, so we'll need
+ * to align the wrap around of ssn so we compare relevant values.
+ */
+ normalized_ssn = tid_data->ssn;
+ if (mvm->trans->cfg->gen2)
+ normalized_ssn &= 0xff;
+
+ if (normalized_ssn != tid_data->next_reclaimed)
return;
switch (tid_data->state) {
@@ -1313,6 +1339,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
struct ieee80211_sta *sta;
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
int txq_id = SEQ_TO_QUEUE(sequence);
+ /* struct iwl_mvm_tx_resp_v3 is almost the same */
struct iwl_mvm_tx_resp *tx_resp = (void *)pkt->data;
int sta_id = IWL_MVM_TX_RES_GET_RA(tx_resp->ra_tid);
int tid = IWL_MVM_TX_RES_GET_TID(tx_resp->ra_tid);
@@ -1330,7 +1357,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
__skb_queue_head_init(&skbs);
if (iwl_mvm_has_new_tx_api(mvm))
- txq_id = le16_to_cpu(tx_resp->v6.tx_queue);
+ txq_id = le16_to_cpu(tx_resp->tx_queue);
seq_ctl = le16_to_cpu(tx_resp->seq_ctl);
@@ -1479,7 +1506,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
if (mvmsta->sleep_tx_count) {
mvmsta->sleep_tx_count--;
if (mvmsta->sleep_tx_count &&
- !iwl_mvm_tid_queued(tid_data)) {
+ !iwl_mvm_tid_queued(mvm, tid_data)) {
/*
* The number of frames in the queue
* dropped to 0 even if we sent less
@@ -1791,6 +1818,7 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
if (iwl_mvm_has_new_tx_api(mvm)) {
struct iwl_mvm_compressed_ba_notif *ba_res =
(void *)pkt->data;
+ int i;
sta_id = ba_res->sta_id;
ba_info.status.ampdu_ack_len = (u8)le16_to_cpu(ba_res->done);
@@ -1803,22 +1831,17 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
if (!le16_to_cpu(ba_res->tfd_cnt))
goto out;
- /*
- * TODO:
- * When supporting multi TID aggregations - we need to move
- * next_reclaimed to be per TXQ and not per TID or handle it
- * in a different way.
- * This will go together with SN and AddBA offload and cannot
- * be handled properly for now.
- */
- WARN_ON(le16_to_cpu(ba_res->ra_tid_cnt) != 1);
- tid = ba_res->ra_tid[0].tid;
- if (tid == IWL_MGMT_TID)
- tid = IWL_MAX_TID_COUNT;
- iwl_mvm_tx_reclaim(mvm, sta_id, tid,
- (int)(le16_to_cpu(ba_res->tfd[0].q_num)),
- le16_to_cpu(ba_res->tfd[0].tfd_index),
- &ba_info, le32_to_cpu(ba_res->tx_rate));
+ /* Free per TID */
+ for (i = 0; i < le16_to_cpu(ba_res->tfd_cnt); i++) {
+ struct iwl_mvm_compressed_ba_tfd *ba_tfd =
+ &ba_res->tfd[i];
+
+ iwl_mvm_tx_reclaim(mvm, sta_id, ba_tfd->tid,
+ (int)(le16_to_cpu(ba_tfd->q_num)),
+ le16_to_cpu(ba_tfd->tfd_index),
+ &ba_info,
+ le32_to_cpu(ba_res->tx_rate));
+ }
out:
IWL_DEBUG_TX_REPLY(mvm,
@@ -1860,7 +1883,7 @@ out:
IWL_DEBUG_TX_REPLY(mvm,
"BA_NOTIFICATION Received from %pM, sta_id = %d\n",
- (u8 *)&ba_notif->sta_addr_lo32, ba_notif->sta_id);
+ ba_notif->sta_addr, ba_notif->sta_id);
IWL_DEBUG_TX_REPLY(mvm,
"TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = %d, scd_ssn = %d sent:%d, acked:%d\n",
@@ -1883,14 +1906,55 @@ out:
int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, u32 flags)
{
int ret;
- struct iwl_tx_path_flush_cmd flush_cmd = {
+ struct iwl_tx_path_flush_cmd_v1 flush_cmd = {
.queues_ctl = cpu_to_le32(tfd_msk),
.flush_ctl = cpu_to_le16(DUMP_TX_FIFO_FLUSH),
};
+ WARN_ON(iwl_mvm_has_new_tx_api(mvm));
+
+ ret = iwl_mvm_send_cmd_pdu(mvm, TXPATH_FLUSH, flags,
+ sizeof(flush_cmd), &flush_cmd);
+ if (ret)
+ IWL_ERR(mvm, "Failed to send flush command (%d)\n", ret);
+ return ret;
+}
+
+int iwl_mvm_flush_sta_tids(struct iwl_mvm *mvm, u32 sta_id,
+ u16 tids, u32 flags)
+{
+ int ret;
+ struct iwl_tx_path_flush_cmd flush_cmd = {
+ .sta_id = cpu_to_le32(sta_id),
+ .tid_mask = cpu_to_le16(tids),
+ };
+
+ WARN_ON(!iwl_mvm_has_new_tx_api(mvm));
+
ret = iwl_mvm_send_cmd_pdu(mvm, TXPATH_FLUSH, flags,
sizeof(flush_cmd), &flush_cmd);
if (ret)
IWL_ERR(mvm, "Failed to send flush command (%d)\n", ret);
return ret;
}
+
+int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal, u32 flags)
+{
+ struct iwl_mvm_int_sta *int_sta = sta;
+ struct iwl_mvm_sta *mvm_sta = sta;
+
+ if (iwl_mvm_has_new_tx_api(mvm)) {
+ if (internal)
+ return iwl_mvm_flush_sta_tids(mvm, int_sta->sta_id,
+ BIT(IWL_MGMT_TID), flags);
+
+ return iwl_mvm_flush_sta_tids(mvm, mvm_sta->sta_id,
+ 0xFF, flags);
+ }
+
+ if (internal)
+ return iwl_mvm_flush_tx_path(mvm, int_sta->tfd_queue_msk,
+ flags);
+
+ return iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, flags);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index 8f4f176..fc5a490 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -69,6 +69,7 @@
#include "iwl-debug.h"
#include "iwl-io.h"
#include "iwl-prph.h"
+#include "iwl-csr.h"
#include "fw-dbg.h"
#include "mvm.h"
#include "fw-api-rs.h"
@@ -168,11 +169,6 @@ int iwl_mvm_send_cmd_status(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd,
}
pkt = cmd->resp_pkt;
- /* Can happen if RFKILL is asserted */
- if (!pkt) {
- ret = 0;
- goto out_free_resp;
- }
resp_len = iwl_rx_packet_payload_len(pkt);
if (WARN_ON_ONCE(resp_len != sizeof(*resp))) {
@@ -502,6 +498,7 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u32 base)
{
struct iwl_trans *trans = mvm->trans;
struct iwl_error_event_table table;
+ u32 val;
if (mvm->cur_ucode == IWL_UCODE_INIT) {
if (!base)
@@ -520,6 +517,36 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u32 base)
return;
}
+ /* check if there is a HW error */
+ val = iwl_trans_read_mem32(trans, base);
+ if (((val & ~0xf) == 0xa5a5a5a0) || ((val & ~0xf) == 0x5a5a5a50)) {
+ int err;
+
+ IWL_ERR(trans, "HW error, resetting before reading\n");
+
+ /* reset the device */
+ iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+ usleep_range(5000, 6000);
+
+ /* set INIT_DONE flag */
+ iwl_set_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+
+ /* and wait for clock stabilization */
+ if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ udelay(2);
+
+ err = iwl_poll_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+ 25000);
+ if (err < 0) {
+ IWL_DEBUG_INFO(trans,
+ "Failed to reset the card for the dump\n");
+ return;
+ }
+ }
+
iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
@@ -671,7 +698,13 @@ static bool iwl_mvm_update_txq_mapping(struct iwl_mvm *mvm, int queue,
if (mvm->queue_info[queue].hw_queue_refcount > 0)
enable_queue = false;
- mvm->hw_queue_to_mac80211[queue] |= BIT(mac80211_queue);
+ if (mac80211_queue != IEEE80211_INVAL_HW_QUEUE) {
+ WARN(mac80211_queue >=
+ BITS_PER_BYTE * sizeof(mvm->hw_queue_to_mac80211[0]),
+ "cannot track mac80211 queue %d (queue %d, sta %d, tid %d)\n",
+ mac80211_queue, queue, sta_id, tid);
+ mvm->hw_queue_to_mac80211[queue] |= BIT(mac80211_queue);
+ }
mvm->queue_info[queue].hw_queue_refcount++;
mvm->queue_info[queue].tid_bitmap |= BIT(tid);
@@ -730,35 +763,39 @@ int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, int mac80211_queue,
return queue;
}
-void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
+bool iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
u16 ssn, const struct iwl_trans_txq_scd_cfg *cfg,
unsigned int wdg_timeout)
{
+ struct iwl_scd_txq_cfg_cmd cmd = {
+ .scd_queue = queue,
+ .action = SCD_CFG_ENABLE_QUEUE,
+ .window = cfg->frame_limit,
+ .sta_id = cfg->sta_id,
+ .ssn = cpu_to_le16(ssn),
+ .tx_fifo = cfg->fifo,
+ .aggregate = cfg->aggregate,
+ .tid = cfg->tid,
+ };
+ bool inc_ssn;
+
if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
- return;
+ return false;
/* Send the enabling command if we need to */
- if (iwl_mvm_update_txq_mapping(mvm, queue, mac80211_queue,
- cfg->sta_id, cfg->tid)) {
- struct iwl_scd_txq_cfg_cmd cmd = {
- .scd_queue = queue,
- .action = SCD_CFG_ENABLE_QUEUE,
- .window = cfg->frame_limit,
- .sta_id = cfg->sta_id,
- .ssn = cpu_to_le16(ssn),
- .tx_fifo = cfg->fifo,
- .aggregate = cfg->aggregate,
- .tid = cfg->tid,
- };
-
- iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, NULL,
- wdg_timeout);
- WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0,
- sizeof(struct iwl_scd_txq_cfg_cmd),
- &cmd),
- "Failed to configure queue %d on FIFO %d\n", queue,
- cfg->fifo);
- }
+ if (!iwl_mvm_update_txq_mapping(mvm, queue, mac80211_queue,
+ cfg->sta_id, cfg->tid))
+ return false;
+
+ inc_ssn = iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn,
+ NULL, wdg_timeout);
+ if (inc_ssn)
+ le16_add_cpu(&cmd.ssn, 1);
+
+ WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd),
+ "Failed to configure queue %d on FIFO %d\n", queue, cfg->fifo);
+
+ return inc_ssn;
}
int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
@@ -1186,7 +1223,11 @@ static void iwl_mvm_remove_inactive_tids(struct iwl_mvm *mvm,
/* Go over all non-active TIDs, incl. IWL_MAX_TID_COUNT (for mgmt) */
for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) {
/* If some TFDs are still queued - don't mark TID as inactive */
- if (iwl_mvm_tid_queued(&mvmsta->tid_data[tid]))
+ if (iwl_mvm_tid_queued(mvm, &mvmsta->tid_data[tid]))
+ tid_bitmap &= ~BIT(tid);
+
+ /* Don't mark as inactive any TID that has an active BA */
+ if (mvmsta->tid_data[tid].state != IWL_AGG_OFF)
tid_bitmap &= ~BIT(tid);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
index b1f43397..eddaca7 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
@@ -103,6 +103,7 @@ static void iwl_pcie_ctxt_info_free_fw_img(struct iwl_trans *trans)
kfree(dram->fw);
dram->fw_cnt = 0;
+ dram->fw = NULL;
}
void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans)
@@ -124,6 +125,7 @@ void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans)
kfree(dram->paging);
dram->paging_cnt = 0;
+ dram->paging = NULL;
}
static int iwl_pcie_ctxt_info_init_fw_sec(struct iwl_trans *trans,
@@ -135,6 +137,11 @@ static int iwl_pcie_ctxt_info_init_fw_sec(struct iwl_trans *trans,
struct iwl_context_info_dram *ctxt_dram = &ctxt_info->dram;
int i, ret, lmac_cnt, umac_cnt, paging_cnt;
+ if (WARN(dram->paging,
+ "paging shouldn't already be initialized (%d pages)\n",
+ dram->paging_cnt))
+ iwl_pcie_ctxt_info_free_paging(trans);
+
lmac_cnt = iwl_pcie_get_num_sections(fw, 0);
/* add 1 due to separator */
umac_cnt = iwl_pcie_get_num_sections(fw, lmac_cnt + 1);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index e51760e..f16c1bb 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -7,7 +7,7 @@
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016-2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -35,6 +35,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
+ * Copyright(c) 2017 Intel Deutschland GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -535,10 +536,27 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x31DC, 0x0030, iwl9560_2ac_cfg)},
{IWL_PCI_DEVICE(0x2526, 0x1030, iwl9560_2ac_cfg)},
{IWL_PCI_DEVICE(0xA370, 0x1030, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x9DF0, 0x0034, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0xA370, 0x0034, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x31DC, 0x0034, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x0038, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x003C, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x9DF0, 0x0038, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0xA370, 0x0038, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x31DC, 0x0038, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x9DF0, 0x003C, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0xA370, 0x003C, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x31DC, 0x003C, iwl9560_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x2526, 0x0034, iwl9560_2ac_cfg)},
/* a000 Series */
{IWL_PCI_DEVICE(0x2720, 0x0A10, iwla000_2ac_cfg_hr_cdb)},
- {IWL_PCI_DEVICE(0x2722, 0x0A10, iwla000_2ac_cfg_hr)},
+ {IWL_PCI_DEVICE(0x34F0, 0x0310, iwla000_2ac_cfg_jf)},
+ {IWL_PCI_DEVICE(0x2720, 0x0000, iwla000_2ax_cfg_hr)},
+ {IWL_PCI_DEVICE(0x34F0, 0x0070, iwla000_2ax_cfg_hr)},
+ {IWL_PCI_DEVICE(0x2720, 0x0078, iwla000_2ax_cfg_hr)},
+ {IWL_PCI_DEVICE(0x2720, 0x0070, iwla000_2ax_cfg_hr)},
+ {IWL_PCI_DEVICE(0x2720, 0x1080, iwla000_2ax_cfg_hr)},
#endif /* CONFIG_IWLMVM */
{0}
@@ -672,10 +690,12 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
iwl_trans->cfg = cfg_7265d;
}
- if (iwl_trans->cfg->rf_id &&
- (cfg == &iwla000_2ac_cfg_hr || cfg == &iwla000_2ac_cfg_hr_cdb) &&
- iwl_trans->hw_rf_id == CSR_HW_RF_ID_TYPE_JF) {
- cfg = &iwla000_2ac_cfg_jf;
+ if (iwl_trans->cfg->rf_id && cfg == &iwla000_2ac_cfg_hr_cdb) {
+ if (iwl_trans->hw_rf_id == CSR_HW_RF_ID_TYPE_JF)
+ cfg = &iwla000_2ac_cfg_jf;
+ else if (iwl_trans->hw_rf_id == CSR_HW_RF_ID_TYPE_HR)
+ cfg = &iwla000_2ac_cfg_hr;
+
iwl_trans->cfg = cfg;
}
#endif
@@ -703,7 +723,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pm_runtime_set_active(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev,
- iwlwifi_mod_params.d0i3_entry_delay);
+ iwlwifi_mod_params.d0i3_timeout);
pm_runtime_use_autosuspend(&pdev->dev);
/* We are not supposed to call pm_runtime_allow() by
@@ -764,7 +784,6 @@ static int iwl_pci_resume(struct device *device)
struct pci_dev *pdev = to_pci_dev(device);
struct iwl_trans *trans = pci_get_drvdata(pdev);
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- bool hw_rfkill;
/* Before you put code here, think about WoWLAN. You cannot check here
* whether WoWLAN is enabled or not, and your code will run even if
@@ -780,17 +799,17 @@ static int iwl_pci_resume(struct device *device)
if (!trans->op_mode)
return 0;
+ /* reconfigure the MSI-X mapping to get the correct IRQ for rfkill */
+ iwl_pcie_conf_msix_hw(trans_pcie);
+
/*
- * Enable rfkill interrupt (in order to keep track of
- * the rfkill status). Must be locked to avoid processing
- * a possible rfkill interrupt between reading the state
- * and calling iwl_trans_pcie_rf_kill() with it.
+ * Enable rfkill interrupt (in order to keep track of the rfkill
+ * status). Must be locked to avoid processing a possible rfkill
+ * interrupt while in iwl_trans_check_hw_rf_kill().
*/
mutex_lock(&trans_pcie->mutex);
iwl_enable_rfkill_int(trans);
-
- hw_rfkill = iwl_is_rfkill_set(trans);
- iwl_trans_pcie_rf_kill(trans, hw_rfkill);
+ iwl_trans_check_hw_rf_kill(trans);
mutex_unlock(&trans_pcie->mutex);
return 0;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
index fd4faaa..fa315d8 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -403,7 +403,8 @@ struct iwl_trans_pcie {
dma_addr_t ict_tbl_dma;
int ict_index;
bool use_ict;
- bool is_down;
+ bool is_down, opmode_down;
+ bool debug_rfkill;
struct isr_statistics isr_stats;
spinlock_t irq_lock;
@@ -515,7 +516,7 @@ int iwl_pcie_gen2_tx_init(struct iwl_trans *trans);
void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr);
int iwl_pcie_tx_stop(struct iwl_trans *trans);
void iwl_pcie_tx_free(struct iwl_trans *trans);
-void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int queue, u16 ssn,
+bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int queue, u16 ssn,
const struct iwl_trans_txq_scd_cfg *cfg,
unsigned int wdg_timeout);
void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue,
@@ -653,6 +654,13 @@ static inline void iwl_enable_fw_load_int(struct iwl_trans *trans)
}
}
+static inline void iwl_pcie_sw_reset(struct iwl_trans *trans)
+{
+ /* Reset entire device - do controller reset (results in SHRD_HW_RST) */
+ iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+ usleep_range(5000, 6000);
+}
+
static inline void *iwl_pcie_get_tfd(struct iwl_trans_pcie *trans_pcie,
struct iwl_txq *txq, int idx)
{
@@ -673,8 +681,20 @@ static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
iwl_enable_hw_int_msk_msix(trans,
MSIX_HW_INT_CAUSES_REG_RF_KILL);
}
+
+ if (trans->cfg->device_family == IWL_DEVICE_FAMILY_9000) {
+ /*
+ * On 9000-series devices this bit isn't enabled by default, so
+ * when we power down the device we need set the bit to allow it
+ * to wake up the PCI-E bus for RF-kill interrupts.
+ */
+ iwl_set_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_RFKILL_WAKE_L1A_EN);
+ }
}
+void iwl_pcie_handle_rfkill_irq(struct iwl_trans *trans);
+
static inline void iwl_wake_queue(struct iwl_trans *trans,
struct iwl_txq *txq)
{
@@ -713,7 +733,12 @@ static inline u8 get_cmd_index(struct iwl_txq *q, u32 index)
static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
{
- lockdep_assert_held(&IWL_TRANS_GET_PCIE_TRANS(trans)->mutex);
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ lockdep_assert_held(&trans_pcie->mutex);
+
+ if (trans_pcie->debug_rfkill)
+ return true;
return !(iwl_read32(trans, CSR_GP_CNTRL) &
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
@@ -767,9 +792,11 @@ void iwl_pcie_apm_config(struct iwl_trans *trans);
int iwl_pcie_prepare_card_hw(struct iwl_trans *trans);
void iwl_pcie_synchronize_irqs(struct iwl_trans *trans);
bool iwl_trans_check_hw_rf_kill(struct iwl_trans *trans);
+void iwl_trans_pcie_handle_stop_rfkill(struct iwl_trans *trans,
+ bool was_in_rfkill);
void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq);
int iwl_queue_space(const struct iwl_txq *q);
-int iwl_pcie_apm_stop_master(struct iwl_trans *trans);
+void iwl_pcie_apm_stop_master(struct iwl_trans *trans);
void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie);
int iwl_pcie_txq_init(struct iwl_trans *trans, struct iwl_txq *txq,
int slots_num, bool cmd_queue);
@@ -779,6 +806,9 @@ int iwl_pcie_alloc_dma_ptr(struct iwl_trans *trans,
struct iwl_dma_ptr *ptr, size_t size);
void iwl_pcie_free_dma_ptr(struct iwl_trans *trans, struct iwl_dma_ptr *ptr);
void iwl_pcie_apply_destination(struct iwl_trans *trans);
+#ifdef CONFIG_INET
+struct iwl_tso_hdr_page *get_page_hdr(struct iwl_trans *trans, size_t len);
+#endif
/* transport gen 2 exported functions */
int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
index 1da2de2..351c442 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
@@ -761,6 +761,15 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
void iwl_pcie_enable_rx_wake(struct iwl_trans *trans, bool enable)
{
+ if (trans->cfg->device_family != IWL_DEVICE_FAMILY_9000)
+ return;
+
+ if (CSR_HW_REV_STEP(trans->hw_rev) != SILICON_A_STEP)
+ return;
+
+ if (!trans->cfg->integrated)
+ return;
+
/*
* Turn on the chicken-bits that cause MAC wakeup for RX-related
* values.
@@ -768,12 +777,10 @@ void iwl_pcie_enable_rx_wake(struct iwl_trans *trans, bool enable)
* bug where shadow registers are not in the retention list and their
* value is lost when NIC powers down
*/
- if (trans->cfg->integrated) {
- iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL,
- CSR_MAC_SHADOW_REG_CTRL_RX_WAKE);
- iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTL2,
- CSR_MAC_SHADOW_REG_CTL2_RX_WAKE);
- }
+ iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL,
+ CSR_MAC_SHADOW_REG_CTRL_RX_WAKE);
+ iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTL2,
+ CSR_MAC_SHADOW_REG_CTL2_RX_WAKE);
}
static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans)
@@ -845,14 +852,14 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans)
* Set RX DMA chunk size to 64B for IOSF and 128B for PCIe
* Default queue is 0
*/
- iwl_write_prph_no_grab(trans, RFH_GEN_CFG, RFH_GEN_CFG_RFH_DMA_SNOOP |
- (DEFAULT_RXQ_NUM <<
- RFH_GEN_CFG_DEFAULT_RXQ_NUM_POS) |
+ iwl_write_prph_no_grab(trans, RFH_GEN_CFG,
+ RFH_GEN_CFG_RFH_DMA_SNOOP |
+ RFH_GEN_CFG_VAL(DEFAULT_RXQ_NUM, 0) |
RFH_GEN_CFG_SERVICE_DMA_SNOOP |
- (trans->cfg->integrated ?
- RFH_GEN_CFG_RB_CHUNK_SIZE_64 :
- RFH_GEN_CFG_RB_CHUNK_SIZE_128) <<
- RFH_GEN_CFG_RB_CHUNK_SIZE_POS);
+ RFH_GEN_CFG_VAL(RB_CHUNK_SIZE,
+ trans->cfg->integrated ?
+ RFH_GEN_CFG_RB_CHUNK_SIZE_64 :
+ RFH_GEN_CFG_RB_CHUNK_SIZE_128));
/* Enable the relevant rx queues */
iwl_write_prph_no_grab(trans, RFH_RXF_RXQ_ACTIVE, enabled);
@@ -1119,15 +1126,23 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
pkt = rxb_addr(&rxcb);
- if (pkt->len_n_flags == cpu_to_le32(FH_RSCSR_FRAME_INVALID))
+ if (pkt->len_n_flags == cpu_to_le32(FH_RSCSR_FRAME_INVALID)) {
+ IWL_DEBUG_RX(trans,
+ "Q %d: RB end marker at offset %d\n",
+ rxq->id, offset);
break;
+ }
- WARN_ON((le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_RXQ_MASK) >>
- FH_RSCSR_RXQ_POS != rxq->id);
+ WARN((le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_RXQ_MASK) >>
+ FH_RSCSR_RXQ_POS != rxq->id,
+ "frame on invalid queue - is on %d and indicates %d\n",
+ rxq->id,
+ (le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_RXQ_MASK) >>
+ FH_RSCSR_RXQ_POS);
IWL_DEBUG_RX(trans,
- "cmd at offset %d: %s (%.2x.%2x, seq 0x%x)\n",
- rxcb._offset,
+ "Q %d: cmd at offset %d: %s (%.2x.%2x, seq 0x%x)\n",
+ rxq->id, offset,
iwl_get_cmd_string(trans,
iwl_cmd_id(pkt->hdr.cmd,
pkt->hdr.group_id,
@@ -1376,6 +1391,8 @@ irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id)
struct iwl_trans_pcie *trans_pcie = iwl_pcie_get_trans_pcie(entry);
struct iwl_trans *trans = trans_pcie->trans;
+ trace_iwlwifi_dev_irq_msix(trans->dev, entry, false, 0, 0);
+
if (WARN_ON(entry->entry >= trans->num_rx_queues))
return IRQ_NONE;
@@ -1413,18 +1430,16 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
return;
}
- local_bh_disable();
- /* The STATUS_FW_ERROR bit is set in this function. This must happen
- * before we wake up the command caller, to ensure a proper cleanup. */
- iwl_trans_fw_error(trans);
- local_bh_enable();
-
for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) {
if (!trans_pcie->txq[i])
continue;
del_timer(&trans_pcie->txq[i]->stuck_timer);
}
+ /* The STATUS_FW_ERROR bit is set in this function. This must happen
+ * before we wake up the command caller, to ensure a proper cleanup. */
+ iwl_trans_fw_error(trans);
+
clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
wake_up(&trans_pcie->wait_command_queue);
}
@@ -1509,6 +1524,46 @@ static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans)
return inta;
}
+void iwl_pcie_handle_rfkill_irq(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
+ bool hw_rfkill, prev, report;
+
+ mutex_lock(&trans_pcie->mutex);
+ prev = test_bit(STATUS_RFKILL_OPMODE, &trans->status);
+ hw_rfkill = iwl_is_rfkill_set(trans);
+ if (hw_rfkill) {
+ set_bit(STATUS_RFKILL_OPMODE, &trans->status);
+ set_bit(STATUS_RFKILL_HW, &trans->status);
+ }
+ if (trans_pcie->opmode_down)
+ report = hw_rfkill;
+ else
+ report = test_bit(STATUS_RFKILL_OPMODE, &trans->status);
+
+ IWL_WARN(trans, "RF_KILL bit toggled to %s.\n",
+ hw_rfkill ? "disable radio" : "enable radio");
+
+ isr_stats->rfkill++;
+
+ if (prev != report)
+ iwl_trans_pcie_rf_kill(trans, report);
+ mutex_unlock(&trans_pcie->mutex);
+
+ if (hw_rfkill) {
+ if (test_and_clear_bit(STATUS_SYNC_HCMD_ACTIVE,
+ &trans->status))
+ IWL_DEBUG_RF_KILL(trans,
+ "Rfkill while SYNC HCMD in flight\n");
+ wake_up(&trans_pcie->wait_command_queue);
+ } else {
+ clear_bit(STATUS_RFKILL_HW, &trans->status);
+ if (trans_pcie->opmode_down)
+ clear_bit(STATUS_RFKILL_OPMODE, &trans->status);
+ }
+}
+
irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
{
struct iwl_trans *trans = dev_id;
@@ -1632,30 +1687,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
/* HW RF KILL switch toggled */
if (inta & CSR_INT_BIT_RF_KILL) {
- bool hw_rfkill;
-
- mutex_lock(&trans_pcie->mutex);
- hw_rfkill = iwl_is_rfkill_set(trans);
- if (hw_rfkill)
- set_bit(STATUS_RFKILL, &trans->status);
-
- IWL_WARN(trans, "RF_KILL bit toggled to %s.\n",
- hw_rfkill ? "disable radio" : "enable radio");
-
- isr_stats->rfkill++;
-
- iwl_trans_pcie_rf_kill(trans, hw_rfkill);
- mutex_unlock(&trans_pcie->mutex);
- if (hw_rfkill) {
- if (test_and_clear_bit(STATUS_SYNC_HCMD_ACTIVE,
- &trans->status))
- IWL_DEBUG_RF_KILL(trans,
- "Rfkill while SYNC HCMD in flight\n");
- wake_up(&trans_pcie->wait_command_queue);
- } else {
- clear_bit(STATUS_RFKILL, &trans->status);
- }
-
+ iwl_pcie_handle_rfkill_irq(trans);
handled |= CSR_INT_BIT_RF_KILL;
}
@@ -1902,6 +1934,8 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
iwl_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD, inta_hw);
spin_unlock(&trans_pcie->irq_lock);
+ trace_iwlwifi_dev_irq_msix(trans->dev, entry, true, inta_fh, inta_hw);
+
if (unlikely(!(inta_fh | inta_hw))) {
IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
lock_map_release(&trans->sync_cmd_lockdep_map);
@@ -1982,31 +2016,8 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
}
/* HW RF KILL switch toggled */
- if (inta_hw & MSIX_HW_INT_CAUSES_REG_RF_KILL) {
- bool hw_rfkill;
-
- mutex_lock(&trans_pcie->mutex);
- hw_rfkill = iwl_is_rfkill_set(trans);
- if (hw_rfkill)
- set_bit(STATUS_RFKILL, &trans->status);
-
- IWL_WARN(trans, "RF_KILL bit toggled to %s.\n",
- hw_rfkill ? "disable radio" : "enable radio");
-
- isr_stats->rfkill++;
-
- iwl_trans_pcie_rf_kill(trans, hw_rfkill);
- mutex_unlock(&trans_pcie->mutex);
- if (hw_rfkill) {
- if (test_and_clear_bit(STATUS_SYNC_HCMD_ACTIVE,
- &trans->status))
- IWL_DEBUG_RF_KILL(trans,
- "Rfkill while SYNC HCMD in flight\n");
- wake_up(&trans_pcie->wait_command_queue);
- } else {
- clear_bit(STATUS_RFKILL, &trans->status);
- }
- }
+ if (inta_hw & MSIX_HW_INT_CAUSES_REG_RF_KILL)
+ iwl_pcie_handle_rfkill_irq(trans);
if (inta_hw & MSIX_HW_INT_CAUSES_REG_HW_ERR) {
IWL_ERR(trans,
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
index ac60a28..b84b782 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
@@ -136,9 +136,7 @@ static void iwl_pcie_gen2_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
/* Stop device's DMA activity */
iwl_pcie_apm_stop_master(trans);
- /* Reset the entire device */
- iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
- usleep_range(1000, 2000);
+ iwl_pcie_sw_reset(trans);
/*
* Clear "initialization complete" bit to move adapter from
@@ -150,7 +148,6 @@ static void iwl_pcie_gen2_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- bool hw_rfkill, was_hw_rfkill;
lockdep_assert_held(&trans_pcie->mutex);
@@ -159,8 +156,6 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
trans_pcie->is_down = true;
- was_hw_rfkill = iwl_is_rfkill_set(trans);
-
/* tell the device to stop sending interrupts */
iwl_disable_interrupts(trans);
@@ -191,9 +186,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
/* Stop the device, and put it in low power state */
iwl_pcie_gen2_apm_stop(trans, false);
- /* stop and reset the on-board processor */
- iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
- usleep_range(1000, 2000);
+ iwl_pcie_sw_reset(trans);
/*
* Upon stop, the IVAR table gets erased, so msi-x won't
@@ -217,7 +210,6 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
clear_bit(STATUS_INT_ENABLED, &trans->status);
clear_bit(STATUS_TPOWER_PMI, &trans->status);
- clear_bit(STATUS_RFKILL, &trans->status);
/*
* Even if we stop the HW, we still want the RF kill
@@ -225,26 +217,6 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
*/
iwl_enable_rfkill_int(trans);
- /*
- * Check again since the RF kill state may have changed while
- * all the interrupts were disabled, in this case we couldn't
- * receive the RF kill interrupt and update the state in the
- * op_mode.
- * Don't call the op_mode if the rkfill state hasn't changed.
- * This allows the op_mode to call stop_device from the rfkill
- * notification without endless recursion. Under very rare
- * circumstances, we might have a small recursion if the rfkill
- * state changed exactly now while we were called from stop_device.
- * This is very unlikely but can happen and is supported.
- */
- hw_rfkill = iwl_is_rfkill_set(trans);
- if (hw_rfkill)
- set_bit(STATUS_RFKILL, &trans->status);
- else
- clear_bit(STATUS_RFKILL, &trans->status);
- if (hw_rfkill != was_hw_rfkill)
- iwl_trans_pcie_rf_kill(trans, hw_rfkill);
-
/* re-take ownership to prevent other users from stealing the device */
iwl_pcie_prepare_card_hw(trans);
}
@@ -252,9 +224,13 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ bool was_in_rfkill;
mutex_lock(&trans_pcie->mutex);
+ trans_pcie->opmode_down = true;
+ was_in_rfkill = test_bit(STATUS_RFKILL_OPMODE, &trans->status);
_iwl_trans_pcie_gen2_stop_device(trans, low_power);
+ iwl_trans_pcie_handle_stop_rfkill(trans, was_in_rfkill);
mutex_unlock(&trans_pcie->mutex);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 93cbc7a..92b3a55 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -80,7 +80,7 @@
#include "iwl-prph.h"
#include "iwl-scd.h"
#include "iwl-agn-hw.h"
-#include "iwl-fw-error-dump.h"
+#include "fw/error-dump.h"
#include "internal.h"
#include "iwl-fh.h"
@@ -224,9 +224,9 @@ void iwl_pcie_apm_config(struct iwl_trans *trans)
pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_DEVCTL2, &cap);
trans->ltr_enabled = cap & PCI_EXP_DEVCTL2_LTR_EN;
- dev_info(trans->dev, "L1 %sabled - LTR %sabled\n",
- (lctl & PCI_EXP_LNKCTL_ASPM_L1) ? "En" : "Dis",
- trans->ltr_enabled ? "En" : "Dis");
+ IWL_DEBUG_POWER(trans, "L1 %sabled - LTR %sabled\n",
+ (lctl & PCI_EXP_LNKCTL_ASPM_L1) ? "En" : "Dis",
+ trans->ltr_enabled ? "En" : "Dis");
}
/*
@@ -236,7 +236,8 @@ void iwl_pcie_apm_config(struct iwl_trans *trans)
*/
static int iwl_pcie_apm_init(struct iwl_trans *trans)
{
- int ret = 0;
+ int ret;
+
IWL_DEBUG_INFO(trans, "Init card's basic functions\n");
/*
@@ -245,7 +246,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
*/
/* Disable L0S exit timer (platform NMI Work/Around) */
- if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (trans->cfg->device_family < IWL_DEVICE_FAMILY_8000)
iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
@@ -287,8 +288,8 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (ret < 0) {
- IWL_DEBUG_INFO(trans, "Failed to init the card\n");
- goto out;
+ IWL_ERR(trans, "Failed to init the card\n");
+ return ret;
}
if (trans->cfg->host_interrupt_operation_mode) {
@@ -336,8 +337,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
set_bit(STATUS_DEVICE_ENABLED, &trans->status);
-out:
- return ret;
+ return 0;
}
/*
@@ -358,9 +358,7 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
- /* Reset entire device - do controller reset (results in SHRD_HW_RST) */
- iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
- usleep_range(1000, 2000);
+ iwl_pcie_sw_reset(trans);
/*
* Set "initialization complete" bit to move adapter from
@@ -401,12 +399,7 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
apmg_xtal_cfg_reg |
SHR_APMG_XTAL_CFG_XTAL_ON_REQ);
- /*
- * Reset entire device again - do controller reset (results in
- * SHRD_HW_RST). Turn MAC off before proceeding.
- */
- iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
- usleep_range(1000, 2000);
+ iwl_pcie_sw_reset(trans);
/* Enable LP XTAL by indirect access through CSR */
apmg_gp1_reg = iwl_trans_pcie_read_shr(trans, SHR_APMG_GP1_REG);
@@ -448,9 +441,9 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
~SHR_APMG_XTAL_CFG_XTAL_ON_REQ);
}
-int iwl_pcie_apm_stop_master(struct iwl_trans *trans)
+void iwl_pcie_apm_stop_master(struct iwl_trans *trans)
{
- int ret = 0;
+ int ret;
/* stop device's busmaster DMA activity */
iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
@@ -462,8 +455,6 @@ int iwl_pcie_apm_stop_master(struct iwl_trans *trans)
IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n");
IWL_DEBUG_INFO(trans, "stop master\n");
-
- return ret;
}
static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
@@ -478,7 +469,7 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000)
iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_WAKE_ME);
- else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
+ else if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) {
iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
CSR_RESET_LINK_PWR_MGMT_DISABLED);
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
@@ -501,9 +492,7 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
return;
}
- /* Reset the entire device */
- iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
- usleep_range(1000, 2000);
+ iwl_pcie_sw_reset(trans);
/*
* Clear "initialization complete" bit to move adapter from
@@ -516,13 +505,16 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
static int iwl_pcie_nic_init(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ int ret;
/* nic_init */
spin_lock(&trans_pcie->irq_lock);
- iwl_pcie_apm_init(trans);
-
+ ret = iwl_pcie_apm_init(trans);
spin_unlock(&trans_pcie->irq_lock);
+ if (ret)
+ return ret;
+
iwl_pcie_set_pwr(trans, false);
iwl_op_mode_nic_config(trans->op_mode);
@@ -892,7 +884,7 @@ monitor:
if (dest->monitor_mode == EXTERNAL_MODE && trans_pcie->fw_mon_size) {
iwl_write_prph(trans, le32_to_cpu(dest->base_reg),
trans_pcie->fw_mon_phys >> dest->base_shift);
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
iwl_write_prph(trans, le32_to_cpu(dest->end_reg),
(trans_pcie->fw_mon_phys +
trans_pcie->fw_mon_size - 256) >>
@@ -996,14 +988,24 @@ static int iwl_pcie_load_given_ucode_8000(struct iwl_trans *trans,
bool iwl_trans_check_hw_rf_kill(struct iwl_trans *trans)
{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
bool hw_rfkill = iwl_is_rfkill_set(trans);
+ bool prev = test_bit(STATUS_RFKILL_OPMODE, &trans->status);
+ bool report;
- if (hw_rfkill)
- set_bit(STATUS_RFKILL, &trans->status);
- else
- clear_bit(STATUS_RFKILL, &trans->status);
+ if (hw_rfkill) {
+ set_bit(STATUS_RFKILL_HW, &trans->status);
+ set_bit(STATUS_RFKILL_OPMODE, &trans->status);
+ } else {
+ clear_bit(STATUS_RFKILL_HW, &trans->status);
+ if (trans_pcie->opmode_down)
+ clear_bit(STATUS_RFKILL_OPMODE, &trans->status);
+ }
- iwl_trans_pcie_rf_kill(trans, hw_rfkill);
+ report = test_bit(STATUS_RFKILL_OPMODE, &trans->status);
+
+ if (prev != report)
+ iwl_trans_pcie_rf_kill(trans, report);
return hw_rfkill;
}
@@ -1128,7 +1130,6 @@ static void iwl_pcie_init_msix(struct iwl_trans_pcie *trans_pcie)
static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- bool hw_rfkill, was_hw_rfkill;
lockdep_assert_held(&trans_pcie->mutex);
@@ -1137,8 +1138,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
trans_pcie->is_down = true;
- was_hw_rfkill = iwl_is_rfkill_set(trans);
-
/* tell the device to stop sending interrupts */
iwl_disable_interrupts(trans);
@@ -1173,9 +1172,7 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
/* Stop the device, and put it in low power state */
iwl_pcie_apm_stop(trans, false);
- /* stop and reset the on-board processor */
- iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
- usleep_range(1000, 2000);
+ iwl_pcie_sw_reset(trans);
/*
* Upon stop, the IVAR table gets erased, so msi-x won't
@@ -1199,7 +1196,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
clear_bit(STATUS_INT_ENABLED, &trans->status);
clear_bit(STATUS_TPOWER_PMI, &trans->status);
- clear_bit(STATUS_RFKILL, &trans->status);
/*
* Even if we stop the HW, we still want the RF kill
@@ -1207,26 +1203,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
*/
iwl_enable_rfkill_int(trans);
- /*
- * Check again since the RF kill state may have changed while
- * all the interrupts were disabled, in this case we couldn't
- * receive the RF kill interrupt and update the state in the
- * op_mode.
- * Don't call the op_mode if the rkfill state hasn't changed.
- * This allows the op_mode to call stop_device from the rfkill
- * notification without endless recursion. Under very rare
- * circumstances, we might have a small recursion if the rfkill
- * state changed exactly now while we were called from stop_device.
- * This is very unlikely but can happen and is supported.
- */
- hw_rfkill = iwl_is_rfkill_set(trans);
- if (hw_rfkill)
- set_bit(STATUS_RFKILL, &trans->status);
- else
- clear_bit(STATUS_RFKILL, &trans->status);
- if (hw_rfkill != was_hw_rfkill)
- iwl_trans_pcie_rf_kill(trans, hw_rfkill);
-
/* re-take ownership to prevent other users from stealing the device */
iwl_pcie_prepare_card_hw(trans);
}
@@ -1318,7 +1294,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
/* Load the given image to the HW */
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
ret = iwl_pcie_load_given_ucode_8000(trans, fw);
else
ret = iwl_pcie_load_given_ucode(trans, fw);
@@ -1339,12 +1315,45 @@ static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
iwl_pcie_tx_start(trans, scd_addr);
}
+void iwl_trans_pcie_handle_stop_rfkill(struct iwl_trans *trans,
+ bool was_in_rfkill)
+{
+ bool hw_rfkill;
+
+ /*
+ * Check again since the RF kill state may have changed while
+ * all the interrupts were disabled, in this case we couldn't
+ * receive the RF kill interrupt and update the state in the
+ * op_mode.
+ * Don't call the op_mode if the rkfill state hasn't changed.
+ * This allows the op_mode to call stop_device from the rfkill
+ * notification without endless recursion. Under very rare
+ * circumstances, we might have a small recursion if the rfkill
+ * state changed exactly now while we were called from stop_device.
+ * This is very unlikely but can happen and is supported.
+ */
+ hw_rfkill = iwl_is_rfkill_set(trans);
+ if (hw_rfkill) {
+ set_bit(STATUS_RFKILL_HW, &trans->status);
+ set_bit(STATUS_RFKILL_OPMODE, &trans->status);
+ } else {
+ clear_bit(STATUS_RFKILL_HW, &trans->status);
+ clear_bit(STATUS_RFKILL_OPMODE, &trans->status);
+ }
+ if (hw_rfkill != was_in_rfkill)
+ iwl_trans_pcie_rf_kill(trans, hw_rfkill);
+}
+
static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ bool was_in_rfkill;
mutex_lock(&trans_pcie->mutex);
+ trans_pcie->opmode_down = true;
+ was_in_rfkill = test_bit(STATUS_RFKILL_OPMODE, &trans->status);
_iwl_trans_pcie_stop_device(trans, low_power);
+ iwl_trans_pcie_handle_stop_rfkill(trans, was_in_rfkill);
mutex_unlock(&trans_pcie->mutex);
}
@@ -1355,6 +1364,8 @@ void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state)
lockdep_assert_held(&trans_pcie->mutex);
+ IWL_WARN(trans, "reporting RF_KILL (radio %s)\n",
+ state ? "disabled" : "enabled");
if (iwl_op_mode_hw_rf_kill(trans->op_mode, state)) {
if (trans->cfg->gen2)
_iwl_trans_pcie_gen2_stop_device(trans, true);
@@ -1435,7 +1446,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
udelay(2);
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
@@ -1635,17 +1646,19 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
return err;
}
- /* Reset the entire device */
- iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
- usleep_range(1000, 2000);
+ iwl_pcie_sw_reset(trans);
- iwl_pcie_apm_init(trans);
+ err = iwl_pcie_apm_init(trans);
+ if (err)
+ return err;
iwl_pcie_init_msix(trans_pcie);
/* From now on, the op_mode will be kept updated about RF kill state */
iwl_enable_rfkill_int(trans);
+ trans_pcie->opmode_down = false;
+
/* Set is_down to false here so that...*/
trans_pcie->is_down = false;
@@ -1822,7 +1835,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans,
/* this bit wakes up the NIC */
__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
udelay(2);
/*
@@ -2045,17 +2058,52 @@ void iwl_trans_pcie_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq)
iwl_read_direct32(trans, FH_TX_TRB_REG(fifo)));
}
-static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm)
+static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_txq *txq;
- int cnt;
unsigned long now = jiffies;
+ u8 wr_ptr;
+
+ if (!test_bit(txq_idx, trans_pcie->queue_used))
+ return -EINVAL;
+
+ IWL_DEBUG_TX_QUEUES(trans, "Emptying queue %d...\n", txq_idx);
+ txq = trans_pcie->txq[txq_idx];
+ wr_ptr = ACCESS_ONCE(txq->write_ptr);
+
+ while (txq->read_ptr != ACCESS_ONCE(txq->write_ptr) &&
+ !time_after(jiffies,
+ now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) {
+ u8 write_ptr = ACCESS_ONCE(txq->write_ptr);
+
+ if (WARN_ONCE(wr_ptr != write_ptr,
+ "WR pointer moved while flushing %d -> %d\n",
+ wr_ptr, write_ptr))
+ return -ETIMEDOUT;
+ usleep_range(1000, 2000);
+ }
+
+ if (txq->read_ptr != txq->write_ptr) {
+ IWL_ERR(trans,
+ "fail to flush all tx fifo queues Q %d\n", txq_idx);
+ iwl_trans_pcie_log_scd_error(trans, txq);
+ return -ETIMEDOUT;
+ }
+
+ IWL_DEBUG_TX_QUEUES(trans, "Queue %d is now empty.\n", txq_idx);
+
+ return 0;
+}
+
+static int iwl_trans_pcie_wait_txqs_empty(struct iwl_trans *trans, u32 txq_bm)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ int cnt;
int ret = 0;
/* waiting for all the tx frames complete might take a while */
for (cnt = 0; cnt < trans->cfg->base_params->num_of_queues; cnt++) {
- u8 wr_ptr;
if (cnt == trans_pcie->cmd_queue)
continue;
@@ -2064,34 +2112,11 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm)
if (!(BIT(cnt) & txq_bm))
continue;
- IWL_DEBUG_TX_QUEUES(trans, "Emptying queue %d...\n", cnt);
- txq = trans_pcie->txq[cnt];
- wr_ptr = ACCESS_ONCE(txq->write_ptr);
-
- while (txq->read_ptr != ACCESS_ONCE(txq->write_ptr) &&
- !time_after(jiffies,
- now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) {
- u8 write_ptr = ACCESS_ONCE(txq->write_ptr);
-
- if (WARN_ONCE(wr_ptr != write_ptr,
- "WR pointer moved while flushing %d -> %d\n",
- wr_ptr, write_ptr))
- return -ETIMEDOUT;
- usleep_range(1000, 2000);
- }
-
- if (txq->read_ptr != txq->write_ptr) {
- IWL_ERR(trans,
- "fail to flush all tx fifo queues Q %d\n", cnt);
- ret = -ETIMEDOUT;
+ ret = iwl_trans_pcie_wait_txq_empty(trans, cnt);
+ if (ret)
break;
- }
- IWL_DEBUG_TX_QUEUES(trans, "Queue %d is now empty.\n", cnt);
}
- if (ret)
- iwl_trans_pcie_log_scd_error(trans, txq);
-
return ret;
}
@@ -2393,17 +2418,12 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
struct iwl_trans *trans = file->private_data;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
-
- char buf[8];
- int buf_size;
u32 reset_flag;
+ int ret;
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%x", &reset_flag) != 1)
- return -EFAULT;
+ ret = kstrtou32_from_user(user_buf, count, 16, &reset_flag);
+ if (ret)
+ return ret;
if (reset_flag == 0)
memset(isr_stats, 0, sizeof(*isr_stats));
@@ -2415,16 +2435,6 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file,
size_t count, loff_t *ppos)
{
struct iwl_trans *trans = file->private_data;
- char buf[8];
- int buf_size;
- int csr;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &csr) != 1)
- return -EFAULT;
iwl_pcie_dump_csr(trans);
@@ -2449,11 +2459,50 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
return ret;
}
+static ssize_t iwl_dbgfs_rfkill_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_trans *trans = file->private_data;
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ char buf[100];
+ int pos;
+
+ pos = scnprintf(buf, sizeof(buf), "debug: %d\nhw: %d\n",
+ trans_pcie->debug_rfkill,
+ !(iwl_read32(trans, CSR_GP_CNTRL) &
+ CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW));
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_dbgfs_rfkill_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_trans *trans = file->private_data;
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ bool old = trans_pcie->debug_rfkill;
+ int ret;
+
+ ret = kstrtobool_from_user(user_buf, count, &trans_pcie->debug_rfkill);
+ if (ret)
+ return ret;
+ if (old == trans_pcie->debug_rfkill)
+ return count;
+ IWL_WARN(trans, "changing debug rfkill %d->%d\n",
+ old, trans_pcie->debug_rfkill);
+ iwl_pcie_handle_rfkill_irq(trans);
+
+ return count;
+}
+
DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
DEBUGFS_READ_FILE_OPS(fh_reg);
DEBUGFS_READ_FILE_OPS(rx_queue);
DEBUGFS_READ_FILE_OPS(tx_queue);
DEBUGFS_WRITE_FILE_OPS(csr);
+DEBUGFS_READ_WRITE_FILE_OPS(rfkill);
/* Create the debugfs files and directories */
int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans)
@@ -2465,6 +2514,7 @@ int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans)
DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(csr, dir, S_IWUSR);
DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR);
+ DEBUGFS_ADD_FILE(rfkill, dir, S_IWUSR | S_IRUSR);
return 0;
err:
@@ -2563,8 +2613,15 @@ static u32 iwl_trans_pcie_fh_regs_dump(struct iwl_trans *trans,
(*data)->len = cpu_to_le32(fh_regs_len);
val = (void *)(*data)->data;
- for (i = FH_MEM_LOWER_BOUND; i < FH_MEM_UPPER_BOUND; i += sizeof(u32))
- *val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
+ if (!trans->cfg->gen2)
+ for (i = FH_MEM_LOWER_BOUND; i < FH_MEM_UPPER_BOUND;
+ i += sizeof(u32))
+ *val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
+ else
+ for (i = FH_MEM_LOWER_BOUND_GEN2; i < FH_MEM_UPPER_BOUND_GEN2;
+ i += sizeof(u32))
+ *val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans,
+ i));
iwl_trans_release_nic_access(trans, &flags);
@@ -2714,7 +2771,7 @@ static struct iwl_trans_dump_data
trans->dbg_dest_tlv->end_shift;
/* Make "end" point to the actual end */
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 ||
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000 ||
trans->dbg_dest_tlv->monitor_mode == MARBH_MODE)
end += (1 << trans->dbg_dest_tlv->end_shift);
monitor_len = end - base;
@@ -2740,7 +2797,12 @@ static struct iwl_trans_dump_data
len += sizeof(*data) + IWL_CSR_TO_DUMP;
/* FH registers */
- len += sizeof(*data) + (FH_MEM_UPPER_BOUND - FH_MEM_LOWER_BOUND);
+ if (trans->cfg->gen2)
+ len += sizeof(*data) +
+ (FH_MEM_UPPER_BOUND_GEN2 - FH_MEM_LOWER_BOUND_GEN2);
+ else
+ len += sizeof(*data) +
+ (FH_MEM_UPPER_BOUND - FH_MEM_LOWER_BOUND);
if (dump_rbs) {
/* Dump RBs is supported only for pre-9000 devices (1 queue) */
@@ -2754,6 +2816,13 @@ static struct iwl_trans_dump_data
(PAGE_SIZE << trans_pcie->rx_page_order));
}
+ /* Paged memory for gen2 HW */
+ if (trans->cfg->gen2)
+ for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++)
+ len += sizeof(*data) +
+ sizeof(struct iwl_fw_error_dump_paging) +
+ trans_pcie->init_dram.paging[i].size;
+
dump_data = vzalloc(len);
if (!dump_data)
return NULL;
@@ -2793,6 +2862,28 @@ static struct iwl_trans_dump_data
if (dump_rbs)
len += iwl_trans_pcie_dump_rbs(trans, &data, num_rbs);
+ /* Paged memory for gen2 HW */
+ if (trans->cfg->gen2) {
+ for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++) {
+ struct iwl_fw_error_dump_paging *paging;
+ dma_addr_t addr =
+ trans_pcie->init_dram.paging[i].physical;
+ u32 page_len = trans_pcie->init_dram.paging[i].size;
+
+ data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING);
+ data->len = cpu_to_le32(sizeof(*paging) + page_len);
+ paging = (void *)data->data;
+ paging->index = cpu_to_le32(i);
+ dma_sync_single_for_cpu(trans->dev, addr, page_len,
+ DMA_BIDIRECTIONAL);
+ memcpy(paging->data,
+ trans_pcie->init_dram.paging[i].block, page_len);
+ data = iwl_fw_error_next_data(data);
+
+ len += sizeof(*data) + sizeof(*paging) + page_len;
+ }
+ }
+
len += iwl_trans_pcie_dump_monitor(trans, &data, monitor_len);
dump_data->len = len;
@@ -2835,7 +2926,6 @@ static void iwl_trans_pcie_resume(struct iwl_trans *trans)
.ref = iwl_trans_pcie_ref, \
.unref = iwl_trans_pcie_unref, \
.dump_data = iwl_trans_pcie_dump_data, \
- .wait_tx_queues_empty = iwl_trans_pcie_wait_txq_empty, \
.d3_suspend = iwl_trans_pcie_d3_suspend, \
.d3_resume = iwl_trans_pcie_d3_resume
@@ -2865,6 +2955,8 @@ static const struct iwl_trans_ops trans_ops_pcie = {
.txq_set_shared_mode = iwl_trans_pcie_txq_set_shared_mode,
+ .wait_tx_queues_empty = iwl_trans_pcie_wait_txqs_empty,
+
.freeze_txq_timer = iwl_trans_pcie_freeze_txq_timer,
.block_txq_ptrs = iwl_trans_pcie_block_txq_ptrs,
};
@@ -2884,6 +2976,7 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = {
.txq_alloc = iwl_trans_pcie_dyn_txq_alloc,
.txq_free = iwl_trans_pcie_dyn_txq_free,
+ .wait_txq_empty = iwl_trans_pcie_wait_txq_empty,
};
struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
@@ -2910,6 +3003,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
trans_pcie->trans = trans;
+ trans_pcie->opmode_down = true;
spin_lock_init(&trans_pcie->irq_lock);
spin_lock_init(&trans_pcie->reg_lock);
mutex_init(&trans_pcie->mutex);
@@ -2988,7 +3082,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
* "dash" value). To keep hw_rev backwards compatible - we'll store it
* in the old format.
*/
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
+ if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) {
unsigned long flags;
trans->hw_rev = (trans->hw_rev & 0xfff0) |
@@ -3032,6 +3126,17 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
}
}
+ /*
+ * 9000-series integrated A-step has a problem with suspend/resume
+ * and sometimes even causes the whole platform to get stuck. This
+ * workaround makes the hardware not go into the problematic state.
+ */
+ if (trans->cfg->integrated &&
+ trans->cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
+ CSR_HW_REV_STEP(trans->hw_rev) == SILICON_A_STEP)
+ iwl_set_bit(trans, CSR_HOST_CHICKEN,
+ CSR_HOST_CHICKEN_PM_IDLE_SRC_DIS_SB_PME);
+
trans->hw_rf_id = iwl_read32(trans, CSR_HW_RF_ID);
iwl_pcie_set_interrupt_capa(pdev, trans);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
index 9c9bfbb..a3795ba 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -49,6 +49,7 @@
*
*****************************************************************************/
#include <linux/pm_runtime.h>
+#include <net/tso.h>
#include "iwl-debug.h"
#include "iwl-csr.h"
@@ -226,6 +227,143 @@ static int iwl_pcie_gen2_set_tb(struct iwl_trans *trans,
return idx;
}
+static int iwl_pcie_gen2_build_amsdu(struct iwl_trans *trans,
+ struct sk_buff *skb,
+ struct iwl_tfh_tfd *tfd, int start_len,
+ u8 hdr_len, struct iwl_device_cmd *dev_cmd)
+{
+#ifdef CONFIG_INET
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload;
+ struct ieee80211_hdr *hdr = (void *)skb->data;
+ unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room;
+ unsigned int mss = skb_shinfo(skb)->gso_size;
+ u16 length, iv_len, amsdu_pad;
+ u8 *start_hdr;
+ struct iwl_tso_hdr_page *hdr_page;
+ struct page **page_ptr;
+ struct tso_t tso;
+
+ /* if the packet is protected, then it must be CCMP or GCMP */
+ iv_len = ieee80211_has_protected(hdr->frame_control) ?
+ IEEE80211_CCMP_HDR_LEN : 0;
+
+ trace_iwlwifi_dev_tx(trans->dev, skb, tfd, sizeof(*tfd),
+ &dev_cmd->hdr, start_len, 0);
+
+ ip_hdrlen = skb_transport_header(skb) - skb_network_header(skb);
+ snap_ip_tcp_hdrlen = 8 + ip_hdrlen + tcp_hdrlen(skb);
+ total_len = skb->len - snap_ip_tcp_hdrlen - hdr_len - iv_len;
+ amsdu_pad = 0;
+
+ /* total amount of header we may need for this A-MSDU */
+ hdr_room = DIV_ROUND_UP(total_len, mss) *
+ (3 + snap_ip_tcp_hdrlen + sizeof(struct ethhdr)) + iv_len;
+
+ /* Our device supports 9 segments at most, it will fit in 1 page */
+ hdr_page = get_page_hdr(trans, hdr_room);
+ if (!hdr_page)
+ return -ENOMEM;
+
+ get_page(hdr_page->page);
+ start_hdr = hdr_page->pos;
+ page_ptr = (void *)((u8 *)skb->cb + trans_pcie->page_offs);
+ *page_ptr = hdr_page->page;
+ memcpy(hdr_page->pos, skb->data + hdr_len, iv_len);
+ hdr_page->pos += iv_len;
+
+ /*
+ * Pull the ieee80211 header + IV to be able to use TSO core,
+ * we will restore it for the tx_status flow.
+ */
+ skb_pull(skb, hdr_len + iv_len);
+
+ /*
+ * Remove the length of all the headers that we don't actually
+ * have in the MPDU by themselves, but that we duplicate into
+ * all the different MSDUs inside the A-MSDU.
+ */
+ le16_add_cpu(&tx_cmd->len, -snap_ip_tcp_hdrlen);
+
+ tso_start(skb, &tso);
+
+ while (total_len) {
+ /* this is the data left for this subframe */
+ unsigned int data_left = min_t(unsigned int, mss, total_len);
+ struct sk_buff *csum_skb = NULL;
+ unsigned int tb_len;
+ dma_addr_t tb_phys;
+ struct tcphdr *tcph;
+ u8 *iph, *subf_hdrs_start = hdr_page->pos;
+
+ total_len -= data_left;
+
+ memset(hdr_page->pos, 0, amsdu_pad);
+ hdr_page->pos += amsdu_pad;
+ amsdu_pad = (4 - (sizeof(struct ethhdr) + snap_ip_tcp_hdrlen +
+ data_left)) & 0x3;
+ ether_addr_copy(hdr_page->pos, ieee80211_get_DA(hdr));
+ hdr_page->pos += ETH_ALEN;
+ ether_addr_copy(hdr_page->pos, ieee80211_get_SA(hdr));
+ hdr_page->pos += ETH_ALEN;
+
+ length = snap_ip_tcp_hdrlen + data_left;
+ *((__be16 *)hdr_page->pos) = cpu_to_be16(length);
+ hdr_page->pos += sizeof(length);
+
+ /*
+ * This will copy the SNAP as well which will be considered
+ * as MAC header.
+ */
+ tso_build_hdr(skb, hdr_page->pos, &tso, data_left, !total_len);
+ iph = hdr_page->pos + 8;
+ tcph = (void *)(iph + ip_hdrlen);
+
+ hdr_page->pos += snap_ip_tcp_hdrlen;
+
+ tb_len = hdr_page->pos - start_hdr;
+ tb_phys = dma_map_single(trans->dev, start_hdr,
+ tb_len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(trans->dev, tb_phys))) {
+ dev_kfree_skb(csum_skb);
+ goto out_err;
+ }
+ iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb_len);
+ trace_iwlwifi_dev_tx_tso_chunk(trans->dev, start_hdr, tb_len);
+ /* add this subframe's headers' length to the tx_cmd */
+ le16_add_cpu(&tx_cmd->len, hdr_page->pos - subf_hdrs_start);
+
+ /* prepare the start_hdr for the next subframe */
+ start_hdr = hdr_page->pos;
+
+ /* put the payload */
+ while (data_left) {
+ tb_len = min_t(unsigned int, tso.size, data_left);
+ tb_phys = dma_map_single(trans->dev, tso.data,
+ tb_len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(trans->dev, tb_phys))) {
+ dev_kfree_skb(csum_skb);
+ goto out_err;
+ }
+ iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb_len);
+ trace_iwlwifi_dev_tx_tso_chunk(trans->dev, tso.data,
+ tb_len);
+
+ data_left -= tb_len;
+ tso_build_data(skb, &tso, tb_len);
+ }
+ }
+
+ /* re -add the WiFi header and IV */
+ skb_push(skb, hdr_len + iv_len);
+
+ return 0;
+
+out_err:
+#endif
+ return -EINVAL;
+}
+
static
struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
struct iwl_txq *txq,
@@ -238,15 +376,21 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
struct iwl_tfh_tfd *tfd =
iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr);
dma_addr_t tb_phys;
+ bool amsdu;
int i, len, tb1_len, tb2_len, hdr_len;
void *tb1_addr;
memset(tfd, 0, sizeof(*tfd));
+ amsdu = ieee80211_is_data_qos(hdr->frame_control) &&
+ (*ieee80211_get_qos_ctl(hdr) &
+ IEEE80211_QOS_CTL_A_MSDU_PRESENT);
+
tb_phys = iwl_pcie_get_first_tb_dma(txq, txq->write_ptr);
/* The first TB points to bi-directional DMA data */
- memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
- IWL_FIRST_TB_SIZE);
+ if (!amsdu)
+ memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
+ IWL_FIRST_TB_SIZE);
iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, IWL_FIRST_TB_SIZE);
@@ -262,7 +406,11 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
len = sizeof(struct iwl_tx_cmd_gen2) + sizeof(struct iwl_cmd_header) +
ieee80211_hdrlen(hdr->frame_control) - IWL_FIRST_TB_SIZE;
- tb1_len = ALIGN(len, 4);
+ /* do not align A-MSDU to dword as the subframe header aligns it */
+ if (amsdu)
+ tb1_len = len;
+ else
+ tb1_len = ALIGN(len, 4);
/* map the data for TB1 */
tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_FIRST_TB_SIZE;
@@ -271,8 +419,24 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
goto out_err;
iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb1_len);
- /* set up TFD's third entry to point to remainder of skb's head */
hdr_len = ieee80211_hdrlen(hdr->frame_control);
+
+ if (amsdu) {
+ if (!iwl_pcie_gen2_build_amsdu(trans, skb, tfd,
+ tb1_len + IWL_FIRST_TB_SIZE,
+ hdr_len, dev_cmd))
+ goto out_err;
+
+ /*
+ * building the A-MSDU might have changed this data, so memcpy
+ * it now
+ */
+ memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
+ IWL_FIRST_TB_SIZE);
+ return tfd;
+ }
+
+ /* set up TFD's third entry to point to remainder of skb's head */
tb2_len = skb_headlen(skb) - hdr_len;
if (tb2_len > 0) {
@@ -303,10 +467,8 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
}
trace_iwlwifi_dev_tx(trans->dev, skb, tfd, sizeof(*tfd), &dev_cmd->hdr,
- IWL_FIRST_TB_SIZE + tb1_len,
- skb->data + hdr_len, tb2_len);
- trace_iwlwifi_dev_tx_data(trans->dev, skb, hdr_len,
- skb->len - hdr_len);
+ IWL_FIRST_TB_SIZE + tb1_len, hdr_len);
+ trace_iwlwifi_dev_tx_data(trans->dev, skb, hdr_len);
return tfd;
@@ -699,7 +861,7 @@ static int iwl_pcie_gen2_send_hcmd_sync(struct iwl_trans *trans,
}
if (!(cmd->flags & CMD_SEND_IN_RFKILL) &&
- test_bit(STATUS_RFKILL, &trans->status)) {
+ test_bit(STATUS_RFKILL_OPMODE, &trans->status)) {
IWL_DEBUG_RF_KILL(trans, "RFKILL in SYNC CMD... no rsp\n");
ret = -ERFKILL;
goto cancel;
@@ -736,7 +898,7 @@ int iwl_trans_pcie_gen2_send_hcmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
{
if (!(cmd->flags & CMD_SEND_IN_RFKILL) &&
- test_bit(STATUS_RFKILL, &trans->status)) {
+ test_bit(STATUS_RFKILL_OPMODE, &trans->status)) {
IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n",
cmd->id);
return -ERFKILL;
@@ -912,7 +1074,7 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,
rsp = (void *)hcmd.resp_pkt->data;
qid = le16_to_cpu(rsp->queue_number);
- if (qid > ARRAY_SIZE(trans_pcie->txq)) {
+ if (qid >= ARRAY_SIZE(trans_pcie->txq)) {
WARN_ONCE(1, "queue index %d unsupported", qid);
ret = -EIO;
goto error_free_resp;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
index 386950a..de50418 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
@@ -762,7 +762,7 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
/* Enable L1-Active */
- if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ if (trans->cfg->device_family < IWL_DEVICE_FAMILY_8000)
iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
}
@@ -1277,13 +1277,14 @@ static int iwl_pcie_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid,
* combined with Traffic ID (QOS priority), in format used by Tx Scheduler */
#define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid))
-void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
+bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
const struct iwl_trans_txq_scd_cfg *cfg,
unsigned int wdg_timeout)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_txq *txq = trans_pcie->txq[txq_id];
int fifo = -1;
+ bool scd_bug = false;
if (test_and_set_bit(txq_id, trans_pcie->queue_used))
WARN_ONCE(1, "queue %d already used - expect issues", txq_id);
@@ -1324,6 +1325,23 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
ssn = txq->read_ptr;
}
+ } else {
+ /*
+ * If we need to move the SCD write pointer by steps of
+ * 0x40, 0x80 or 0xc0, it gets stuck. Avoids this and let
+ * the op_mode know by returning true later.
+ * Do this only in case cfg is NULL since this trick can
+ * be done only if we have DQA enabled which is true for mvm
+ * only. And mvm never sets a cfg pointer.
+ * This is really ugly, but this is the easiest way out for
+ * this sad hardware issue.
+ * This bug has been fixed on devices 9000 and up.
+ */
+ scd_bug = !trans->cfg->mq_rx_supported &&
+ !((ssn - txq->write_ptr) & 0x3f) &&
+ (ssn != txq->write_ptr);
+ if (scd_bug)
+ ssn++;
}
/* Place first TFD at index corresponding to start sequence number.
@@ -1344,10 +1362,8 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
iwl_trans_write_mem32(trans,
trans_pcie->scd_base_addr +
SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32),
- ((frame_limit << SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
- SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
- ((frame_limit << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
- SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
+ SCD_QUEUE_CTX_REG2_VAL(WIN_SIZE, frame_limit) |
+ SCD_QUEUE_CTX_REG2_VAL(FRAME_LIMIT, frame_limit));
/* Set up status area in SRAM, map to Tx DMA/FIFO, activate */
iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id),
@@ -1369,6 +1385,8 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
"Activate queue %d WrPtr: %d\n",
txq_id, ssn & 0xff);
}
+
+ return scd_bug;
}
void iwl_trans_pcie_txq_set_shared_mode(struct iwl_trans *trans, u32 txq_id,
@@ -1708,7 +1726,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
- u8 group_id = iwl_cmd_groupid(pkt->hdr.group_id);
+ u8 group_id;
u32 cmd_id;
int txq_id = SEQ_TO_QUEUE(sequence);
int index = SEQ_TO_INDEX(sequence);
@@ -1734,6 +1752,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
cmd_index = get_cmd_index(txq, index);
cmd = txq->entries[cmd_index].cmd;
meta = &txq->entries[cmd_index].meta;
+ group_id = cmd->hdr.group_id;
cmd_id = iwl_cmd_id(cmd->hdr.cmd, group_id, 0);
iwl_pcie_tfd_unmap(trans, meta, txq, index);
@@ -1876,7 +1895,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
}
if (!(cmd->flags & CMD_SEND_IN_RFKILL) &&
- test_bit(STATUS_RFKILL, &trans->status)) {
+ test_bit(STATUS_RFKILL_OPMODE, &trans->status)) {
IWL_DEBUG_RF_KILL(trans, "RFKILL in SYNC CMD... no rsp\n");
ret = -ERFKILL;
goto cancel;
@@ -1913,7 +1932,7 @@ cancel:
int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
{
if (!(cmd->flags & CMD_SEND_IN_RFKILL) &&
- test_bit(STATUS_RFKILL, &trans->status)) {
+ test_bit(STATUS_RFKILL_OPMODE, &trans->status)) {
IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n",
cmd->id);
return -ERFKILL;
@@ -1980,15 +1999,13 @@ static int iwl_fill_data_tbs(struct iwl_trans *trans, struct sk_buff *skb,
iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr),
trans_pcie->tfd_size,
&dev_cmd->hdr, IWL_FIRST_TB_SIZE + tb1_len,
- skb->data + hdr_len, tb2_len);
- trace_iwlwifi_dev_tx_data(trans->dev, skb,
- hdr_len, skb->len - hdr_len);
+ hdr_len);
+ trace_iwlwifi_dev_tx_data(trans->dev, skb, hdr_len);
return 0;
}
#ifdef CONFIG_INET
-static struct iwl_tso_hdr_page *
-get_page_hdr(struct iwl_trans *trans, size_t len)
+struct iwl_tso_hdr_page *get_page_hdr(struct iwl_trans *trans, size_t len)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_tso_hdr_page *p = this_cpu_ptr(trans_pcie->tso_hdr_page);
@@ -2055,8 +2072,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
trace_iwlwifi_dev_tx(trans->dev, skb,
iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr),
trans_pcie->tfd_size,
- &dev_cmd->hdr, IWL_FIRST_TB_SIZE + tb1_len,
- NULL, 0);
+ &dev_cmd->hdr, IWL_FIRST_TB_SIZE + tb1_len, 0);
ip_hdrlen = skb_transport_header(skb) - skb_network_header(skb);
snap_ip_tcp_hdrlen = 8 + ip_hdrlen + tcp_hdrlen(skb);
@@ -2141,8 +2157,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
htons(ETH_P_IPV6),
data_left);
- memcpy(skb_put(csum_skb, tcp_hdrlen(skb)),
- tcph, tcp_hdrlen(skb));
+ skb_put_data(csum_skb, tcph, tcp_hdrlen(skb));
skb_reset_transport_header(csum_skb);
csum_skb->csum_start =
(unsigned char *)tcp_hdr(csum_skb) -
@@ -2176,7 +2191,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
dma_addr_t tb_phys;
if (trans_pcie->sw_csum_tx)
- memcpy(skb_put(csum_skb, size), tso.data, size);
+ skb_put_data(csum_skb, tso.data, size);
tb_phys = dma_map_single(trans->dev, tso.data,
size, DMA_TO_DEVICE);
diff --git a/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c b/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c
index 34dbddb..6d8b64c 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c
@@ -131,8 +131,7 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
if (prism_header == 1) {
struct linux_wlan_ng_prism_hdr *hdr;
- hdr = (struct linux_wlan_ng_prism_hdr *)
- skb_push(skb, phdrlen);
+ hdr = skb_push(skb, phdrlen);
memset(hdr, 0, phdrlen);
hdr->msgcode = LWNG_CAP_DID_BASE;
hdr->msglen = sizeof(*hdr);
@@ -153,8 +152,7 @@ hdr->f.status = s; hdr->f.len = l; hdr->f.data = d
#undef LWNG_SETVAL
} else if (prism_header == 2) {
struct linux_wlan_ng_cap_hdr *hdr;
- hdr = (struct linux_wlan_ng_cap_hdr *)
- skb_push(skb, phdrlen);
+ hdr = skb_push(skb, phdrlen);
memset(hdr, 0, phdrlen);
hdr->version = htonl(LWNG_CAPHDR_VERSION);
hdr->length = htonl(phdrlen);
@@ -172,7 +170,7 @@ hdr->f.status = s; hdr->f.len = l; hdr->f.data = d
hdr->encoding = htonl(1); /* cck */
} else if (prism_header == 3) {
struct hostap_radiotap_rx *hdr;
- hdr = (struct hostap_radiotap_rx *)skb_push(skb, phdrlen);
+ hdr = skb_push(skb, phdrlen);
memset(hdr, 0, phdrlen);
hdr->hdr.it_len = cpu_to_le16(phdrlen);
hdr->hdr.it_present =
diff --git a/drivers/net/wireless/intersil/hostap/hostap_80211_tx.c b/drivers/net/wireless/intersil/hostap/hostap_80211_tx.c
index 055e11d..c1b10d5 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_80211_tx.c
@@ -242,7 +242,7 @@ netdev_tx_t hostap_data_start_xmit(struct sk_buff *skb,
memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
memcpy(skb_push(skb, hdr_len), &hdr, hdr_len);
if (use_wds == WDS_OWN_FRAME) {
- memcpy(skb_put(skb, ETH_ALEN), &hdr.addr4, ETH_ALEN);
+ skb_put_data(skb, &hdr.addr4, ETH_ALEN);
}
iface->stats.tx_packets++;
diff --git a/drivers/net/wireless/intersil/hostap/hostap_ap.c b/drivers/net/wireless/intersil/hostap/hostap_ap.c
index c995ace..eb9cd6f 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_ap.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_ap.c
@@ -998,11 +998,9 @@ static void prism2_send_mgmt(struct net_device *dev,
fc = type_subtype;
hdrlen = hostap_80211_get_hdrlen(cpu_to_le16(type_subtype));
- hdr = (struct ieee80211_hdr *) skb_put(skb, hdrlen);
+ hdr = skb_put_zero(skb, hdrlen);
if (body)
- memcpy(skb_put(skb, body_len), body, body_len);
-
- memset(hdr, 0, hdrlen);
+ skb_put_data(skb, body, body_len);
/* FIX: ctrl::ack sending used special HFA384X_TX_CTRL_802_11
* tx_control instead of using local->tx_control */
@@ -1325,8 +1323,7 @@ static char * ap_auth_make_challenge(struct ap_data *ap)
}
skb_reserve(skb, ap->crypt->extra_mpdu_prefix_len);
- memset(skb_put(skb, WLAN_AUTH_CHALLENGE_LEN), 0,
- WLAN_AUTH_CHALLENGE_LEN);
+ skb_put_zero(skb, WLAN_AUTH_CHALLENGE_LEN);
if (ap->crypt->encrypt_mpdu(skb, 0, ap->crypt_priv)) {
dev_kfree_skb(skb);
kfree(tmpbuf);
@@ -2364,7 +2361,7 @@ static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
return;
}
- hdr = (struct ieee80211_hdr *) skb_put(skb, 16);
+ hdr = skb_put(skb, 16);
/* Generate a fake pspoll frame to start packet delivery */
hdr->frame_control = cpu_to_le16(
diff --git a/drivers/net/wireless/intersil/hostap/hostap_hw.c b/drivers/net/wireless/intersil/hostap/hostap_hw.c
index 04dfd040..72b46ea 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_hw.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_hw.c
@@ -190,7 +190,7 @@ static inline void __hostap_cmd_queue_free(local_info_t *local,
}
}
- if (atomic_dec_and_test(&entry->usecnt) && entry->del_req)
+ if (refcount_dec_and_test(&entry->usecnt) && entry->del_req)
kfree(entry);
}
@@ -228,7 +228,7 @@ static void prism2_clear_cmd_queue(local_info_t *local)
spin_lock_irqsave(&local->cmdlock, flags);
list_for_each_safe(ptr, n, &local->cmd_queue) {
entry = list_entry(ptr, struct hostap_cmd_queue, list);
- atomic_inc(&entry->usecnt);
+ refcount_inc(&entry->usecnt);
printk(KERN_DEBUG "%s: removed pending cmd_queue entry "
"(type=%d, cmd=0x%04x, param0=0x%04x)\n",
local->dev->name, entry->type, entry->cmd,
@@ -350,7 +350,7 @@ static int hfa384x_cmd(struct net_device *dev, u16 cmd, u16 param0,
if (entry == NULL)
return -ENOMEM;
- atomic_set(&entry->usecnt, 1);
+ refcount_set(&entry->usecnt, 1);
entry->type = CMD_SLEEP;
entry->cmd = cmd;
entry->param0 = param0;
@@ -516,7 +516,7 @@ static int hfa384x_cmd_callback(struct net_device *dev, u16 cmd, u16 param0,
if (entry == NULL)
return -ENOMEM;
- atomic_set(&entry->usecnt, 1);
+ refcount_set(&entry->usecnt, 1);
entry->type = CMD_CALLBACK;
entry->cmd = cmd;
entry->param0 = param0;
@@ -666,7 +666,7 @@ static void prism2_cmd_ev(struct net_device *dev)
if (!list_empty(&local->cmd_queue)) {
entry = list_entry(local->cmd_queue.next,
struct hostap_cmd_queue, list);
- atomic_inc(&entry->usecnt);
+ refcount_inc(&entry->usecnt);
list_del_init(&entry->list);
local->cmd_queue_len--;
@@ -718,7 +718,7 @@ static void prism2_cmd_ev(struct net_device *dev)
entry = NULL;
}
if (entry)
- atomic_inc(&entry->usecnt);
+ refcount_inc(&entry->usecnt);
}
spin_unlock(&local->cmdlock);
@@ -2005,7 +2005,7 @@ static void prism2_rx(local_info_t *local)
goto rx_dropped;
}
skb->dev = dev;
- memcpy(skb_put(skb, hdr_len), &rxdesc, hdr_len);
+ skb_put_data(skb, &rxdesc, hdr_len);
if (len > 0)
res = hfa384x_from_bap(dev, BAP0, skb_put(skb, len), len);
@@ -2209,9 +2209,9 @@ static void hostap_tx_callback(local_info_t *local,
return;
}
- memcpy(skb_put(skb, hdrlen), (void *) &txdesc->frame_control, hdrlen);
+ skb_put_data(skb, (void *)&txdesc->frame_control, hdrlen);
if (payload)
- memcpy(skb_put(skb, len), payload, len);
+ skb_put_data(skb, payload, len);
skb->dev = local->dev;
skb_reset_mac_header(skb);
@@ -2362,8 +2362,7 @@ static void prism2_txexc(local_info_t *local)
struct sk_buff *skb;
skb = dev_alloc_skb(sizeof(txdesc));
if (skb) {
- memcpy(skb_put(skb, sizeof(txdesc)), &txdesc,
- sizeof(txdesc));
+ skb_put_data(skb, &txdesc, sizeof(txdesc));
skb_queue_tail(&local->sta_tx_exc_list, skb);
tasklet_schedule(&local->sta_tx_exc_tasklet);
}
@@ -2460,7 +2459,7 @@ static void prism2_info(local_info_t *local)
goto out;
}
- memcpy(skb_put(skb, sizeof(info)), &info, sizeof(info));
+ skb_put_data(skb, &info, sizeof(info));
if (left > 0 && hfa384x_from_bap(dev, BAP0, skb_put(skb, left), left))
{
spin_unlock(&local->baplock);
diff --git a/drivers/net/wireless/intersil/hostap/hostap_main.c b/drivers/net/wireless/intersil/hostap/hostap_main.c
index 1372b20..a3c066f 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_main.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_main.c
@@ -1039,15 +1039,13 @@ int prism2_sta_send_mgmt(local_info_t *local, u8 *dst, u16 stype,
if (skb == NULL)
return -ENOMEM;
- mgmt = (struct hostap_ieee80211_mgmt *)
- skb_put(skb, IEEE80211_MGMT_HDR_LEN);
- memset(mgmt, 0, IEEE80211_MGMT_HDR_LEN);
+ mgmt = skb_put_zero(skb, IEEE80211_MGMT_HDR_LEN);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
memcpy(mgmt->da, dst, ETH_ALEN);
memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
memcpy(mgmt->bssid, dst, ETH_ALEN);
if (body)
- memcpy(skb_put(skb, bodylen), body, bodylen);
+ skb_put_data(skb, body, bodylen);
meta = (struct hostap_skb_tx_data *) skb->cb;
memset(meta, 0, sizeof(*meta));
diff --git a/drivers/net/wireless/intersil/hostap/hostap_wlan.h b/drivers/net/wireless/intersil/hostap/hostap_wlan.h
index ca25283..5352adb 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/intersil/hostap/hostap_wlan.h
@@ -6,6 +6,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/mutex.h>
+#include <linux/refcount.h>
#include <net/iw_handler.h>
#include <net/ieee80211_radiotap.h>
#include <net/lib80211.h>
@@ -557,7 +558,7 @@ struct hostap_cmd_queue {
u16 resp0, res;
volatile int issued, issuing;
- atomic_t usecnt;
+ refcount_t usecnt;
int del_req;
};
diff --git a/drivers/net/wireless/intersil/orinoco/main.c b/drivers/net/wireless/intersil/orinoco/main.c
index d9128bb..28dac36 100644
--- a/drivers/net/wireless/intersil/orinoco/main.c
+++ b/drivers/net/wireless/intersil/orinoco/main.c
@@ -396,7 +396,7 @@ int orinoco_process_xmit_skb(struct sk_buff *skb,
memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
/* Make room for the new header, and copy it in */
- eh = (struct ethhdr *) skb_push(skb, ENCAPS_OVERHEAD);
+ eh = skb_push(skb, ENCAPS_OVERHEAD);
memcpy(eh, &hdr, sizeof(hdr));
}
@@ -792,7 +792,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
}
/* Copy the 802.11 header to the skb */
- memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen);
+ skb_put_data(skb, &(desc->frame_ctl), hdrlen);
skb_reset_mac_header(skb);
/* If any, copy the data from the card to the skb */
@@ -1029,11 +1029,10 @@ static void orinoco_rx(struct net_device *dev,
/* These indicate a SNAP within 802.2 LLC within
802.11 frame which we'll need to de-encapsulate to
the original EthernetII frame. */
- hdr = (struct ethhdr *)skb_push(skb,
- ETH_HLEN - ENCAPS_OVERHEAD);
+ hdr = skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD);
} else {
/* 802.3 frame - prepend 802.3 header as is */
- hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN);
+ hdr = skb_push(skb, ETH_HLEN);
hdr->h_proto = htons(length);
}
memcpy(hdr->h_dest, desc->addr1, ETH_ALEN);
diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
index 132f5fb..c84fd84 100644
--- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
@@ -64,6 +64,7 @@
#include <linux/etherdevice.h>
#include <linux/wireless.h>
#include <linux/firmware.h>
+#include <linux/refcount.h>
#include "mic.h"
#include "orinoco.h"
@@ -268,7 +269,7 @@ enum ezusb_state {
struct request_context {
struct list_head list;
- atomic_t refcount;
+ refcount_t refcount;
struct completion done; /* Signals that CTX is dead */
int killed;
struct urb *outurb; /* OUT for req pkt */
@@ -298,7 +299,7 @@ static inline u8 ezusb_reply_inc(u8 count)
static void ezusb_request_context_put(struct request_context *ctx)
{
- if (!atomic_dec_and_test(&ctx->refcount))
+ if (!refcount_dec_and_test(&ctx->refcount))
return;
WARN_ON(!ctx->done.done);
@@ -328,7 +329,7 @@ static void ezusb_request_timerfn(u_long _ctx)
} else {
ctx->state = EZUSB_CTX_RESP_TIMEOUT;
dev_dbg(&ctx->outurb->dev->dev, "couldn't unlink\n");
- atomic_inc(&ctx->refcount);
+ refcount_inc(&ctx->refcount);
ctx->killed = 1;
ezusb_ctx_complete(ctx);
ezusb_request_context_put(ctx);
@@ -361,7 +362,7 @@ static struct request_context *ezusb_alloc_ctx(struct ezusb_priv *upriv,
ctx->out_rid = out_rid;
ctx->in_rid = in_rid;
- atomic_set(&ctx->refcount, 1);
+ refcount_set(&ctx->refcount, 1);
init_completion(&ctx->done);
setup_timer(&ctx->timer, ezusb_request_timerfn, (u_long)ctx);
@@ -469,7 +470,7 @@ static void ezusb_req_queue_run(struct ezusb_priv *upriv)
list_move_tail(&ctx->list, &upriv->req_active);
if (ctx->state == EZUSB_CTX_QUEUED) {
- atomic_inc(&ctx->refcount);
+ refcount_inc(&ctx->refcount);
result = usb_submit_urb(ctx->outurb, GFP_ATOMIC);
if (result) {
ctx->state = EZUSB_CTX_REQSUBMIT_FAIL;
@@ -507,7 +508,7 @@ static void ezusb_req_enqueue_run(struct ezusb_priv *upriv,
spin_unlock_irqrestore(&upriv->req_lock, flags);
goto done;
}
- atomic_inc(&ctx->refcount);
+ refcount_inc(&ctx->refcount);
list_add_tail(&ctx->list, &upriv->req_pending);
spin_unlock_irqrestore(&upriv->req_lock, flags);
@@ -1477,7 +1478,7 @@ static inline void ezusb_delete(struct ezusb_priv *upriv)
int err;
ctx = list_entry(item, struct request_context, list);
- atomic_inc(&ctx->refcount);
+ refcount_inc(&ctx->refcount);
ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK;
err = usb_unlink_urb(ctx->outurb);
diff --git a/drivers/net/wireless/intersil/p54/fwio.c b/drivers/net/wireless/intersil/p54/fwio.c
index 4ac6764..52c095c 100644
--- a/drivers/net/wireless/intersil/p54/fwio.c
+++ b/drivers/net/wireless/intersil/p54/fwio.c
@@ -176,8 +176,9 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
* keeping a extra list for uploaded keys.
*/
- priv->used_rxkeys = kzalloc(BITS_TO_LONGS(
- priv->rx_keycache_size), GFP_KERNEL);
+ priv->used_rxkeys = kcalloc(BITS_TO_LONGS(priv->rx_keycache_size),
+ sizeof(long),
+ GFP_KERNEL);
if (!priv->used_rxkeys)
return -ENOMEM;
@@ -205,7 +206,7 @@ static struct sk_buff *p54_alloc_skb(struct p54_common *priv, u16 hdr_flags,
return NULL;
skb_reserve(skb, priv->tx_hdr_len);
- hdr = (struct p54_hdr *) skb_put(skb, sizeof(*hdr));
+ hdr = skb_put(skb, sizeof(*hdr));
hdr->flags = cpu_to_le16(hdr_flags);
hdr->len = cpu_to_le16(payload_len);
hdr->type = cpu_to_le16(type);
@@ -235,8 +236,7 @@ int p54_download_eeprom(struct p54_common *priv, void *buf,
mutex_lock(&priv->eeprom_mutex);
priv->eeprom = buf;
- eeprom_hdr = (struct p54_eeprom_lm86 *) skb_put(skb,
- eeprom_hdr_size + len);
+ eeprom_hdr = skb_put(skb, eeprom_hdr_size + len);
if (priv->fw_var < 0x509) {
eeprom_hdr->v1.offset = cpu_to_le16(offset);
@@ -272,7 +272,7 @@ int p54_update_beacon_tim(struct p54_common *priv, u16 aid, bool set)
if (unlikely(!skb))
return -ENOMEM;
- tim = (struct p54_tim *) skb_put(skb, sizeof(*tim));
+ tim = skb_put(skb, sizeof(*tim));
tim->count = 1;
tim->entry[0] = cpu_to_le16(set ? (aid | 0x8000) : aid);
p54_tx(priv, skb);
@@ -289,7 +289,7 @@ int p54_sta_unlock(struct p54_common *priv, u8 *addr)
if (unlikely(!skb))
return -ENOMEM;
- sta = (struct p54_sta_unlock *)skb_put(skb, sizeof(*sta));
+ sta = skb_put(skb, sizeof(*sta));
memcpy(sta->addr, addr, ETH_ALEN);
p54_tx(priv, skb);
return 0;
@@ -309,7 +309,7 @@ int p54_tx_cancel(struct p54_common *priv, __le32 req_id)
if (unlikely(!skb))
return -ENOMEM;
- cancel = (struct p54_txcancel *)skb_put(skb, sizeof(*cancel));
+ cancel = skb_put(skb, sizeof(*cancel));
cancel->req_id = req_id;
p54_tx(priv, skb);
return 0;
@@ -326,7 +326,7 @@ int p54_setup_mac(struct p54_common *priv)
if (!skb)
return -ENOMEM;
- setup = (struct p54_setup_mac *) skb_put(skb, sizeof(*setup));
+ setup = skb_put(skb, sizeof(*setup));
if (!(priv->hw->conf.flags & IEEE80211_CONF_IDLE)) {
switch (priv->mode) {
case NL80211_IFTYPE_STATION:
@@ -412,18 +412,18 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
if (!skb)
return -ENOMEM;
- head = (struct p54_scan_head *) skb_put(skb, sizeof(*head));
+ head = skb_put(skb, sizeof(*head));
memset(head->scan_params, 0, sizeof(head->scan_params));
head->mode = cpu_to_le16(mode);
head->dwell = cpu_to_le16(dwell);
head->freq = freq;
if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
- __le16 *pa_power_points = (__le16 *) skb_put(skb, 2);
+ __le16 *pa_power_points = skb_put(skb, 2);
*pa_power_points = cpu_to_le16(0x0c);
}
- iq_autocal = (void *) skb_put(skb, sizeof(*iq_autocal));
+ iq_autocal = skb_put(skb, sizeof(*iq_autocal));
for (i = 0; i < priv->iq_autocal_len; i++) {
if (priv->iq_autocal[i].freq != freq)
continue;
@@ -436,9 +436,9 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
goto err;
if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW)
- body = (void *) skb_put(skb, sizeof(body->longbow));
+ body = skb_put(skb, sizeof(body->longbow));
else
- body = (void *) skb_put(skb, sizeof(body->normal));
+ body = skb_put(skb, sizeof(body->normal));
for (i = 0; i < priv->output_limit->entries; i++) {
__le16 *entry_freq = (void *) (priv->output_limit->data +
@@ -499,25 +499,25 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
goto err;
if ((priv->fw_var >= 0x500) && (priv->fw_var < 0x509)) {
- rate = (void *) skb_put(skb, sizeof(*rate));
+ rate = skb_put(skb, sizeof(*rate));
rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
for (i = 0; i < sizeof(rate->rts_rates); i++)
rate->rts_rates[i] = i;
}
- rssi = (struct pda_rssi_cal_entry *) skb_put(skb, sizeof(*rssi));
+ rssi = skb_put(skb, sizeof(*rssi));
rssi_data = p54_rssi_find(priv, le16_to_cpu(freq));
rssi->mul = cpu_to_le16(rssi_data->mul);
rssi->add = cpu_to_le16(rssi_data->add);
if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
/* Longbow frontend needs ever more */
- rssi = (void *) skb_put(skb, sizeof(*rssi));
+ rssi = skb_put(skb, sizeof(*rssi));
rssi->mul = cpu_to_le16(rssi_data->longbow_unkn);
rssi->add = cpu_to_le16(rssi_data->longbow_unk2);
}
if (priv->fw_var >= 0x509) {
- rate = (void *) skb_put(skb, sizeof(*rate));
+ rate = skb_put(skb, sizeof(*rate));
rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
for (i = 0; i < sizeof(rate->rts_rates); i++)
rate->rts_rates[i] = i;
@@ -549,7 +549,7 @@ int p54_set_leds(struct p54_common *priv)
if (unlikely(!skb))
return -ENOMEM;
- led = (struct p54_led *) skb_put(skb, sizeof(*led));
+ led = skb_put(skb, sizeof(*led));
led->flags = cpu_to_le16(0x0003);
led->mask[0] = led->mask[1] = cpu_to_le16(priv->softled_state);
led->delay[0] = cpu_to_le16(1);
@@ -569,7 +569,7 @@ int p54_set_edcf(struct p54_common *priv)
if (unlikely(!skb))
return -ENOMEM;
- edcf = (struct p54_edcf *)skb_put(skb, sizeof(*edcf));
+ edcf = skb_put(skb, sizeof(*edcf));
if (priv->use_short_slot) {
edcf->slottime = 9;
edcf->sifs = 0x10;
@@ -614,7 +614,7 @@ int p54_set_ps(struct p54_common *priv)
if (!skb)
return -ENOMEM;
- psm = (struct p54_psm *)skb_put(skb, sizeof(*psm));
+ psm = skb_put(skb, sizeof(*psm));
psm->mode = cpu_to_le16(mode);
psm->aid = cpu_to_le16(priv->aid);
for (i = 0; i < ARRAY_SIZE(psm->intervals); i++) {
@@ -643,7 +643,7 @@ int p54_init_xbow_synth(struct p54_common *priv)
if (unlikely(!skb))
return -ENOMEM;
- xbow = (struct p54_xbow_synth *)skb_put(skb, sizeof(*xbow));
+ xbow = skb_put(skb, sizeof(*xbow));
xbow->magic1 = cpu_to_le16(0x1);
xbow->magic2 = cpu_to_le16(0x2);
xbow->freq = cpu_to_le16(5390);
@@ -663,7 +663,7 @@ int p54_upload_key(struct p54_common *priv, u8 algo, int slot, u8 idx, u8 len,
if (unlikely(!skb))
return -ENOMEM;
- rxkey = (struct p54_keycache *)skb_put(skb, sizeof(*rxkey));
+ rxkey = skb_put(skb, sizeof(*rxkey));
rxkey->entry = slot;
rxkey->key_id = idx;
rxkey->key_type = algo;
@@ -743,7 +743,7 @@ int p54_set_groupfilter(struct p54_common *priv)
if (!skb)
return -ENOMEM;
- grp = (struct p54_group_address_table *)skb_put(skb, sizeof(*grp));
+ grp = skb_put(skb, sizeof(*grp));
on = !(priv->filter_flags & FIF_ALLMULTI) &&
(priv->mc_maclist_num > 0 &&
diff --git a/drivers/net/wireless/intersil/p54/p54spi.c b/drivers/net/wireless/intersil/p54/p54spi.c
index 7ab2f43..e41bf04 100644
--- a/drivers/net/wireless/intersil/p54/p54spi.c
+++ b/drivers/net/wireless/intersil/p54/p54spi.c
@@ -372,9 +372,9 @@ static int p54spi_rx(struct p54s_priv *priv)
}
if (len <= READAHEAD_SZ) {
- memcpy(skb_put(skb, len), rx_head + 1, len);
+ skb_put_data(skb, rx_head + 1, len);
} else {
- memcpy(skb_put(skb, READAHEAD_SZ), rx_head + 1, READAHEAD_SZ);
+ skb_put_data(skb, rx_head + 1, READAHEAD_SZ);
p54spi_spi_read(priv, SPI_ADRS_DMA_DATA,
skb_put(skb, len - READAHEAD_SZ),
len - READAHEAD_SZ);
diff --git a/drivers/net/wireless/intersil/p54/txrx.c b/drivers/net/wireless/intersil/p54/txrx.c
index 5e1c91a..3a4214d 100644
--- a/drivers/net/wireless/intersil/p54/txrx.c
+++ b/drivers/net/wireless/intersil/p54/txrx.c
@@ -815,8 +815,8 @@ void p54_tx_80211(struct ieee80211_hw *dev,
}
}
- txhdr = (struct p54_tx_data *) skb_push(skb, sizeof(*txhdr) + padding);
- hdr = (struct p54_hdr *) skb_push(skb, sizeof(*hdr));
+ txhdr = skb_push(skb, sizeof(*txhdr) + padding);
+ hdr = skb_push(skb, sizeof(*hdr));
if (padding)
hdr_flags |= P54_HDR_FLAG_DATA_ALIGN;
@@ -905,13 +905,13 @@ void p54_tx_80211(struct ieee80211_hw *dev,
if (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
/* reserve space for the MIC key */
len += 8;
- memcpy(skb_put(skb, 8), &(info->control.hw_key->key
- [NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY]), 8);
+ skb_put_data(skb,
+ &(info->control.hw_key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY]),
+ 8);
}
/* reserve some space for ICV */
len += info->control.hw_key->icv_len;
- memset(skb_put(skb, info->control.hw_key->icv_len), 0,
- info->control.hw_key->icv_len);
+ skb_put_zero(skb, info->control.hw_key->icv_len);
} else {
txhdr->key_type = 0;
txhdr->key_len = 0;
diff --git a/drivers/net/wireless/intersil/prism54/islpci_eth.c b/drivers/net/wireless/intersil/prism54/islpci_eth.c
index d83f633..9b0ded7 100644
--- a/drivers/net/wireless/intersil/prism54/islpci_eth.c
+++ b/drivers/net/wireless/intersil/prism54/islpci_eth.c
@@ -276,10 +276,7 @@ islpci_monitor_rx(islpci_private *priv, struct sk_buff **skb)
}
/* make room for the new header and fill it. */
- avs =
- (struct avs_80211_1_header *) skb_push(*skb,
- sizeof (struct
- avs_80211_1_header));
+ avs = skb_push(*skb, sizeof(struct avs_80211_1_header));
avs->version = cpu_to_be32(P80211CAPTURE_VERSION);
avs->length = cpu_to_be32(sizeof (struct avs_80211_1_header));
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index c854a55..c8852ac 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -650,7 +650,7 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
skb = dev_alloc_skb(sizeof(*pspoll));
if (!skb)
return;
- pspoll = (void *) skb_put(skb, sizeof(*pspoll));
+ pspoll = skb_put(skb, sizeof(*pspoll));
pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
IEEE80211_STYPE_PSPOLL |
IEEE80211_FCTL_PM);
@@ -681,7 +681,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
skb = dev_alloc_skb(sizeof(*hdr));
if (!skb)
return;
- hdr = (void *) skb_put(skb, sizeof(*hdr) - ETH_ALEN);
+ hdr = skb_put(skb, sizeof(*hdr) - ETH_ALEN);
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
IEEE80211_STYPE_NULLFUNC |
(ps ? IEEE80211_FCTL_PM : 0));
@@ -848,7 +848,7 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
if (skb == NULL)
return;
- hdr = (struct hwsim_radiotap_hdr *) skb_push(skb, sizeof(*hdr));
+ hdr = skb_push(skb, sizeof(*hdr));
hdr->hdr.it_version = PKTHDR_RADIOTAP_VERSION;
hdr->hdr.it_pad = 0;
hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr));
@@ -892,7 +892,7 @@ static void mac80211_hwsim_monitor_ack(struct ieee80211_channel *chan,
if (skb == NULL)
return;
- hdr = (struct hwsim_radiotap_ack_hdr *) skb_put(skb, sizeof(*hdr));
+ hdr = skb_put(skb, sizeof(*hdr));
hdr->hdr.it_version = PKTHDR_RADIOTAP_VERSION;
hdr->hdr.it_pad = 0;
hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr));
@@ -904,7 +904,7 @@ static void mac80211_hwsim_monitor_ack(struct ieee80211_channel *chan,
flags = IEEE80211_CHAN_2GHZ;
hdr->rt_chbitmask = cpu_to_le16(flags);
- hdr11 = (struct ieee80211_hdr *) skb_put(skb, 10);
+ hdr11 = skb_put(skb, 10);
hdr11->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
IEEE80211_STYPE_ACK);
hdr11->duration_id = cpu_to_le16(0);
@@ -1146,7 +1146,7 @@ static void mac80211_hwsim_add_vendor_rtap(struct sk_buff *skb)
* Note that this code requires the headroom in the SKB
* that was allocated earlier.
*/
- rtap = (void *)skb_push(skb, sizeof(*rtap) + 8 + 4);
+ rtap = skb_push(skb, sizeof(*rtap) + 8 + 4);
rtap->oui[0] = HWSIM_RADIOTAP_OUI[0];
rtap->oui[1] = HWSIM_RADIOTAP_OUI[1];
rtap->oui[2] = HWSIM_RADIOTAP_OUI[2];
@@ -2020,8 +2020,7 @@ static void hw_scan_work(struct work_struct *work)
memcpy(mgmt->bssid, req->bssid, ETH_ALEN);
if (req->ie_len)
- memcpy(skb_put(probe, req->ie_len), req->ie,
- req->ie_len);
+ skb_put_data(probe, req->ie, req->ie_len);
local_bh_disable();
mac80211_hwsim_tx_frame(hwsim->hw, probe,
@@ -3021,7 +3020,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
goto err;
/* Copy the data */
- memcpy(skb_put(skb, frame_data_len), frame_data, frame_data_len);
+ skb_put_data(skb, frame_data, frame_data_len);
data2 = get_hwsim_data_ref_from_addr(dst);
if (!data2)
diff --git a/drivers/net/wireless/marvell/libertas/cfg.c b/drivers/net/wireless/marvell/libertas/cfg.c
index a0463fe..71ba2c8 100644
--- a/drivers/net/wireless/marvell/libertas/cfg.c
+++ b/drivers/net/wireless/marvell/libertas/cfg.c
@@ -443,17 +443,12 @@ static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy,
struct lbs_private *priv = wiphy_priv(wiphy);
int ret = -ENOTSUPP;
- lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d",
- chandef->chan->center_freq,
- cfg80211_get_chandef_type(chandef));
-
if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT)
goto out;
ret = lbs_set_channel(priv, chandef->chan->hw_value);
out:
- lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ret;
}
@@ -464,16 +459,12 @@ static int lbs_cfg_set_mesh_channel(struct wiphy *wiphy,
struct lbs_private *priv = wiphy_priv(wiphy);
int ret = -ENOTSUPP;
- lbs_deb_enter_args(LBS_DEB_CFG80211, "iface %s freq %d",
- netdev_name(netdev), channel->center_freq);
-
if (netdev != priv->mesh_dev)
goto out;
ret = lbs_mesh_set_channel(priv, channel->hw_value);
out:
- lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ret;
}
@@ -512,8 +503,6 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
int i;
int ret = -EILSEQ;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
bsssize = get_unaligned_le16(&scanresp->bssdescriptsize);
lbs_deb_scan("scan response: %d BSSs (%d bytes); resp size %d bytes\n",
@@ -665,7 +654,6 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
ret = 0;
done:
- lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
return ret;
}
@@ -693,11 +681,9 @@ static void lbs_scan_worker(struct work_struct *work)
int last_channel;
int running, carrier;
- lbs_deb_enter(LBS_DEB_SCAN);
-
scan_cmd = kzalloc(LBS_SCAN_MAX_CMD_SIZE, GFP_KERNEL);
if (scan_cmd == NULL)
- goto out_no_scan_cmd;
+ return;
/* prepare fixed part of scan command */
scan_cmd->bsstype = CMD_BSS_TYPE_ANY;
@@ -766,16 +752,11 @@ static void lbs_scan_worker(struct work_struct *work)
lbs_deb_scan("scan: waking up waiters\n");
wake_up_all(&priv->scan_q);
}
-
- out_no_scan_cmd:
- lbs_deb_leave(LBS_DEB_SCAN);
}
static void _internal_start_scan(struct lbs_private *priv, bool internal,
struct cfg80211_scan_request *request)
{
- lbs_deb_enter(LBS_DEB_CFG80211);
-
lbs_deb_scan("scan: ssids %d, channels %d, ie_len %zd\n",
request->n_ssids, request->n_channels, request->ie_len);
@@ -785,8 +766,6 @@ static void _internal_start_scan(struct lbs_private *priv, bool internal,
queue_delayed_work(priv->work_thread, &priv->scan_work,
msecs_to_jiffies(50));
-
- lbs_deb_leave(LBS_DEB_CFG80211);
}
/*
@@ -815,8 +794,6 @@ static int lbs_cfg_scan(struct wiphy *wiphy,
struct lbs_private *priv = wiphy_priv(wiphy);
int ret = 0;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
if (priv->scan_req || delayed_work_pending(&priv->scan_work)) {
/* old scan request not yet processed */
ret = -EAGAIN;
@@ -829,7 +806,6 @@ static int lbs_cfg_scan(struct wiphy *wiphy,
ret = -EIO;
out:
- lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ret;
}
@@ -843,18 +819,12 @@ static int lbs_cfg_scan(struct wiphy *wiphy,
void lbs_send_disconnect_notification(struct lbs_private *priv,
bool locally_generated)
{
- lbs_deb_enter(LBS_DEB_CFG80211);
-
cfg80211_disconnected(priv->dev, 0, NULL, 0, locally_generated,
GFP_KERNEL);
-
- lbs_deb_leave(LBS_DEB_CFG80211);
}
void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event)
{
- lbs_deb_enter(LBS_DEB_CFG80211);
-
cfg80211_michael_mic_failure(priv->dev,
priv->assoc_bss,
event == MACREG_INT_CODE_MIC_ERR_MULTICAST ?
@@ -863,8 +833,6 @@ void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event)
-1,
NULL,
GFP_KERNEL);
-
- lbs_deb_leave(LBS_DEB_CFG80211);
}
@@ -883,8 +851,6 @@ static int lbs_remove_wep_keys(struct lbs_private *priv)
struct cmd_ds_802_11_set_wep cmd;
int ret;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.keyindex = cpu_to_le16(priv->wep_tx_key);
@@ -892,7 +858,6 @@ static int lbs_remove_wep_keys(struct lbs_private *priv)
ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
- lbs_deb_leave(LBS_DEB_CFG80211);
return ret;
}
@@ -905,8 +870,6 @@ static int lbs_set_wep_keys(struct lbs_private *priv)
int i;
int ret;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
/*
* command 13 00
* size 50 00
@@ -956,7 +919,6 @@ static int lbs_set_wep_keys(struct lbs_private *priv)
ret = lbs_remove_wep_keys(priv);
}
- lbs_deb_leave(LBS_DEB_CFG80211);
return ret;
}
@@ -969,8 +931,6 @@ static int lbs_enable_rsn(struct lbs_private *priv, int enable)
struct cmd_ds_802_11_enable_rsn cmd;
int ret;
- lbs_deb_enter_args(LBS_DEB_CFG80211, "%d", enable);
-
/*
* cmd 2f 00
* size 0c 00
@@ -986,7 +946,6 @@ static int lbs_enable_rsn(struct lbs_private *priv, int enable)
ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
- lbs_deb_leave(LBS_DEB_CFG80211);
return ret;
}
@@ -1014,8 +973,6 @@ static int lbs_set_key_material(struct lbs_private *priv,
struct cmd_key_material cmd;
int ret;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
/*
* Example for WPA (TKIP):
*
@@ -1044,7 +1001,6 @@ static int lbs_set_key_material(struct lbs_private *priv,
ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
- lbs_deb_leave(LBS_DEB_CFG80211);
return ret;
}
@@ -1061,8 +1017,6 @@ static int lbs_set_authtype(struct lbs_private *priv,
struct cmd_ds_802_11_authenticate cmd;
int ret;
- lbs_deb_enter_args(LBS_DEB_CFG80211, "%d", sme->auth_type);
-
/*
* cmd 11 00
* size 19 00
@@ -1085,7 +1039,6 @@ static int lbs_set_authtype(struct lbs_private *priv,
ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd);
done:
- lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ret;
}
@@ -1116,8 +1069,6 @@ static int lbs_associate(struct lbs_private *priv,
u8 *pos;
u8 *tmp;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
if (!cmd) {
ret = -ENOMEM;
goto done;
@@ -1262,7 +1213,6 @@ static int lbs_associate(struct lbs_private *priv,
kfree(cmd);
done:
- lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ret;
}
@@ -1329,8 +1279,6 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
if (dev == priv->mesh_dev)
return -EOPNOTSUPP;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
if (!sme->bssid) {
struct cfg80211_scan_request *creq;
@@ -1442,7 +1390,6 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
done:
if (bss)
cfg80211_put_bss(wiphy, bss);
- lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ret;
}
@@ -1478,8 +1425,6 @@ static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
if (dev == priv->mesh_dev)
return -EOPNOTSUPP;
- lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code);
-
/* store for lbs_cfg_ret_disconnect() */
priv->disassoc_reason = reason_code;
@@ -1496,8 +1441,6 @@ static int lbs_cfg_set_default_key(struct wiphy *wiphy,
if (netdev == priv->mesh_dev)
return -EOPNOTSUPP;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
if (key_index != priv->wep_tx_key) {
lbs_deb_assoc("set_default_key: to %d\n", key_index);
priv->wep_tx_key = key_index;
@@ -1520,8 +1463,6 @@ static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev,
if (netdev == priv->mesh_dev)
return -EOPNOTSUPP;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
lbs_deb_assoc("add_key: cipher 0x%x, mac_addr %pM\n",
params->cipher, mac_addr);
lbs_deb_assoc("add_key: key index %d, key len %d\n",
@@ -1575,8 +1516,6 @@ static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev,
u8 key_index, bool pairwise, const u8 *mac_addr)
{
- lbs_deb_enter(LBS_DEB_CFG80211);
-
lbs_deb_assoc("del_key: key_idx %d, mac_addr %pM\n",
key_index, mac_addr);
@@ -1619,8 +1558,6 @@ static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev,
int ret;
size_t i;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES) |
BIT(NL80211_STA_INFO_TX_PACKETS) |
BIT(NL80211_STA_INFO_RX_BYTES) |
@@ -1675,15 +1612,12 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev,
return -EOPNOTSUPP;
}
- lbs_deb_enter(LBS_DEB_CFG80211);
-
if (priv->iface_running)
ret = lbs_set_iface_type(priv, type);
if (!ret)
priv->wdev->iftype = type;
- lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ret;
}
@@ -1713,8 +1647,6 @@ static void lbs_join_post(struct lbs_private *priv,
u8 *fake = fake_ie;
struct cfg80211_bss *bss;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
/*
* For cfg80211_inform_bss, we'll need a fake IE, as we can't get
* the real IE from the firmware. So we fabricate a fake IE based on
@@ -1777,8 +1709,6 @@ static void lbs_join_post(struct lbs_private *priv,
netif_carrier_on(priv->dev);
if (!priv->tx_pending_len)
netif_wake_queue(priv->dev);
-
- lbs_deb_leave(LBS_DEB_CFG80211);
}
static int lbs_ibss_join_existing(struct lbs_private *priv,
@@ -1790,8 +1720,6 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
u8 preamble = RADIO_PREAMBLE_SHORT;
int ret = 0;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
/* TODO: set preamble based on scan result */
ret = lbs_set_radio(priv, preamble, 1);
if (ret)
@@ -1888,7 +1816,6 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
lbs_join_post(priv, params, bss->bssid, bss->capability);
out:
- lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ret;
}
@@ -1904,8 +1831,6 @@ static int lbs_ibss_start_new(struct lbs_private *priv,
int ret = 0;
u16 capability;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
ret = lbs_set_radio(priv, preamble, 1);
if (ret)
goto out;
@@ -1975,7 +1900,6 @@ static int lbs_ibss_start_new(struct lbs_private *priv,
lbs_join_post(priv, params, resp->bssid, capability);
out:
- lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ret;
}
@@ -1990,8 +1914,6 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
if (dev == priv->mesh_dev)
return -EOPNOTSUPP;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
if (!params->chandef.chan) {
ret = -ENOTSUPP;
goto out;
@@ -2015,7 +1937,6 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
out:
- lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ret;
}
@@ -2029,8 +1950,6 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
if (dev == priv->mesh_dev)
return -EOPNOTSUPP;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd);
@@ -2038,7 +1957,6 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
/* TODO: consider doing this at MACREG_INT_CODE_ADHOC_BCN_LOST time */
lbs_mac_event_disconnected(priv, true);
- lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ret;
}
@@ -2114,8 +2032,6 @@ struct wireless_dev *lbs_cfg_alloc(struct device *dev)
int ret = 0;
struct wireless_dev *wdev;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
if (!wdev)
return ERR_PTR(-ENOMEM);
@@ -2127,12 +2043,10 @@ struct wireless_dev *lbs_cfg_alloc(struct device *dev)
goto err_wiphy_new;
}
- lbs_deb_leave(LBS_DEB_CFG80211);
return wdev;
err_wiphy_new:
kfree(wdev);
- lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ERR_PTR(ret);
}
@@ -2155,15 +2069,11 @@ static void lbs_cfg_set_regulatory_hint(struct lbs_private *priv)
};
size_t i;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
for (i = 0; i < ARRAY_SIZE(regmap); i++)
if (regmap[i].code == priv->regioncode) {
regulatory_hint(priv->wdev->wiphy, regmap[i].cn);
break;
}
-
- lbs_deb_leave(LBS_DEB_CFG80211);
}
static void lbs_reg_notifier(struct wiphy *wiphy,
@@ -2171,15 +2081,9 @@ static void lbs_reg_notifier(struct wiphy *wiphy,
{
struct lbs_private *priv = wiphy_priv(wiphy);
- lbs_deb_enter_args(LBS_DEB_CFG80211, "cfg80211 regulatory domain "
- "callback for domain %c%c\n", request->alpha2[0],
- request->alpha2[1]);
-
memcpy(priv->country_code, request->alpha2, sizeof(request->alpha2));
if (lbs_iface_active(priv))
lbs_set_11d_domain_info(priv);
-
- lbs_deb_leave(LBS_DEB_CFG80211);
}
/*
@@ -2192,8 +2096,6 @@ int lbs_cfg_register(struct lbs_private *priv)
struct wireless_dev *wdev = priv->wdev;
int ret;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
wdev->wiphy->max_scan_ssids = 1;
wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
@@ -2229,13 +2131,11 @@ int lbs_cfg_register(struct lbs_private *priv)
lbs_cfg_set_regulatory_hint(priv);
- lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ret;
}
void lbs_scan_deinit(struct lbs_private *priv)
{
- lbs_deb_enter(LBS_DEB_CFG80211);
cancel_delayed_work_sync(&priv->scan_work);
}
@@ -2244,8 +2144,6 @@ void lbs_cfg_free(struct lbs_private *priv)
{
struct wireless_dev *wdev = priv->wdev;
- lbs_deb_enter(LBS_DEB_CFG80211);
-
if (!wdev)
return;
diff --git a/drivers/net/wireless/marvell/libertas/cmd.c b/drivers/net/wireless/marvell/libertas/cmd.c
index 033ff88..c1f4229 100644
--- a/drivers/net/wireless/marvell/libertas/cmd.c
+++ b/drivers/net/wireless/marvell/libertas/cmd.c
@@ -91,8 +91,6 @@ int lbs_update_hw_spec(struct lbs_private *priv)
int ret = -1;
u32 i;
- lbs_deb_enter(LBS_DEB_CMD);
-
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
@@ -159,14 +157,12 @@ int lbs_update_hw_spec(struct lbs_private *priv)
}
out:
- lbs_deb_leave(LBS_DEB_CMD);
return ret;
}
static int lbs_ret_host_sleep_cfg(struct lbs_private *priv, unsigned long dummy,
struct cmd_header *resp)
{
- lbs_deb_enter(LBS_DEB_CMD);
if (priv->is_host_sleep_activated) {
priv->is_host_sleep_configured = 0;
if (priv->psstate == PS_STATE_FULL_POWER) {
@@ -176,7 +172,7 @@ static int lbs_ret_host_sleep_cfg(struct lbs_private *priv, unsigned long dummy,
} else {
priv->is_host_sleep_configured = 1;
}
- lbs_deb_leave(LBS_DEB_CMD);
+
return 0;
}
@@ -236,8 +232,6 @@ int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block)
struct cmd_ds_802_11_ps_mode cmd;
int ret = 0;
- lbs_deb_enter(LBS_DEB_CMD);
-
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(cmd_action);
@@ -262,7 +256,6 @@ int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block)
lbs_cmd_async(priv, CMD_802_11_PS_MODE, &cmd.hdr, sizeof (cmd));
out:
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -272,8 +265,6 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
struct cmd_ds_802_11_sleep_params cmd;
int ret;
- lbs_deb_enter(LBS_DEB_CMD);
-
if (cmd_action == CMD_ACT_GET) {
memset(&cmd, 0, sizeof(cmd));
} else {
@@ -304,7 +295,6 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
sp->sp_reserved = le16_to_cpu(cmd.reserved);
}
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -312,8 +302,6 @@ static int lbs_wait_for_ds_awake(struct lbs_private *priv)
{
int ret = 0;
- lbs_deb_enter(LBS_DEB_CMD);
-
if (priv->is_deep_sleep) {
if (!wait_event_interruptible_timeout(priv->ds_awake_q,
!priv->is_deep_sleep, (10 * HZ))) {
@@ -322,7 +310,6 @@ static int lbs_wait_for_ds_awake(struct lbs_private *priv)
}
}
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -330,8 +317,6 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
{
int ret = 0;
- lbs_deb_enter(LBS_DEB_CMD);
-
if (deep_sleep) {
if (priv->is_deep_sleep != 1) {
lbs_deb_cmd("deep sleep: sleep\n");
@@ -358,7 +343,6 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
}
}
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -366,10 +350,9 @@ static int lbs_ret_host_sleep_activate(struct lbs_private *priv,
unsigned long dummy,
struct cmd_header *cmd)
{
- lbs_deb_enter(LBS_DEB_FW);
priv->is_host_sleep_activated = 1;
wake_up_interruptible(&priv->host_sleep_q);
- lbs_deb_leave(LBS_DEB_FW);
+
return 0;
}
@@ -379,8 +362,6 @@ int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep)
int ret = 0;
uint32_t criteria = EHS_REMOVE_WAKEUP;
- lbs_deb_enter(LBS_DEB_CMD);
-
if (host_sleep) {
if (priv->is_host_sleep_activated != 1) {
memset(&cmd, 0, sizeof(cmd));
@@ -438,8 +419,6 @@ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val)
struct cmd_ds_802_11_snmp_mib cmd;
int ret;
- lbs_deb_enter(LBS_DEB_CMD);
-
memset(&cmd, 0, sizeof (cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_SET);
@@ -470,7 +449,6 @@ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val)
ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
out:
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -488,8 +466,6 @@ int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)
struct cmd_ds_802_11_snmp_mib cmd;
int ret;
- lbs_deb_enter(LBS_DEB_CMD);
-
memset(&cmd, 0, sizeof (cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_GET);
@@ -513,7 +489,6 @@ int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)
}
out:
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -533,8 +508,6 @@ int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
struct cmd_ds_802_11_rf_tx_power cmd;
int ret;
- lbs_deb_enter(LBS_DEB_CMD);
-
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_GET);
@@ -548,7 +521,6 @@ int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
*maxlevel = cmd.maxlevel;
}
- lbs_deb_leave(LBS_DEB_CMD);
return ret;
}
@@ -565,8 +537,6 @@ int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)
struct cmd_ds_802_11_rf_tx_power cmd;
int ret;
- lbs_deb_enter(LBS_DEB_CMD);
-
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_SET);
@@ -576,7 +546,6 @@ int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)
ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
- lbs_deb_leave(LBS_DEB_CMD);
return ret;
}
@@ -608,7 +577,6 @@ int lbs_set_monitor_mode(struct lbs_private *priv, int enable)
ARPHRD_ETHER;
}
- lbs_deb_leave(LBS_DEB_CMD);
return ret;
}
@@ -624,8 +592,6 @@ static int lbs_get_channel(struct lbs_private *priv)
struct cmd_ds_802_11_rf_channel cmd;
int ret = 0;
- lbs_deb_enter(LBS_DEB_CMD);
-
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET);
@@ -638,7 +604,6 @@ static int lbs_get_channel(struct lbs_private *priv)
lbs_deb_cmd("current radio channel is %d\n", ret);
out:
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -647,14 +612,12 @@ int lbs_update_channel(struct lbs_private *priv)
int ret;
/* the channel in f/w could be out of sync; get the current channel */
- lbs_deb_enter(LBS_DEB_ASSOC);
-
ret = lbs_get_channel(priv);
if (ret > 0) {
priv->channel = ret;
ret = 0;
}
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+
return ret;
}
@@ -674,8 +637,6 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel)
#endif
int ret = 0;
- lbs_deb_enter(LBS_DEB_CMD);
-
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
@@ -690,7 +651,6 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel)
priv->channel);
out:
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -708,8 +668,6 @@ int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf)
struct cmd_ds_802_11_rssi cmd;
int ret = 0;
- lbs_deb_enter(LBS_DEB_CMD);
-
BUG_ON(rssi == NULL);
BUG_ON(nf == NULL);
@@ -724,7 +682,6 @@ int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf)
*rssi = CAL_RSSI(le16_to_cpu(cmd.n_or_snr), le16_to_cpu(cmd.nf));
}
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -752,7 +709,6 @@ int lbs_set_11d_domain_info(struct lbs_private *priv)
size_t triplet_size;
int ret = 0;
- lbs_deb_enter(LBS_DEB_11D);
if (!priv->country_code[0])
goto out;
@@ -849,7 +805,6 @@ int lbs_set_11d_domain_info(struct lbs_private *priv)
ret = lbs_cmd_with_response(priv, CMD_802_11D_DOMAIN_INFO, &cmd);
out:
- lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
return ret;
}
@@ -869,8 +824,6 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)
struct cmd_ds_reg_access cmd;
int ret = 0;
- lbs_deb_enter(LBS_DEB_CMD);
-
BUG_ON(value == NULL);
memset(&cmd, 0, sizeof(cmd));
@@ -894,7 +847,6 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)
}
out:
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -914,8 +866,6 @@ int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value)
struct cmd_ds_reg_access cmd;
int ret = 0;
- lbs_deb_enter(LBS_DEB_CMD);
-
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_SET);
@@ -933,7 +883,6 @@ int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value)
ret = lbs_cmd_with_response(priv, reg, &cmd);
out:
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -943,15 +892,13 @@ static void lbs_queue_cmd(struct lbs_private *priv,
unsigned long flags;
int addtail = 1;
- lbs_deb_enter(LBS_DEB_HOST);
-
if (!cmdnode) {
lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n");
- goto done;
+ return;
}
if (!cmdnode->cmdbuf->size) {
lbs_deb_host("DNLD_CMD: cmd size is zero\n");
- goto done;
+ return;
}
cmdnode->result = 0;
@@ -979,9 +926,6 @@ static void lbs_queue_cmd(struct lbs_private *priv,
lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
le16_to_cpu(cmdnode->cmdbuf->command));
-
-done:
- lbs_deb_leave(LBS_DEB_HOST);
}
static void lbs_submit_command(struct lbs_private *priv,
@@ -994,8 +938,6 @@ static void lbs_submit_command(struct lbs_private *priv,
int timeo = 3 * HZ;
int ret;
- lbs_deb_enter(LBS_DEB_HOST);
-
cmd = cmdnode->cmdbuf;
spin_lock_irqsave(&priv->driver_lock, flags);
@@ -1036,8 +978,6 @@ static void lbs_submit_command(struct lbs_private *priv,
/* Setup the timer after transmit command */
mod_timer(&priv->command_timer, jiffies + timeo);
}
-
- lbs_deb_leave(LBS_DEB_HOST);
}
/*
@@ -1047,10 +987,8 @@ static void lbs_submit_command(struct lbs_private *priv,
static void __lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
struct cmd_ctrl_node *cmdnode)
{
- lbs_deb_enter(LBS_DEB_HOST);
-
if (!cmdnode)
- goto out;
+ return;
cmdnode->callback = NULL;
cmdnode->callback_arg = 0;
@@ -1058,8 +996,6 @@ static void __lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
list_add_tail(&cmdnode->list, &priv->cmdfreeq);
- out:
- lbs_deb_leave(LBS_DEB_HOST);
}
static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
@@ -1107,8 +1043,6 @@ int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
struct cmd_ds_802_11_radio_control cmd;
int ret = -EINVAL;
- lbs_deb_enter(LBS_DEB_CMD);
-
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_SET);
cmd.control = 0;
@@ -1141,7 +1075,6 @@ int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
out:
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -1149,15 +1082,11 @@ void lbs_set_mac_control(struct lbs_private *priv)
{
struct cmd_ds_mac_control cmd;
- lbs_deb_enter(LBS_DEB_CMD);
-
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(priv->mac_control);
cmd.reserved = 0;
lbs_cmd_async(priv, CMD_MAC_CONTROL, &cmd.hdr, sizeof(cmd));
-
- lbs_deb_leave(LBS_DEB_CMD);
}
int lbs_set_mac_control_sync(struct lbs_private *priv)
@@ -1165,14 +1094,11 @@ int lbs_set_mac_control_sync(struct lbs_private *priv)
struct cmd_ds_mac_control cmd;
int ret = 0;
- lbs_deb_enter(LBS_DEB_CMD);
-
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(priv->mac_control);
cmd.reserved = 0;
ret = lbs_cmd_with_response(priv, CMD_MAC_CONTROL, &cmd);
- lbs_deb_leave(LBS_DEB_CMD);
return ret;
}
@@ -1191,8 +1117,6 @@ int lbs_allocate_cmd_buffer(struct lbs_private *priv)
u32 i;
struct cmd_ctrl_node *cmdarray;
- lbs_deb_enter(LBS_DEB_HOST);
-
/* Allocate and initialize the command array */
bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
if (!(cmdarray = kzalloc(bufsize, GFP_KERNEL))) {
@@ -1219,7 +1143,6 @@ int lbs_allocate_cmd_buffer(struct lbs_private *priv)
ret = 0;
done:
- lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
return ret;
}
@@ -1235,8 +1158,6 @@ int lbs_free_cmd_buffer(struct lbs_private *priv)
struct cmd_ctrl_node *cmdarray;
unsigned int i;
- lbs_deb_enter(LBS_DEB_HOST);
-
/* need to check if cmd array is allocated or not */
if (priv->cmd_array == NULL) {
lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
@@ -1260,7 +1181,6 @@ int lbs_free_cmd_buffer(struct lbs_private *priv)
}
done:
- lbs_deb_leave(LBS_DEB_HOST);
return 0;
}
@@ -1278,8 +1198,6 @@ static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv)
struct cmd_ctrl_node *tempnode;
unsigned long flags;
- lbs_deb_enter(LBS_DEB_HOST);
-
if (!priv)
return NULL;
@@ -1296,7 +1214,6 @@ static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv)
spin_unlock_irqrestore(&priv->driver_lock, flags);
- lbs_deb_leave(LBS_DEB_HOST);
return tempnode;
}
@@ -1318,8 +1235,6 @@ int lbs_execute_next_command(struct lbs_private *priv)
/* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
* only caller to us is lbs_thread() and we get even when a
* data packet is received */
- lbs_deb_enter(LBS_DEB_THREAD);
-
spin_lock_irqsave(&priv->driver_lock, flags);
if (priv->cur_cmd) {
@@ -1440,7 +1355,6 @@ int lbs_execute_next_command(struct lbs_private *priv)
ret = 0;
done:
- lbs_deb_leave(LBS_DEB_THREAD);
return ret;
}
@@ -1449,7 +1363,6 @@ static void lbs_send_confirmsleep(struct lbs_private *priv)
unsigned long flags;
int ret;
- lbs_deb_enter(LBS_DEB_HOST);
lbs_deb_hex(LBS_DEB_HOST, "sleep confirm", (u8 *) &confirm_sleep,
sizeof(confirm_sleep));
@@ -1457,7 +1370,7 @@ static void lbs_send_confirmsleep(struct lbs_private *priv)
sizeof(confirm_sleep));
if (ret) {
netdev_alert(priv->dev, "confirm_sleep failed\n");
- goto out;
+ return;
}
spin_lock_irqsave(&priv->driver_lock, flags);
@@ -1475,9 +1388,6 @@ static void lbs_send_confirmsleep(struct lbs_private *priv)
priv->psstate = PS_STATE_SLEEP;
spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-out:
- lbs_deb_leave(LBS_DEB_HOST);
}
/**
@@ -1493,8 +1403,6 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv)
unsigned long flags =0;
int allowed = 1;
- lbs_deb_enter(LBS_DEB_HOST);
-
spin_lock_irqsave(&priv->driver_lock, flags);
if (priv->dnld_sent) {
allowed = 0;
@@ -1520,8 +1428,6 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv)
} else {
lbs_deb_host("sleep confirm has been delayed\n");
}
-
- lbs_deb_leave(LBS_DEB_HOST);
}
@@ -1596,8 +1502,6 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
{
struct cmd_ctrl_node *cmdnode;
- lbs_deb_enter(LBS_DEB_HOST);
-
if (priv->surpriseremoved) {
lbs_deb_host("PREP_CMD: card removed\n");
cmdnode = ERR_PTR(-ENOENT);
@@ -1643,17 +1547,14 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
wake_up(&priv->waitq);
done:
- lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode);
return cmdnode;
}
void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
struct cmd_header *in_cmd, int in_cmd_size)
{
- lbs_deb_enter(LBS_DEB_CMD);
__lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
lbs_cmd_async_callback, 0);
- lbs_deb_leave(LBS_DEB_CMD);
}
int __lbs_cmd(struct lbs_private *priv, uint16_t command,
@@ -1665,8 +1566,6 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
unsigned long flags;
int ret = 0;
- lbs_deb_enter(LBS_DEB_HOST);
-
cmdnode = __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
callback, callback_arg);
if (IS_ERR(cmdnode)) {
@@ -1693,7 +1592,6 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
spin_unlock_irqrestore(&priv->driver_lock, flags);
done:
- lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
return ret;
}
EXPORT_SYMBOL_GPL(__lbs_cmd);
diff --git a/drivers/net/wireless/marvell/libertas/cmdresp.c b/drivers/net/wireless/marvell/libertas/cmdresp.c
index c753e36..aaf0161 100644
--- a/drivers/net/wireless/marvell/libertas/cmdresp.c
+++ b/drivers/net/wireless/marvell/libertas/cmdresp.c
@@ -32,8 +32,6 @@ void lbs_mac_event_disconnected(struct lbs_private *priv,
if (priv->connect_status != LBS_CONNECTED)
return;
- lbs_deb_enter(LBS_DEB_ASSOC);
-
/*
* Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
* It causes problem in the Supplicant
@@ -61,7 +59,6 @@ void lbs_mac_event_disconnected(struct lbs_private *priv,
lbs_deb_cmd("disconnected, so exit PS mode\n");
lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false);
}
- lbs_deb_leave(LBS_DEB_ASSOC);
}
int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
@@ -72,8 +69,6 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
unsigned long flags;
uint16_t result;
- lbs_deb_enter(LBS_DEB_HOST);
-
mutex_lock(&priv->lock);
spin_lock_irqsave(&priv->driver_lock, flags);
@@ -221,7 +216,6 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
done:
mutex_unlock(&priv->lock);
- lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
return ret;
}
@@ -230,8 +224,6 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
int ret = 0;
struct cmd_header cmd;
- lbs_deb_enter(LBS_DEB_CMD);
-
switch (event) {
case MACREG_INT_CODE_LINK_SENSED:
lbs_deb_cmd("EVENT: link sensed\n");
@@ -359,6 +351,5 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
break;
}
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
diff --git a/drivers/net/wireless/marvell/libertas/defs.h b/drivers/net/wireless/marvell/libertas/defs.h
index 407784a..d322144 100644
--- a/drivers/net/wireless/marvell/libertas/defs.h
+++ b/drivers/net/wireless/marvell/libertas/defs.h
@@ -55,15 +55,6 @@ do { if ((lbs_debug & (grp)) == (grp)) \
#define LBS_DEB_LL(grp, grpnam, fmt, args...) do {} while (0)
#endif
-#define lbs_deb_enter(grp) \
- LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s()\n", __func__);
-#define lbs_deb_enter_args(grp, fmt, args...) \
- LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args);
-#define lbs_deb_leave(grp) \
- LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s()\n", __func__);
-#define lbs_deb_leave_args(grp, fmt, args...) \
- LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s(), " fmt "\n", \
- __func__, ##args);
#define lbs_deb_main(fmt, args...) LBS_DEB_LL(LBS_DEB_MAIN, " main", fmt, ##args)
#define lbs_deb_net(fmt, args...) LBS_DEB_LL(LBS_DEB_NET, " net", fmt, ##args)
#define lbs_deb_mesh(fmt, args...) LBS_DEB_LL(LBS_DEB_MESH, " mesh", fmt, ##args)
diff --git a/drivers/net/wireless/marvell/libertas/ethtool.c b/drivers/net/wireless/marvell/libertas/ethtool.c
index f955b2d..693868f 100644
--- a/drivers/net/wireless/marvell/libertas/ethtool.c
+++ b/drivers/net/wireless/marvell/libertas/ethtool.c
@@ -41,8 +41,6 @@ static int lbs_ethtool_get_eeprom(struct net_device *dev,
struct cmd_ds_802_11_eeprom_access cmd;
int ret;
- lbs_deb_enter(LBS_DEB_ETHTOOL);
-
if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN ||
eeprom->len > LBS_EEPROM_READ_LEN) {
ret = -EINVAL;
@@ -59,7 +57,6 @@ static int lbs_ethtool_get_eeprom(struct net_device *dev,
memcpy(bytes, cmd.value, eeprom->len);
out:
- lbs_deb_leave_args(LBS_DEB_ETHTOOL, "ret %d", ret);
return ret;
}
diff --git a/drivers/net/wireless/marvell/libertas/if_cs.c b/drivers/net/wireless/marvell/libertas/if_cs.c
index f499efc..7d88223 100644
--- a/drivers/net/wireless/marvell/libertas/if_cs.c
+++ b/drivers/net/wireless/marvell/libertas/if_cs.c
@@ -336,13 +336,11 @@ static inline u32 get_model(u16 manf_id, u16 card_id)
static inline void if_cs_enable_ints(struct if_cs_card *card)
{
- lbs_deb_enter(LBS_DEB_CS);
if_cs_write16(card, IF_CS_HOST_INT_MASK, 0);
}
static inline void if_cs_disable_ints(struct if_cs_card *card)
{
- lbs_deb_enter(LBS_DEB_CS);
if_cs_write16(card, IF_CS_HOST_INT_MASK, IF_CS_BIT_MASK);
}
@@ -355,7 +353,6 @@ static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb)
int ret = -1;
int loops = 0;
- lbs_deb_enter(LBS_DEB_CS);
if_cs_disable_ints(card);
/* Is hardware ready? */
@@ -388,7 +385,6 @@ static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb)
done:
if_cs_enable_ints(card);
- lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
return ret;
}
@@ -400,7 +396,6 @@ static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb)
struct if_cs_card *card = (struct if_cs_card *)priv->card;
u16 status;
- lbs_deb_enter(LBS_DEB_CS);
if_cs_disable_ints(card);
status = if_cs_read16(card, IF_CS_CARD_STATUS);
@@ -416,8 +411,6 @@ static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb)
if_cs_write16(card, IF_CS_HOST_STATUS, IF_CS_BIT_TX);
if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_TX);
if_cs_enable_ints(card);
-
- lbs_deb_leave(LBS_DEB_CS);
}
/*
@@ -429,8 +422,6 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
int ret = -1;
u16 status;
- lbs_deb_enter(LBS_DEB_CS);
-
/* is hardware ready? */
status = if_cs_read16(priv->card, IF_CS_CARD_STATUS);
if ((status & IF_CS_BIT_RESP) == 0) {
@@ -463,7 +454,6 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
spin_unlock_irqrestore(&priv->driver_lock, flags);
out:
- lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len);
return ret;
}
@@ -473,8 +463,6 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv)
u16 len;
u8 *data;
- lbs_deb_enter(LBS_DEB_CS);
-
len = if_cs_read16(priv->card, IF_CS_READ_LEN);
if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
netdev_err(priv->dev,
@@ -501,7 +489,6 @@ dat_err:
if_cs_write16(priv->card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_RX);
out:
- lbs_deb_leave_args(LBS_DEB_CS, "ret %p", skb);
return skb;
}
@@ -511,8 +498,6 @@ static irqreturn_t if_cs_interrupt(int irq, void *data)
struct lbs_private *priv = card->priv;
u16 cause;
- lbs_deb_enter(LBS_DEB_CS);
-
/* Ask card interrupt cause register if there is something for us */
cause = if_cs_read16(card, IF_CS_CARD_INT_CAUSE);
lbs_deb_cs("cause 0x%04x\n", cause);
@@ -569,7 +554,6 @@ static irqreturn_t if_cs_interrupt(int irq, void *data)
/* Clear interrupt cause */
if_cs_write16(card, IF_CS_CARD_INT_CAUSE, cause & IF_CS_BIT_MASK);
- lbs_deb_leave(LBS_DEB_CS);
return IRQ_HANDLED;
}
@@ -591,8 +575,6 @@ static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw)
int sent = 0;
u8 scratch;
- lbs_deb_enter(LBS_DEB_CS);
-
/*
* This is the only place where an unaligned register access happens on
* the CF8305 card, therefore for the sake of speed of the driver, we do
@@ -671,7 +653,6 @@ static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw)
}
done:
- lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
return ret;
}
@@ -683,8 +664,6 @@ static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw)
int len = 0;
int sent;
- lbs_deb_enter(LBS_DEB_CS);
-
lbs_deb_cs("fw size %td\n", fw->size);
ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW,
@@ -734,7 +713,6 @@ static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw)
pr_err("firmware download failed\n");
done:
- lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
return ret;
}
@@ -792,8 +770,6 @@ static int if_cs_host_to_card(struct lbs_private *priv,
{
int ret = -1;
- lbs_deb_enter_args(LBS_DEB_CS, "type %d, bytes %d", type, nb);
-
switch (type) {
case MVMS_DAT:
priv->dnld_sent = DNLD_DATA_SENT;
@@ -809,7 +785,6 @@ static int if_cs_host_to_card(struct lbs_private *priv,
__func__, type);
}
- lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
return ret;
}
@@ -818,14 +793,10 @@ static void if_cs_release(struct pcmcia_device *p_dev)
{
struct if_cs_card *card = p_dev->priv;
- lbs_deb_enter(LBS_DEB_CS);
-
free_irq(p_dev->irq, card);
pcmcia_disable_device(p_dev);
if (card->iobase)
ioport_unmap(card->iobase);
-
- lbs_deb_leave(LBS_DEB_CS);
}
@@ -850,8 +821,6 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
struct lbs_private *priv;
struct if_cs_card *card;
- lbs_deb_enter(LBS_DEB_CS);
-
card = kzalloc(sizeof(struct if_cs_card), GFP_KERNEL);
if (!card)
goto out;
@@ -961,7 +930,6 @@ out2:
out1:
pcmcia_disable_device(p_dev);
out:
- lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
return ret;
}
@@ -970,15 +938,11 @@ static void if_cs_detach(struct pcmcia_device *p_dev)
{
struct if_cs_card *card = p_dev->priv;
- lbs_deb_enter(LBS_DEB_CS);
-
lbs_stop_card(card->priv);
lbs_remove_card(card->priv);
if_cs_disable_ints(card);
if_cs_release(p_dev);
kfree(card);
-
- lbs_deb_leave(LBS_DEB_CS);
}
diff --git a/drivers/net/wireless/marvell/libertas/if_sdio.c b/drivers/net/wireless/marvell/libertas/if_sdio.c
index 47f4a14..2300e79 100644
--- a/drivers/net/wireless/marvell/libertas/if_sdio.c
+++ b/drivers/net/wireless/marvell/libertas/if_sdio.c
@@ -211,8 +211,6 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card,
unsigned long flags;
u8 i;
- lbs_deb_enter(LBS_DEB_SDIO);
-
if (size > LBS_CMD_BUFFER_SIZE) {
lbs_deb_sdio("response packet too large (%d bytes)\n",
(int)size);
@@ -233,7 +231,6 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card,
ret = 0;
out:
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
return ret;
}
@@ -242,9 +239,6 @@ static int if_sdio_handle_data(struct if_sdio_card *card,
{
int ret;
struct sk_buff *skb;
- char *data;
-
- lbs_deb_enter(LBS_DEB_SDIO);
if (size > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
lbs_deb_sdio("response packet too large (%d bytes)\n",
@@ -261,17 +255,13 @@ static int if_sdio_handle_data(struct if_sdio_card *card,
skb_reserve(skb, NET_IP_ALIGN);
- data = skb_put(skb, size);
-
- memcpy(data, buffer, size);
+ skb_put_data(skb, buffer, size);
lbs_process_rxed_packet(card->priv, skb);
ret = 0;
out:
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
return ret;
}
@@ -281,8 +271,6 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
int ret;
u32 event;
- lbs_deb_enter(LBS_DEB_SDIO);
-
if (card->model == MODEL_8385) {
event = sdio_readb(card->func, IF_SDIO_EVENT, &ret);
if (ret)
@@ -307,8 +295,6 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
ret = 0;
out:
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
return ret;
}
@@ -337,8 +323,6 @@ static int if_sdio_card_to_host(struct if_sdio_card *card)
int ret;
u16 size, type, chunk;
- lbs_deb_enter(LBS_DEB_SDIO);
-
size = if_sdio_read_rx_len(card, &ret);
if (ret)
goto out;
@@ -410,8 +394,6 @@ out:
if (ret)
pr_err("problem fetching packet from firmware\n");
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
return ret;
}
@@ -422,8 +404,6 @@ static void if_sdio_host_to_card_worker(struct work_struct *work)
int ret;
unsigned long flags;
- lbs_deb_enter(LBS_DEB_SDIO);
-
card = container_of(work, struct if_sdio_card, packet_worker);
while (1) {
@@ -451,8 +431,6 @@ static void if_sdio_host_to_card_worker(struct work_struct *work)
kfree(packet);
}
-
- lbs_deb_leave(LBS_DEB_SDIO);
}
/********************************************************************/
@@ -471,8 +449,6 @@ static int if_sdio_prog_helper(struct if_sdio_card *card,
const u8 *firmware;
size_t size;
- lbs_deb_enter(LBS_DEB_SDIO);
-
chunk_buffer = kzalloc(64, GFP_KERNEL);
if (!chunk_buffer) {
ret = -ENOMEM;
@@ -556,7 +532,6 @@ out:
if (ret)
pr_err("failed to load helper firmware\n");
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
return ret;
}
@@ -570,8 +545,6 @@ static int if_sdio_prog_real(struct if_sdio_card *card,
const u8 *firmware;
size_t size, req_size;
- lbs_deb_enter(LBS_DEB_SDIO);
-
chunk_buffer = kzalloc(512, GFP_KERNEL);
if (!chunk_buffer) {
ret = -ENOMEM;
@@ -691,7 +664,6 @@ out:
if (ret)
pr_err("failed to load firmware\n");
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
return ret;
}
@@ -725,8 +697,6 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
int ret;
u16 scratch;
- lbs_deb_enter(LBS_DEB_SDIO);
-
/*
* Disable interrupts
*/
@@ -769,7 +739,6 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
fw_table, if_sdio_do_prog_firmware);
out:
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
return ret;
}
@@ -948,8 +917,6 @@ static int if_sdio_host_to_card(struct lbs_private *priv,
u16 size;
unsigned long flags;
- lbs_deb_enter_args(LBS_DEB_SDIO, "type %d, bytes %d", type, nb);
-
card = priv->card;
if (nb > (65536 - sizeof(struct if_sdio_packet) - 4)) {
@@ -1013,8 +980,6 @@ static int if_sdio_host_to_card(struct lbs_private *priv,
ret = 0;
out:
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
return ret;
}
@@ -1040,7 +1005,6 @@ static int if_sdio_exit_deep_sleep(struct lbs_private *priv)
struct if_sdio_card *card = priv->card;
int ret = -1;
- lbs_deb_enter(LBS_DEB_SDIO);
sdio_claim_host(card->func);
sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
@@ -1048,7 +1012,7 @@ static int if_sdio_exit_deep_sleep(struct lbs_private *priv)
netdev_err(priv->dev, "sdio_writeb failed!\n");
sdio_release_host(card->func);
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+
return ret;
}
@@ -1057,7 +1021,6 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv)
struct if_sdio_card *card = priv->card;
int ret = -1;
- lbs_deb_enter(LBS_DEB_SDIO);
sdio_claim_host(card->func);
sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret);
@@ -1065,7 +1028,7 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv)
netdev_err(priv->dev, "sdio_writeb failed!\n");
sdio_release_host(card->func);
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+
return ret;
}
@@ -1143,19 +1106,17 @@ static void if_sdio_interrupt(struct sdio_func *func)
struct if_sdio_card *card;
u8 cause;
- lbs_deb_enter(LBS_DEB_SDIO);
-
card = sdio_get_drvdata(func);
cause = sdio_readb(card->func, IF_SDIO_H_INT_STATUS, &ret);
if (ret || !cause)
- goto out;
+ return;
lbs_deb_sdio("interrupt: 0x%X\n", (unsigned)cause);
sdio_writeb(card->func, ~cause, IF_SDIO_H_INT_STATUS, &ret);
if (ret)
- goto out;
+ return;
/*
* Ignore the define name, this really means the card has
@@ -1169,13 +1130,8 @@ static void if_sdio_interrupt(struct sdio_func *func)
if (cause & IF_SDIO_H_INT_UPLD) {
ret = if_sdio_card_to_host(card);
if (ret)
- goto out;
+ return;
}
-
- ret = 0;
-
-out:
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
}
static int if_sdio_probe(struct sdio_func *func,
@@ -1187,8 +1143,6 @@ static int if_sdio_probe(struct sdio_func *func,
unsigned int model;
struct if_sdio_packet *packet;
- lbs_deb_enter(LBS_DEB_SDIO);
-
for (i = 0;i < func->card->num_info;i++) {
if (sscanf(func->card->info[i],
"802.11 SDIO ID: %x", &model) == 1)
@@ -1273,8 +1227,6 @@ static int if_sdio_probe(struct sdio_func *func,
goto err_activate_card;
out:
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
return ret;
err_activate_card:
@@ -1298,8 +1250,6 @@ static void if_sdio_remove(struct sdio_func *func)
struct if_sdio_card *card;
struct if_sdio_packet *packet;
- lbs_deb_enter(LBS_DEB_SDIO);
-
card = sdio_get_drvdata(func);
/* Undo decrement done above in if_sdio_probe */
@@ -1335,7 +1285,6 @@ static void if_sdio_remove(struct sdio_func *func)
}
kfree(card);
- lbs_deb_leave(LBS_DEB_SDIO);
}
static int if_sdio_suspend(struct device *dev)
@@ -1415,8 +1364,6 @@ static int __init if_sdio_init_module(void)
{
int ret = 0;
- lbs_deb_enter(LBS_DEB_SDIO);
-
printk(KERN_INFO "libertas_sdio: Libertas SDIO driver\n");
printk(KERN_INFO "libertas_sdio: Copyright Pierre Ossman\n");
@@ -1425,23 +1372,17 @@ static int __init if_sdio_init_module(void)
/* Clear the flag in case user removes the card. */
user_rmmod = 0;
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
return ret;
}
static void __exit if_sdio_exit_module(void)
{
- lbs_deb_enter(LBS_DEB_SDIO);
-
/* Set the flag as user is removing this module. */
user_rmmod = 1;
cancel_work_sync(&card_reset_work);
sdio_unregister_driver(&if_sdio_driver);
-
- lbs_deb_leave(LBS_DEB_SDIO);
}
module_init(if_sdio_init_module);
diff --git a/drivers/net/wireless/marvell/libertas/if_spi.c b/drivers/net/wireless/marvell/libertas/if_spi.c
index 7b4955c..e9aec6c 100644
--- a/drivers/net/wireless/marvell/libertas/if_spi.c
+++ b/drivers/net/wireless/marvell/libertas/if_spi.c
@@ -466,8 +466,6 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card,
const u8 *fw;
u8 temp[HELPER_FW_LOAD_CHUNK_SZ];
- lbs_deb_enter(LBS_DEB_SPI);
-
err = spu_set_interrupt_mode(card, 1, 0);
if (err)
goto out;
@@ -533,7 +531,7 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card,
out:
if (err)
pr_err("failed to load helper firmware (err=%d)\n", err);
- lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
+
return err;
}
@@ -588,8 +586,6 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card,
const u8 *fw;
u16 num_crc_errs;
- lbs_deb_enter(LBS_DEB_SPI);
-
err = spu_set_interrupt_mode(card, 1, 0);
if (err)
goto out;
@@ -666,7 +662,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card,
out:
if (err)
pr_err("failed to load firmware (err=%d)\n", err);
- lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
+
return err;
}
@@ -699,8 +695,6 @@ static int if_spi_c2h_cmd(struct if_spi_card *card)
*/
BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE % 4 != 0);
- lbs_deb_enter(LBS_DEB_SPI);
-
/* How many bytes are there to read? */
err = spu_read_u16(card, IF_SPI_SCRATCH_2_REG, &len);
if (err)
@@ -735,7 +729,7 @@ static int if_spi_c2h_cmd(struct if_spi_card *card)
out:
if (err)
netdev_err(priv->dev, "%s: err=%d\n", __func__, err);
- lbs_deb_leave(LBS_DEB_SPI);
+
return err;
}
@@ -748,8 +742,6 @@ static int if_spi_c2h_data(struct if_spi_card *card)
u16 len;
int err = 0;
- lbs_deb_enter(LBS_DEB_SPI);
-
/* How many bytes are there to read? */
err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len);
if (err)
@@ -794,7 +786,7 @@ free_skb:
out:
if (err)
netdev_err(priv->dev, "%s: err=%d\n", __func__, err);
- lbs_deb_leave(LBS_DEB_SPI);
+
return err;
}
@@ -870,8 +862,6 @@ static void if_spi_host_to_card_worker(struct work_struct *work)
card = container_of(work, struct if_spi_card, packet_work);
priv = card->priv;
- lbs_deb_enter(LBS_DEB_SPI);
-
/*
* Read the host interrupt status register to see what we
* can do.
@@ -943,8 +933,6 @@ static void if_spi_host_to_card_worker(struct work_struct *work)
err:
if (err)
netdev_err(priv->dev, "%s: got error %d\n", __func__, err);
-
- lbs_deb_leave(LBS_DEB_SPI);
}
/*
@@ -962,8 +950,6 @@ static int if_spi_host_to_card(struct lbs_private *priv,
struct if_spi_packet *packet;
u16 blen;
- lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb);
-
if (nb == 0) {
netdev_err(priv->dev, "%s: invalid size requested: %d\n",
__func__, nb);
@@ -1004,7 +990,6 @@ static int if_spi_host_to_card(struct lbs_private *priv,
/* Queue spi xfer work */
queue_work(card->workqueue, &card->packet_work);
out:
- lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err);
return err;
}
@@ -1035,8 +1020,6 @@ static int if_spi_init_card(struct if_spi_card *card)
const struct firmware *helper = NULL;
const struct firmware *mainfw = NULL;
- lbs_deb_enter(LBS_DEB_SPI);
-
err = spu_init(card, card->pdata->use_dummy_writes);
if (err)
goto out;
@@ -1093,7 +1076,6 @@ static int if_spi_init_card(struct if_spi_card *card)
goto out;
out:
- lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
return err;
}
@@ -1126,8 +1108,6 @@ static int if_spi_probe(struct spi_device *spi)
struct libertas_spi_platform_data *pdata = dev_get_platdata(&spi->dev);
int err = 0;
- lbs_deb_enter(LBS_DEB_SPI);
-
if (!pdata) {
err = -EINVAL;
goto out;
@@ -1221,7 +1201,6 @@ teardown:
if (pdata->teardown)
pdata->teardown(spi);
out:
- lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
return err;
}
@@ -1231,7 +1210,6 @@ static int libertas_spi_remove(struct spi_device *spi)
struct lbs_private *priv = card->priv;
lbs_deb_spi("libertas_spi_remove\n");
- lbs_deb_enter(LBS_DEB_SPI);
cancel_work_sync(&card->resume_work);
@@ -1243,7 +1221,7 @@ static int libertas_spi_remove(struct spi_device *spi)
if (card->pdata->teardown)
card->pdata->teardown(spi);
free_if_spi_card(card);
- lbs_deb_leave(LBS_DEB_SPI);
+
return 0;
}
@@ -1297,18 +1275,16 @@ static struct spi_driver libertas_spi_driver = {
static int __init if_spi_init_module(void)
{
int ret = 0;
- lbs_deb_enter(LBS_DEB_SPI);
+
printk(KERN_INFO "libertas_spi: Libertas SPI driver\n");
ret = spi_register_driver(&libertas_spi_driver);
- lbs_deb_leave(LBS_DEB_SPI);
+
return ret;
}
static void __exit if_spi_exit_module(void)
{
- lbs_deb_enter(LBS_DEB_SPI);
spi_unregister_driver(&libertas_spi_driver);
- lbs_deb_leave(LBS_DEB_SPI);
}
module_init(if_spi_init_module);
diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c
index aba0c99..e53025e 100644
--- a/drivers/net/wireless/marvell/libertas/if_usb.c
+++ b/drivers/net/wireless/marvell/libertas/if_usb.c
@@ -111,8 +111,6 @@ static void if_usb_write_bulk_callback(struct urb *urb)
*/
static void if_usb_free(struct if_usb_card *cardp)
{
- lbs_deb_enter(LBS_DEB_USB);
-
/* Unlink tx & rx urb */
usb_kill_urb(cardp->tx_urb);
usb_kill_urb(cardp->rx_urb);
@@ -125,8 +123,6 @@ static void if_usb_free(struct if_usb_card *cardp)
kfree(cardp->ep_out_buf);
cardp->ep_out_buf = NULL;
-
- lbs_deb_leave(LBS_DEB_USB);
}
static void if_usb_setup_firmware(struct lbs_private *priv)
@@ -306,8 +302,6 @@ static void if_usb_disconnect(struct usb_interface *intf)
struct if_usb_card *cardp = usb_get_intfdata(intf);
struct lbs_private *priv = cardp->priv;
- lbs_deb_enter(LBS_DEB_MAIN);
-
cardp->surprise_removed = 1;
if (priv) {
@@ -320,8 +314,6 @@ static void if_usb_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
usb_put_dev(interface_to_usbdev(intf));
-
- lbs_deb_leave(LBS_DEB_MAIN);
}
/**
@@ -388,8 +380,6 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
struct cmd_header *cmd = cardp->ep_out_buf + 4;
int ret;
- lbs_deb_enter(LBS_DEB_USB);
-
*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
cmd->command = cpu_to_le16(CMD_802_11_RESET);
@@ -407,8 +397,6 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
if_usb_reset_olpc_card(NULL);
#endif
- lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
-
return ret;
}
@@ -671,8 +659,6 @@ static void if_usb_receive(struct urb *urb)
__le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET);
uint32_t event;
- lbs_deb_enter(LBS_DEB_USB);
-
if (recvlength) {
if (urb->status) {
lbs_deb_usbd(&cardp->udev->dev, "RX URB failed: %d\n",
@@ -688,7 +674,7 @@ static void if_usb_receive(struct urb *urb)
recvlength, recvtype);
} else if (urb->status) {
kfree_skb(skb);
- goto rx_exit;
+ return;
}
switch (recvtype) {
@@ -724,8 +710,6 @@ static void if_usb_receive(struct urb *urb)
setup_for_next:
if_usb_submit_rx_urb(cardp);
-rx_exit:
- lbs_deb_leave(LBS_DEB_USB);
}
/**
@@ -835,8 +819,6 @@ static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
int i = 0;
static int reset_count = 10;
- lbs_deb_enter(LBS_DEB_USB);
-
if (ret) {
pr_err("failed to find firmware (%d)\n", ret);
goto done;
@@ -942,7 +924,6 @@ restart:
done:
cardp->fw = NULL;
- lbs_deb_leave(LBS_DEB_USB);
}
@@ -953,8 +934,6 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
struct lbs_private *priv = cardp->priv;
int ret;
- lbs_deb_enter(LBS_DEB_USB);
-
if (priv->psstate != PS_STATE_FULL_POWER) {
ret = -1;
goto out;
@@ -978,7 +957,6 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
usb_kill_urb(cardp->rx_urb);
out:
- lbs_deb_leave(LBS_DEB_USB);
return ret;
}
@@ -987,13 +965,10 @@ static int if_usb_resume(struct usb_interface *intf)
struct if_usb_card *cardp = usb_get_intfdata(intf);
struct lbs_private *priv = cardp->priv;
- lbs_deb_enter(LBS_DEB_USB);
-
if_usb_submit_rx_urb(cardp);
lbs_resume(priv);
- lbs_deb_leave(LBS_DEB_USB);
return 0;
}
#else
diff --git a/drivers/net/wireless/marvell/libertas/main.c b/drivers/net/wireless/marvell/libertas/main.c
index dde065d..aefa88f 100644
--- a/drivers/net/wireless/marvell/libertas/main.c
+++ b/drivers/net/wireless/marvell/libertas/main.c
@@ -180,7 +180,6 @@ static int lbs_dev_open(struct net_device *dev)
struct lbs_private *priv = dev->ml_priv;
int ret = 0;
- lbs_deb_enter(LBS_DEB_NET);
if (!priv->iface_running) {
ret = lbs_start_iface(priv);
if (ret)
@@ -197,7 +196,6 @@ static int lbs_dev_open(struct net_device *dev)
spin_unlock_irq(&priv->driver_lock);
out:
- lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
return ret;
}
@@ -216,8 +214,6 @@ int lbs_stop_iface(struct lbs_private *priv)
unsigned long flags;
int ret = 0;
- lbs_deb_enter(LBS_DEB_MAIN);
-
spin_lock_irqsave(&priv->driver_lock, flags);
priv->iface_running = false;
kfree_skb(priv->currenttxskb);
@@ -236,7 +232,6 @@ int lbs_stop_iface(struct lbs_private *priv)
if (priv->power_save)
ret = priv->power_save(priv);
- lbs_deb_leave(LBS_DEB_MAIN);
return ret;
}
@@ -250,8 +245,6 @@ static int lbs_eth_stop(struct net_device *dev)
{
struct lbs_private *priv = dev->ml_priv;
- lbs_deb_enter(LBS_DEB_NET);
-
if (priv->connect_status == LBS_CONNECTED)
lbs_disconnect(priv, WLAN_REASON_DEAUTH_LEAVING);
@@ -269,7 +262,6 @@ static int lbs_eth_stop(struct net_device *dev)
if (!lbs_iface_active(priv))
lbs_stop_iface(priv);
- lbs_deb_leave(LBS_DEB_NET);
return 0;
}
@@ -277,8 +269,6 @@ void lbs_host_to_card_done(struct lbs_private *priv)
{
unsigned long flags;
- lbs_deb_enter(LBS_DEB_THREAD);
-
spin_lock_irqsave(&priv->driver_lock, flags);
del_timer(&priv->tx_lockup_timer);
@@ -291,7 +281,6 @@ void lbs_host_to_card_done(struct lbs_private *priv)
}
spin_unlock_irqrestore(&priv->driver_lock, flags);
- lbs_deb_leave(LBS_DEB_THREAD);
}
EXPORT_SYMBOL_GPL(lbs_host_to_card_done);
@@ -301,8 +290,6 @@ int lbs_set_mac_address(struct net_device *dev, void *addr)
struct lbs_private *priv = dev->ml_priv;
struct sockaddr *phwaddr = addr;
- lbs_deb_enter(LBS_DEB_NET);
-
/*
* Can only set MAC address when all interfaces are down, to be written
* to the hardware when one of them is brought up.
@@ -318,7 +305,6 @@ int lbs_set_mac_address(struct net_device *dev, void *addr)
if (priv->mesh_dev)
memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
- lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
return ret;
}
@@ -378,8 +364,6 @@ void lbs_update_mcast(struct lbs_private *priv)
int nr_addrs;
int old_mac_control = priv->mac_control;
- lbs_deb_enter(LBS_DEB_NET);
-
if (netif_running(priv->dev))
dev_flags |= priv->dev->flags;
if (priv->mesh_dev && netif_running(priv->mesh_dev))
@@ -424,8 +408,6 @@ void lbs_update_mcast(struct lbs_private *priv)
out_set_mac_control:
if (priv->mac_control != old_mac_control)
lbs_set_mac_control(priv);
-
- lbs_deb_leave(LBS_DEB_NET);
}
static void lbs_set_mcast_worker(struct work_struct *work)
@@ -455,8 +437,6 @@ static int lbs_thread(void *data)
struct lbs_private *priv = dev->ml_priv;
wait_queue_entry_t wait;
- lbs_deb_enter(LBS_DEB_THREAD);
-
init_waitqueue_entry(&wait, current);
for (;;) {
@@ -648,7 +628,6 @@ static int lbs_thread(void *data)
del_timer(&priv->tx_lockup_timer);
del_timer(&priv->auto_deepsleep_timer);
- lbs_deb_leave(LBS_DEB_THREAD);
return 0;
}
@@ -664,8 +643,6 @@ static int lbs_setup_firmware(struct lbs_private *priv)
int ret = -1;
s16 curlevel = 0, minlevel = 0, maxlevel = 0;
- lbs_deb_enter(LBS_DEB_FW);
-
/* Read MAC address from firmware */
eth_broadcast_addr(priv->current_addr);
ret = lbs_update_hw_spec(priv);
@@ -687,7 +664,6 @@ static int lbs_setup_firmware(struct lbs_private *priv)
ret = lbs_set_mac_control_sync(priv);
done:
- lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
return ret;
}
@@ -695,8 +671,6 @@ int lbs_suspend(struct lbs_private *priv)
{
int ret;
- lbs_deb_enter(LBS_DEB_FW);
-
if (priv->is_deep_sleep) {
ret = lbs_set_deep_sleep(priv, 0);
if (ret) {
@@ -713,7 +687,6 @@ int lbs_suspend(struct lbs_private *priv)
if (priv->mesh_dev)
netif_device_detach(priv->mesh_dev);
- lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
return ret;
}
EXPORT_SYMBOL_GPL(lbs_suspend);
@@ -722,8 +695,6 @@ int lbs_resume(struct lbs_private *priv)
{
int ret;
- lbs_deb_enter(LBS_DEB_FW);
-
ret = lbs_set_host_sleep(priv, 0);
netif_device_attach(priv->dev);
@@ -741,7 +712,6 @@ int lbs_resume(struct lbs_private *priv)
if (priv->setup_fw_on_resume)
ret = lbs_setup_firmware(priv);
- lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
return ret;
}
EXPORT_SYMBOL_GPL(lbs_resume);
@@ -757,7 +727,6 @@ static void lbs_cmd_timeout_handler(unsigned long data)
struct lbs_private *priv = (struct lbs_private *)data;
unsigned long flags;
- lbs_deb_enter(LBS_DEB_CMD);
spin_lock_irqsave(&priv->driver_lock, flags);
if (!priv->cur_cmd)
@@ -778,7 +747,6 @@ static void lbs_cmd_timeout_handler(unsigned long data)
wake_up(&priv->waitq);
out:
spin_unlock_irqrestore(&priv->driver_lock, flags);
- lbs_deb_leave(LBS_DEB_CMD);
}
/**
@@ -793,7 +761,6 @@ static void lbs_tx_lockup_handler(unsigned long data)
struct lbs_private *priv = (struct lbs_private *)data;
unsigned long flags;
- lbs_deb_enter(LBS_DEB_TX);
spin_lock_irqsave(&priv->driver_lock, flags);
netdev_info(priv->dev, "TX lockup detected\n");
@@ -804,7 +771,6 @@ static void lbs_tx_lockup_handler(unsigned long data)
wake_up_interruptible(&priv->waitq);
spin_unlock_irqrestore(&priv->driver_lock, flags);
- lbs_deb_leave(LBS_DEB_TX);
}
/**
@@ -817,8 +783,6 @@ static void auto_deepsleep_timer_fn(unsigned long data)
{
struct lbs_private *priv = (struct lbs_private *)data;
- lbs_deb_enter(LBS_DEB_CMD);
-
if (priv->is_activity_detected) {
priv->is_activity_detected = 0;
} else {
@@ -836,32 +800,25 @@ static void auto_deepsleep_timer_fn(unsigned long data)
}
mod_timer(&priv->auto_deepsleep_timer , jiffies +
(priv->auto_deep_sleep_timeout * HZ)/1000);
- lbs_deb_leave(LBS_DEB_CMD);
}
int lbs_enter_auto_deep_sleep(struct lbs_private *priv)
{
- lbs_deb_enter(LBS_DEB_SDIO);
-
priv->is_auto_deep_sleep_enabled = 1;
if (priv->is_deep_sleep)
priv->wakeup_dev_required = 1;
mod_timer(&priv->auto_deepsleep_timer ,
jiffies + (priv->auto_deep_sleep_timeout * HZ)/1000);
- lbs_deb_leave(LBS_DEB_SDIO);
return 0;
}
int lbs_exit_auto_deep_sleep(struct lbs_private *priv)
{
- lbs_deb_enter(LBS_DEB_SDIO);
-
priv->is_auto_deep_sleep_enabled = 0;
priv->auto_deep_sleep_timeout = 0;
del_timer(&priv->auto_deepsleep_timer);
- lbs_deb_leave(LBS_DEB_SDIO);
return 0;
}
@@ -869,8 +826,6 @@ static int lbs_init_adapter(struct lbs_private *priv)
{
int ret;
- lbs_deb_enter(LBS_DEB_MAIN);
-
eth_broadcast_addr(priv->current_addr);
priv->connect_status = LBS_DISCONNECTED;
@@ -921,22 +876,16 @@ static int lbs_init_adapter(struct lbs_private *priv)
}
out:
- lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
-
return ret;
}
static void lbs_free_adapter(struct lbs_private *priv)
{
- lbs_deb_enter(LBS_DEB_MAIN);
-
lbs_free_cmd_buffer(priv);
kfifo_free(&priv->event_fifo);
del_timer(&priv->command_timer);
del_timer(&priv->tx_lockup_timer);
del_timer(&priv->auto_deepsleep_timer);
-
- lbs_deb_leave(LBS_DEB_MAIN);
}
static const struct net_device_ops lbs_netdev_ops = {
@@ -962,8 +911,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
struct wireless_dev *wdev;
struct lbs_private *priv = NULL;
- lbs_deb_enter(LBS_DEB_MAIN);
-
/* Allocate an Ethernet device and register it */
wdev = lbs_cfg_alloc(dmdev);
if (IS_ERR(wdev)) {
@@ -1031,7 +978,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
priv = NULL;
done:
- lbs_deb_leave_args(LBS_DEB_MAIN, "priv %p", priv);
return priv;
}
EXPORT_SYMBOL_GPL(lbs_add_card);
@@ -1041,8 +987,6 @@ void lbs_remove_card(struct lbs_private *priv)
{
struct net_device *dev = priv->dev;
- lbs_deb_enter(LBS_DEB_MAIN);
-
lbs_remove_mesh(priv);
if (priv->wiphy_registered)
@@ -1083,8 +1027,6 @@ void lbs_remove_card(struct lbs_private *priv)
lbs_free_adapter(priv);
lbs_cfg_free(priv);
free_netdev(dev);
-
- lbs_deb_leave(LBS_DEB_MAIN);
}
EXPORT_SYMBOL_GPL(lbs_remove_card);
@@ -1105,8 +1047,6 @@ int lbs_start_card(struct lbs_private *priv)
struct net_device *dev = priv->dev;
int ret = -1;
- lbs_deb_enter(LBS_DEB_MAIN);
-
/* poke the firmware */
ret = lbs_setup_firmware(priv);
if (ret)
@@ -1133,7 +1073,6 @@ int lbs_start_card(struct lbs_private *priv)
ret = 0;
done:
- lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
return ret;
}
EXPORT_SYMBOL_GPL(lbs_start_card);
@@ -1143,16 +1082,14 @@ void lbs_stop_card(struct lbs_private *priv)
{
struct net_device *dev;
- lbs_deb_enter(LBS_DEB_MAIN);
-
if (!priv)
- goto out;
+ return;
dev = priv->dev;
/* If the netdev isn't registered, it means that lbs_start_card() was
* never called so we have nothing to do here. */
if (dev->reg_state != NETREG_REGISTERED)
- goto out;
+ return;
netif_stop_queue(dev);
netif_carrier_off(dev);
@@ -1160,9 +1097,6 @@ void lbs_stop_card(struct lbs_private *priv)
lbs_debugfs_remove_one(priv);
lbs_deinit_mesh(priv);
unregister_netdev(dev);
-
-out:
- lbs_deb_leave(LBS_DEB_MAIN);
}
EXPORT_SYMBOL_GPL(lbs_stop_card);
@@ -1171,7 +1105,6 @@ void lbs_queue_event(struct lbs_private *priv, u32 event)
{
unsigned long flags;
- lbs_deb_enter(LBS_DEB_THREAD);
spin_lock_irqsave(&priv->driver_lock, flags);
if (priv->psstate == PS_STATE_SLEEP)
@@ -1182,14 +1115,11 @@ void lbs_queue_event(struct lbs_private *priv, u32 event)
wake_up(&priv->waitq);
spin_unlock_irqrestore(&priv->driver_lock, flags);
- lbs_deb_leave(LBS_DEB_THREAD);
}
EXPORT_SYMBOL_GPL(lbs_queue_event);
void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx)
{
- lbs_deb_enter(LBS_DEB_THREAD);
-
if (priv->psstate == PS_STATE_SLEEP)
priv->psstate = PS_STATE_AWAKE;
@@ -1198,28 +1128,23 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx)
priv->resp_idx = resp_idx;
wake_up(&priv->waitq);
-
- lbs_deb_leave(LBS_DEB_THREAD);
}
EXPORT_SYMBOL_GPL(lbs_notify_command_response);
static int __init lbs_init_module(void)
{
- lbs_deb_enter(LBS_DEB_MAIN);
memset(&confirm_sleep, 0, sizeof(confirm_sleep));
confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE);
confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep));
confirm_sleep.action = cpu_to_le16(PS_MODE_ACTION_SLEEP_CONFIRMED);
lbs_debugfs_init();
- lbs_deb_leave(LBS_DEB_MAIN);
+
return 0;
}
static void __exit lbs_exit_module(void)
{
- lbs_deb_enter(LBS_DEB_MAIN);
lbs_debugfs_remove();
- lbs_deb_leave(LBS_DEB_MAIN);
}
module_init(lbs_init_module);
diff --git a/drivers/net/wireless/marvell/libertas/mesh.c b/drivers/net/wireless/marvell/libertas/mesh.c
index d0c881d..37ace5c 100644
--- a/drivers/net/wireless/marvell/libertas/mesh.c
+++ b/drivers/net/wireless/marvell/libertas/mesh.c
@@ -26,8 +26,6 @@ static int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
{
int ret;
- lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
cmd->hdr.result = 0;
@@ -36,7 +34,6 @@ static int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
- lbs_deb_leave(LBS_DEB_CMD);
return ret;
}
@@ -47,8 +44,6 @@ static int __lbs_mesh_config_send(struct lbs_private *priv,
int ret;
u16 command = CMD_MESH_CONFIG_OLD;
- lbs_deb_enter(LBS_DEB_CMD);
-
/*
* Command id is 0xac for v10 FW along with mesh interface
* id in bits 14-13-12.
@@ -66,7 +61,6 @@ static int __lbs_mesh_config_send(struct lbs_private *priv,
ret = lbs_cmd_with_response(priv, command, cmd);
- lbs_deb_leave(LBS_DEB_CMD);
return ret;
}
@@ -239,8 +233,9 @@ static ssize_t lbs_prb_rsp_limit_set(struct device *dev,
memset(&mesh_access, 0, sizeof(mesh_access));
mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET);
- if (!kstrtoul(buf, 10, &retry_limit))
- return -ENOTSUPP;
+ ret = kstrtoul(buf, 10, &retry_limit);
+ if (ret)
+ return ret;
if (retry_limit > 15)
return -ENOTSUPP;
@@ -823,8 +818,6 @@ int lbs_init_mesh(struct lbs_private *priv)
{
int ret = 0;
- lbs_deb_enter(LBS_DEB_MESH);
-
/* Determine mesh_fw_ver from fwrelease and fwcapinfo */
/* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */
/* 5.110.22 have mesh command with 0xa3 command id */
@@ -870,7 +863,6 @@ int lbs_init_mesh(struct lbs_private *priv)
ret = 1;
}
- lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
return ret;
}
@@ -887,14 +879,11 @@ int lbs_deinit_mesh(struct lbs_private *priv)
struct net_device *dev = priv->dev;
int ret = 0;
- lbs_deb_enter(LBS_DEB_MESH);
-
if (priv->mesh_tlv) {
device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
ret = 1;
}
- lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
return ret;
}
@@ -909,7 +898,6 @@ static int lbs_mesh_stop(struct net_device *dev)
{
struct lbs_private *priv = dev->ml_priv;
- lbs_deb_enter(LBS_DEB_MESH);
lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP,
lbs_mesh_get_channel(priv));
@@ -924,7 +912,6 @@ static int lbs_mesh_stop(struct net_device *dev)
if (!lbs_iface_active(priv))
lbs_stop_iface(priv);
- lbs_deb_leave(LBS_DEB_MESH);
return 0;
}
@@ -939,7 +926,6 @@ static int lbs_mesh_dev_open(struct net_device *dev)
struct lbs_private *priv = dev->ml_priv;
int ret = 0;
- lbs_deb_enter(LBS_DEB_NET);
if (!priv->iface_running) {
ret = lbs_start_iface(priv);
if (ret)
@@ -965,7 +951,6 @@ static int lbs_mesh_dev_open(struct net_device *dev)
lbs_mesh_get_channel(priv));
out:
- lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
return ret;
}
@@ -989,8 +974,6 @@ static int lbs_add_mesh(struct lbs_private *priv)
struct wireless_dev *mesh_wdev;
int ret = 0;
- lbs_deb_enter(LBS_DEB_MESH);
-
/* Allocate a virtual mesh device */
mesh_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
if (!mesh_wdev) {
@@ -1048,7 +1031,6 @@ err_free_wdev:
kfree(mesh_wdev);
done:
- lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
return ret;
}
@@ -1060,7 +1042,6 @@ void lbs_remove_mesh(struct lbs_private *priv)
if (!mesh_dev)
return;
- lbs_deb_enter(LBS_DEB_MESH);
netif_stop_queue(mesh_dev);
netif_carrier_off(mesh_dev);
sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
@@ -1069,7 +1050,6 @@ void lbs_remove_mesh(struct lbs_private *priv)
priv->mesh_dev = NULL;
kfree(mesh_dev->ieee80211_ptr);
free_netdev(mesh_dev);
- lbs_deb_leave(LBS_DEB_MESH);
}
@@ -1108,15 +1088,15 @@ void lbs_mesh_set_txpd(struct lbs_private *priv,
* Ethtool related
*/
-static const char * const mesh_stat_strings[] = {
- "drop_duplicate_bcast",
- "drop_ttl_zero",
- "drop_no_fwd_route",
- "drop_no_buffers",
- "fwded_unicast_cnt",
- "fwded_bcast_cnt",
- "drop_blind_table",
- "tx_failed_cnt"
+static const char mesh_stat_strings[MESH_STATS_NUM][ETH_GSTRING_LEN] = {
+ "drop_duplicate_bcast",
+ "drop_ttl_zero",
+ "drop_no_fwd_route",
+ "drop_no_buffers",
+ "fwded_unicast_cnt",
+ "fwded_bcast_cnt",
+ "drop_blind_table",
+ "tx_failed_cnt"
};
void lbs_mesh_ethtool_get_stats(struct net_device *dev,
@@ -1126,8 +1106,6 @@ void lbs_mesh_ethtool_get_stats(struct net_device *dev,
struct cmd_ds_mesh_access mesh_access;
int ret;
- lbs_deb_enter(LBS_DEB_ETHTOOL);
-
/* Get Mesh Statistics */
ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access);
@@ -1153,8 +1131,6 @@ void lbs_mesh_ethtool_get_stats(struct net_device *dev,
data[5] = priv->mstats.fwd_bcast_cnt;
data[6] = priv->mstats.drop_blind;
data[7] = priv->mstats.tx_failed_cnt;
-
- lbs_deb_enter(LBS_DEB_ETHTOOL);
}
int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset)
@@ -1170,18 +1146,9 @@ int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset)
void lbs_mesh_ethtool_get_strings(struct net_device *dev,
uint32_t stringset, uint8_t *s)
{
- int i;
-
- lbs_deb_enter(LBS_DEB_ETHTOOL);
-
switch (stringset) {
case ETH_SS_STATS:
- for (i = 0; i < MESH_STATS_NUM; i++) {
- memcpy(s + i * ETH_GSTRING_LEN,
- mesh_stat_strings[i],
- ETH_GSTRING_LEN);
- }
+ memcpy(s, mesh_stat_strings, sizeof(mesh_stat_strings));
break;
}
- lbs_deb_enter(LBS_DEB_ETHTOOL);
}
diff --git a/drivers/net/wireless/marvell/libertas/rx.c b/drivers/net/wireless/marvell/libertas/rx.c
index e446fed..7586ff6 100644
--- a/drivers/net/wireless/marvell/libertas/rx.c
+++ b/drivers/net/wireless/marvell/libertas/rx.c
@@ -65,8 +65,6 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00
};
- lbs_deb_enter(LBS_DEB_RX);
-
BUG_ON(!skb);
skb->ip_summed = CHECKSUM_NONE;
@@ -158,7 +156,6 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
ret = 0;
done:
- lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
return ret;
}
EXPORT_SYMBOL_GPL(lbs_process_rxed_packet);
@@ -221,8 +218,6 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
struct rx_radiotap_hdr radiotap_hdr;
struct rx_radiotap_hdr *pradiotap_hdr;
- lbs_deb_enter(LBS_DEB_RX);
-
p_rx_pkt = (struct rx80211packethdr *) skb->data;
prxpd = &p_rx_pkt->rx_pd;
@@ -262,7 +257,7 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
goto done;
}
- pradiotap_hdr = (void *)skb_push(skb, sizeof(struct rx_radiotap_hdr));
+ pradiotap_hdr = skb_push(skb, sizeof(struct rx_radiotap_hdr));
memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr));
priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
@@ -281,6 +276,5 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
ret = 0;
done:
- lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
return ret;
}
diff --git a/drivers/net/wireless/marvell/libertas/tx.c b/drivers/net/wireless/marvell/libertas/tx.c
index c025f9c..723ba5f 100644
--- a/drivers/net/wireless/marvell/libertas/tx.c
+++ b/drivers/net/wireless/marvell/libertas/tx.c
@@ -70,8 +70,6 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
uint16_t pkt_len;
netdev_tx_t ret = NETDEV_TX_OK;
- lbs_deb_enter(LBS_DEB_TX);
-
/* We need to protect against the queues being restarted before
we get round to stopping them */
spin_lock_irqsave(&priv->driver_lock, flags);
@@ -166,7 +164,6 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&priv->driver_lock, flags);
wake_up(&priv->waitq);
- lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret);
return ret;
}
diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c
index d803331..81228bf 100644
--- a/drivers/net/wireless/marvell/libertas_tf/main.c
+++ b/drivers/net/wireless/marvell/libertas_tf/main.c
@@ -260,7 +260,7 @@ static void lbtf_tx_work(struct work_struct *work)
len = skb->len;
info = IEEE80211_SKB_CB(skb);
- txpd = (struct txpd *) skb_push(skb, sizeof(struct txpd));
+ txpd = skb_push(skb, sizeof(struct txpd));
if (priv->surpriseremoved) {
dev_kfree_skb_any(skb);
diff --git a/drivers/net/wireless/marvell/mwifiex/11h.c b/drivers/net/wireless/marvell/mwifiex/11h.c
index 366eb49..238accf 100644
--- a/drivers/net/wireless/marvell/mwifiex/11h.c
+++ b/drivers/net/wireless/marvell/mwifiex/11h.c
@@ -128,9 +128,6 @@ void mwifiex_dfs_cac_work_queue(struct work_struct *work)
container_of(delayed_work, struct mwifiex_private,
dfs_cac_work);
- if (WARN_ON(!priv))
- return;
-
chandef = priv->dfs_chandef;
if (priv->wdev.cac_started) {
mwifiex_dbg(priv->adapter, MSG,
@@ -289,9 +286,6 @@ void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work)
container_of(delayed_work, struct mwifiex_private,
dfs_chan_sw_work);
- if (WARN_ON(!priv))
- return;
-
bss_cfg = &priv->bss_cfg;
if (!bss_cfg->beacon_period) {
mwifiex_dbg(priv->adapter, ERROR,
diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c
index c174e79..16c77c2 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n.c
@@ -653,11 +653,13 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
void mwifiex_11n_delba(struct mwifiex_private *priv, int tid)
{
struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr;
+ unsigned long flags;
+ spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
if (list_empty(&priv->rx_reorder_tbl_ptr)) {
dev_dbg(priv->adapter->dev,
"mwifiex_11n_delba: rx_reorder_tbl_ptr empty\n");
- return;
+ goto exit;
}
list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) {
@@ -666,9 +668,11 @@ void mwifiex_11n_delba(struct mwifiex_private *priv, int tid)
"Send delba to tid=%d, %pM\n",
tid, rx_reor_tbl_ptr->ta);
mwifiex_send_delba(priv, tid, rx_reor_tbl_ptr->ta, 0);
- return;
+ goto exit;
}
}
+exit:
+ spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
}
/*
@@ -764,14 +768,9 @@ void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra)
return;
spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
- list_for_each_entry_safe(tbl, tmp, &priv->tx_ba_stream_tbl_ptr, list) {
- if (!memcmp(tbl->ra, ra, ETH_ALEN)) {
- spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
- flags);
+ list_for_each_entry_safe(tbl, tmp, &priv->tx_ba_stream_tbl_ptr, list)
+ if (!memcmp(tbl->ra, ra, ETH_ALEN))
mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, tbl);
- spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
- }
- }
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
return;
diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
index a75013a..042a1d0 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
@@ -62,7 +62,7 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
};
struct tx_packet_hdr *tx_header;
- tx_header = (void *)skb_put(skb_aggr, sizeof(*tx_header));
+ tx_header = skb_put(skb_aggr, sizeof(*tx_header));
/* Copy DA and SA */
dt_offset = 2 * ETH_ALEN;
@@ -81,7 +81,7 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
tx_header->eth803_hdr.h_proto = htons(skb_src->len + LLC_SNAP_LEN);
/* Add payload */
- memcpy(skb_put(skb_aggr, skb_src->len), skb_src->data, skb_src->len);
+ skb_put_data(skb_aggr, skb_src->data, skb_src->len);
/* Add padding for new MSDU to start from 4 byte boundary */
*pad = (4 - ((unsigned long)skb_aggr->tail & 0x3)) % 4;
@@ -164,7 +164,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
int pad = 0, aggr_num = 0, ret;
struct mwifiex_tx_param tx_param;
struct txpd *ptx_pd = NULL;
- int headroom = adapter->iface_type == MWIFIEX_USB ? 0 : INTF_HEADER_LEN;
+ int headroom = adapter->intf_hdr_len;
skb_src = skb_peek(&pra_list->skb_head);
if (!skb_src) {
@@ -250,15 +250,15 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
return 0;
}
+ if (skb_src)
+ tx_param.next_pkt_len = skb_src->len + sizeof(struct txpd);
+ else
+ tx_param.next_pkt_len = 0;
+
if (adapter->iface_type == MWIFIEX_USB) {
ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
- skb_aggr, NULL);
+ skb_aggr, &tx_param);
} else {
- if (skb_src)
- tx_param.next_pkt_len =
- skb_src->len + sizeof(struct txpd);
- else
- tx_param.next_pkt_len = 0;
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
skb_aggr, &tx_param);
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 7ec06bf..06ad2d5 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -176,12 +176,10 @@ mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len)
memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type));
/* Add packet data and address4 */
- memcpy(skb_put(skb, sizeof(struct ieee80211_hdr_3addr)), buf,
- sizeof(struct ieee80211_hdr_3addr));
- memcpy(skb_put(skb, ETH_ALEN), addr, ETH_ALEN);
- memcpy(skb_put(skb, len - sizeof(struct ieee80211_hdr_3addr)),
- buf + sizeof(struct ieee80211_hdr_3addr),
- len - sizeof(struct ieee80211_hdr_3addr));
+ skb_put_data(skb, buf, sizeof(struct ieee80211_hdr_3addr));
+ skb_put_data(skb, addr, ETH_ALEN);
+ skb_put_data(skb, buf + sizeof(struct ieee80211_hdr_3addr),
+ len - sizeof(struct ieee80211_hdr_3addr));
skb->priority = LOW_PRIO_TID;
__net_timestamp(skb);
@@ -894,24 +892,20 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv,
priv->bss_num = mwifiex_get_unused_bss_num(adapter,
MWIFIEX_BSS_TYPE_STA);
priv->bss_role = MWIFIEX_BSS_ROLE_STA;
- priv->bss_type = MWIFIEX_BSS_TYPE_STA;
break;
case NL80211_IFTYPE_P2P_CLIENT:
priv->bss_num = mwifiex_get_unused_bss_num(adapter,
MWIFIEX_BSS_TYPE_P2P);
priv->bss_role = MWIFIEX_BSS_ROLE_STA;
- priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
break;
case NL80211_IFTYPE_P2P_GO:
priv->bss_num = mwifiex_get_unused_bss_num(adapter,
MWIFIEX_BSS_TYPE_P2P);
priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
- priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
break;
case NL80211_IFTYPE_AP:
priv->bss_num = mwifiex_get_unused_bss_num(adapter,
MWIFIEX_BSS_TYPE_UAP);
- priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
break;
default:
@@ -1983,7 +1977,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
mwifiex_dbg(priv->adapter, ERROR,
- "Failed to parse secuirty parameters!\n");
+ "Failed to parse security parameters!\n");
goto out;
}
@@ -2964,10 +2958,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
if (!dev) {
mwifiex_dbg(adapter, ERROR,
"no memory available for netdevice\n");
- memset(&priv->wdev, 0, sizeof(priv->wdev));
- priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
- priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
- return ERR_PTR(-ENOMEM);
+ ret = -ENOMEM;
+ goto err_alloc_netdev;
}
mwifiex_init_priv_params(priv, dev);
@@ -2976,11 +2968,11 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
ret = mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
HostCmd_ACT_GEN_SET, 0, NULL, true);
if (ret)
- return ERR_PTR(ret);
+ goto err_set_bss_mode;
ret = mwifiex_sta_init_cmd(priv, false, false);
if (ret)
- return ERR_PTR(ret);
+ goto err_sta_init;
mwifiex_setup_ht_caps(&wiphy->bands[NL80211_BAND_2GHZ]->ht_cap, priv);
if (adapter->is_hw_11ac_capable)
@@ -3011,31 +3003,14 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
SET_NETDEV_DEV(dev, adapter->dev);
- /* Register network device */
- if (register_netdevice(dev)) {
- mwifiex_dbg(adapter, ERROR,
- "cannot register virtual network device\n");
- free_netdev(dev);
- priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
- priv->netdev = NULL;
- memset(&priv->wdev, 0, sizeof(priv->wdev));
- priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
- return ERR_PTR(-EFAULT);
- }
-
priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s",
WQ_HIGHPRI |
WQ_MEM_RECLAIM |
WQ_UNBOUND, 1, name);
if (!priv->dfs_cac_workqueue) {
- mwifiex_dbg(adapter, ERROR,
- "cannot register virtual network device\n");
- free_netdev(dev);
- priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
- priv->netdev = NULL;
- memset(&priv->wdev, 0, sizeof(priv->wdev));
- priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
- return ERR_PTR(-ENOMEM);
+ mwifiex_dbg(adapter, ERROR, "cannot alloc DFS CAC queue\n");
+ ret = -ENOMEM;
+ goto err_alloc_cac;
}
INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue);
@@ -3044,22 +3019,22 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
WQ_HIGHPRI | WQ_UNBOUND |
WQ_MEM_RECLAIM, 1, name);
if (!priv->dfs_chan_sw_workqueue) {
- mwifiex_dbg(adapter, ERROR,
- "cannot register virtual network device\n");
- free_netdev(dev);
- priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
- priv->netdev = NULL;
- memset(&priv->wdev, 0, sizeof(priv->wdev));
- priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
- destroy_workqueue(priv->dfs_cac_workqueue);
- priv->dfs_cac_workqueue = NULL;
- return ERR_PTR(-ENOMEM);
+ mwifiex_dbg(adapter, ERROR, "cannot alloc DFS channel sw queue\n");
+ ret = -ENOMEM;
+ goto err_alloc_chsw;
}
INIT_DELAYED_WORK(&priv->dfs_chan_sw_work,
mwifiex_dfs_chan_sw_work_queue);
- sema_init(&priv->async_sem, 1);
+ mutex_init(&priv->async_mutex);
+
+ /* Register network device */
+ if (register_netdevice(dev)) {
+ mwifiex_dbg(adapter, ERROR, "cannot register network device\n");
+ ret = -EFAULT;
+ goto err_reg_netdev;
+ }
mwifiex_dbg(adapter, INFO,
"info: %s: Marvell 802.11 Adapter\n", dev->name);
@@ -3081,11 +3056,29 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
adapter->curr_iface_comb.p2p_intf++;
break;
default:
+ /* This should be dead code; checked above */
mwifiex_dbg(adapter, ERROR, "type not supported\n");
return ERR_PTR(-EINVAL);
}
return &priv->wdev;
+
+err_reg_netdev:
+ destroy_workqueue(priv->dfs_chan_sw_workqueue);
+ priv->dfs_chan_sw_workqueue = NULL;
+err_alloc_chsw:
+ destroy_workqueue(priv->dfs_cac_workqueue);
+ priv->dfs_cac_workqueue = NULL;
+err_alloc_cac:
+ free_netdev(dev);
+ priv->netdev = NULL;
+err_sta_init:
+err_set_bss_mode:
+err_alloc_netdev:
+ memset(&priv->wdev, 0, sizeof(priv->wdev));
+ priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+ priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+ return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
diff --git a/drivers/net/wireless/marvell/mwifiex/cfp.c b/drivers/net/wireless/marvell/mwifiex/cfp.c
index 1ff2205..6e29943 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfp.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfp.c
@@ -350,7 +350,7 @@ mwifiex_get_cfp(struct mwifiex_private *priv, u8 band, u16 channel, u32 freq)
}
}
if (i == sband->n_channels) {
- mwifiex_dbg(priv->adapter, ERROR,
+ mwifiex_dbg(priv->adapter, WARN,
"%s: cannot find cfp by band %d\t"
"& channel=%d freq=%d\n",
__func__, band, channel, freq);
diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index 0c3b217..8dad528 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -258,10 +258,10 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
if (ret == -EBUSY)
cmd_node->cmd_skb = NULL;
} else {
- skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN);
+ skb_push(cmd_node->cmd_skb, adapter->intf_hdr_len);
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
cmd_node->cmd_skb, NULL);
- skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN);
+ skb_pull(cmd_node->cmd_skb, adapter->intf_hdr_len);
}
if (ret == -1) {
@@ -351,10 +351,10 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
if (ret != -EBUSY)
dev_kfree_skb_any(sleep_cfm_tmp);
} else {
- skb_push(adapter->sleep_cfm, INTF_HEADER_LEN);
+ skb_push(adapter->sleep_cfm, adapter->intf_hdr_len);
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
adapter->sleep_cfm, NULL);
- skb_pull(adapter->sleep_cfm, INTF_HEADER_LEN);
+ skb_pull(adapter->sleep_cfm, adapter->intf_hdr_len);
}
if (ret == -1) {
@@ -622,8 +622,7 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
return -1;
}
- memset(skb_put(cmd_node->cmd_skb, sizeof(struct host_cmd_ds_command)),
- 0, sizeof(struct host_cmd_ds_command));
+ skb_put_zero(cmd_node->cmd_skb, sizeof(struct host_cmd_ds_command));
cmd_ptr = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
cmd_ptr->command = cpu_to_le16(cmd_no);
@@ -761,8 +760,6 @@ int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter)
}
cmd_node = list_first_entry(&adapter->cmd_pending_q,
struct cmd_ctrl_node, list);
- spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
- cmd_pending_q_flags);
host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
priv = cmd_node->priv;
@@ -771,11 +768,12 @@ int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter)
mwifiex_dbg(adapter, ERROR,
"%s: cannot send cmd in sleep state,\t"
"this should not happen\n", __func__);
+ spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
+ cmd_pending_q_flags);
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
return ret;
}
- spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags);
list_del(&cmd_node->list);
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
cmd_pending_q_flags);
@@ -1056,12 +1054,10 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
list_for_each_entry_safe(cmd_node, tmp_node,
&adapter->cmd_pending_q, list) {
list_del(&cmd_node->list);
- spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
if (cmd_node->wait_q_enabled)
adapter->cmd_wait_q.status = -1;
mwifiex_recycle_cmd_node(adapter, cmd_node);
- spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
}
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c
index ae2b69d..f6f105a 100644
--- a/drivers/net/wireless/marvell/mwifiex/debugfs.c
+++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c
@@ -1046,6 +1046,5 @@ mwifiex_debugfs_init(void)
void
mwifiex_debugfs_remove(void)
{
- if (mwifiex_dfs_dir)
- debugfs_remove(mwifiex_dfs_dir);
+ debugfs_remove(mwifiex_dfs_dir);
}
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index 6cf9ab9..9e75522 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -247,11 +247,6 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define MWIFIEX_DEF_AMPDU IEEE80211_HT_AMPDU_PARM_FACTOR
-#define GET_RXSTBC(x) (x & IEEE80211_HT_CAP_RX_STBC)
-#define MWIFIEX_RX_STBC1 0x0100
-#define MWIFIEX_RX_STBC12 0x0200
-#define MWIFIEX_RX_STBC123 0x0300
-
/* dev_cap bitmap
* BIT
* 0-16 reserved
@@ -405,6 +400,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define HostCmd_CMD_TDLS_OPER 0x0122
#define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG 0x0223
#define HostCmd_CMD_CHAN_REGION_CFG 0x0242
+#define HostCmd_CMD_PACKET_AGGR_CTRL 0x0251
#define PROTOCOL_NO_SECURITY 0x01
#define PROTOCOL_STATIC_WEP 0x02
@@ -2268,6 +2264,14 @@ struct host_cmd_ds_chan_region_cfg {
__le16 action;
} __packed;
+struct host_cmd_ds_pkt_aggr_ctrl {
+ __le16 action;
+ __le16 enable;
+ __le16 tx_aggr_max_size;
+ __le16 tx_aggr_max_num;
+ __le16 tx_aggr_align;
+} __packed;
+
struct host_cmd_ds_command {
__le16 command;
__le16 size;
@@ -2343,6 +2347,7 @@ struct host_cmd_ds_command {
struct host_cmd_ds_wakeup_reason hs_wakeup_reason;
struct host_cmd_ds_gtk_rekey_params rekey;
struct host_cmd_ds_chan_region_cfg reg_cfg;
+ struct host_cmd_ds_pkt_aggr_ctrl pkt_aggr_ctrl;
} params;
} __packed;
diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index 7569483..3ecb59f 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -217,6 +217,11 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
else
adapter->data_sent = false;
+ if (adapter->iface_type == MWIFIEX_USB)
+ adapter->intf_hdr_len = 0;
+ else
+ adapter->intf_hdr_len = INTF_HEADER_LEN;
+
adapter->cmd_resp_received = false;
adapter->event_received = false;
adapter->data_received = false;
@@ -409,11 +414,6 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
static void
mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
{
- if (!adapter) {
- pr_err("%s: adapter is NULL\n", __func__);
- return;
- }
-
del_timer(&adapter->wakeup_timer);
mwifiex_cancel_all_pending_cmd(adapter);
wake_up_interruptible(&adapter->cmd_wait_q.wait);
@@ -439,7 +439,6 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
struct mwifiex_private *priv;
s32 i, j;
- spin_lock_init(&adapter->mwifiex_lock);
spin_lock_init(&adapter->int_lock);
spin_lock_init(&adapter->main_proc_lock);
spin_lock_init(&adapter->mwifiex_cmd_lock);
@@ -670,8 +669,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
mwifiex_clean_auto_tdls(priv);
mwifiex_abort_cac(priv);
- mwifiex_clean_txrx(priv);
- mwifiex_delete_bss_prio_tbl(priv);
+ mwifiex_free_priv(priv);
}
}
@@ -694,11 +692,8 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
- spin_lock(&adapter->mwifiex_lock);
-
mwifiex_adapter_cleanup(adapter);
- spin_unlock(&adapter->mwifiex_lock);
adapter->hw_status = MWIFIEX_HW_STATUS_NOT_READY;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 39b6b5e..f2600b8 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -44,6 +44,10 @@ bool mfg_mode;
module_param(mfg_mode, bool, 0);
MODULE_PARM_DESC(mfg_mode, "manufacturing mode enable:1, disable:0");
+bool aggr_ctrl;
+module_param(aggr_ctrl, bool, 0000);
+MODULE_PARM_DESC(aggr_ctrl, "usb tx aggreataon enable:1, disable:0");
+
/*
* This function registers the device and performs all the necessary
* initializations.
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index bb2a467..f8cf307 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -60,6 +60,7 @@
extern const char driver_version[];
extern bool mfg_mode;
+extern bool aggr_ctrl;
struct mwifiex_adapter;
struct mwifiex_private;
@@ -628,7 +629,7 @@ struct mwifiex_private {
struct dentry *dfs_dev_dir;
#endif
u16 current_key_index;
- struct semaphore async_sem;
+ struct mutex async_mutex;
struct cfg80211_scan_request *scan_request;
u8 cfg_bssid[6];
struct wps wps;
@@ -798,6 +799,18 @@ struct mwifiex_auto_tdls_peer {
u8 do_setup;
};
+#define MWIFIEX_TYPE_AGGR_DATA_V2 11
+#define MWIFIEX_BUS_AGGR_MODE_LEN_V2 (2)
+#define MWIFIEX_BUS_AGGR_MAX_LEN 16000
+#define MWIFIEX_BUS_AGGR_MAX_NUM 10
+struct bus_aggr_params {
+ u16 enable;
+ u16 mode;
+ u16 tx_aggr_max_size;
+ u16 tx_aggr_max_num;
+ u16 tx_aggr_align;
+};
+
struct mwifiex_if_ops {
int (*init_if) (struct mwifiex_adapter *);
void (*cleanup_if) (struct mwifiex_adapter *);
@@ -849,6 +862,7 @@ struct mwifiex_adapter {
u8 perm_addr[ETH_ALEN];
bool surprise_removed;
u32 fw_release_number;
+ u8 intf_hdr_len;
u16 init_wait_q_woken;
wait_queue_head_t init_wait_q;
void *card;
@@ -870,8 +884,6 @@ struct mwifiex_adapter {
bool rx_locked;
bool main_locked;
struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM];
- /* spin lock for init/shutdown */
- spinlock_t mwifiex_lock;
/* spin lock for main process */
spinlock_t main_proc_lock;
u32 mwifiex_processing;
@@ -1017,6 +1029,8 @@ struct mwifiex_adapter {
/* Wake-on-WLAN (WoWLAN) */
int irq_wakeup;
bool wake_by_wifi;
+ /* Aggregation parameters*/
+ struct bus_aggr_params bus_aggr;
};
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
@@ -1235,7 +1249,8 @@ mwifiex_queuing_ra_based(struct mwifiex_private *priv)
* Currently we assume if we are in Infra, then DA=RA. This might not be
* true in the future
*/
- if ((priv->bss_mode == NL80211_IFTYPE_STATION) &&
+ if ((priv->bss_mode == NL80211_IFTYPE_STATION ||
+ priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) &&
(GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA))
return false;
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index ac62bce..b53ecf1 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -370,7 +370,6 @@ static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare)
* PCIe and HW.
*/
mwifiex_shutdown_sw(adapter);
- adapter->surprise_removed = true;
clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
} else {
@@ -378,7 +377,6 @@ static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare)
* after performing FLR respectively. Reconfigure the software
* and firmware including firmware redownload
*/
- adapter->surprise_removed = false;
ret = mwifiex_reinit_sw(adapter);
if (ret) {
dev_err(&pdev->dev, "reinit failed: %d\n", ret);
@@ -1391,7 +1389,7 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
* first 2 bytes for len, next 2 bytes is for type
*/
rx_len = get_unaligned_le16(skb_data->data);
- if (WARN_ON(rx_len <= INTF_HEADER_LEN ||
+ if (WARN_ON(rx_len <= adapter->intf_hdr_len ||
rx_len > MWIFIEX_RX_DATA_BUF_SIZE)) {
mwifiex_dbg(adapter, ERROR,
"Invalid RX len %d, Rd=%#x, Wr=%#x\n",
@@ -1402,7 +1400,7 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
mwifiex_dbg(adapter, DATA,
"info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
card->rxbd_rdptr, wrptr, rx_len);
- skb_pull(skb_data, INTF_HEADER_LEN);
+ skb_pull(skb_data, adapter->intf_hdr_len);
if (adapter->rx_work_enabled) {
skb_queue_tail(&adapter->rx_data_q, skb_data);
adapter->data_received = true;
@@ -1736,7 +1734,7 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
MWIFIEX_MAX_DELAY_COUNT);
mwifiex_unmap_pci_memory(adapter, skb,
PCI_DMA_FROMDEVICE);
- skb_pull(skb, INTF_HEADER_LEN);
+ skb_pull(skb, adapter->intf_hdr_len);
while (reg->sleep_cookie && (count++ < 10) &&
mwifiex_pcie_ok_to_access_hw(adapter))
usleep_range(50, 60);
@@ -1749,12 +1747,12 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
}
memcpy(adapter->upld_buf, skb->data,
min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
- skb_push(skb, INTF_HEADER_LEN);
+ skb_push(skb, adapter->intf_hdr_len);
if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
PCI_DMA_FROMDEVICE))
return -1;
} else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
- skb_pull(skb, INTF_HEADER_LEN);
+ skb_pull(skb, adapter->intf_hdr_len);
adapter->curr_cmd->resp_skb = skb;
adapter->cmd_resp_received = true;
/* Take the pointer and set it to CMD node and will
@@ -1791,7 +1789,7 @@ static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
if (skb) {
card->cmdrsp_buf = skb;
- skb_push(card->cmdrsp_buf, INTF_HEADER_LEN);
+ skb_push(card->cmdrsp_buf, adapter->intf_hdr_len);
if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
PCI_DMA_FROMDEVICE))
return -1;
@@ -1856,14 +1854,15 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
desc = card->evtbd_ring[rdptr];
memset(desc, 0, sizeof(*desc));
- event = get_unaligned_le32(&skb_cmd->data[INTF_HEADER_LEN]);
+ event = get_unaligned_le32(
+ &skb_cmd->data[adapter->intf_hdr_len]);
adapter->event_cause = event;
/* The first 4bytes will be the event transfer header
len is 2 bytes followed by type which is 2 bytes */
memcpy(&data_len, skb_cmd->data, sizeof(__le16));
evt_len = le16_to_cpu(data_len);
skb_trim(skb_cmd, evt_len);
- skb_pull(skb_cmd, INTF_HEADER_LEN);
+ skb_pull(skb_cmd, adapter->intf_hdr_len);
mwifiex_dbg(adapter, EVENT,
"info: Event length: %d\n", evt_len);
@@ -1922,7 +1921,7 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
}
if (!card->evt_buf_list[rdptr]) {
- skb_push(skb, INTF_HEADER_LEN);
+ skb_push(skb, adapter->intf_hdr_len);
skb_put(skb, MAX_EVENT_SIZE - skb->len);
if (mwifiex_map_pci_memory(adapter, skb,
MAX_EVENT_SIZE,
@@ -2380,11 +2379,6 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
struct pcie_service_card *card;
struct mwifiex_adapter *adapter;
- if (!pdev) {
- pr_err("info: %s: pdev is NULL\n", __func__);
- goto exit;
- }
-
card = pci_get_drvdata(pdev);
if (!card->adapter) {
@@ -2822,6 +2816,13 @@ static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
mwifiex_upload_device_dump(adapter, drv_info, drv_info_size);
}
+static void mwifiex_pcie_card_reset_work(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+
+ pci_reset_function(card->dev);
+}
+
static void mwifiex_pcie_work(struct work_struct *work)
{
struct pcie_service_card *card =
@@ -2830,6 +2831,9 @@ static void mwifiex_pcie_work(struct work_struct *work)
if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
&card->work_flags))
mwifiex_pcie_device_dump_work(card->adapter);
+ if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET,
+ &card->work_flags))
+ mwifiex_pcie_card_reset_work(card->adapter);
}
/* This function dumps FW information */
@@ -2837,12 +2841,72 @@ static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
- if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags))
- return;
+ if (!test_and_set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
+ &card->work_flags))
+ schedule_work(&card->work);
+}
+
+static void mwifiex_pcie_card_reset(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+
+ if (!test_and_set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags))
+ schedule_work(&card->work);
+}
+
+static int mwifiex_pcie_alloc_buffers(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+ int ret;
+
+ card->cmdrsp_buf = NULL;
+ ret = mwifiex_pcie_create_txbd_ring(adapter);
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR, "Failed to create txbd ring\n");
+ goto err_cre_txbd;
+ }
+
+ ret = mwifiex_pcie_create_rxbd_ring(adapter);
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR, "Failed to create rxbd ring\n");
+ goto err_cre_rxbd;
+ }
+
+ ret = mwifiex_pcie_create_evtbd_ring(adapter);
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR, "Failed to create evtbd ring\n");
+ goto err_cre_evtbd;
+ }
- set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
+ ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR, "Failed to allocate cmdbuf buffer\n");
+ goto err_alloc_cmdbuf;
+ }
- schedule_work(&card->work);
+ if (reg->sleep_cookie) {
+ ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
+ if (ret) {
+ mwifiex_dbg(adapter, ERROR, "Failed to allocate sleep_cookie buffer\n");
+ goto err_alloc_cookie;
+ }
+ } else {
+ card->sleep_cookie_vbase = NULL;
+ }
+
+ return 0;
+
+err_alloc_cookie:
+ mwifiex_pcie_delete_cmdrsp_buf(adapter);
+err_alloc_cmdbuf:
+ mwifiex_pcie_delete_evtbd_ring(adapter);
+err_cre_evtbd:
+ mwifiex_pcie_delete_rxbd_ring(adapter);
+err_cre_rxbd:
+ mwifiex_pcie_delete_txbd_ring(adapter);
+err_cre_txbd:
+ return ret;
}
static void mwifiex_pcie_free_buffers(struct mwifiex_adapter *adapter)
@@ -2862,20 +2926,12 @@ static void mwifiex_pcie_free_buffers(struct mwifiex_adapter *adapter)
/*
* This function initializes the PCI-E host memory space, WCB rings, etc.
- *
- * The following initializations steps are followed -
- * - Allocate TXBD ring buffers
- * - Allocate RXBD ring buffers
- * - Allocate event BD ring buffers
- * - Allocate command response ring buffer
- * - Allocate sleep cookie buffer
*/
static int mwifiex_init_pcie(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
int ret;
struct pci_dev *pdev = card->dev;
- const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
pci_set_drvdata(pdev, card);
@@ -2924,37 +2980,13 @@ static int mwifiex_init_pcie(struct mwifiex_adapter *adapter)
pr_notice("PCI memory map Virt0: %p PCI memory map Virt2: %p\n",
card->pci_mmap, card->pci_mmap1);
- card->cmdrsp_buf = NULL;
- ret = mwifiex_pcie_create_txbd_ring(adapter);
- if (ret)
- goto err_cre_txbd;
- ret = mwifiex_pcie_create_rxbd_ring(adapter);
+ ret = mwifiex_pcie_alloc_buffers(adapter);
if (ret)
- goto err_cre_rxbd;
- ret = mwifiex_pcie_create_evtbd_ring(adapter);
- if (ret)
- goto err_cre_evtbd;
- ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
- if (ret)
- goto err_alloc_cmdbuf;
- if (reg->sleep_cookie) {
- ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
- if (ret)
- goto err_alloc_cookie;
- } else {
- card->sleep_cookie_vbase = NULL;
- }
- return ret;
+ goto err_alloc_buffers;
-err_alloc_cookie:
- mwifiex_pcie_delete_cmdrsp_buf(adapter);
-err_alloc_cmdbuf:
- mwifiex_pcie_delete_evtbd_ring(adapter);
-err_cre_evtbd:
- mwifiex_pcie_delete_rxbd_ring(adapter);
-err_cre_rxbd:
- mwifiex_pcie_delete_txbd_ring(adapter);
-err_cre_txbd:
+ return 0;
+
+err_alloc_buffers:
pci_iounmap(pdev, card->pci_mmap1);
err_iomap2:
pci_release_region(pdev, 2);
@@ -3168,73 +3200,25 @@ static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
card->adapter = NULL;
}
-/* This function initializes the PCI-E host memory space, WCB rings, etc.
- *
- * The following initializations steps are followed -
- * - Allocate TXBD ring buffers
- * - Allocate RXBD ring buffers
- * - Allocate event BD ring buffers
- * - Allocate command response ring buffer
- * - Allocate sleep cookie buffer
- * Part of mwifiex_init_pcie(), not reset the PCIE registers
+/*
+ * This function initializes the PCI-E host memory space, WCB rings, etc.,
+ * similar to mwifiex_init_pcie(), but without resetting PCI-E state.
*/
static void mwifiex_pcie_up_dev(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
int ret;
struct pci_dev *pdev = card->dev;
- const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
/* tx_buf_size might be changed to 3584 by firmware during
* data transfer, we should reset it to default size.
*/
adapter->tx_buf_size = card->pcie.tx_buf_size;
- card->cmdrsp_buf = NULL;
- ret = mwifiex_pcie_create_txbd_ring(adapter);
- if (ret) {
- mwifiex_dbg(adapter, ERROR, "Failed to create txbd ring\n");
- goto err_cre_txbd;
- }
-
- ret = mwifiex_pcie_create_rxbd_ring(adapter);
- if (ret) {
- mwifiex_dbg(adapter, ERROR, "Failed to create rxbd ring\n");
- goto err_cre_rxbd;
- }
-
- ret = mwifiex_pcie_create_evtbd_ring(adapter);
- if (ret) {
- mwifiex_dbg(adapter, ERROR, "Failed to create evtbd ring\n");
- goto err_cre_evtbd;
- }
-
- ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
- if (ret) {
- mwifiex_dbg(adapter, ERROR, "Failed to allocate cmdbuf buffer\n");
- goto err_alloc_cmdbuf;
- }
-
- if (reg->sleep_cookie) {
- ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
- if (ret) {
- mwifiex_dbg(adapter, ERROR, "Failed to allocate sleep_cookie buffer\n");
- goto err_alloc_cookie;
- }
- } else {
- card->sleep_cookie_vbase = NULL;
- }
- return;
+ ret = mwifiex_pcie_alloc_buffers(adapter);
+ if (!ret)
+ return;
-err_alloc_cookie:
- mwifiex_pcie_delete_cmdrsp_buf(adapter);
-err_alloc_cmdbuf:
- mwifiex_pcie_delete_evtbd_ring(adapter);
-err_cre_evtbd:
- mwifiex_pcie_delete_rxbd_ring(adapter);
-err_cre_rxbd:
- mwifiex_pcie_delete_txbd_ring(adapter);
-err_cre_txbd:
pci_iounmap(pdev, card->pci_mmap1);
}
@@ -3274,6 +3258,7 @@ static struct mwifiex_if_ops pcie_ops = {
.cleanup_mpa_buf = NULL,
.init_fw_port = mwifiex_pcie_init_fw_port,
.clean_pcie_ring = mwifiex_clean_pcie_ring_buf,
+ .card_reset = mwifiex_pcie_card_reset,
.reg_dump = mwifiex_pcie_reg_dump,
.device_dump = mwifiex_pcie_device_dump,
.down_dev = mwifiex_pcie_down_dev,
diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c
index ce6936d..ae9630b 100644
--- a/drivers/net/wireless/marvell/mwifiex/scan.c
+++ b/drivers/net/wireless/marvell/mwifiex/scan.c
@@ -2809,7 +2809,7 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
{
int ret;
- if (down_interruptible(&priv->async_sem)) {
+ if (mutex_lock_interruptible(&priv->async_mutex)) {
mwifiex_dbg(priv->adapter, ERROR,
"%s: acquire semaphore fail\n",
__func__);
@@ -2825,7 +2825,7 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
/* Normal scan */
ret = mwifiex_scan_networks(priv, NULL);
- up(&priv->async_sem);
+ mutex_unlock(&priv->async_mutex);
return ret;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index 0af1c67..f81a006 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -1125,7 +1125,7 @@ static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter,
data = skb->data;
total_pkt_len = skb->len;
- while (total_pkt_len >= (SDIO_HEADER_OFFSET + INTF_HEADER_LEN)) {
+ while (total_pkt_len >= (SDIO_HEADER_OFFSET + adapter->intf_hdr_len)) {
if (total_pkt_len < adapter->sdio_rx_block_size)
break;
blk_num = *(data + BLOCK_NUMBER_OFFSET);
@@ -1152,7 +1152,7 @@ static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter,
break;
skb_put(skb_deaggr, pkt_len);
memcpy(skb_deaggr->data, data + SDIO_HEADER_OFFSET, pkt_len);
- skb_pull(skb_deaggr, INTF_HEADER_LEN);
+ skb_pull(skb_deaggr, adapter->intf_hdr_len);
mwifiex_handle_rx_packet(adapter, skb_deaggr);
data += blk_size;
@@ -1178,7 +1178,7 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
if (upld_typ != MWIFIEX_TYPE_AGGR_DATA) {
skb_trim(skb, pkt_len);
- skb_pull(skb, INTF_HEADER_LEN);
+ skb_pull(skb, adapter->intf_hdr_len);
}
switch (upld_typ) {
@@ -1537,7 +1537,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
rx_len = card->mp_regs[reg->cmd_rd_len_1] << 8;
rx_len |= (u16)card->mp_regs[reg->cmd_rd_len_0];
rx_blocks = DIV_ROUND_UP(rx_len, MWIFIEX_SDIO_BLOCK_SIZE);
- if (rx_len <= INTF_HEADER_LEN ||
+ if (rx_len <= adapter->intf_hdr_len ||
(rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
MWIFIEX_RX_DATA_BUF_SIZE)
return -1;
@@ -1635,7 +1635,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
rx_blocks =
(rx_len + MWIFIEX_SDIO_BLOCK_SIZE -
1) / MWIFIEX_SDIO_BLOCK_SIZE;
- if (rx_len <= INTF_HEADER_LEN ||
+ if (rx_len <= adapter->intf_hdr_len ||
(card->mpa_rx.enabled &&
((rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
card->mpa_rx.buf_size))) {
@@ -1896,7 +1896,7 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter,
adapter->cmd_sent = true;
/* Type must be MWIFIEX_TYPE_CMD */
- if (pkt_len <= INTF_HEADER_LEN ||
+ if (pkt_len <= adapter->intf_hdr_len ||
pkt_len > MWIFIEX_UPLD_SIZE)
mwifiex_dbg(adapter, ERROR,
"%s: payload=%p, nb=%d\n",
@@ -2533,12 +2533,8 @@ static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter)
{
struct sdio_mmc_card *card = adapter->card;
- if (test_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags))
- return;
-
- set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
-
- schedule_work(&card->work);
+ if (!test_and_set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags))
+ schedule_work(&card->work);
}
/* This function dumps FW information */
@@ -2546,11 +2542,9 @@ static void mwifiex_sdio_device_dump(struct mwifiex_adapter *adapter)
{
struct sdio_mmc_card *card = adapter->card;
- if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags))
- return;
-
- set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
- schedule_work(&card->work);
+ if (!test_and_set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
+ &card->work_flags))
+ schedule_work(&card->work);
}
/* Function to dump SDIO function registers and SDIO scratch registers in case
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
index 83916c1..534d94a 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
@@ -2064,6 +2064,15 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
case HostCmd_CMD_11AC_CFG:
ret = mwifiex_cmd_11ac_cfg(priv, cmd_ptr, cmd_action, data_buf);
break;
+ case HostCmd_CMD_PACKET_AGGR_CTRL:
+ cmd_ptr->command = cpu_to_le16(cmd_no);
+ cmd_ptr->params.pkt_aggr_ctrl.action = cpu_to_le16(cmd_action);
+ cmd_ptr->params.pkt_aggr_ctrl.enable =
+ cpu_to_le16(*(u16 *)data_buf);
+ cmd_ptr->size =
+ cpu_to_le16(sizeof(struct host_cmd_ds_pkt_aggr_ctrl) +
+ S_DS_GEN);
+ break;
case HostCmd_CMD_P2P_MODE_CFG:
cmd_ptr->command = cpu_to_le16(cmd_no);
cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action);
@@ -2241,6 +2250,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
enum state_11d_t state_11d;
struct mwifiex_ds_11n_tx_cfg tx_cfg;
u8 sdio_sp_rx_aggr_enable;
+ u16 packet_aggr_enable;
int data;
if (first_sta) {
@@ -2387,6 +2397,14 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
"11D: failed to enable 11D\n");
}
+ /* Pacekt aggregation handshake with firmware */
+ if (aggr_ctrl) {
+ packet_aggr_enable = true;
+ mwifiex_send_cmd(priv, HostCmd_CMD_PACKET_AGGR_CTRL,
+ HostCmd_ACT_GEN_SET, 0,
+ &packet_aggr_enable, true);
+ }
+
/* Send cmd to FW to configure 11n specific configuration
* (Short GI, Channel BW, Green field support etc.) for transmit
*/
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
index f1d1f56..2945775 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
@@ -1154,6 +1154,27 @@ static int mwifiex_ret_chan_region_cfg(struct mwifiex_private *priv,
return 0;
}
+static int mwifiex_ret_pkt_aggr_ctrl(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *resp)
+{
+ struct host_cmd_ds_pkt_aggr_ctrl *pkt_aggr_ctrl =
+ &resp->params.pkt_aggr_ctrl;
+ struct mwifiex_adapter *adapter = priv->adapter;
+
+ adapter->bus_aggr.enable = le16_to_cpu(pkt_aggr_ctrl->enable);
+ if (adapter->bus_aggr.enable)
+ adapter->intf_hdr_len = INTF_HEADER_LEN;
+ adapter->bus_aggr.mode = MWIFIEX_BUS_AGGR_MODE_LEN_V2;
+ adapter->bus_aggr.tx_aggr_max_size =
+ le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_size);
+ adapter->bus_aggr.tx_aggr_max_num =
+ le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_num);
+ adapter->bus_aggr.tx_aggr_align =
+ le16_to_cpu(pkt_aggr_ctrl->tx_aggr_align);
+
+ return 0;
+}
+
/*
* This function handles the command responses.
*
@@ -1255,6 +1276,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
break;
case HostCmd_CMD_11AC_CFG:
break;
+ case HostCmd_CMD_PACKET_AGGR_CTRL:
+ ret = mwifiex_ret_pkt_aggr_ctrl(priv, resp);
+ break;
case HostCmd_CMD_P2P_MODE_CFG:
ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf);
break;
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_tx.c b/drivers/net/wireless/marvell/mwifiex/sta_tx.c
index f6683ea..620f865 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_tx.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_tx.c
@@ -49,8 +49,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
unsigned int pad;
u16 pkt_type, pkt_offset;
- int hroom = (priv->adapter->iface_type == MWIFIEX_USB) ? 0 :
- INTF_HEADER_LEN;
+ int hroom = adapter->intf_hdr_len;
if (!skb->len) {
mwifiex_dbg(adapter, ERROR,
@@ -116,7 +115,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
local_tx_pd->tx_pkt_offset = cpu_to_le16(pkt_offset);
- /* make space for INTF_HEADER_LEN */
+ /* make space for adapter->intf_hdr_len */
skb_push(skb, hroom);
if (!local_tx_pd->tx_control)
@@ -165,8 +164,9 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
memset(tx_info, 0, sizeof(*tx_info));
tx_info->bss_num = priv->bss_num;
tx_info->bss_type = priv->bss_type;
- tx_info->pkt_len = data_len - (sizeof(struct txpd) + INTF_HEADER_LEN);
- skb_reserve(skb, sizeof(struct txpd) + INTF_HEADER_LEN);
+ tx_info->pkt_len = data_len -
+ (sizeof(struct txpd) + adapter->intf_hdr_len);
+ skb_reserve(skb, sizeof(struct txpd) + adapter->intf_hdr_len);
skb_push(skb, sizeof(struct txpd));
local_tx_pd = (struct txpd *) skb->data;
@@ -177,11 +177,11 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
local_tx_pd->bss_num = priv->bss_num;
local_tx_pd->bss_type = priv->bss_type;
+ skb_push(skb, adapter->intf_hdr_len);
if (adapter->iface_type == MWIFIEX_USB) {
ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
skb, NULL);
} else {
- skb_push(skb, INTF_HEADER_LEN);
tx_param.next_pkt_len = 0;
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
skb, &tx_param);
diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c
index 7d0d3ff..39cd677 100644
--- a/drivers/net/wireless/marvell/mwifiex/tdls.c
+++ b/drivers/net/wireless/marvell/mwifiex/tdls.c
@@ -55,11 +55,8 @@ static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
} else {
tid_list = &priv->wmm.tid_tbl_ptr[tid_down].ra_list;
- if (!list_empty(tid_list))
- ra_list = list_first_entry(tid_list,
- struct mwifiex_ra_list_tbl, list);
- else
- ra_list = NULL;
+ ra_list = list_first_entry_or_null(tid_list,
+ struct mwifiex_ra_list_tbl, list);
tx_info->flags &= ~MWIFIEX_BUF_FLAG_TDLS_PKT;
}
@@ -161,7 +158,7 @@ static void mwifiex_tdls_add_aid(struct mwifiex_private *priv,
u8 *pos;
assoc_rsp = (struct ieee_types_assoc_rsp *)&priv->assoc_rsp_buf;
- pos = (void *)skb_put(skb, 4);
+ pos = skb_put(skb, 4);
*pos++ = WLAN_EID_AID;
*pos++ = 2;
memcpy(pos, &assoc_rsp->a_id, sizeof(assoc_rsp->a_id));
@@ -175,7 +172,7 @@ static int mwifiex_tdls_add_vht_capab(struct mwifiex_private *priv,
struct ieee80211_vht_cap vht_cap;
u8 *pos;
- pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
+ pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
*pos++ = WLAN_EID_VHT_CAPABILITY;
*pos++ = sizeof(struct ieee80211_vht_cap);
@@ -210,7 +207,7 @@ mwifiex_tdls_add_ht_oper(struct mwifiex_private *priv, const u8 *mac,
return 0;
}
- pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_operation) + 2);
+ pos = skb_put(skb, sizeof(struct ieee80211_ht_operation) + 2);
*pos++ = WLAN_EID_HT_OPERATION;
*pos++ = sizeof(struct ieee80211_ht_operation);
ht_oper = (void *)pos;
@@ -275,7 +272,7 @@ static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv,
ap_vht_cap = bss_desc->bcn_vht_cap;
}
- pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_operation) + 2);
+ pos = skb_put(skb, sizeof(struct ieee80211_vht_operation) + 2);
*pos++ = WLAN_EID_VHT_OPERATION;
*pos++ = sizeof(struct ieee80211_vht_operation);
vht_oper = (struct ieee80211_vht_operation *)pos;
@@ -362,7 +359,7 @@ static void mwifiex_tdls_add_ext_capab(struct mwifiex_private *priv,
{
struct ieee_types_extcap *extcap;
- extcap = (void *)skb_put(skb, sizeof(struct ieee_types_extcap));
+ extcap = skb_put(skb, sizeof(struct ieee_types_extcap));
extcap->ieee_hdr.element_id = WLAN_EID_EXT_CAPABILITY;
extcap->ieee_hdr.len = 8;
memset(extcap->ext_capab, 0, 8);
@@ -375,7 +372,7 @@ static void mwifiex_tdls_add_ext_capab(struct mwifiex_private *priv,
static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb)
{
- u8 *pos = (void *)skb_put(skb, 3);
+ u8 *pos = skb_put(skb, 3);
*pos++ = WLAN_EID_QOS_CAPA;
*pos++ = 1;
@@ -391,8 +388,7 @@ mwifiex_tdls_add_wmm_param_ie(struct mwifiex_private *priv, struct sk_buff *skb)
u8 ac_be[] = {0x03, 0xa4, 0x00, 0x00};
u8 ac_bk[] = {0x27, 0xa4, 0x00, 0x00};
- wmm = (void *)skb_put(skb, sizeof(*wmm));
- memset(wmm, 0, sizeof(*wmm));
+ wmm = skb_put_zero(skb, sizeof(*wmm));
wmm->element_id = WLAN_EID_VENDOR_SPECIFIC;
wmm->len = sizeof(*wmm) - 2;
@@ -417,8 +413,8 @@ mwifiex_add_wmm_info_ie(struct mwifiex_private *priv, struct sk_buff *skb,
{
u8 *buf;
- buf = (void *)skb_put(skb, MWIFIEX_TDLS_WMM_INFO_SIZE +
- sizeof(struct ieee_types_header));
+ buf = skb_put(skb,
+ MWIFIEX_TDLS_WMM_INFO_SIZE + sizeof(struct ieee_types_header));
*buf++ = WLAN_EID_VENDOR_SPECIFIC;
*buf++ = 7; /* len */
@@ -435,7 +431,7 @@ static void mwifiex_tdls_add_bss_co_2040(struct sk_buff *skb)
{
struct ieee_types_bss_co_2040 *bssco;
- bssco = (void *)skb_put(skb, sizeof(struct ieee_types_bss_co_2040));
+ bssco = skb_put(skb, sizeof(struct ieee_types_bss_co_2040));
bssco->ieee_hdr.element_id = WLAN_EID_BSS_COEX_2040;
bssco->ieee_hdr.len = sizeof(struct ieee_types_bss_co_2040) -
sizeof(struct ieee_types_header);
@@ -447,8 +443,8 @@ static void mwifiex_tdls_add_supported_chan(struct sk_buff *skb)
struct ieee_types_generic *supp_chan;
u8 chan_supp[] = {1, 11};
- supp_chan = (void *)skb_put(skb, (sizeof(struct ieee_types_header) +
- sizeof(chan_supp)));
+ supp_chan = skb_put(skb,
+ (sizeof(struct ieee_types_header) + sizeof(chan_supp)));
supp_chan->ieee_hdr.element_id = WLAN_EID_SUPPORTED_CHANNELS;
supp_chan->ieee_hdr.len = sizeof(chan_supp);
memcpy(supp_chan->data, chan_supp, sizeof(chan_supp));
@@ -459,8 +455,8 @@ static void mwifiex_tdls_add_oper_class(struct sk_buff *skb)
struct ieee_types_generic *reg_class;
u8 rc_list[] = {1,
1, 2, 3, 4, 12, 22, 23, 24, 25, 27, 28, 29, 30, 32, 33};
- reg_class = (void *)skb_put(skb, (sizeof(struct ieee_types_header) +
- sizeof(rc_list)));
+ reg_class = skb_put(skb,
+ (sizeof(struct ieee_types_header) + sizeof(rc_list)));
reg_class->ieee_hdr.element_id = WLAN_EID_SUPPORTED_REGULATORY_CLASSES;
reg_class->ieee_hdr.len = sizeof(rc_list);
memcpy(reg_class->data, rc_list, sizeof(rc_list));
@@ -479,7 +475,7 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
- tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
+ tf = skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
memcpy(tf->da, peer, ETH_ALEN);
memcpy(tf->sa, priv->curr_addr, ETH_ALEN);
tf->ether_type = cpu_to_be16(ETH_P_TDLS);
@@ -498,7 +494,7 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
return ret;
}
- pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
+ pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
*pos++ = WLAN_EID_HT_CAPABILITY;
*pos++ = sizeof(struct ieee80211_ht_cap);
ht_cap = (void *)pos;
@@ -538,7 +534,7 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
return ret;
}
- pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
+ pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
*pos++ = WLAN_EID_HT_CAPABILITY;
*pos++ = sizeof(struct ieee80211_ht_cap);
ht_cap = (void *)pos;
@@ -620,7 +616,7 @@ mwifiex_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,
{
struct ieee80211_tdls_lnkie *lnkid;
- lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
+ lnkid = skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
lnkid->ie_type = WLAN_EID_LINK_ID;
lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) -
sizeof(struct ieee_types_header);
@@ -683,8 +679,7 @@ int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
return ret;
}
if (extra_ies_len)
- memcpy(skb_put(skb, extra_ies_len), extra_ies,
- extra_ies_len);
+ skb_put_data(skb, extra_ies, extra_ies_len);
mwifiex_tdls_add_link_ie(skb, priv->curr_addr, peer,
priv->cfg_bssid);
break;
@@ -697,8 +692,7 @@ int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
return ret;
}
if (extra_ies_len)
- memcpy(skb_put(skb, extra_ies_len), extra_ies,
- extra_ies_len);
+ skb_put_data(skb, extra_ies, extra_ies_len);
mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
priv->cfg_bssid);
break;
@@ -747,7 +741,7 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
- mgmt = (void *)skb_put(skb, offsetof(struct ieee80211_mgmt, u));
+ mgmt = skb_put(skb, offsetof(struct ieee80211_mgmt, u));
memset(mgmt, 0, 24);
memcpy(mgmt->da, peer, ETH_ALEN);
@@ -781,7 +775,7 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
return ret;
}
- pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
+ pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
*pos++ = WLAN_EID_HT_CAPABILITY;
*pos++ = sizeof(struct ieee80211_ht_cap);
ht_cap = (void *)pos;
@@ -856,8 +850,8 @@ int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
pkt_type = PKT_TYPE_MGMT;
tx_control = 0;
- pos = skb_put(skb, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
- memset(pos, 0, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
+ pos = skb_put_zero(skb,
+ MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
memcpy(pos, &pkt_type, sizeof(pkt_type));
memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control));
@@ -869,7 +863,7 @@ int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
}
if (extra_ies_len)
- memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
+ skb_put_data(skb, extra_ies, extra_ies_len);
/* the TDLS link IE is always added last we are the responder */
diff --git a/drivers/net/wireless/marvell/mwifiex/txrx.c b/drivers/net/wireless/marvell/mwifiex/txrx.c
index fac28bd..d848933 100644
--- a/drivers/net/wireless/marvell/mwifiex/txrx.c
+++ b/drivers/net/wireless/marvell/mwifiex/txrx.c
@@ -91,7 +91,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
struct mwifiex_sta_node *dest_node;
struct ethhdr *hdr = (void *)skb->data;
- hroom = (adapter->iface_type == MWIFIEX_USB) ? 0 : INTF_HEADER_LEN;
+ hroom = adapter->intf_hdr_len;
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
dest_node = mwifiex_get_sta_entry(priv, hdr->h_dest);
@@ -117,7 +117,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
if (adapter->iface_type == MWIFIEX_USB) {
ret = adapter->if_ops.host_to_card(adapter,
priv->usb_port,
- skb, NULL);
+ skb, tx_param);
} else {
ret = adapter->if_ops.host_to_card(adapter,
MWIFIEX_TYPE_DATA,
@@ -179,18 +179,13 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter,
mwifiex_write_data_complete(adapter, skb, 0, 0);
return ret;
}
- if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
- if (adapter->iface_type == MWIFIEX_USB)
- local_tx_pd = (struct txpd *)head_ptr;
- else
- local_tx_pd = (struct txpd *) (head_ptr +
- INTF_HEADER_LEN);
- }
+ if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
+ local_tx_pd = (struct txpd *)(head_ptr + adapter->intf_hdr_len);
if (adapter->iface_type == MWIFIEX_USB) {
ret = adapter->if_ops.host_to_card(adapter,
priv->usb_port,
- skb, NULL);
+ skb, tx_param);
} else {
ret = adapter->if_ops.host_to_card(adapter,
MWIFIEX_TYPE_DATA,
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
index 35d8636..477c29c 100644
--- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
@@ -160,7 +160,6 @@ mwifiex_set_ht_params(struct mwifiex_private *priv,
struct cfg80211_ap_settings *params)
{
const u8 *ht_ie;
- u16 cap_info;
if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info))
return;
@@ -170,27 +169,6 @@ mwifiex_set_ht_params(struct mwifiex_private *priv,
if (ht_ie) {
memcpy(&bss_cfg->ht_cap, ht_ie + 2,
sizeof(struct ieee80211_ht_cap));
- cap_info = le16_to_cpu(bss_cfg->ht_cap.cap_info);
- memset(&bss_cfg->ht_cap.mcs, 0,
- priv->adapter->number_of_antenna);
- switch (GET_RXSTBC(cap_info)) {
- case MWIFIEX_RX_STBC1:
- /* HT_CAP 1X1 mode */
- bss_cfg->ht_cap.mcs.rx_mask[0] = 0xff;
- break;
- case MWIFIEX_RX_STBC12: /* fall through */
- case MWIFIEX_RX_STBC123:
- /* HT_CAP 2X2 mode */
- bss_cfg->ht_cap.mcs.rx_mask[0] = 0xff;
- bss_cfg->ht_cap.mcs.rx_mask[1] = 0xff;
- break;
- default:
- mwifiex_dbg(priv->adapter, WARN,
- "Unsupported RX-STBC, default to 2x2\n");
- bss_cfg->ht_cap.mcs.rx_mask[0] = 0xff;
- bss_cfg->ht_cap.mcs.rx_mask[1] = 0xff;
- break;
- }
priv->ap_11n_enabled = 1;
} else {
memset(&bss_cfg->ht_cap, 0, sizeof(struct ieee80211_ht_cap));
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c
index e10b2a5..e8c8728 100644
--- a/drivers/net/wireless/marvell/mwifiex/uap_event.c
+++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c
@@ -312,6 +312,17 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
adapter->event_skb->len -
sizeof(eventcause));
break;
+
+ case EVENT_REMAIN_ON_CHAN_EXPIRED:
+ mwifiex_dbg(adapter, EVENT,
+ "event: uap: Remain on channel expired\n");
+ cfg80211_remain_on_channel_expired(&priv->wdev,
+ priv->roc_cfg.cookie,
+ &priv->roc_cfg.chan,
+ GFP_ATOMIC);
+ memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg));
+ break;
+
default:
mwifiex_dbg(adapter, EVENT,
"event: unknown event id: %#x\n", eventcause);
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
index bf5660e..1e6a62c 100644
--- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
@@ -468,8 +468,7 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv,
struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
int pad;
u16 pkt_type, pkt_offset;
- int hroom = (priv->adapter->iface_type == MWIFIEX_USB) ? 0 :
- INTF_HEADER_LEN;
+ int hroom = adapter->intf_hdr_len;
if (!skb->len) {
mwifiex_dbg(adapter, ERROR,
@@ -521,7 +520,7 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv,
txpd->tx_pkt_offset = cpu_to_le16(pkt_offset);
- /* make space for INTF_HEADER_LEN */
+ /* make space for adapter->intf_hdr_len */
skb_push(skb, hroom);
if (!txpd->tx_control)
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index 2f7705c..cb1753e 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -363,6 +363,7 @@ static void mwifiex_usb_free(struct usb_card_rec *card)
for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
port = &card->port[i];
for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
+ usb_kill_urb(port->tx_data_list[j].urb);
usb_free_urb(port->tx_data_list[j].urb);
port->tx_data_list[j].urb = NULL;
}
@@ -424,7 +425,8 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
card->intf = intf;
pr_debug("info: bcdUSB=%#x Device Class=%#x SubClass=%#x Protocol=%#x\n",
- udev->descriptor.bcdUSB, udev->descriptor.bDeviceClass,
+ le16_to_cpu(udev->descriptor.bcdUSB),
+ udev->descriptor.bDeviceClass,
udev->descriptor.bDeviceSubClass,
udev->descriptor.bDeviceProtocol);
@@ -661,75 +663,6 @@ static struct usb_driver mwifiex_usb_driver = {
.soft_unbind = 1,
};
-static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
-{
- struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
- struct usb_tx_data_port *port;
- int i, j;
-
- card->tx_cmd.adapter = adapter;
- card->tx_cmd.ep = card->tx_cmd_ep;
-
- card->tx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!card->tx_cmd.urb)
- return -ENOMEM;
-
- for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
- port = &card->port[i];
- if (!port->tx_data_ep)
- continue;
- port->tx_data_ix = 0;
- if (port->tx_data_ep == MWIFIEX_USB_EP_DATA)
- port->block_status = false;
- else
- port->block_status = true;
- for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
- port->tx_data_list[j].adapter = adapter;
- port->tx_data_list[j].ep = port->tx_data_ep;
- port->tx_data_list[j].urb =
- usb_alloc_urb(0, GFP_KERNEL);
- if (!port->tx_data_list[j].urb)
- return -ENOMEM;
- }
- }
-
- return 0;
-}
-
-static int mwifiex_usb_rx_init(struct mwifiex_adapter *adapter)
-{
- struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
- int i;
-
- card->rx_cmd.adapter = adapter;
- card->rx_cmd.ep = card->rx_cmd_ep;
-
- card->rx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!card->rx_cmd.urb)
- return -ENOMEM;
-
- card->rx_cmd.skb = dev_alloc_skb(MWIFIEX_RX_CMD_BUF_SIZE);
- if (!card->rx_cmd.skb)
- return -ENOMEM;
-
- if (mwifiex_usb_submit_rx_urb(&card->rx_cmd, MWIFIEX_RX_CMD_BUF_SIZE))
- return -1;
-
- for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
- card->rx_data_list[i].adapter = adapter;
- card->rx_data_list[i].ep = card->rx_data_ep;
-
- card->rx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!card->rx_data_list[i].urb)
- return -1;
- if (mwifiex_usb_submit_rx_urb(&card->rx_data_list[i],
- MWIFIEX_RX_DATA_BUF_SIZE))
- return -1;
- }
-
- return 0;
-}
-
static int mwifiex_write_data_sync(struct mwifiex_adapter *adapter, u8 *pbuf,
u32 *len, u8 ep, u32 timeout)
{
@@ -845,6 +778,364 @@ static inline u8 mwifiex_usb_data_sent(struct mwifiex_adapter *adapter)
return true;
}
+static int mwifiex_usb_construct_send_urb(struct mwifiex_adapter *adapter,
+ struct usb_tx_data_port *port, u8 ep,
+ struct urb_context *context,
+ struct sk_buff *skb_send)
+{
+ struct usb_card_rec *card = adapter->card;
+ int ret = -EINPROGRESS;
+ struct urb *tx_urb;
+
+ context->adapter = adapter;
+ context->ep = ep;
+ context->skb = skb_send;
+ tx_urb = context->urb;
+
+ if (ep == card->tx_cmd_ep &&
+ card->tx_cmd_ep_type == USB_ENDPOINT_XFER_INT)
+ usb_fill_int_urb(tx_urb, card->udev,
+ usb_sndintpipe(card->udev, ep), skb_send->data,
+ skb_send->len, mwifiex_usb_tx_complete,
+ (void *)context, card->tx_cmd_interval);
+ else
+ usb_fill_bulk_urb(tx_urb, card->udev,
+ usb_sndbulkpipe(card->udev, ep),
+ skb_send->data, skb_send->len,
+ mwifiex_usb_tx_complete, (void *)context);
+
+ tx_urb->transfer_flags |= URB_ZERO_PACKET;
+
+ if (ep == card->tx_cmd_ep)
+ atomic_inc(&card->tx_cmd_urb_pending);
+ else
+ atomic_inc(&port->tx_data_urb_pending);
+
+ if (ep != card->tx_cmd_ep &&
+ atomic_read(&port->tx_data_urb_pending) ==
+ MWIFIEX_TX_DATA_URB) {
+ port->block_status = true;
+ adapter->data_sent = mwifiex_usb_data_sent(adapter);
+ ret = -ENOSR;
+ }
+
+ if (usb_submit_urb(tx_urb, GFP_ATOMIC)) {
+ mwifiex_dbg(adapter, ERROR,
+ "%s: usb_submit_urb failed\n", __func__);
+ if (ep == card->tx_cmd_ep) {
+ atomic_dec(&card->tx_cmd_urb_pending);
+ } else {
+ atomic_dec(&port->tx_data_urb_pending);
+ port->block_status = false;
+ adapter->data_sent = false;
+ if (port->tx_data_ix)
+ port->tx_data_ix--;
+ else
+ port->tx_data_ix = MWIFIEX_TX_DATA_URB;
+ }
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int mwifiex_usb_prepare_tx_aggr_skb(struct mwifiex_adapter *adapter,
+ struct usb_tx_data_port *port,
+ struct sk_buff **skb_send)
+{
+ struct sk_buff *skb_aggr, *skb_tmp;
+ u8 *payload, pad;
+ u16 align = adapter->bus_aggr.tx_aggr_align;
+ struct mwifiex_txinfo *tx_info = NULL;
+ bool is_txinfo_set = false;
+
+ /* Packets in aggr_list will be send in either skb_aggr or
+ * write complete, delete the tx_aggr timer
+ */
+ if (port->tx_aggr.timer_cnxt.is_hold_timer_set) {
+ del_timer(&port->tx_aggr.timer_cnxt.hold_timer);
+ port->tx_aggr.timer_cnxt.is_hold_timer_set = false;
+ port->tx_aggr.timer_cnxt.hold_tmo_msecs = 0;
+ }
+
+ skb_aggr = mwifiex_alloc_dma_align_buf(port->tx_aggr.aggr_len,
+ GFP_ATOMIC);
+ if (!skb_aggr) {
+ mwifiex_dbg(adapter, ERROR,
+ "%s: alloc skb_aggr failed\n", __func__);
+
+ while ((skb_tmp = skb_dequeue(&port->tx_aggr.aggr_list)))
+ mwifiex_write_data_complete(adapter, skb_tmp, 0, -1);
+
+ port->tx_aggr.aggr_num = 0;
+ port->tx_aggr.aggr_len = 0;
+ return -EBUSY;
+ }
+
+ tx_info = MWIFIEX_SKB_TXCB(skb_aggr);
+ memset(tx_info, 0, sizeof(*tx_info));
+
+ while ((skb_tmp = skb_dequeue(&port->tx_aggr.aggr_list))) {
+ /* padding for aligning next packet header*/
+ pad = (align - (skb_tmp->len & (align - 1))) % align;
+ payload = skb_put(skb_aggr, skb_tmp->len + pad);
+ memcpy(payload, skb_tmp->data, skb_tmp->len);
+ if (skb_queue_empty(&port->tx_aggr.aggr_list)) {
+ /* do not padding for last packet*/
+ *(u16 *)payload = cpu_to_le16(skb_tmp->len);
+ *(u16 *)&payload[2] =
+ cpu_to_le16(MWIFIEX_TYPE_AGGR_DATA_V2 | 0x80);
+ skb_trim(skb_aggr, skb_aggr->len - pad);
+ } else {
+ /* add aggregation interface header */
+ *(u16 *)payload = cpu_to_le16(skb_tmp->len + pad);
+ *(u16 *)&payload[2] =
+ cpu_to_le16(MWIFIEX_TYPE_AGGR_DATA_V2);
+ }
+
+ if (!is_txinfo_set) {
+ tx_info->bss_num = MWIFIEX_SKB_TXCB(skb_tmp)->bss_num;
+ tx_info->bss_type = MWIFIEX_SKB_TXCB(skb_tmp)->bss_type;
+ is_txinfo_set = true;
+ }
+
+ port->tx_aggr.aggr_num--;
+ port->tx_aggr.aggr_len -= (skb_tmp->len + pad);
+ mwifiex_write_data_complete(adapter, skb_tmp, 0, 0);
+ }
+
+ tx_info->pkt_len = skb_aggr->len -
+ (sizeof(struct txpd) + adapter->intf_hdr_len);
+ tx_info->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT;
+
+ port->tx_aggr.aggr_num = 0;
+ port->tx_aggr.aggr_len = 0;
+ *skb_send = skb_aggr;
+
+ return 0;
+}
+
+/* This function prepare data packet to be send under usb tx aggregation
+ * protocol, check current usb aggregation status, link packet to aggrgation
+ * list if possible, work flow as below:
+ * (1) if only 1 packet available, add usb tx aggregation header and send.
+ * (2) if packet is able to aggregated, link it to current aggregation list.
+ * (3) if packet is not able to aggregated, aggregate and send exist packets
+ * in aggrgation list. Then, link packet in the list if there is more
+ * packet in transmit queue, otherwise try to transmit single packet.
+ */
+static int mwifiex_usb_aggr_tx_data(struct mwifiex_adapter *adapter, u8 ep,
+ struct sk_buff *skb,
+ struct mwifiex_tx_param *tx_param,
+ struct usb_tx_data_port *port)
+{
+ u8 *payload, pad;
+ u16 align = adapter->bus_aggr.tx_aggr_align;
+ struct sk_buff *skb_send = NULL;
+ struct urb_context *context = NULL;
+ struct txpd *local_tx_pd =
+ (struct txpd *)((u8 *)skb->data + adapter->intf_hdr_len);
+ u8 f_send_aggr_buf = 0;
+ u8 f_send_cur_buf = 0;
+ u8 f_precopy_cur_buf = 0;
+ u8 f_postcopy_cur_buf = 0;
+ u32 timeout;
+ int ret;
+
+ /* padding to ensure each packet alginment */
+ pad = (align - (skb->len & (align - 1))) % align;
+
+ if (tx_param && tx_param->next_pkt_len) {
+ /* next packet available in tx queue*/
+ if (port->tx_aggr.aggr_len + skb->len + pad >
+ adapter->bus_aggr.tx_aggr_max_size) {
+ f_send_aggr_buf = 1;
+ f_postcopy_cur_buf = 1;
+ } else {
+ /* current packet could be aggregated*/
+ f_precopy_cur_buf = 1;
+
+ if (port->tx_aggr.aggr_len + skb->len + pad +
+ tx_param->next_pkt_len >
+ adapter->bus_aggr.tx_aggr_max_size ||
+ port->tx_aggr.aggr_num + 2 >
+ adapter->bus_aggr.tx_aggr_max_num) {
+ /* next packet could not be aggregated
+ * send current aggregation buffer
+ */
+ f_send_aggr_buf = 1;
+ }
+ }
+ } else {
+ /* last packet in tx queue */
+ if (port->tx_aggr.aggr_num > 0) {
+ /* pending packets in aggregation buffer*/
+ if (port->tx_aggr.aggr_len + skb->len + pad >
+ adapter->bus_aggr.tx_aggr_max_size) {
+ /* current packet not be able to aggregated,
+ * send aggr buffer first, then send packet.
+ */
+ f_send_cur_buf = 1;
+ } else {
+ /* last packet, Aggregation and send */
+ f_precopy_cur_buf = 1;
+ }
+
+ f_send_aggr_buf = 1;
+ } else {
+ /* no pending packets in aggregation buffer,
+ * send current packet immediately
+ */
+ f_send_cur_buf = 1;
+ }
+ }
+
+ if (local_tx_pd->flags & MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET) {
+ /* Send NULL packet immediately*/
+ if (f_precopy_cur_buf) {
+ if (skb_queue_empty(&port->tx_aggr.aggr_list)) {
+ f_precopy_cur_buf = 0;
+ f_send_aggr_buf = 0;
+ f_send_cur_buf = 1;
+ } else {
+ f_send_aggr_buf = 1;
+ }
+ } else if (f_postcopy_cur_buf) {
+ f_send_cur_buf = 1;
+ f_postcopy_cur_buf = 0;
+ }
+ }
+
+ if (f_precopy_cur_buf) {
+ skb_queue_tail(&port->tx_aggr.aggr_list, skb);
+ port->tx_aggr.aggr_len += (skb->len + pad);
+ port->tx_aggr.aggr_num++;
+ if (f_send_aggr_buf)
+ goto send_aggr_buf;
+
+ /* packet will not been send immediately,
+ * set a timer to make sure it will be sent under
+ * strict time limit. Dynamically fit the timeout
+ * value, according to packets number in aggr_list
+ */
+ if (!port->tx_aggr.timer_cnxt.is_hold_timer_set) {
+ port->tx_aggr.timer_cnxt.hold_tmo_msecs =
+ MWIFIEX_USB_TX_AGGR_TMO_MIN;
+ timeout =
+ port->tx_aggr.timer_cnxt.hold_tmo_msecs;
+ mod_timer(&port->tx_aggr.timer_cnxt.hold_timer,
+ jiffies + msecs_to_jiffies(timeout));
+ port->tx_aggr.timer_cnxt.is_hold_timer_set = true;
+ } else {
+ if (port->tx_aggr.timer_cnxt.hold_tmo_msecs <
+ MWIFIEX_USB_TX_AGGR_TMO_MAX) {
+ /* Dyanmic fit timeout */
+ timeout =
+ ++port->tx_aggr.timer_cnxt.hold_tmo_msecs;
+ mod_timer(&port->tx_aggr.timer_cnxt.hold_timer,
+ jiffies + msecs_to_jiffies(timeout));
+ }
+ }
+ }
+
+send_aggr_buf:
+ if (f_send_aggr_buf) {
+ ret = mwifiex_usb_prepare_tx_aggr_skb(adapter, port, &skb_send);
+ if (!ret) {
+ context = &port->tx_data_list[port->tx_data_ix++];
+ ret = mwifiex_usb_construct_send_urb(adapter, port, ep,
+ context, skb_send);
+ if (ret == -1)
+ mwifiex_write_data_complete(adapter, skb_send,
+ 0, -1);
+ }
+ }
+
+ if (f_send_cur_buf) {
+ if (f_send_aggr_buf) {
+ if (atomic_read(&port->tx_data_urb_pending) >=
+ MWIFIEX_TX_DATA_URB) {
+ port->block_status = true;
+ adapter->data_sent =
+ mwifiex_usb_data_sent(adapter);
+ /* no available urb, postcopy packet*/
+ f_postcopy_cur_buf = 1;
+ goto postcopy_cur_buf;
+ }
+
+ if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB)
+ port->tx_data_ix = 0;
+ }
+
+ payload = skb->data;
+ *(u16 *)&payload[2] =
+ cpu_to_le16(MWIFIEX_TYPE_AGGR_DATA_V2 | 0x80);
+ *(u16 *)payload = cpu_to_le16(skb->len);
+ skb_send = skb;
+ context = &port->tx_data_list[port->tx_data_ix++];
+ return mwifiex_usb_construct_send_urb(adapter, port, ep,
+ context, skb_send);
+ }
+
+postcopy_cur_buf:
+ if (f_postcopy_cur_buf) {
+ skb_queue_tail(&port->tx_aggr.aggr_list, skb);
+ port->tx_aggr.aggr_len += (skb->len + pad);
+ port->tx_aggr.aggr_num++;
+ /* New aggregation begin, start timer */
+ if (!port->tx_aggr.timer_cnxt.is_hold_timer_set) {
+ port->tx_aggr.timer_cnxt.hold_tmo_msecs =
+ MWIFIEX_USB_TX_AGGR_TMO_MIN;
+ timeout = port->tx_aggr.timer_cnxt.hold_tmo_msecs;
+ mod_timer(&port->tx_aggr.timer_cnxt.hold_timer,
+ jiffies + msecs_to_jiffies(timeout));
+ port->tx_aggr.timer_cnxt.is_hold_timer_set = true;
+ }
+ }
+
+ return -EINPROGRESS;
+}
+
+static void mwifiex_usb_tx_aggr_tmo(unsigned long context)
+{
+ struct urb_context *urb_cnxt = NULL;
+ struct sk_buff *skb_send = NULL;
+ struct tx_aggr_tmr_cnxt *timer_context =
+ (struct tx_aggr_tmr_cnxt *)context;
+ struct mwifiex_adapter *adapter = timer_context->adapter;
+ struct usb_tx_data_port *port = timer_context->port;
+ unsigned long flags;
+ int err = 0;
+
+ spin_lock_irqsave(&port->tx_aggr_lock, flags);
+ err = mwifiex_usb_prepare_tx_aggr_skb(adapter, port, &skb_send);
+ if (err) {
+ mwifiex_dbg(adapter, ERROR,
+ "prepare tx aggr skb failed, err=%d\n", err);
+ return;
+ }
+
+ if (atomic_read(&port->tx_data_urb_pending) >=
+ MWIFIEX_TX_DATA_URB) {
+ port->block_status = true;
+ adapter->data_sent =
+ mwifiex_usb_data_sent(adapter);
+ err = -1;
+ goto done;
+ }
+
+ if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB)
+ port->tx_data_ix = 0;
+
+ urb_cnxt = &port->tx_data_list[port->tx_data_ix++];
+ err = mwifiex_usb_construct_send_urb(adapter, port, port->tx_data_ep,
+ urb_cnxt, skb_send);
+done:
+ if (err == -1)
+ mwifiex_write_data_complete(adapter, skb_send, 0, -1);
+ spin_unlock_irqrestore(&port->tx_aggr_lock, flags);
+}
+
/* This function write a command/data packet to card. */
static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
struct sk_buff *skb,
@@ -853,9 +1144,8 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
struct usb_card_rec *card = adapter->card;
struct urb_context *context = NULL;
struct usb_tx_data_port *port = NULL;
- u8 *data = (u8 *)skb->data;
- struct urb *tx_urb;
- int idx, ret = -EINPROGRESS;
+ unsigned long flags;
+ int idx, ret;
if (adapter->is_suspended) {
mwifiex_dbg(adapter, ERROR,
@@ -873,6 +1163,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
if (ep == card->tx_cmd_ep) {
context = &card->tx_cmd;
} else {
+ /* get the data port structure for endpoint */
for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) {
if (ep == card->port[idx].tx_data_ep) {
port = &card->port[idx];
@@ -885,67 +1176,105 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
}
if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB)
port->tx_data_ix = 0;
- context =
- &port->tx_data_list[port->tx_data_ix++];
break;
}
}
+
if (!port) {
mwifiex_dbg(adapter, ERROR, "Wrong usb tx data port\n");
return -1;
}
- }
- context->adapter = adapter;
- context->ep = ep;
- context->skb = skb;
- tx_urb = context->urb;
+ if (adapter->bus_aggr.enable) {
+ spin_lock_irqsave(&port->tx_aggr_lock, flags);
+ ret = mwifiex_usb_aggr_tx_data(adapter, ep, skb,
+ tx_param, port);
+ spin_unlock_irqrestore(&port->tx_aggr_lock, flags);
+ return ret;
+ }
- if (ep == card->tx_cmd_ep &&
- card->tx_cmd_ep_type == USB_ENDPOINT_XFER_INT)
- usb_fill_int_urb(tx_urb, card->udev,
- usb_sndintpipe(card->udev, ep), data,
- skb->len, mwifiex_usb_tx_complete,
- (void *)context, card->tx_cmd_interval);
- else
- usb_fill_bulk_urb(tx_urb, card->udev,
- usb_sndbulkpipe(card->udev, ep), data,
- skb->len, mwifiex_usb_tx_complete,
- (void *)context);
+ context = &port->tx_data_list[port->tx_data_ix++];
+ }
- tx_urb->transfer_flags |= URB_ZERO_PACKET;
+ return mwifiex_usb_construct_send_urb(adapter, port, ep, context, skb);
+}
- if (ep == card->tx_cmd_ep)
- atomic_inc(&card->tx_cmd_urb_pending);
- else
- atomic_inc(&port->tx_data_urb_pending);
+static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
+{
+ struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+ struct usb_tx_data_port *port;
+ int i, j;
- if (ep != card->tx_cmd_ep &&
- atomic_read(&port->tx_data_urb_pending) ==
- MWIFIEX_TX_DATA_URB) {
- port->block_status = true;
- adapter->data_sent = mwifiex_usb_data_sent(adapter);
- ret = -ENOSR;
- }
+ card->tx_cmd.adapter = adapter;
+ card->tx_cmd.ep = card->tx_cmd_ep;
- if (usb_submit_urb(tx_urb, GFP_ATOMIC)) {
- mwifiex_dbg(adapter, ERROR,
- "%s: usb_submit_urb failed\n", __func__);
- if (ep == card->tx_cmd_ep) {
- atomic_dec(&card->tx_cmd_urb_pending);
- } else {
- atomic_dec(&port->tx_data_urb_pending);
+ card->tx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!card->tx_cmd.urb)
+ return -ENOMEM;
+
+ for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
+ port = &card->port[i];
+ if (!port->tx_data_ep)
+ continue;
+ port->tx_data_ix = 0;
+ skb_queue_head_init(&port->tx_aggr.aggr_list);
+ if (port->tx_data_ep == MWIFIEX_USB_EP_DATA)
port->block_status = false;
- adapter->data_sent = false;
- if (port->tx_data_ix)
- port->tx_data_ix--;
- else
- port->tx_data_ix = MWIFIEX_TX_DATA_URB;
+ else
+ port->block_status = true;
+ for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
+ port->tx_data_list[j].adapter = adapter;
+ port->tx_data_list[j].ep = port->tx_data_ep;
+ port->tx_data_list[j].urb =
+ usb_alloc_urb(0, GFP_KERNEL);
+ if (!port->tx_data_list[j].urb)
+ return -ENOMEM;
}
- ret = -1;
+
+ port->tx_aggr.timer_cnxt.adapter = adapter;
+ port->tx_aggr.timer_cnxt.port = port;
+ port->tx_aggr.timer_cnxt.is_hold_timer_set = false;
+ port->tx_aggr.timer_cnxt.hold_tmo_msecs = 0;
+ setup_timer(&port->tx_aggr.timer_cnxt.hold_timer,
+ mwifiex_usb_tx_aggr_tmo,
+ (unsigned long)&port->tx_aggr.timer_cnxt);
}
- return ret;
+ return 0;
+}
+
+static int mwifiex_usb_rx_init(struct mwifiex_adapter *adapter)
+{
+ struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+ int i;
+
+ card->rx_cmd.adapter = adapter;
+ card->rx_cmd.ep = card->rx_cmd_ep;
+
+ card->rx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!card->rx_cmd.urb)
+ return -ENOMEM;
+
+ card->rx_cmd.skb = dev_alloc_skb(MWIFIEX_RX_CMD_BUF_SIZE);
+ if (!card->rx_cmd.skb)
+ return -ENOMEM;
+
+ if (mwifiex_usb_submit_rx_urb(&card->rx_cmd, MWIFIEX_RX_CMD_BUF_SIZE))
+ return -1;
+
+ for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
+ card->rx_data_list[i].adapter = adapter;
+ card->rx_data_list[i].ep = card->rx_data_ep;
+
+ card->rx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!card->rx_data_list[i].urb)
+ return -1;
+ if (mwifiex_usb_submit_rx_urb(&card->rx_data_list[i],
+ MWIFIEX_RX_DATA_BUF_SIZE))
+ return -1;
+ }
+
+ return 0;
}
/* This function register usb device and initialize parameter. */
@@ -988,10 +1317,32 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
return 0;
}
+static void mwifiex_usb_cleanup_tx_aggr(struct mwifiex_adapter *adapter)
+{
+ struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+ struct usb_tx_data_port *port;
+ struct sk_buff *skb_tmp;
+ int idx;
+
+ for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) {
+ port = &card->port[idx];
+ if (adapter->bus_aggr.enable)
+ while ((skb_tmp =
+ skb_dequeue(&port->tx_aggr.aggr_list)))
+ mwifiex_write_data_complete(adapter, skb_tmp,
+ 0, -1);
+ del_timer_sync(&port->tx_aggr.timer_cnxt.hold_timer);
+ port->tx_aggr.timer_cnxt.is_hold_timer_set = false;
+ port->tx_aggr.timer_cnxt.hold_tmo_msecs = 0;
+ }
+}
+
static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
{
struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+ mwifiex_usb_cleanup_tx_aggr(adapter);
+
card->adapter = NULL;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.h b/drivers/net/wireless/marvell/mwifiex/usb.h
index e36bd63..37abd22 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.h
+++ b/drivers/net/wireless/marvell/mwifiex/usb.h
@@ -64,12 +64,35 @@ struct urb_context {
u8 ep;
};
+#define MWIFIEX_USB_TX_AGGR_TMO_MIN 1
+#define MWIFIEX_USB_TX_AGGR_TMO_MAX 4
+
+struct tx_aggr_tmr_cnxt {
+ struct mwifiex_adapter *adapter;
+ struct usb_tx_data_port *port;
+ struct timer_list hold_timer;
+ bool is_hold_timer_set;
+ u32 hold_tmo_msecs;
+};
+
+struct usb_tx_aggr {
+ struct sk_buff_head aggr_list;
+ int aggr_len;
+ int aggr_num;
+ struct tx_aggr_tmr_cnxt timer_cnxt;
+};
+
struct usb_tx_data_port {
u8 tx_data_ep;
u8 block_status;
atomic_t tx_data_urb_pending;
int tx_data_ix;
struct urb_context tx_data_list[MWIFIEX_TX_DATA_URB];
+ /* usb tx aggregation*/
+ struct usb_tx_aggr tx_aggr;
+ struct sk_buff *skb_aggr[MWIFIEX_TX_DATA_URB];
+ /* lock for protect tx aggregation data path*/
+ spinlock_t tx_aggr_lock;
};
struct usb_card_rec {
diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.c b/drivers/net/wireless/marvell/mwifiex/wmm.c
index e4ff3b9..0edd268 100644
--- a/drivers/net/wireless/marvell/mwifiex/wmm.c
+++ b/drivers/net/wireless/marvell/mwifiex/wmm.c
@@ -868,12 +868,8 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
return;
default:
list_head = priv->wmm.tid_tbl_ptr[tid_down].ra_list;
- if (!list_empty(&list_head))
- ra_list = list_first_entry(
- &list_head, struct mwifiex_ra_list_tbl,
- list);
- else
- ra_list = NULL;
+ ra_list = list_first_entry_or_null(&list_head,
+ struct mwifiex_ra_list_tbl, list);
break;
}
} else {
@@ -1363,13 +1359,13 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
+ tx_param.next_pkt_len =
+ ((skb_next) ? skb_next->len +
+ sizeof(struct txpd) : 0);
if (adapter->iface_type == MWIFIEX_USB) {
ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
- skb, NULL);
+ skb, &tx_param);
} else {
- tx_param.next_pkt_len =
- ((skb_next) ? skb_next->len +
- sizeof(struct txpd) : 0);
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
skb, &tx_param);
}
diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c
index a8bc064..660267b 100644
--- a/drivers/net/wireless/mediatek/mt7601u/dma.c
+++ b/drivers/net/wireless/mediatek/mt7601u/dma.c
@@ -52,7 +52,7 @@ mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
goto bad_frame;
if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) {
- memcpy(skb_put(skb, hdr_len), data, hdr_len);
+ skb_put_data(skb, data, hdr_len);
data += hdr_len + 2;
true_len -= hdr_len;
@@ -63,7 +63,7 @@ mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
copy = (true_len <= skb_tailroom(skb)) ? true_len : hdr_len + 8;
frag = true_len - copy;
- memcpy(skb_put(skb, copy), data, copy);
+ skb_put_data(skb, data, copy);
data += copy;
if (frag) {
diff --git a/drivers/net/wireless/mediatek/mt7601u/mcu.c b/drivers/net/wireless/mediatek/mt7601u/mcu.c
index a9f5f39..65a8004 100644
--- a/drivers/net/wireless/mediatek/mt7601u/mcu.c
+++ b/drivers/net/wireless/mediatek/mt7601u/mcu.c
@@ -68,7 +68,7 @@ mt7601u_mcu_msg_alloc(struct mt7601u_dev *dev, const void *data, int len)
skb = alloc_skb(len + MT_DMA_HDR_LEN + 4, GFP_KERNEL);
if (skb) {
skb_reserve(skb, MT_DMA_HDR_LEN);
- memcpy(skb_put(skb, len), data, len);
+ skb_put_data(skb, data, len);
}
return skb;
diff --git a/drivers/net/wireless/mediatek/mt7601u/tx.c b/drivers/net/wireless/mediatek/mt7601u/tx.c
index ad77bec..3600e91 100644
--- a/drivers/net/wireless/mediatek/mt7601u/tx.c
+++ b/drivers/net/wireless/mediatek/mt7601u/tx.c
@@ -148,7 +148,7 @@ mt7601u_push_txwi(struct mt7601u_dev *dev, struct sk_buff *skb,
u16 rate_ctl;
u8 nss;
- txwi = (struct mt76_txwi *)skb_push(skb, sizeof(struct mt76_txwi));
+ txwi = skb_push(skb, sizeof(struct mt76_txwi));
memset(txwi, 0, sizeof(*txwi));
if (!wcid->tx_rate_set)
diff --git a/drivers/net/wireless/quantenna/Kconfig b/drivers/net/wireless/quantenna/Kconfig
new file mode 100644
index 0000000..3094365
--- /dev/null
+++ b/drivers/net/wireless/quantenna/Kconfig
@@ -0,0 +1,16 @@
+config WLAN_VENDOR_QUANTENNA
+ bool "Quantenna wireless cards support"
+ default y
+ ---help---
+ If you have a wireless card belonging to this class, say Y.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if WLAN_VENDOR_QUANTENNA
+
+source "drivers/net/wireless/quantenna/qtnfmac/Kconfig"
+
+endif # WLAN_VENDOR_QUANTENNA
diff --git a/drivers/net/wireless/quantenna/Makefile b/drivers/net/wireless/quantenna/Makefile
new file mode 100644
index 0000000..baebfbd
--- /dev/null
+++ b/drivers/net/wireless/quantenna/Makefile
@@ -0,0 +1,6 @@
+#
+# Copyright (c) 2015-2016 Quantenna Communications, Inc.
+# All rights reserved.
+#
+
+obj-$(CONFIG_QTNFMAC) += qtnfmac/
diff --git a/drivers/net/wireless/quantenna/qtnfmac/Kconfig b/drivers/net/wireless/quantenna/qtnfmac/Kconfig
new file mode 100644
index 0000000..025fa60
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/Kconfig
@@ -0,0 +1,19 @@
+config QTNFMAC
+ tristate
+ depends on QTNFMAC_PEARL_PCIE
+ default m if QTNFMAC_PEARL_PCIE=m
+ default y if QTNFMAC_PEARL_PCIE=y
+
+config QTNFMAC_PEARL_PCIE
+ tristate "Quantenna QSR10g PCIe support"
+ default n
+ depends on HAS_DMA && PCI && CFG80211
+ select QTNFMAC
+ select FW_LOADER
+ select CRC32
+ ---help---
+ This option adds support for wireless adapters based on Quantenna
+ 802.11ac QSR10g (aka Pearl) FullMAC chipset running over PCIe.
+
+ If you choose to build it as a module, two modules will be built:
+ qtnfmac.ko and qtnfmac_pearl_pcie.ko.
diff --git a/drivers/net/wireless/quantenna/qtnfmac/Makefile b/drivers/net/wireless/quantenna/qtnfmac/Makefile
new file mode 100644
index 0000000..0d618e5
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/Makefile
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 2015-2016 Quantenna Communications, Inc.
+# All rights reserved.
+#
+
+ccflags-y += \
+ -Idrivers/net/wireless/quantenna/qtnfmac
+
+obj-$(CONFIG_QTNFMAC) += qtnfmac.o
+qtnfmac-objs += \
+ core.o \
+ commands.o \
+ trans.o \
+ cfg80211.o \
+ event.o \
+ util.o \
+ qlink_util.o
+
+#
+
+obj-$(CONFIG_QTNFMAC_PEARL_PCIE) += qtnfmac_pearl_pcie.o
+
+qtnfmac_pearl_pcie-objs += \
+ shm_ipc.o \
+ pearl/pcie.o
+
+qtnfmac_pearl_pcie-$(CONFIG_DEBUG_FS) += debug.o
+
+#
+
+ccflags-y += -D__CHECK_ENDIAN
diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h b/drivers/net/wireless/quantenna/qtnfmac/bus.h
new file mode 100644
index 0000000..dda0500
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2015 Quantenna Communications
+ *
+ * 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 QTNFMAC_BUS_H
+#define QTNFMAC_BUS_H
+
+#include <linux/netdevice.h>
+#include <linux/workqueue.h>
+
+#define QTNF_MAX_MAC 3
+
+enum qtnf_fw_state {
+ QTNF_FW_STATE_RESET,
+ QTNF_FW_STATE_FW_DNLD_DONE,
+ QTNF_FW_STATE_BOOT_DONE,
+ QTNF_FW_STATE_ACTIVE,
+ QTNF_FW_STATE_DEAD,
+};
+
+struct qtnf_bus;
+
+struct qtnf_bus_ops {
+ /* mgmt methods */
+ int (*preinit)(struct qtnf_bus *);
+ void (*stop)(struct qtnf_bus *);
+
+ /* control path methods */
+ int (*control_tx)(struct qtnf_bus *, struct sk_buff *);
+
+ /* data xfer methods */
+ int (*data_tx)(struct qtnf_bus *, struct sk_buff *);
+ void (*data_tx_timeout)(struct qtnf_bus *, struct net_device *);
+ void (*data_rx_start)(struct qtnf_bus *);
+ void (*data_rx_stop)(struct qtnf_bus *);
+};
+
+struct qtnf_bus {
+ struct device *dev;
+ enum qtnf_fw_state fw_state;
+ u32 chip;
+ u32 chiprev;
+ const struct qtnf_bus_ops *bus_ops;
+ struct qtnf_wmac *mac[QTNF_MAX_MAC];
+ struct qtnf_qlink_transport trans;
+ struct qtnf_hw_info hw_info;
+ char fwname[32];
+ struct napi_struct mux_napi;
+ struct net_device mux_dev;
+ struct completion request_firmware_complete;
+ struct workqueue_struct *workqueue;
+ struct work_struct event_work;
+ struct mutex bus_lock; /* lock during command/event processing */
+ struct dentry *dbg_dir;
+ /* bus private data */
+ char bus_priv[0] __aligned(sizeof(void *));
+};
+
+static inline void *get_bus_priv(struct qtnf_bus *bus)
+{
+ if (WARN(!bus, "qtnfmac: invalid bus pointer"))
+ return NULL;
+
+ return &bus->bus_priv;
+}
+
+/* callback wrappers */
+
+static inline int qtnf_bus_preinit(struct qtnf_bus *bus)
+{
+ if (!bus->bus_ops->preinit)
+ return 0;
+ return bus->bus_ops->preinit(bus);
+}
+
+static inline void qtnf_bus_stop(struct qtnf_bus *bus)
+{
+ if (!bus->bus_ops->stop)
+ return;
+ bus->bus_ops->stop(bus);
+}
+
+static inline int qtnf_bus_data_tx(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+ return bus->bus_ops->data_tx(bus, skb);
+}
+
+static inline void
+qtnf_bus_data_tx_timeout(struct qtnf_bus *bus, struct net_device *ndev)
+{
+ return bus->bus_ops->data_tx_timeout(bus, ndev);
+}
+
+static inline int qtnf_bus_control_tx(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+ return bus->bus_ops->control_tx(bus, skb);
+}
+
+static inline void qtnf_bus_data_rx_start(struct qtnf_bus *bus)
+{
+ return bus->bus_ops->data_rx_start(bus);
+}
+
+static inline void qtnf_bus_data_rx_stop(struct qtnf_bus *bus)
+{
+ return bus->bus_ops->data_rx_stop(bus);
+}
+
+static __always_inline void qtnf_bus_lock(struct qtnf_bus *bus)
+{
+ mutex_lock(&bus->bus_lock);
+}
+
+static __always_inline void qtnf_bus_unlock(struct qtnf_bus *bus)
+{
+ mutex_unlock(&bus->bus_lock);
+}
+
+/* interface functions from common layer */
+
+void qtnf_rx_frame(struct device *dev, struct sk_buff *rxp);
+int qtnf_core_attach(struct qtnf_bus *bus);
+void qtnf_core_detach(struct qtnf_bus *bus);
+void qtnf_txflowblock(struct device *dev, bool state);
+void qtnf_txcomplete(struct device *dev, struct sk_buff *txp, bool success);
+
+#endif /* QTNFMAC_BUS_H */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
new file mode 100644
index 0000000..e3c0900
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -0,0 +1,995 @@
+/*
+ * Copyright (c) 2012-2012 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/etherdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+#include <net/netlink.h>
+
+#include "cfg80211.h"
+#include "commands.h"
+#include "core.h"
+#include "util.h"
+#include "bus.h"
+
+/* Supported rates to be advertised to the cfg80211 */
+static struct ieee80211_rate qtnf_rates_2g[] = {
+ {.bitrate = 10, .hw_value = 2, },
+ {.bitrate = 20, .hw_value = 4, },
+ {.bitrate = 55, .hw_value = 11, },
+ {.bitrate = 110, .hw_value = 22, },
+ {.bitrate = 60, .hw_value = 12, },
+ {.bitrate = 90, .hw_value = 18, },
+ {.bitrate = 120, .hw_value = 24, },
+ {.bitrate = 180, .hw_value = 36, },
+ {.bitrate = 240, .hw_value = 48, },
+ {.bitrate = 360, .hw_value = 72, },
+ {.bitrate = 480, .hw_value = 96, },
+ {.bitrate = 540, .hw_value = 108, },
+};
+
+/* Supported rates to be advertised to the cfg80211 */
+static struct ieee80211_rate qtnf_rates_5g[] = {
+ {.bitrate = 60, .hw_value = 12, },
+ {.bitrate = 90, .hw_value = 18, },
+ {.bitrate = 120, .hw_value = 24, },
+ {.bitrate = 180, .hw_value = 36, },
+ {.bitrate = 240, .hw_value = 48, },
+ {.bitrate = 360, .hw_value = 72, },
+ {.bitrate = 480, .hw_value = 96, },
+ {.bitrate = 540, .hw_value = 108, },
+};
+
+/* Supported crypto cipher suits to be advertised to cfg80211 */
+static const u32 qtnf_cipher_suites[] = {
+ WLAN_CIPHER_SUITE_TKIP,
+ WLAN_CIPHER_SUITE_CCMP,
+ WLAN_CIPHER_SUITE_AES_CMAC,
+};
+
+/* Supported mgmt frame types to be advertised to cfg80211 */
+static const struct ieee80211_txrx_stypes
+qtnf_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+ [NL80211_IFTYPE_STATION] = {
+ .tx = BIT(IEEE80211_STYPE_ACTION >> 4),
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+ },
+ [NL80211_IFTYPE_AP] = {
+ .tx = BIT(IEEE80211_STYPE_ACTION >> 4),
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+ },
+};
+
+static int
+qtnf_change_virtual_intf(struct wiphy *wiphy,
+ struct net_device *dev,
+ enum nl80211_iftype type,
+ struct vif_params *params)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+ u8 *mac_addr;
+ int ret;
+
+ if (params)
+ mac_addr = params->macaddr;
+ else
+ mac_addr = NULL;
+
+ qtnf_scan_done(vif->mac, true);
+
+ ret = qtnf_cmd_send_change_intf_type(vif, type, mac_addr);
+ if (ret) {
+ pr_err("VIF%u.%u: failed to change VIF type: %d\n",
+ vif->mac->macid, vif->vifid, ret);
+ return ret;
+ }
+
+ vif->wdev.iftype = type;
+ return 0;
+}
+
+int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+ struct net_device *netdev = wdev->netdev;
+ struct qtnf_vif *vif;
+
+ if (WARN_ON(!netdev))
+ return -EFAULT;
+
+ vif = qtnf_netdev_get_priv(wdev->netdev);
+
+ if (qtnf_cmd_send_del_intf(vif))
+ pr_err("VIF%u.%u: failed to delete VIF\n", vif->mac->macid,
+ vif->vifid);
+
+ /* Stop data */
+ netif_tx_stop_all_queues(netdev);
+ if (netif_carrier_ok(netdev))
+ netif_carrier_off(netdev);
+
+ if (netdev->reg_state == NETREG_REGISTERED)
+ unregister_netdevice(netdev);
+
+ vif->netdev->ieee80211_ptr = NULL;
+ vif->netdev = NULL;
+ vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+ eth_zero_addr(vif->mac_addr);
+
+ return 0;
+}
+
+static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy,
+ const char *name,
+ unsigned char name_assign_t,
+ enum nl80211_iftype type,
+ struct vif_params *params)
+{
+ struct qtnf_wmac *mac;
+ struct qtnf_vif *vif;
+ u8 *mac_addr = NULL;
+
+ mac = wiphy_priv(wiphy);
+
+ if (!mac)
+ return ERR_PTR(-EFAULT);
+
+ switch (type) {
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_AP:
+ vif = qtnf_mac_get_free_vif(mac);
+ if (!vif) {
+ pr_err("MAC%u: no free VIF available\n", mac->macid);
+ return ERR_PTR(-EFAULT);
+ }
+
+ eth_zero_addr(vif->mac_addr);
+ vif->bss_priority = QTNF_DEF_BSS_PRIORITY;
+ vif->wdev.wiphy = wiphy;
+ vif->wdev.iftype = type;
+ vif->sta_state = QTNF_STA_DISCONNECTED;
+ break;
+ default:
+ pr_err("MAC%u: unsupported IF type %d\n", mac->macid, type);
+ return ERR_PTR(-ENOTSUPP);
+ }
+
+ if (params)
+ mac_addr = params->macaddr;
+
+ if (qtnf_cmd_send_add_intf(vif, type, mac_addr)) {
+ pr_err("VIF%u.%u: failed to add VIF\n", mac->macid, vif->vifid);
+ goto err_cmd;
+ }
+
+ if (!is_valid_ether_addr(vif->mac_addr)) {
+ pr_err("VIF%u.%u: FW reported bad MAC: %pM\n",
+ mac->macid, vif->vifid, vif->mac_addr);
+ goto err_mac;
+ }
+
+ if (qtnf_core_net_attach(mac, vif, name, name_assign_t, type)) {
+ pr_err("VIF%u.%u: failed to attach netdev\n", mac->macid,
+ vif->vifid);
+ goto err_net;
+ }
+
+ vif->wdev.netdev = vif->netdev;
+ return &vif->wdev;
+
+err_net:
+ vif->netdev = NULL;
+err_mac:
+ qtnf_cmd_send_del_intf(vif);
+err_cmd:
+ vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+
+ return ERR_PTR(-EFAULT);
+}
+
+static int qtnf_mgmt_set_appie(struct qtnf_vif *vif,
+ const struct cfg80211_beacon_data *info)
+{
+ int ret = 0;
+
+ if (!info->beacon_ies || !info->beacon_ies_len) {
+ ret = qtnf_cmd_send_mgmt_set_appie(vif, QLINK_MGMT_FRAME_BEACON,
+ NULL, 0);
+ } else {
+ ret = qtnf_cmd_send_mgmt_set_appie(vif, QLINK_MGMT_FRAME_BEACON,
+ info->beacon_ies,
+ info->beacon_ies_len);
+ }
+
+ if (ret)
+ goto out;
+
+ if (!info->proberesp_ies || !info->proberesp_ies_len) {
+ ret = qtnf_cmd_send_mgmt_set_appie(vif,
+ QLINK_MGMT_FRAME_PROBE_RESP,
+ NULL, 0);
+ } else {
+ ret = qtnf_cmd_send_mgmt_set_appie(vif,
+ QLINK_MGMT_FRAME_PROBE_RESP,
+ info->proberesp_ies,
+ info->proberesp_ies_len);
+ }
+
+ if (ret)
+ goto out;
+
+ if (!info->assocresp_ies || !info->assocresp_ies_len) {
+ ret = qtnf_cmd_send_mgmt_set_appie(vif,
+ QLINK_MGMT_FRAME_ASSOC_RESP,
+ NULL, 0);
+ } else {
+ ret = qtnf_cmd_send_mgmt_set_appie(vif,
+ QLINK_MGMT_FRAME_ASSOC_RESP,
+ info->assocresp_ies,
+ info->assocresp_ies_len);
+ }
+
+out:
+ return ret;
+}
+
+static int qtnf_change_beacon(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_beacon_data *info)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+
+ if (!(vif->bss_status & QTNF_STATE_AP_START)) {
+ pr_err("VIF%u.%u: not started\n", vif->mac->macid, vif->vifid);
+ return -EFAULT;
+ }
+
+ return qtnf_mgmt_set_appie(vif, info);
+}
+
+static int qtnf_start_ap(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_ap_settings *settings)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+ struct qtnf_bss_config *bss_cfg;
+ int ret;
+
+ bss_cfg = &vif->bss_cfg;
+
+ memset(bss_cfg, 0, sizeof(*bss_cfg));
+
+ bss_cfg->bcn_period = settings->beacon_interval;
+ bss_cfg->dtim = settings->dtim_period;
+ bss_cfg->auth_type = settings->auth_type;
+ bss_cfg->privacy = settings->privacy;
+
+ bss_cfg->ssid_len = settings->ssid_len;
+ memcpy(&bss_cfg->ssid, settings->ssid, bss_cfg->ssid_len);
+
+ memcpy(&bss_cfg->chandef, &settings->chandef,
+ sizeof(struct cfg80211_chan_def));
+ memcpy(&bss_cfg->crypto, &settings->crypto,
+ sizeof(struct cfg80211_crypto_settings));
+
+ ret = qtnf_cmd_send_config_ap(vif);
+ if (ret) {
+ pr_err("VIF%u.%u: failed to push config to FW\n",
+ vif->mac->macid, vif->vifid);
+ goto out;
+ }
+
+ if (!(vif->bss_status & QTNF_STATE_AP_CONFIG)) {
+ pr_err("VIF%u.%u: AP config failed in FW\n", vif->mac->macid,
+ vif->vifid);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ ret = qtnf_mgmt_set_appie(vif, &settings->beacon);
+ if (ret) {
+ pr_err("VIF%u.%u: failed to add IEs to beacon\n",
+ vif->mac->macid, vif->vifid);
+ goto out;
+ }
+
+ ret = qtnf_cmd_send_start_ap(vif);
+ if (ret) {
+ pr_err("VIF%u.%u: failed to start AP\n", vif->mac->macid,
+ vif->vifid);
+ goto out;
+ }
+
+ if (!(vif->bss_status & QTNF_STATE_AP_START)) {
+ pr_err("VIF%u.%u: FW failed to start AP operation\n",
+ vif->mac->macid, vif->vifid);
+ ret = -EFAULT;
+ }
+
+out:
+ return ret;
+}
+
+static int qtnf_stop_ap(struct wiphy *wiphy, struct net_device *dev)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+ int ret;
+
+ ret = qtnf_cmd_send_stop_ap(vif);
+ if (ret) {
+ pr_err("VIF%u.%u: failed to stop AP operation in FW\n",
+ vif->mac->macid, vif->vifid);
+ vif->bss_status &= ~QTNF_STATE_AP_START;
+ vif->bss_status &= ~QTNF_STATE_AP_CONFIG;
+
+ netif_carrier_off(vif->netdev);
+ }
+
+ return ret;
+}
+
+static int qtnf_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+ struct qtnf_wmac *mac = wiphy_priv(wiphy);
+ struct qtnf_vif *vif;
+ int ret;
+
+ vif = qtnf_mac_get_base_vif(mac);
+ if (!vif) {
+ pr_err("MAC%u: primary VIF is not configured\n", mac->macid);
+ return -EFAULT;
+ }
+
+ if (changed & (WIPHY_PARAM_RETRY_LONG | WIPHY_PARAM_RETRY_SHORT)) {
+ pr_err("MAC%u: can't modify retry params\n", mac->macid);
+ return -EOPNOTSUPP;
+ }
+
+ ret = qtnf_cmd_send_update_phy_params(mac, changed);
+ if (ret)
+ pr_err("MAC%u: failed to update PHY params\n", mac->macid);
+
+ return ret;
+}
+
+static void
+qtnf_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
+ u16 frame_type, bool reg)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(wdev->netdev);
+ u16 mgmt_type;
+ u16 new_mask;
+ u16 qlink_frame_type = 0;
+
+ mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
+
+ if (reg)
+ new_mask = vif->mgmt_frames_bitmask | BIT(mgmt_type);
+ else
+ new_mask = vif->mgmt_frames_bitmask & ~BIT(mgmt_type);
+
+ if (new_mask == vif->mgmt_frames_bitmask)
+ return;
+
+ switch (frame_type & IEEE80211_FCTL_STYPE) {
+ case IEEE80211_STYPE_PROBE_REQ:
+ qlink_frame_type = QLINK_MGMT_FRAME_PROBE_REQ;
+ break;
+ case IEEE80211_STYPE_ACTION:
+ qlink_frame_type = QLINK_MGMT_FRAME_ACTION;
+ break;
+ default:
+ pr_warn("VIF%u.%u: unsupported frame type: %X\n",
+ vif->mac->macid, vif->vifid,
+ (frame_type & IEEE80211_FCTL_STYPE) >> 4);
+ return;
+ }
+
+ if (qtnf_cmd_send_register_mgmt(vif, qlink_frame_type, reg)) {
+ pr_warn("VIF%u.%u: failed to %sregister mgmt frame type 0x%x\n",
+ vif->mac->macid, vif->vifid, reg ? "" : "un",
+ frame_type);
+ return;
+ }
+
+ vif->mgmt_frames_bitmask = new_mask;
+ pr_debug("VIF%u.%u: %sregistered mgmt frame type 0x%x\n",
+ vif->mac->macid, vif->vifid, reg ? "" : "un", frame_type);
+}
+
+static int
+qtnf_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
+ struct cfg80211_mgmt_tx_params *params, u64 *cookie)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(wdev->netdev);
+ const struct ieee80211_mgmt *mgmt_frame = (void *)params->buf;
+ u32 short_cookie = prandom_u32();
+ u16 flags = 0;
+
+ *cookie = short_cookie;
+
+ if (params->offchan)
+ flags |= QLINK_MGMT_FRAME_TX_FLAG_OFFCHAN;
+
+ if (params->no_cck)
+ flags |= QLINK_MGMT_FRAME_TX_FLAG_NO_CCK;
+
+ if (params->dont_wait_for_ack)
+ flags |= QLINK_MGMT_FRAME_TX_FLAG_ACK_NOWAIT;
+
+ pr_debug("%s freq:%u; FC:%.4X; DA:%pM; len:%zu; C:%.8X; FL:%.4X\n",
+ wdev->netdev->name, params->chan->center_freq,
+ le16_to_cpu(mgmt_frame->frame_control), mgmt_frame->da,
+ params->len, short_cookie, flags);
+
+ return qtnf_cmd_send_mgmt_frame(vif, short_cookie, flags,
+ params->chan->center_freq,
+ params->buf, params->len);
+}
+
+static int
+qtnf_get_station(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *mac, struct station_info *sinfo)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+
+ return qtnf_cmd_get_sta_info(vif, mac, sinfo);
+}
+
+static int
+qtnf_dump_station(struct wiphy *wiphy, struct net_device *dev,
+ int idx, u8 *mac, struct station_info *sinfo)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+ const struct qtnf_sta_node *sta_node;
+ int ret;
+
+ sta_node = qtnf_sta_list_lookup_index(&vif->sta_list, idx);
+
+ if (unlikely(!sta_node))
+ return -ENOENT;
+
+ ether_addr_copy(mac, sta_node->mac_addr);
+
+ ret = qtnf_cmd_get_sta_info(vif, sta_node->mac_addr, sinfo);
+
+ if (unlikely(ret == -ENOENT)) {
+ qtnf_sta_list_del(&vif->sta_list, mac);
+ cfg80211_del_sta(vif->netdev, mac, GFP_KERNEL);
+ sinfo->filled = 0;
+ }
+
+ return ret;
+}
+
+static int qtnf_add_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_index, bool pairwise, const u8 *mac_addr,
+ struct key_params *params)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+ int ret;
+
+ ret = qtnf_cmd_send_add_key(vif, key_index, pairwise, mac_addr, params);
+ if (ret)
+ pr_err("VIF%u.%u: failed to add key: cipher=%x idx=%u pw=%u\n",
+ vif->mac->macid, vif->vifid, params->cipher, key_index,
+ pairwise);
+
+ return ret;
+}
+
+static int qtnf_del_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_index, bool pairwise, const u8 *mac_addr)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+ int ret;
+
+ ret = qtnf_cmd_send_del_key(vif, key_index, pairwise, mac_addr);
+ if (ret)
+ pr_err("VIF%u.%u: failed to delete key: idx=%u pw=%u\n",
+ vif->mac->macid, vif->vifid, key_index, pairwise);
+
+ return ret;
+}
+
+static int qtnf_set_default_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_index, bool unicast, bool multicast)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+ int ret;
+
+ ret = qtnf_cmd_send_set_default_key(vif, key_index, unicast, multicast);
+ if (ret)
+ pr_err("VIF%u.%u: failed to set dflt key: idx=%u uc=%u mc=%u\n",
+ vif->mac->macid, vif->vifid, key_index, unicast,
+ multicast);
+
+ return ret;
+}
+
+static int
+qtnf_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_index)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+ int ret;
+
+ ret = qtnf_cmd_send_set_default_mgmt_key(vif, key_index);
+ if (ret)
+ pr_err("VIF%u.%u: failed to set default MGMT key: idx=%u\n",
+ vif->mac->macid, vif->vifid, key_index);
+
+ return ret;
+}
+
+static int
+qtnf_change_station(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *mac, struct station_parameters *params)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+ int ret;
+
+ ret = qtnf_cmd_send_change_sta(vif, mac, params);
+ if (ret)
+ pr_err("VIF%u.%u: failed to change STA %pM\n",
+ vif->mac->macid, vif->vifid, mac);
+
+ return ret;
+}
+
+static int
+qtnf_del_station(struct wiphy *wiphy, struct net_device *dev,
+ struct station_del_parameters *params)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+ int ret;
+
+ if (params->mac &&
+ (vif->wdev.iftype == NL80211_IFTYPE_AP) &&
+ !is_broadcast_ether_addr(params->mac) &&
+ !qtnf_sta_list_lookup(&vif->sta_list, params->mac))
+ return 0;
+
+ qtnf_scan_done(vif->mac, true);
+
+ ret = qtnf_cmd_send_del_sta(vif, params);
+ if (ret)
+ pr_err("VIF%u.%u: failed to delete STA %pM\n",
+ vif->mac->macid, vif->vifid, params->mac);
+ return ret;
+}
+
+static int
+qtnf_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
+{
+ struct qtnf_wmac *mac = wiphy_priv(wiphy);
+ int ret;
+
+ mac->scan_req = request;
+
+ ret = qtnf_cmd_send_scan(mac);
+ if (ret)
+ pr_err("MAC%u: failed to start scan\n", mac->macid);
+
+ return ret;
+}
+
+static int
+qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+ struct qtnf_bss_config *bss_cfg;
+ int ret;
+
+ if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
+ return -EOPNOTSUPP;
+
+ if (vif->sta_state != QTNF_STA_DISCONNECTED)
+ return -EBUSY;
+
+ bss_cfg = &vif->bss_cfg;
+ memset(bss_cfg, 0, sizeof(*bss_cfg));
+
+ bss_cfg->ssid_len = sme->ssid_len;
+ memcpy(&bss_cfg->ssid, sme->ssid, bss_cfg->ssid_len);
+ bss_cfg->chandef.chan = sme->channel;
+ bss_cfg->auth_type = sme->auth_type;
+ bss_cfg->privacy = sme->privacy;
+ bss_cfg->mfp = sme->mfp;
+
+ if ((sme->bg_scan_period > 0) &&
+ (sme->bg_scan_period <= QTNF_MAX_BG_SCAN_PERIOD))
+ bss_cfg->bg_scan_period = sme->bg_scan_period;
+ else if (sme->bg_scan_period == -1)
+ bss_cfg->bg_scan_period = QTNF_DEFAULT_BG_SCAN_PERIOD;
+ else
+ bss_cfg->bg_scan_period = 0; /* disabled */
+
+ bss_cfg->connect_flags = 0;
+
+ if (sme->flags & ASSOC_REQ_DISABLE_HT)
+ bss_cfg->connect_flags |= QLINK_STA_CONNECT_DISABLE_HT;
+ if (sme->flags & ASSOC_REQ_DISABLE_VHT)
+ bss_cfg->connect_flags |= QLINK_STA_CONNECT_DISABLE_VHT;
+ if (sme->flags & ASSOC_REQ_USE_RRM)
+ bss_cfg->connect_flags |= QLINK_STA_CONNECT_USE_RRM;
+
+ memcpy(&bss_cfg->crypto, &sme->crypto, sizeof(bss_cfg->crypto));
+ if (sme->bssid)
+ ether_addr_copy(bss_cfg->bssid, sme->bssid);
+ else
+ eth_zero_addr(bss_cfg->bssid);
+
+ ret = qtnf_cmd_send_connect(vif, sme);
+ if (ret) {
+ pr_err("VIF%u.%u: failed to connect\n", vif->mac->macid,
+ vif->vifid);
+ return ret;
+ }
+
+ vif->sta_state = QTNF_STA_CONNECTING;
+ return 0;
+}
+
+static int
+qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
+ u16 reason_code)
+{
+ struct qtnf_wmac *mac = wiphy_priv(wiphy);
+ struct qtnf_vif *vif;
+ int ret;
+
+ vif = qtnf_mac_get_base_vif(mac);
+ if (!vif) {
+ pr_err("MAC%u: primary VIF is not configured\n", mac->macid);
+ return -EFAULT;
+ }
+
+ if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
+ return -EOPNOTSUPP;
+
+ if (vif->sta_state == QTNF_STA_DISCONNECTED)
+ return 0;
+
+ ret = qtnf_cmd_send_disconnect(vif, reason_code);
+ if (ret) {
+ pr_err("VIF%u.%u: failed to disconnect\n", mac->macid,
+ vif->vifid);
+ return ret;
+ }
+
+ vif->sta_state = QTNF_STA_DISCONNECTED;
+ return 0;
+}
+
+static struct cfg80211_ops qtn_cfg80211_ops = {
+ .add_virtual_intf = qtnf_add_virtual_intf,
+ .change_virtual_intf = qtnf_change_virtual_intf,
+ .del_virtual_intf = qtnf_del_virtual_intf,
+ .start_ap = qtnf_start_ap,
+ .change_beacon = qtnf_change_beacon,
+ .stop_ap = qtnf_stop_ap,
+ .set_wiphy_params = qtnf_set_wiphy_params,
+ .mgmt_frame_register = qtnf_mgmt_frame_register,
+ .mgmt_tx = qtnf_mgmt_tx,
+ .change_station = qtnf_change_station,
+ .del_station = qtnf_del_station,
+ .get_station = qtnf_get_station,
+ .dump_station = qtnf_dump_station,
+ .add_key = qtnf_add_key,
+ .del_key = qtnf_del_key,
+ .set_default_key = qtnf_set_default_key,
+ .set_default_mgmt_key = qtnf_set_default_mgmt_key,
+ .scan = qtnf_scan,
+ .connect = qtnf_connect,
+ .disconnect = qtnf_disconnect
+};
+
+static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy,
+ struct regulatory_request *req)
+{
+ struct qtnf_wmac *mac = wiphy_priv(wiphy);
+ struct qtnf_bus *bus;
+ struct qtnf_vif *vif;
+ struct qtnf_wmac *chan_mac;
+ int i;
+ enum nl80211_band band;
+
+ bus = mac->bus;
+
+ pr_debug("MAC%u: initiator=%d alpha=%c%c\n", mac->macid, req->initiator,
+ req->alpha2[0], req->alpha2[1]);
+
+ vif = qtnf_mac_get_base_vif(mac);
+ if (!vif) {
+ pr_err("MAC%u: primary VIF is not configured\n", mac->macid);
+ return;
+ }
+
+ /* ignore non-ISO3166 country codes */
+ for (i = 0; i < sizeof(req->alpha2); i++) {
+ if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
+ pr_err("MAC%u: not an ISO3166 code\n", mac->macid);
+ return;
+ }
+ }
+ if (!strncasecmp(req->alpha2, bus->hw_info.alpha2_code,
+ sizeof(req->alpha2))) {
+ pr_warn("MAC%u: unchanged country code\n", mac->macid);
+ return;
+ }
+
+ if (qtnf_cmd_send_regulatory_config(mac, req->alpha2)) {
+ pr_err("MAC%u: failed to configure regulatory\n", mac->macid);
+ return;
+ }
+
+ for (i = 0; i < bus->hw_info.num_mac; i++) {
+ chan_mac = bus->mac[i];
+
+ if (!chan_mac)
+ continue;
+
+ if (!(bus->hw_info.mac_bitmap & BIT(i)))
+ continue;
+
+ for (band = 0; band < NUM_NL80211_BANDS; ++band) {
+ if (!wiphy->bands[band])
+ continue;
+
+ if (qtnf_cmd_get_mac_chan_info(chan_mac,
+ wiphy->bands[band])) {
+ pr_err("MAC%u: can't get channel info\n",
+ chan_mac->macid);
+ qtnf_core_detach(bus);
+
+ return;
+ }
+ }
+ }
+}
+
+void qtnf_band_setup_htvht_caps(struct qtnf_mac_info *macinfo,
+ struct ieee80211_supported_band *band)
+{
+ struct ieee80211_sta_ht_cap *ht_cap;
+ struct ieee80211_sta_vht_cap *vht_cap;
+
+ ht_cap = &band->ht_cap;
+ ht_cap->ht_supported = true;
+ memcpy(&ht_cap->cap, &macinfo->ht_cap.cap_info,
+ sizeof(u16));
+ ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+ ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
+ memcpy(&ht_cap->mcs, &macinfo->ht_cap.mcs,
+ sizeof(ht_cap->mcs));
+
+ if (macinfo->phymode_cap & QLINK_PHYMODE_AC) {
+ vht_cap = &band->vht_cap;
+ vht_cap->vht_supported = true;
+ memcpy(&vht_cap->cap,
+ &macinfo->vht_cap.vht_cap_info, sizeof(u32));
+ /* Update MCS support for VHT */
+ memcpy(&vht_cap->vht_mcs,
+ &macinfo->vht_cap.supp_mcs,
+ sizeof(struct ieee80211_vht_mcs_info));
+ }
+}
+
+struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus)
+{
+ struct wiphy *wiphy;
+
+ wiphy = wiphy_new(&qtn_cfg80211_ops, sizeof(struct qtnf_wmac));
+ if (!wiphy)
+ return NULL;
+
+ set_wiphy_dev(wiphy, bus->dev);
+
+ return wiphy;
+}
+
+static int qtnf_wiphy_setup_if_comb(struct wiphy *wiphy,
+ struct ieee80211_iface_combination *if_comb,
+ const struct qtnf_mac_info *mac_info)
+{
+ size_t max_interfaces = 0;
+ u16 interface_modes = 0;
+ size_t i;
+
+ if (unlikely(!mac_info->limits || !mac_info->n_limits))
+ return -ENOENT;
+
+ if_comb->limits = mac_info->limits;
+ if_comb->n_limits = mac_info->n_limits;
+
+ for (i = 0; i < mac_info->n_limits; i++) {
+ max_interfaces += mac_info->limits[i].max;
+ interface_modes |= mac_info->limits[i].types;
+ }
+
+ if_comb->num_different_channels = 1;
+ if_comb->beacon_int_infra_match = true;
+ if_comb->max_interfaces = max_interfaces;
+ if_comb->radar_detect_widths = mac_info->radar_detect_widths;
+ wiphy->interface_modes = interface_modes;
+
+ return 0;
+}
+
+int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
+{
+ struct wiphy *wiphy = priv_to_wiphy(mac);
+ struct ieee80211_iface_combination *iface_comb = NULL;
+ int ret;
+
+ if (!wiphy) {
+ pr_err("invalid wiphy pointer\n");
+ return -EFAULT;
+ }
+
+ iface_comb = kzalloc(sizeof(*iface_comb), GFP_KERNEL);
+ if (!iface_comb) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = qtnf_wiphy_setup_if_comb(wiphy, iface_comb, &mac->macinfo);
+ if (ret)
+ goto out;
+
+ pr_info("MAC%u: phymode=%#x radar=%#x\n", mac->macid,
+ mac->macinfo.phymode_cap, mac->macinfo.radar_detect_widths);
+
+ wiphy->frag_threshold = mac->macinfo.frag_thr;
+ wiphy->rts_threshold = mac->macinfo.rts_thr;
+ wiphy->retry_short = mac->macinfo.sretry_limit;
+ wiphy->retry_long = mac->macinfo.lretry_limit;
+ wiphy->coverage_class = mac->macinfo.coverage_class;
+
+ wiphy->max_scan_ssids = QTNF_MAX_SSID_LIST_LENGTH;
+ wiphy->max_scan_ie_len = QTNF_MAX_VSIE_LEN;
+ wiphy->mgmt_stypes = qtnf_mgmt_stypes;
+ wiphy->max_remain_on_channel_duration = 5000;
+
+ wiphy->iface_combinations = iface_comb;
+ wiphy->n_iface_combinations = 1;
+
+ /* Initialize cipher suits */
+ wiphy->cipher_suites = qtnf_cipher_suites;
+ wiphy->n_cipher_suites = ARRAY_SIZE(qtnf_cipher_suites);
+ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+ wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
+ WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
+ WIPHY_FLAG_AP_UAPSD;
+
+ wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
+ NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2;
+
+ wiphy->available_antennas_tx = mac->macinfo.num_tx_chain;
+ wiphy->available_antennas_rx = mac->macinfo.num_rx_chain;
+
+ wiphy->max_ap_assoc_sta = mac->macinfo.max_ap_assoc_sta;
+
+ ether_addr_copy(wiphy->perm_addr, mac->macaddr);
+
+ if (hw_info->hw_capab & QLINK_HW_SUPPORTS_REG_UPDATE) {
+ pr_debug("device supports REG_UPDATE\n");
+ wiphy->reg_notifier = qtnf_cfg80211_reg_notifier;
+ pr_debug("hint regulatory about EP region: %c%c\n",
+ hw_info->alpha2_code[0],
+ hw_info->alpha2_code[1]);
+ regulatory_hint(wiphy, hw_info->alpha2_code);
+ } else {
+ pr_debug("device doesn't support REG_UPDATE\n");
+ wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
+ }
+
+ ret = wiphy_register(wiphy);
+
+out:
+ if (ret < 0) {
+ kfree(iface_comb);
+ return ret;
+ }
+
+ return 0;
+}
+
+void qtnf_netdev_updown(struct net_device *ndev, bool up)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
+
+ if (qtnf_cmd_send_updown_intf(vif, up))
+ pr_err("failed to send up/down command to FW\n");
+}
+
+void qtnf_virtual_intf_cleanup(struct net_device *ndev)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
+ struct qtnf_wmac *mac = wiphy_priv(vif->wdev.wiphy);
+
+ if (vif->wdev.iftype == NL80211_IFTYPE_STATION) {
+ switch (vif->sta_state) {
+ case QTNF_STA_DISCONNECTED:
+ break;
+ case QTNF_STA_CONNECTING:
+ cfg80211_connect_result(vif->netdev,
+ vif->bss_cfg.bssid, NULL, 0,
+ NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ GFP_KERNEL);
+ qtnf_disconnect(vif->wdev.wiphy, ndev,
+ WLAN_REASON_DEAUTH_LEAVING);
+ break;
+ case QTNF_STA_CONNECTED:
+ cfg80211_disconnected(vif->netdev,
+ WLAN_REASON_DEAUTH_LEAVING,
+ NULL, 0, 1, GFP_KERNEL);
+ qtnf_disconnect(vif->wdev.wiphy, ndev,
+ WLAN_REASON_DEAUTH_LEAVING);
+ break;
+ }
+
+ vif->sta_state = QTNF_STA_DISCONNECTED;
+ qtnf_scan_done(mac, true);
+ }
+}
+
+void qtnf_cfg80211_vif_reset(struct qtnf_vif *vif)
+{
+ if (vif->wdev.iftype == NL80211_IFTYPE_STATION) {
+ switch (vif->sta_state) {
+ case QTNF_STA_CONNECTING:
+ cfg80211_connect_result(vif->netdev,
+ vif->bss_cfg.bssid, NULL, 0,
+ NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ GFP_KERNEL);
+ break;
+ case QTNF_STA_CONNECTED:
+ cfg80211_disconnected(vif->netdev,
+ WLAN_REASON_DEAUTH_LEAVING,
+ NULL, 0, 1, GFP_KERNEL);
+ break;
+ case QTNF_STA_DISCONNECTED:
+ break;
+ }
+ }
+
+ cfg80211_shutdown_all_interfaces(vif->wdev.wiphy);
+ vif->sta_state = QTNF_STA_DISCONNECTED;
+}
+
+void qtnf_band_init_rates(struct ieee80211_supported_band *band)
+{
+ switch (band->band) {
+ case NL80211_BAND_2GHZ:
+ band->bitrates = qtnf_rates_2g;
+ band->n_bitrates = ARRAY_SIZE(qtnf_rates_2g);
+ break;
+ case NL80211_BAND_5GHZ:
+ band->bitrates = qtnf_rates_5g;
+ band->n_bitrates = ARRAY_SIZE(qtnf_rates_5g);
+ break;
+ default:
+ band->bitrates = NULL;
+ band->n_bitrates = 0;
+ break;
+ }
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
new file mode 100644
index 0000000..5bd3312
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _QTN_FMAC_CFG80211_H_
+#define _QTN_FMAC_CFG80211_H_
+
+#include <net/cfg80211.h>
+
+#include "core.h"
+
+int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac);
+int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev);
+void qtnf_cfg80211_vif_reset(struct qtnf_vif *vif);
+void qtnf_band_init_rates(struct ieee80211_supported_band *band);
+void qtnf_band_setup_htvht_caps(struct qtnf_mac_info *macinfo,
+ struct ieee80211_supported_band *band);
+
+static inline void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted)
+{
+ struct cfg80211_scan_info info = {
+ .aborted = aborted,
+ };
+
+ if (mac->scan_req) {
+ cfg80211_scan_done(mac->scan_req, &info);
+ mac->scan_req = NULL;
+ }
+}
+
+#endif /* _QTN_FMAC_CFG80211_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
new file mode 100644
index 0000000..b39dbc3
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -0,0 +1,1978 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+
+#include "cfg80211.h"
+#include "core.h"
+#include "qlink.h"
+#include "qlink_util.h"
+#include "bus.h"
+#include "commands.h"
+
+static int qtnf_cmd_check_reply_header(const struct qlink_resp *resp,
+ u16 cmd_id, u8 mac_id, u8 vif_id,
+ size_t resp_size)
+{
+ if (unlikely(le16_to_cpu(resp->cmd_id) != cmd_id)) {
+ pr_warn("VIF%u.%u CMD%x: bad cmd_id in response: 0x%.4X\n",
+ mac_id, vif_id, cmd_id, le16_to_cpu(resp->cmd_id));
+ return -EINVAL;
+ }
+
+ if (unlikely(resp->macid != mac_id)) {
+ pr_warn("VIF%u.%u CMD%x: bad MAC in response: %u\n",
+ mac_id, vif_id, cmd_id, resp->macid);
+ return -EINVAL;
+ }
+
+ if (unlikely(resp->vifid != vif_id)) {
+ pr_warn("VIF%u.%u CMD%x: bad VIF in response: %u\n",
+ mac_id, vif_id, cmd_id, resp->vifid);
+ return -EINVAL;
+ }
+
+ if (unlikely(le16_to_cpu(resp->mhdr.len) < resp_size)) {
+ pr_warn("VIF%u.%u CMD%x: bad response size %u < %zu\n",
+ mac_id, vif_id, cmd_id,
+ le16_to_cpu(resp->mhdr.len), resp_size);
+ return -ENOSPC;
+ }
+
+ return 0;
+}
+
+static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
+ struct sk_buff *cmd_skb,
+ struct sk_buff **response_skb,
+ u16 *result_code,
+ size_t const_resp_size,
+ size_t *var_resp_size)
+{
+ struct qlink_cmd *cmd;
+ const struct qlink_resp *resp;
+ struct sk_buff *resp_skb = NULL;
+ u16 cmd_id;
+ u8 mac_id, vif_id;
+ int ret;
+
+ cmd = (struct qlink_cmd *)cmd_skb->data;
+ cmd_id = le16_to_cpu(cmd->cmd_id);
+ mac_id = cmd->macid;
+ vif_id = cmd->vifid;
+ cmd->mhdr.len = cpu_to_le16(cmd_skb->len);
+
+ if (unlikely(bus->fw_state != QTNF_FW_STATE_ACTIVE &&
+ le16_to_cpu(cmd->cmd_id) != QLINK_CMD_FW_INIT)) {
+ pr_warn("VIF%u.%u: drop cmd 0x%.4X in fw state %d\n",
+ mac_id, vif_id, le16_to_cpu(cmd->cmd_id),
+ bus->fw_state);
+ return -ENODEV;
+ }
+
+ pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id,
+ le16_to_cpu(cmd->cmd_id));
+
+ ret = qtnf_trans_send_cmd_with_resp(bus, cmd_skb, &resp_skb);
+
+ if (unlikely(ret))
+ goto out;
+
+ resp = (const struct qlink_resp *)resp_skb->data;
+ ret = qtnf_cmd_check_reply_header(resp, cmd_id, mac_id, vif_id,
+ const_resp_size);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (likely(result_code))
+ *result_code = le16_to_cpu(resp->result);
+
+ /* Return length of variable part of response */
+ if (response_skb && var_resp_size)
+ *var_resp_size = le16_to_cpu(resp->mhdr.len) - const_resp_size;
+
+out:
+ if (response_skb)
+ *response_skb = resp_skb;
+ else
+ consume_skb(resp_skb);
+
+ return ret;
+}
+
+static inline int qtnf_cmd_send(struct qtnf_bus *bus,
+ struct sk_buff *cmd_skb,
+ u16 *result_code)
+{
+ return qtnf_cmd_send_with_reply(bus, cmd_skb, NULL, result_code,
+ sizeof(struct qlink_resp), NULL);
+}
+
+static struct sk_buff *qtnf_cmd_alloc_new_cmdskb(u8 macid, u8 vifid, u16 cmd_no,
+ size_t cmd_size)
+{
+ struct qlink_cmd *cmd;
+ struct sk_buff *cmd_skb;
+
+ cmd_skb = __dev_alloc_skb(sizeof(*cmd) +
+ QTNF_MAX_CMD_BUF_SIZE, GFP_KERNEL);
+ if (unlikely(!cmd_skb)) {
+ pr_err("VIF%u.%u CMD %u: alloc failed\n", macid, vifid, cmd_no);
+ return NULL;
+ }
+
+ skb_put_zero(cmd_skb, cmd_size);
+
+ cmd = (struct qlink_cmd *)cmd_skb->data;
+ cmd->mhdr.len = cpu_to_le16(cmd_skb->len);
+ cmd->mhdr.type = cpu_to_le16(QLINK_MSG_TYPE_CMD);
+ cmd->cmd_id = cpu_to_le16(cmd_no);
+ cmd->macid = macid;
+ cmd->vifid = vifid;
+
+ return cmd_skb;
+}
+
+int qtnf_cmd_send_start_ap(struct qtnf_vif *vif)
+{
+ struct sk_buff *cmd_skb;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_START_AP,
+ sizeof(struct qlink_cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+ vif->vifid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ vif->bss_status |= QTNF_STATE_AP_START;
+ netif_carrier_on(vif->netdev);
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
+
+int qtnf_cmd_send_regulatory_config(struct qtnf_wmac *mac, const char *alpha2)
+{
+ struct sk_buff *cmd_skb;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
+ QLINK_CMD_REG_REGION,
+ sizeof(struct qlink_cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_COUNTRY, alpha2,
+ QTNF_MAX_ALPHA_LEN);
+
+ ret = qtnf_cmd_send(mac->bus, cmd_skb, &res_code);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ memcpy(mac->bus->hw_info.alpha2_code, alpha2,
+ sizeof(mac->bus->hw_info.alpha2_code));
+out:
+ return ret;
+}
+
+int qtnf_cmd_send_config_ap(struct qtnf_vif *vif)
+{
+ struct sk_buff *cmd_skb;
+ struct qtnf_bss_config *bss_cfg = &vif->bss_cfg;
+ struct cfg80211_chan_def *chandef = &bss_cfg->chandef;
+ struct qlink_tlv_channel *qchan;
+ struct qlink_auth_encr aen;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret;
+ int i;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_CONFIG_AP,
+ sizeof(struct qlink_cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, bss_cfg->ssid,
+ bss_cfg->ssid_len);
+ qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_BCN_PERIOD,
+ bss_cfg->bcn_period);
+ qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_DTIM, bss_cfg->dtim);
+
+ qchan = skb_put_zero(cmd_skb, sizeof(*qchan));
+ qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
+ qchan->hdr.len = cpu_to_le16(sizeof(*qchan) -
+ sizeof(struct qlink_tlv_hdr));
+ qchan->hw_value = cpu_to_le16(
+ ieee80211_frequency_to_channel(chandef->chan->center_freq));
+
+ memset(&aen, 0, sizeof(aen));
+ aen.auth_type = bss_cfg->auth_type;
+ aen.privacy = !!bss_cfg->privacy;
+ aen.mfp = bss_cfg->mfp;
+ aen.wpa_versions = cpu_to_le32(bss_cfg->crypto.wpa_versions);
+ aen.cipher_group = cpu_to_le32(bss_cfg->crypto.cipher_group);
+ aen.n_ciphers_pairwise = cpu_to_le32(
+ bss_cfg->crypto.n_ciphers_pairwise);
+ for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
+ aen.ciphers_pairwise[i] = cpu_to_le32(
+ bss_cfg->crypto.ciphers_pairwise[i]);
+ aen.n_akm_suites = cpu_to_le32(
+ bss_cfg->crypto.n_akm_suites);
+ for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
+ aen.akm_suites[i] = cpu_to_le32(
+ bss_cfg->crypto.akm_suites[i]);
+ aen.control_port = bss_cfg->crypto.control_port;
+ aen.control_port_no_encrypt =
+ bss_cfg->crypto.control_port_no_encrypt;
+ aen.control_port_ethertype = cpu_to_le16(be16_to_cpu(
+ bss_cfg->crypto.control_port_ethertype));
+
+ qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_CRYPTO, (u8 *)&aen,
+ sizeof(aen));
+
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+ vif->vifid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ vif->bss_status |= QTNF_STATE_AP_CONFIG;
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
+
+int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif)
+{
+ struct sk_buff *cmd_skb;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_STOP_AP,
+ sizeof(struct qlink_cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+ vif->vifid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ vif->bss_status &= ~QTNF_STATE_AP_START;
+ vif->bss_status &= ~QTNF_STATE_AP_CONFIG;
+
+ netif_carrier_off(vif->netdev);
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
+
+int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg)
+{
+ struct sk_buff *cmd_skb;
+ struct qlink_cmd_mgmt_frame_register *cmd;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_REGISTER_MGMT,
+ sizeof(*cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ cmd = (struct qlink_cmd_mgmt_frame_register *)cmd_skb->data;
+ cmd->frame_type = cpu_to_le16(frame_type);
+ cmd->do_register = reg;
+
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+ vif->vifid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
+
+int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
+ u16 freq, const u8 *buf, size_t len)
+{
+ struct sk_buff *cmd_skb;
+ struct qlink_cmd_mgmt_frame_tx *cmd;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret;
+
+ if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) {
+ pr_warn("VIF%u.%u: frame is too big: %zu\n", vif->mac->macid,
+ vif->vifid, len);
+ return -E2BIG;
+ }
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_SEND_MGMT_FRAME,
+ sizeof(*cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ cmd = (struct qlink_cmd_mgmt_frame_tx *)cmd_skb->data;
+ cmd->cookie = cpu_to_le32(cookie);
+ cmd->freq = cpu_to_le16(freq);
+ cmd->flags = cpu_to_le16(flags);
+
+ if (len && buf)
+ qtnf_cmd_skb_put_buffer(cmd_skb, buf, len);
+
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+ vif->vifid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
+
+int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type,
+ const u8 *buf, size_t len)
+{
+ struct sk_buff *cmd_skb;
+ struct qlink_cmd_mgmt_append_ie *cmd;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret;
+
+ if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) {
+ pr_warn("VIF%u.%u: %u frame is too big: %zu\n", vif->mac->macid,
+ vif->vifid, frame_type, len);
+ return -E2BIG;
+ }
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_MGMT_SET_APPIE,
+ sizeof(*cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ cmd = (struct qlink_cmd_mgmt_append_ie *)cmd_skb->data;
+ cmd->type = frame_type;
+ cmd->flags = 0;
+
+ /* If len == 0 then IE buf for specified frame type
+ * should be cleared on EP.
+ */
+ if (len && buf)
+ qtnf_cmd_skb_put_buffer(cmd_skb, buf, len);
+
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u frame %u: CMD failed: %u\n", vif->mac->macid,
+ vif->vifid, frame_type, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
+
+static void
+qtnf_sta_info_parse_basic_counters(struct station_info *sinfo,
+ const struct qlink_sta_stat_basic_counters *counters)
+{
+ sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES) |
+ BIT(NL80211_STA_INFO_TX_BYTES);
+ sinfo->rx_bytes = get_unaligned_le64(&counters->rx_bytes);
+ sinfo->tx_bytes = get_unaligned_le64(&counters->tx_bytes);
+
+ sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS) |
+ BIT(NL80211_STA_INFO_TX_PACKETS) |
+ BIT(NL80211_STA_INFO_BEACON_RX);
+ sinfo->rx_packets = get_unaligned_le32(&counters->rx_packets);
+ sinfo->tx_packets = get_unaligned_le32(&counters->tx_packets);
+ sinfo->rx_beacon = get_unaligned_le64(&counters->rx_beacons);
+
+ sinfo->filled |= BIT(NL80211_STA_INFO_RX_DROP_MISC) |
+ BIT(NL80211_STA_INFO_TX_FAILED);
+ sinfo->rx_dropped_misc = get_unaligned_le32(&counters->rx_dropped);
+ sinfo->tx_failed = get_unaligned_le32(&counters->tx_failed);
+}
+
+static void
+qtnf_sta_info_parse_rate(struct rate_info *rate_dst,
+ const struct qlink_sta_info_rate *rate_src)
+{
+ rate_dst->legacy = get_unaligned_le16(&rate_src->rate) * 10;
+
+ rate_dst->mcs = rate_src->mcs;
+ rate_dst->nss = rate_src->nss;
+ rate_dst->flags = 0;
+
+ switch (rate_src->bw) {
+ case QLINK_STA_INFO_RATE_BW_5:
+ rate_dst->bw = RATE_INFO_BW_5;
+ break;
+ case QLINK_STA_INFO_RATE_BW_10:
+ rate_dst->bw = RATE_INFO_BW_10;
+ break;
+ case QLINK_STA_INFO_RATE_BW_20:
+ rate_dst->bw = RATE_INFO_BW_20;
+ break;
+ case QLINK_STA_INFO_RATE_BW_40:
+ rate_dst->bw = RATE_INFO_BW_40;
+ break;
+ case QLINK_STA_INFO_RATE_BW_80:
+ rate_dst->bw = RATE_INFO_BW_80;
+ break;
+ case QLINK_STA_INFO_RATE_BW_160:
+ rate_dst->bw = RATE_INFO_BW_160;
+ break;
+ default:
+ rate_dst->bw = 0;
+ break;
+ }
+
+ if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_HT_MCS)
+ rate_dst->flags |= RATE_INFO_FLAGS_MCS;
+ else if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_VHT_MCS)
+ rate_dst->flags |= RATE_INFO_FLAGS_VHT_MCS;
+}
+
+static void
+qtnf_sta_info_parse_flags(struct nl80211_sta_flag_update *dst,
+ const struct qlink_sta_info_state *src)
+{
+ u32 mask, value;
+
+ dst->mask = 0;
+ dst->set = 0;
+
+ mask = le32_to_cpu(src->mask);
+ value = le32_to_cpu(src->value);
+
+ if (mask & QLINK_STA_FLAG_AUTHORIZED) {
+ dst->mask |= BIT(NL80211_STA_FLAG_AUTHORIZED);
+ if (value & QLINK_STA_FLAG_AUTHORIZED)
+ dst->set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
+ }
+
+ if (mask & QLINK_STA_FLAG_SHORT_PREAMBLE) {
+ dst->mask |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
+ if (value & QLINK_STA_FLAG_SHORT_PREAMBLE)
+ dst->set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
+ }
+
+ if (mask & QLINK_STA_FLAG_WME) {
+ dst->mask |= BIT(NL80211_STA_FLAG_WME);
+ if (value & QLINK_STA_FLAG_WME)
+ dst->set |= BIT(NL80211_STA_FLAG_WME);
+ }
+
+ if (mask & QLINK_STA_FLAG_MFP) {
+ dst->mask |= BIT(NL80211_STA_FLAG_MFP);
+ if (value & QLINK_STA_FLAG_MFP)
+ dst->set |= BIT(NL80211_STA_FLAG_MFP);
+ }
+
+ if (mask & QLINK_STA_FLAG_AUTHENTICATED) {
+ dst->mask |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
+ if (value & QLINK_STA_FLAG_AUTHENTICATED)
+ dst->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
+ }
+
+ if (mask & QLINK_STA_FLAG_TDLS_PEER) {
+ dst->mask |= BIT(NL80211_STA_FLAG_TDLS_PEER);
+ if (value & QLINK_STA_FLAG_TDLS_PEER)
+ dst->set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
+ }
+
+ if (mask & QLINK_STA_FLAG_ASSOCIATED) {
+ dst->mask |= BIT(NL80211_STA_FLAG_ASSOCIATED);
+ if (value & QLINK_STA_FLAG_ASSOCIATED)
+ dst->set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
+ }
+}
+
+static void
+qtnf_sta_info_parse_generic_info(struct station_info *sinfo,
+ const struct qlink_sta_info_generic *info)
+{
+ sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME) |
+ BIT(NL80211_STA_INFO_INACTIVE_TIME);
+ sinfo->connected_time = get_unaligned_le32(&info->connected_time);
+ sinfo->inactive_time = get_unaligned_le32(&info->inactive_time);
+
+ sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) |
+ BIT(NL80211_STA_INFO_SIGNAL_AVG);
+ sinfo->signal = info->rssi - 120;
+ sinfo->signal_avg = info->rssi_avg - QLINK_RSSI_OFFSET;
+
+ if (info->rx_rate.rate) {
+ sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
+ qtnf_sta_info_parse_rate(&sinfo->rxrate, &info->rx_rate);
+ }
+
+ if (info->tx_rate.rate) {
+ sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
+ qtnf_sta_info_parse_rate(&sinfo->txrate, &info->tx_rate);
+ }
+
+ sinfo->filled |= BIT(NL80211_STA_INFO_STA_FLAGS);
+ qtnf_sta_info_parse_flags(&sinfo->sta_flags, &info->state);
+}
+
+static int qtnf_cmd_sta_info_parse(struct station_info *sinfo,
+ const u8 *payload, size_t payload_size)
+{
+ const struct qlink_sta_stat_basic_counters *counters;
+ const struct qlink_sta_info_generic *sta_info;
+ u16 tlv_type;
+ u16 tlv_value_len;
+ size_t tlv_full_len;
+ const struct qlink_tlv_hdr *tlv;
+
+ sinfo->filled = 0;
+
+ tlv = (const struct qlink_tlv_hdr *)payload;
+ while (payload_size >= sizeof(struct qlink_tlv_hdr)) {
+ tlv_type = le16_to_cpu(tlv->type);
+ tlv_value_len = le16_to_cpu(tlv->len);
+ tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
+ if (tlv_full_len > payload_size) {
+ pr_warn("malformed TLV 0x%.2X; LEN: %u\n",
+ tlv_type, tlv_value_len);
+ return -EINVAL;
+ }
+ switch (tlv_type) {
+ case QTN_TLV_ID_STA_BASIC_COUNTERS:
+ if (unlikely(tlv_value_len < sizeof(*counters))) {
+ pr_err("invalid TLV size %.4X: %u\n",
+ tlv_type, tlv_value_len);
+ break;
+ }
+
+ counters = (void *)tlv->val;
+ qtnf_sta_info_parse_basic_counters(sinfo, counters);
+ break;
+ case QTN_TLV_ID_STA_GENERIC_INFO:
+ if (unlikely(tlv_value_len < sizeof(*sta_info)))
+ break;
+
+ sta_info = (void *)tlv->val;
+ qtnf_sta_info_parse_generic_info(sinfo, sta_info);
+ break;
+ default:
+ pr_warn("unexpected TLV type: %.4X\n", tlv_type);
+ break;
+ }
+ payload_size -= tlv_full_len;
+ tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
+ }
+
+ if (payload_size) {
+ pr_warn("malformed TLV buf; bytes left: %zu\n", payload_size);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac,
+ struct station_info *sinfo)
+{
+ struct sk_buff *cmd_skb, *resp_skb = NULL;
+ struct qlink_cmd_get_sta_info *cmd;
+ const struct qlink_resp_get_sta_info *resp;
+ size_t var_resp_len;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret = 0;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_GET_STA_INFO,
+ sizeof(*cmd));
+
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ cmd = (struct qlink_cmd_get_sta_info *)cmd_skb->data;
+ ether_addr_copy(cmd->sta_addr, sta_mac);
+
+ ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb,
+ &res_code, sizeof(*resp),
+ &var_resp_len);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ switch (res_code) {
+ case QLINK_CMD_RESULT_ENOTFOUND:
+ pr_warn("VIF%u.%u: %pM STA not found\n",
+ vif->mac->macid, vif->vifid, sta_mac);
+ ret = -ENOENT;
+ break;
+ default:
+ pr_err("VIF%u.%u: can't get info for %pM: %u\n",
+ vif->mac->macid, vif->vifid, sta_mac, res_code);
+ ret = -EFAULT;
+ break;
+ }
+ goto out;
+ }
+
+ resp = (const struct qlink_resp_get_sta_info *)resp_skb->data;
+
+ if (unlikely(!ether_addr_equal(sta_mac, resp->sta_addr))) {
+ pr_err("VIF%u.%u: wrong mac in reply: %pM != %pM\n",
+ vif->mac->macid, vif->vifid, resp->sta_addr, sta_mac);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = qtnf_cmd_sta_info_parse(sinfo, resp->info, var_resp_len);
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ consume_skb(resp_skb);
+
+ return ret;
+}
+
+static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif,
+ enum nl80211_iftype iftype,
+ u8 *mac_addr,
+ enum qlink_cmd_type cmd_type)
+{
+ struct sk_buff *cmd_skb, *resp_skb = NULL;
+ struct qlink_cmd_manage_intf *cmd;
+ const struct qlink_resp_manage_intf *resp;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret = 0;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ cmd_type,
+ sizeof(*cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ cmd = (struct qlink_cmd_manage_intf *)cmd_skb->data;
+
+ switch (iftype) {
+ case NL80211_IFTYPE_AP:
+ cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_AP);
+ break;
+ case NL80211_IFTYPE_STATION:
+ cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_STATION);
+ break;
+ default:
+ pr_err("VIF%u.%u: unsupported type %d\n", vif->mac->macid,
+ vif->vifid, iftype);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (mac_addr)
+ ether_addr_copy(cmd->intf_info.mac_addr, mac_addr);
+ else
+ eth_zero_addr(cmd->intf_info.mac_addr);
+
+ ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb,
+ &res_code, sizeof(*resp), NULL);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD %d failed: %u\n", vif->mac->macid,
+ vif->vifid, cmd_type, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ resp = (const struct qlink_resp_manage_intf *)resp_skb->data;
+ ether_addr_copy(vif->mac_addr, resp->intf_info.mac_addr);
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ consume_skb(resp_skb);
+
+ return ret;
+}
+
+int qtnf_cmd_send_add_intf(struct qtnf_vif *vif,
+ enum nl80211_iftype iftype, u8 *mac_addr)
+{
+ return qtnf_cmd_send_add_change_intf(vif, iftype, mac_addr,
+ QLINK_CMD_ADD_INTF);
+}
+
+int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif,
+ enum nl80211_iftype iftype, u8 *mac_addr)
+{
+ return qtnf_cmd_send_add_change_intf(vif, iftype, mac_addr,
+ QLINK_CMD_CHANGE_INTF);
+}
+
+int qtnf_cmd_send_del_intf(struct qtnf_vif *vif)
+{
+ struct sk_buff *cmd_skb;
+ struct qlink_cmd_manage_intf *cmd;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret = 0;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_DEL_INTF,
+ sizeof(*cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ cmd = (struct qlink_cmd_manage_intf *)cmd_skb->data;
+
+ switch (vif->wdev.iftype) {
+ case NL80211_IFTYPE_AP:
+ cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_AP);
+ break;
+ case NL80211_IFTYPE_STATION:
+ cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_STATION);
+ break;
+ default:
+ pr_warn("VIF%u.%u: unsupported iftype %d\n", vif->mac->macid,
+ vif->vifid, vif->wdev.iftype);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ eth_zero_addr(cmd->intf_info.mac_addr);
+
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+ vif->vifid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
+
+static int
+qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
+ const struct qlink_resp_get_hw_info *resp)
+{
+ struct qtnf_hw_info *hwinfo = &bus->hw_info;
+
+ hwinfo->num_mac = resp->num_mac;
+ hwinfo->mac_bitmap = resp->mac_bitmap;
+ hwinfo->fw_ver = le32_to_cpu(resp->fw_ver);
+ hwinfo->ql_proto_ver = le16_to_cpu(resp->ql_proto_ver);
+ memcpy(hwinfo->alpha2_code, resp->alpha2_code,
+ sizeof(hwinfo->alpha2_code));
+ hwinfo->total_tx_chain = resp->total_tx_chain;
+ hwinfo->total_rx_chain = resp->total_rx_chain;
+ hwinfo->hw_capab = le32_to_cpu(resp->hw_capab);
+
+ pr_info("fw_version=%d, MACs map %#x, alpha2=\"%c%c\", chains Tx=%u Rx=%u\n",
+ hwinfo->fw_ver, hwinfo->mac_bitmap,
+ hwinfo->alpha2_code[0], hwinfo->alpha2_code[1],
+ hwinfo->total_tx_chain, hwinfo->total_rx_chain);
+
+ return 0;
+}
+
+static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac,
+ const u8 *tlv_buf, size_t tlv_buf_size)
+{
+ struct ieee80211_iface_limit *limits = NULL;
+ const struct qlink_iface_limit *limit_record;
+ size_t record_count = 0, rec = 0;
+ u16 tlv_type, tlv_value_len, mask;
+ struct qlink_iface_comb_num *comb;
+ size_t tlv_full_len;
+ const struct qlink_tlv_hdr *tlv;
+
+ mac->macinfo.n_limits = 0;
+
+ tlv = (const struct qlink_tlv_hdr *)tlv_buf;
+ while (tlv_buf_size >= sizeof(struct qlink_tlv_hdr)) {
+ tlv_type = le16_to_cpu(tlv->type);
+ tlv_value_len = le16_to_cpu(tlv->len);
+ tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
+ if (tlv_full_len > tlv_buf_size) {
+ pr_warn("MAC%u: malformed TLV 0x%.2X; LEN: %u\n",
+ mac->macid, tlv_type, tlv_value_len);
+ return -EINVAL;
+ }
+
+ switch (tlv_type) {
+ case QTN_TLV_ID_NUM_IFACE_COMB:
+ if (unlikely(tlv_value_len != sizeof(*comb)))
+ return -EINVAL;
+
+ comb = (void *)tlv->val;
+ record_count = le16_to_cpu(comb->iface_comb_num);
+
+ mac->macinfo.n_limits = record_count;
+ /* free earlier iface limits memory */
+ kfree(mac->macinfo.limits);
+ mac->macinfo.limits =
+ kzalloc(sizeof(*mac->macinfo.limits) *
+ record_count, GFP_KERNEL);
+
+ if (unlikely(!mac->macinfo.limits))
+ return -ENOMEM;
+
+ limits = mac->macinfo.limits;
+ break;
+ case QTN_TLV_ID_IFACE_LIMIT:
+ if (unlikely(!limits)) {
+ pr_warn("MAC%u: limits are not inited\n",
+ mac->macid);
+ return -EINVAL;
+ }
+
+ if (unlikely(tlv_value_len != sizeof(*limit_record))) {
+ pr_warn("MAC%u: record size mismatch\n",
+ mac->macid);
+ return -EINVAL;
+ }
+
+ limit_record = (void *)tlv->val;
+ limits[rec].max = le16_to_cpu(limit_record->max_num);
+ mask = le16_to_cpu(limit_record->type_mask);
+ limits[rec].types = qlink_iface_type_mask_to_nl(mask);
+ /* only AP and STA modes are supported */
+ limits[rec].types &= BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_STATION);
+
+ pr_debug("MAC%u: MAX: %u; TYPES: %.4X\n", mac->macid,
+ limits[rec].max, limits[rec].types);
+
+ if (limits[rec].types)
+ rec++;
+ break;
+ default:
+ break;
+ }
+ tlv_buf_size -= tlv_full_len;
+ tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
+ }
+
+ if (tlv_buf_size) {
+ pr_warn("MAC%u: malformed TLV buf; bytes left: %zu\n",
+ mac->macid, tlv_buf_size);
+ return -EINVAL;
+ }
+
+ if (mac->macinfo.n_limits != rec) {
+ pr_err("MAC%u: combination mismatch: reported=%zu parsed=%zu\n",
+ mac->macid, mac->macinfo.n_limits, rec);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void
+qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac,
+ const struct qlink_resp_get_mac_info *resp_info)
+{
+ struct qtnf_mac_info *mac_info;
+ struct qtnf_vif *vif;
+
+ mac_info = &mac->macinfo;
+
+ mac_info->bands_cap = resp_info->bands_cap;
+ mac_info->phymode_cap = resp_info->phymode_cap;
+ memcpy(&mac_info->dev_mac, &resp_info->dev_mac,
+ sizeof(mac_info->dev_mac));
+
+ ether_addr_copy(mac->macaddr, mac_info->dev_mac);
+
+ vif = qtnf_mac_get_base_vif(mac);
+ if (vif)
+ ether_addr_copy(vif->mac_addr, mac->macaddr);
+ else
+ pr_err("could not get valid base vif\n");
+
+ mac_info->num_tx_chain = resp_info->num_tx_chain;
+ mac_info->num_rx_chain = resp_info->num_rx_chain;
+
+ mac_info->max_ap_assoc_sta = le16_to_cpu(resp_info->max_ap_assoc_sta);
+ mac_info->radar_detect_widths =
+ qlink_chan_width_mask_to_nl(le16_to_cpu(
+ resp_info->radar_detect_widths));
+
+ memcpy(&mac_info->ht_cap, &resp_info->ht_cap, sizeof(mac_info->ht_cap));
+ memcpy(&mac_info->vht_cap, &resp_info->vht_cap,
+ sizeof(mac_info->vht_cap));
+}
+
+static int
+qtnf_cmd_resp_fill_channels_info(struct ieee80211_supported_band *band,
+ struct qlink_resp_get_chan_info *resp,
+ size_t payload_len)
+{
+ u16 tlv_type;
+ size_t tlv_len;
+ const struct qlink_tlv_hdr *tlv;
+ const struct qlink_tlv_channel *qchan;
+ struct ieee80211_channel *chan;
+ unsigned int chidx = 0;
+ u32 qflags;
+
+ kfree(band->channels);
+ band->channels = NULL;
+
+ band->n_channels = resp->num_chans;
+ if (band->n_channels == 0)
+ return 0;
+
+ band->channels = kcalloc(band->n_channels, sizeof(*chan), GFP_KERNEL);
+ if (!band->channels) {
+ band->n_channels = 0;
+ return -ENOMEM;
+ }
+
+ tlv = (struct qlink_tlv_hdr *)resp->info;
+
+ while (payload_len >= sizeof(*tlv)) {
+ tlv_type = le16_to_cpu(tlv->type);
+ tlv_len = le16_to_cpu(tlv->len) + sizeof(*tlv);
+
+ if (tlv_len > payload_len) {
+ pr_warn("malformed TLV 0x%.2X; LEN: %zu\n",
+ tlv_type, tlv_len);
+ goto error_ret;
+ }
+
+ switch (tlv_type) {
+ case QTN_TLV_ID_CHANNEL:
+ if (unlikely(tlv_len != sizeof(*qchan))) {
+ pr_err("invalid channel TLV len %zu\n",
+ tlv_len);
+ goto error_ret;
+ }
+
+ if (chidx == band->n_channels) {
+ pr_err("too many channel TLVs\n");
+ goto error_ret;
+ }
+
+ qchan = (const struct qlink_tlv_channel *)tlv;
+ chan = &band->channels[chidx++];
+ qflags = le32_to_cpu(qchan->flags);
+
+ chan->hw_value = le16_to_cpu(qchan->hw_value);
+ chan->band = band->band;
+ chan->center_freq = le16_to_cpu(qchan->center_freq);
+ chan->max_antenna_gain = (int)qchan->max_antenna_gain;
+ chan->max_power = (int)qchan->max_power;
+ chan->max_reg_power = (int)qchan->max_reg_power;
+ chan->beacon_found = qchan->beacon_found;
+ chan->dfs_cac_ms = le32_to_cpu(qchan->dfs_cac_ms);
+ chan->flags = 0;
+
+ if (qflags & QLINK_CHAN_DISABLED)
+ chan->flags |= IEEE80211_CHAN_DISABLED;
+
+ if (qflags & QLINK_CHAN_NO_IR)
+ chan->flags |= IEEE80211_CHAN_NO_IR;
+
+ if (qflags & QLINK_CHAN_NO_HT40PLUS)
+ chan->flags |= IEEE80211_CHAN_NO_HT40PLUS;
+
+ if (qflags & QLINK_CHAN_NO_HT40MINUS)
+ chan->flags |= IEEE80211_CHAN_NO_HT40MINUS;
+
+ if (qflags & QLINK_CHAN_NO_OFDM)
+ chan->flags |= IEEE80211_CHAN_NO_OFDM;
+
+ if (qflags & QLINK_CHAN_NO_80MHZ)
+ chan->flags |= IEEE80211_CHAN_NO_80MHZ;
+
+ if (qflags & QLINK_CHAN_NO_160MHZ)
+ chan->flags |= IEEE80211_CHAN_NO_160MHZ;
+
+ if (qflags & QLINK_CHAN_INDOOR_ONLY)
+ chan->flags |= IEEE80211_CHAN_INDOOR_ONLY;
+
+ if (qflags & QLINK_CHAN_IR_CONCURRENT)
+ chan->flags |= IEEE80211_CHAN_IR_CONCURRENT;
+
+ if (qflags & QLINK_CHAN_NO_20MHZ)
+ chan->flags |= IEEE80211_CHAN_NO_20MHZ;
+
+ if (qflags & QLINK_CHAN_NO_10MHZ)
+ chan->flags |= IEEE80211_CHAN_NO_10MHZ;
+
+ if (qflags & QLINK_CHAN_RADAR) {
+ chan->flags |= IEEE80211_CHAN_RADAR;
+ chan->dfs_state_entered = jiffies;
+
+ if (qchan->dfs_state == QLINK_DFS_USABLE)
+ chan->dfs_state = NL80211_DFS_USABLE;
+ else if (qchan->dfs_state ==
+ QLINK_DFS_AVAILABLE)
+ chan->dfs_state = NL80211_DFS_AVAILABLE;
+ else
+ chan->dfs_state =
+ NL80211_DFS_UNAVAILABLE;
+ }
+
+ pr_debug("chan=%d flags=%#x max_pow=%d max_reg_pow=%d\n",
+ chan->hw_value, chan->flags, chan->max_power,
+ chan->max_reg_power);
+ break;
+ default:
+ pr_warn("unknown TLV type: %#x\n", tlv_type);
+ break;
+ }
+
+ payload_len -= tlv_len;
+ tlv = (struct qlink_tlv_hdr *)((u8 *)tlv + tlv_len);
+ }
+
+ if (payload_len) {
+ pr_err("malformed TLV buf; bytes left: %zu\n", payload_len);
+ goto error_ret;
+ }
+
+ if (band->n_channels != chidx) {
+ pr_err("channel count mismatch: reported=%d, parsed=%d\n",
+ band->n_channels, chidx);
+ goto error_ret;
+ }
+
+ return 0;
+
+error_ret:
+ kfree(band->channels);
+ band->channels = NULL;
+ band->n_channels = 0;
+
+ return -EINVAL;
+}
+
+static int qtnf_cmd_resp_proc_phy_params(struct qtnf_wmac *mac,
+ const u8 *payload, size_t payload_len)
+{
+ struct qtnf_mac_info *mac_info;
+ struct qlink_tlv_frag_rts_thr *phy_thr;
+ struct qlink_tlv_rlimit *limit;
+ struct qlink_tlv_cclass *class;
+ u16 tlv_type;
+ u16 tlv_value_len;
+ size_t tlv_full_len;
+ const struct qlink_tlv_hdr *tlv;
+
+ mac_info = &mac->macinfo;
+
+ tlv = (struct qlink_tlv_hdr *)payload;
+ while (payload_len >= sizeof(struct qlink_tlv_hdr)) {
+ tlv_type = le16_to_cpu(tlv->type);
+ tlv_value_len = le16_to_cpu(tlv->len);
+ tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
+
+ if (tlv_full_len > payload_len) {
+ pr_warn("MAC%u: malformed TLV 0x%.2X; LEN: %u\n",
+ mac->macid, tlv_type, tlv_value_len);
+ return -EINVAL;
+ }
+
+ switch (tlv_type) {
+ case QTN_TLV_ID_FRAG_THRESH:
+ phy_thr = (void *)tlv;
+ mac_info->frag_thr = (u32)le16_to_cpu(phy_thr->thr);
+ break;
+ case QTN_TLV_ID_RTS_THRESH:
+ phy_thr = (void *)tlv;
+ mac_info->rts_thr = (u32)le16_to_cpu(phy_thr->thr);
+ break;
+ case QTN_TLV_ID_SRETRY_LIMIT:
+ limit = (void *)tlv;
+ mac_info->sretry_limit = limit->rlimit;
+ break;
+ case QTN_TLV_ID_LRETRY_LIMIT:
+ limit = (void *)tlv;
+ mac_info->lretry_limit = limit->rlimit;
+ break;
+ case QTN_TLV_ID_COVERAGE_CLASS:
+ class = (void *)tlv;
+ mac_info->coverage_class = class->cclass;
+ break;
+ default:
+ pr_err("MAC%u: Unknown TLV type: %#x\n", mac->macid,
+ le16_to_cpu(tlv->type));
+ break;
+ }
+
+ payload_len -= tlv_full_len;
+ tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
+ }
+
+ if (payload_len) {
+ pr_warn("MAC%u: malformed TLV buf; bytes left: %zu\n",
+ mac->macid, payload_len);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac)
+{
+ struct sk_buff *cmd_skb, *resp_skb = NULL;
+ const struct qlink_resp_get_mac_info *resp;
+ size_t var_data_len;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret = 0;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
+ QLINK_CMD_MAC_INFO,
+ sizeof(struct qlink_cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(mac->bus);
+
+ ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code,
+ sizeof(*resp), &var_data_len);
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ resp = (const struct qlink_resp_get_mac_info *)resp_skb->data;
+ qtnf_cmd_resp_proc_mac_info(mac, resp);
+ ret = qtnf_parse_variable_mac_info(mac, resp->var_info, var_data_len);
+
+out:
+ qtnf_bus_unlock(mac->bus);
+ consume_skb(resp_skb);
+
+ return ret;
+}
+
+int qtnf_cmd_get_hw_info(struct qtnf_bus *bus)
+{
+ struct sk_buff *cmd_skb, *resp_skb = NULL;
+ const struct qlink_resp_get_hw_info *resp;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret = 0;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
+ QLINK_CMD_GET_HW_INFO,
+ sizeof(struct qlink_cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(bus);
+
+ ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, &res_code,
+ sizeof(*resp), NULL);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("cmd exec failed: 0x%.4X\n", res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ resp = (const struct qlink_resp_get_hw_info *)resp_skb->data;
+ ret = qtnf_cmd_resp_proc_hw_info(bus, resp);
+
+out:
+ qtnf_bus_unlock(bus);
+ consume_skb(resp_skb);
+
+ return ret;
+}
+
+int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
+ struct ieee80211_supported_band *band)
+{
+ struct sk_buff *cmd_skb, *resp_skb = NULL;
+ size_t info_len;
+ struct qlink_cmd_chans_info_get *cmd;
+ struct qlink_resp_get_chan_info *resp;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret = 0;
+ u8 qband;
+
+ switch (band->band) {
+ case NL80211_BAND_2GHZ:
+ qband = QLINK_BAND_2GHZ;
+ break;
+ case NL80211_BAND_5GHZ:
+ qband = QLINK_BAND_5GHZ;
+ break;
+ case NL80211_BAND_60GHZ:
+ qband = QLINK_BAND_60GHZ;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
+ QLINK_CMD_CHANS_INFO_GET,
+ sizeof(*cmd));
+ if (!cmd_skb)
+ return -ENOMEM;
+
+ cmd = (struct qlink_cmd_chans_info_get *)cmd_skb->data;
+ cmd->band = qband;
+ ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code,
+ sizeof(*resp), &info_len);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ resp = (struct qlink_resp_get_chan_info *)resp_skb->data;
+ if (resp->band != qband) {
+ pr_err("MAC%u: reply band %u != cmd band %u\n", mac->macid,
+ resp->band, qband);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = qtnf_cmd_resp_fill_channels_info(band, resp, info_len);
+
+out:
+ consume_skb(resp_skb);
+
+ return ret;
+}
+
+int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac)
+{
+ struct sk_buff *cmd_skb, *resp_skb = NULL;
+ size_t response_size;
+ struct qlink_resp_phy_params *resp;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret = 0;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
+ QLINK_CMD_PHY_PARAMS_GET,
+ sizeof(struct qlink_cmd));
+ if (!cmd_skb)
+ return -ENOMEM;
+
+ qtnf_bus_lock(mac->bus);
+
+ ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code,
+ sizeof(*resp), &response_size);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ resp = (struct qlink_resp_phy_params *)resp_skb->data;
+ ret = qtnf_cmd_resp_proc_phy_params(mac, resp->info, response_size);
+
+out:
+ qtnf_bus_unlock(mac->bus);
+ consume_skb(resp_skb);
+
+ return ret;
+}
+
+int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed)
+{
+ struct wiphy *wiphy = priv_to_wiphy(mac);
+ struct sk_buff *cmd_skb;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret = 0;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
+ QLINK_CMD_PHY_PARAMS_SET,
+ sizeof(struct qlink_cmd));
+ if (!cmd_skb)
+ return -ENOMEM;
+
+ qtnf_bus_lock(mac->bus);
+
+ if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
+ qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_FRAG_THRESH,
+ wiphy->frag_threshold);
+ if (changed & WIPHY_PARAM_RTS_THRESHOLD)
+ qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_RTS_THRESH,
+ wiphy->rts_threshold);
+ if (changed & WIPHY_PARAM_COVERAGE_CLASS)
+ qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS,
+ wiphy->coverage_class);
+
+ ret = qtnf_cmd_send(mac->bus, cmd_skb, &res_code);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+out:
+ qtnf_bus_unlock(mac->bus);
+ return ret;
+}
+
+int qtnf_cmd_send_init_fw(struct qtnf_bus *bus)
+{
+ struct sk_buff *cmd_skb;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret = 0;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
+ QLINK_CMD_FW_INIT,
+ sizeof(struct qlink_cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(bus);
+
+ ret = qtnf_cmd_send(bus, cmd_skb, &res_code);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("cmd exec failed: 0x%.4X\n", res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+out:
+ qtnf_bus_unlock(bus);
+ return ret;
+}
+
+void qtnf_cmd_send_deinit_fw(struct qtnf_bus *bus)
+{
+ struct sk_buff *cmd_skb;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
+ QLINK_CMD_FW_DEINIT,
+ sizeof(struct qlink_cmd));
+ if (!cmd_skb)
+ return;
+
+ qtnf_bus_lock(bus);
+
+ qtnf_cmd_send(bus, cmd_skb, NULL);
+
+ qtnf_bus_unlock(bus);
+}
+
+int qtnf_cmd_send_add_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
+ const u8 *mac_addr, struct key_params *params)
+{
+ struct sk_buff *cmd_skb;
+ struct qlink_cmd_add_key *cmd;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret = 0;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_ADD_KEY,
+ sizeof(*cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ cmd = (struct qlink_cmd_add_key *)cmd_skb->data;
+
+ if (mac_addr)
+ ether_addr_copy(cmd->addr, mac_addr);
+ else
+ eth_broadcast_addr(cmd->addr);
+
+ cmd->cipher = cpu_to_le32(params->cipher);
+ cmd->key_index = key_index;
+ cmd->pairwise = pairwise;
+
+ if (params->key && params->key_len > 0)
+ qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_KEY,
+ params->key,
+ params->key_len);
+
+ if (params->seq && params->seq_len > 0)
+ qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_SEQ,
+ params->seq,
+ params->seq_len);
+
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD failed: %u\n",
+ vif->mac->macid, vif->vifid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
+
+int qtnf_cmd_send_del_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
+ const u8 *mac_addr)
+{
+ struct sk_buff *cmd_skb;
+ struct qlink_cmd_del_key *cmd;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret = 0;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_DEL_KEY,
+ sizeof(*cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ cmd = (struct qlink_cmd_del_key *)cmd_skb->data;
+
+ if (mac_addr)
+ ether_addr_copy(cmd->addr, mac_addr);
+ else
+ eth_broadcast_addr(cmd->addr);
+
+ cmd->key_index = key_index;
+ cmd->pairwise = pairwise;
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD failed: %u\n",
+ vif->mac->macid, vif->vifid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
+
+int qtnf_cmd_send_set_default_key(struct qtnf_vif *vif, u8 key_index,
+ bool unicast, bool multicast)
+{
+ struct sk_buff *cmd_skb;
+ struct qlink_cmd_set_def_key *cmd;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret = 0;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_SET_DEFAULT_KEY,
+ sizeof(*cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ cmd = (struct qlink_cmd_set_def_key *)cmd_skb->data;
+ cmd->key_index = key_index;
+ cmd->unicast = unicast;
+ cmd->multicast = multicast;
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+ vif->vifid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
+
+int qtnf_cmd_send_set_default_mgmt_key(struct qtnf_vif *vif, u8 key_index)
+{
+ struct sk_buff *cmd_skb;
+ struct qlink_cmd_set_def_mgmt_key *cmd;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret = 0;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_SET_DEFAULT_MGMT_KEY,
+ sizeof(*cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ cmd = (struct qlink_cmd_set_def_mgmt_key *)cmd_skb->data;
+ cmd->key_index = key_index;
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+ vif->vifid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
+
+static u32 qtnf_encode_sta_flags(u32 flags)
+{
+ u32 code = 0;
+
+ if (flags & BIT(NL80211_STA_FLAG_AUTHORIZED))
+ code |= QLINK_STA_FLAG_AUTHORIZED;
+ if (flags & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
+ code |= QLINK_STA_FLAG_SHORT_PREAMBLE;
+ if (flags & BIT(NL80211_STA_FLAG_WME))
+ code |= QLINK_STA_FLAG_WME;
+ if (flags & BIT(NL80211_STA_FLAG_MFP))
+ code |= QLINK_STA_FLAG_MFP;
+ if (flags & BIT(NL80211_STA_FLAG_AUTHENTICATED))
+ code |= QLINK_STA_FLAG_AUTHENTICATED;
+ if (flags & BIT(NL80211_STA_FLAG_TDLS_PEER))
+ code |= QLINK_STA_FLAG_TDLS_PEER;
+ if (flags & BIT(NL80211_STA_FLAG_ASSOCIATED))
+ code |= QLINK_STA_FLAG_ASSOCIATED;
+ return code;
+}
+
+int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac,
+ struct station_parameters *params)
+{
+ struct sk_buff *cmd_skb;
+ struct qlink_cmd_change_sta *cmd;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret = 0;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_CHANGE_STA,
+ sizeof(*cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ cmd = (struct qlink_cmd_change_sta *)cmd_skb->data;
+ ether_addr_copy(cmd->sta_addr, mac);
+ cmd->sta_flags_mask = cpu_to_le32(qtnf_encode_sta_flags(
+ params->sta_flags_mask));
+ cmd->sta_flags_set = cpu_to_le32(qtnf_encode_sta_flags(
+ params->sta_flags_set));
+
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+ vif->vifid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
+
+int qtnf_cmd_send_del_sta(struct qtnf_vif *vif,
+ struct station_del_parameters *params)
+{
+ struct sk_buff *cmd_skb;
+ struct qlink_cmd_del_sta *cmd;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret = 0;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_DEL_STA,
+ sizeof(*cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ cmd = (struct qlink_cmd_del_sta *)cmd_skb->data;
+
+ if (params->mac)
+ ether_addr_copy(cmd->sta_addr, params->mac);
+ else
+ eth_broadcast_addr(cmd->sta_addr); /* flush all stations */
+
+ cmd->subtype = params->subtype;
+ cmd->reason_code = cpu_to_le16(params->reason_code);
+
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+ vif->vifid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
+
+int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
+{
+ struct sk_buff *cmd_skb;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ struct ieee80211_channel *sc;
+ struct cfg80211_scan_request *scan_req = mac->scan_req;
+ struct qlink_tlv_channel *qchan;
+ int n_channels;
+ int count = 0;
+ int ret;
+ u32 flags;
+
+ if (scan_req->n_ssids > QTNF_MAX_SSID_LIST_LENGTH) {
+ pr_err("MAC%u: too many SSIDs in scan request\n", mac->macid);
+ return -EINVAL;
+ }
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
+ QLINK_CMD_SCAN,
+ sizeof(struct qlink_cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(mac->bus);
+
+ if (scan_req->n_ssids != 0) {
+ while (count < scan_req->n_ssids) {
+ qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID,
+ scan_req->ssids[count].ssid,
+ scan_req->ssids[count].ssid_len);
+ count++;
+ }
+ }
+
+ if (scan_req->ie_len != 0)
+ qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET,
+ scan_req->ie,
+ scan_req->ie_len);
+
+ if (scan_req->n_channels) {
+ n_channels = scan_req->n_channels;
+ count = 0;
+
+ while (n_channels != 0) {
+ sc = scan_req->channels[count];
+ if (sc->flags & IEEE80211_CHAN_DISABLED) {
+ n_channels--;
+ continue;
+ }
+
+ pr_debug("MAC%u: scan chan=%d, freq=%d, flags=%#x\n",
+ mac->macid, sc->hw_value, sc->center_freq,
+ sc->flags);
+ qchan = skb_put_zero(cmd_skb, sizeof(*qchan));
+ flags = 0;
+
+ qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
+ qchan->hdr.len = cpu_to_le16(sizeof(*qchan) -
+ sizeof(struct qlink_tlv_hdr));
+ qchan->center_freq = cpu_to_le16(sc->center_freq);
+ qchan->hw_value = cpu_to_le16(sc->hw_value);
+
+ if (sc->flags & IEEE80211_CHAN_NO_IR)
+ flags |= QLINK_CHAN_NO_IR;
+
+ if (sc->flags & IEEE80211_CHAN_RADAR)
+ flags |= QLINK_CHAN_RADAR;
+
+ qchan->flags = cpu_to_le32(flags);
+ n_channels--;
+ count++;
+ }
+ }
+
+ ret = qtnf_cmd_send(mac->bus, cmd_skb, &res_code);
+
+ if (unlikely(ret))
+ goto out;
+
+ pr_debug("MAC%u: scan started\n", mac->macid);
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+out:
+ qtnf_bus_unlock(mac->bus);
+ return ret;
+}
+
+int qtnf_cmd_send_connect(struct qtnf_vif *vif,
+ struct cfg80211_connect_params *sme)
+{
+ struct sk_buff *cmd_skb;
+ struct qlink_cmd_connect *cmd;
+ struct qtnf_bss_config *bss_cfg = &vif->bss_cfg;
+ struct qlink_auth_encr aen;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret;
+ int i;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_CONNECT,
+ sizeof(*cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ cmd = (struct qlink_cmd_connect *)cmd_skb->data;
+
+ ether_addr_copy(cmd->bssid, bss_cfg->bssid);
+
+ if (bss_cfg->chandef.chan)
+ cmd->freq = cpu_to_le16(bss_cfg->chandef.chan->center_freq);
+
+ cmd->bg_scan_period = cpu_to_le16(bss_cfg->bg_scan_period);
+
+ memset(&aen, 0, sizeof(aen));
+ aen.auth_type = bss_cfg->auth_type;
+ aen.privacy = !!bss_cfg->privacy;
+ aen.mfp = bss_cfg->mfp;
+ aen.wpa_versions = cpu_to_le32(bss_cfg->crypto.wpa_versions);
+ aen.cipher_group = cpu_to_le32(bss_cfg->crypto.cipher_group);
+ aen.n_ciphers_pairwise = cpu_to_le32(
+ bss_cfg->crypto.n_ciphers_pairwise);
+
+ for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
+ aen.ciphers_pairwise[i] = cpu_to_le32(
+ bss_cfg->crypto.ciphers_pairwise[i]);
+
+ aen.n_akm_suites = cpu_to_le32(bss_cfg->crypto.n_akm_suites);
+
+ for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
+ aen.akm_suites[i] = cpu_to_le32(
+ bss_cfg->crypto.akm_suites[i]);
+
+ aen.control_port = bss_cfg->crypto.control_port;
+ aen.control_port_no_encrypt =
+ bss_cfg->crypto.control_port_no_encrypt;
+ aen.control_port_ethertype = cpu_to_le16(be16_to_cpu(
+ bss_cfg->crypto.control_port_ethertype));
+
+ qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, bss_cfg->ssid,
+ bss_cfg->ssid_len);
+ qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_CRYPTO, (u8 *)&aen,
+ sizeof(aen));
+
+ if (sme->ie_len != 0)
+ qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET,
+ sme->ie,
+ sme->ie_len);
+
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+ vif->vifid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
+
+int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, u16 reason_code)
+{
+ struct sk_buff *cmd_skb;
+ struct qlink_cmd_disconnect *cmd;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_DISCONNECT,
+ sizeof(*cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ cmd = (struct qlink_cmd_disconnect *)cmd_skb->data;
+ cmd->reason = cpu_to_le16(reason_code);
+
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+ vif->vifid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
+
+int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool up)
+{
+ struct sk_buff *cmd_skb;
+ struct qlink_cmd_updown *cmd;
+ u16 res_code = QLINK_CMD_RESULT_OK;
+ int ret;
+
+ cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+ QLINK_CMD_UPDOWN_INTF,
+ sizeof(*cmd));
+ if (unlikely(!cmd_skb))
+ return -ENOMEM;
+
+ cmd = (struct qlink_cmd_updown *)cmd_skb->data;
+ cmd->if_up = !!up;
+
+ qtnf_bus_lock(vif->mac->bus);
+
+ ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+ if (unlikely(ret))
+ goto out;
+
+ if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+ pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+ vif->vifid, res_code);
+ ret = -EFAULT;
+ goto out;
+ }
+out:
+ qtnf_bus_unlock(vif->mac->bus);
+ return ret;
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h
new file mode 100644
index 0000000..6c51854
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016 Quantenna Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef QLINK_COMMANDS_H_
+#define QLINK_COMMANDS_H_
+
+#include <linux/nl80211.h>
+
+#include "core.h"
+#include "bus.h"
+
+int qtnf_cmd_send_init_fw(struct qtnf_bus *bus);
+void qtnf_cmd_send_deinit_fw(struct qtnf_bus *bus);
+int qtnf_cmd_get_hw_info(struct qtnf_bus *bus);
+int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac);
+int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, enum nl80211_iftype iftype,
+ u8 *mac_addr);
+int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif,
+ enum nl80211_iftype iftype, u8 *mac_addr);
+int qtnf_cmd_send_del_intf(struct qtnf_vif *vif);
+int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
+ struct ieee80211_supported_band *band);
+int qtnf_cmd_send_regulatory_config(struct qtnf_wmac *mac, const char *alpha2);
+int qtnf_cmd_send_config_ap(struct qtnf_vif *vif);
+int qtnf_cmd_send_start_ap(struct qtnf_vif *vif);
+int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif);
+int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg);
+int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
+ u16 freq, const u8 *buf, size_t len);
+int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type,
+ const u8 *buf, size_t len);
+int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac,
+ struct station_info *sinfo);
+int qtnf_cmd_send_phy_params(struct qtnf_wmac *mac, u16 cmd_action,
+ void *data_buf);
+int qtnf_cmd_send_add_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
+ const u8 *mac_addr, struct key_params *params);
+int qtnf_cmd_send_del_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
+ const u8 *mac_addr);
+int qtnf_cmd_send_set_default_key(struct qtnf_vif *vif, u8 key_index,
+ bool unicast, bool multicast);
+int qtnf_cmd_send_set_default_mgmt_key(struct qtnf_vif *vif, u8 key_index);
+int qtnf_cmd_send_add_sta(struct qtnf_vif *vif, const u8 *mac,
+ struct station_parameters *params);
+int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac,
+ struct station_parameters *params);
+int qtnf_cmd_send_del_sta(struct qtnf_vif *vif,
+ struct station_del_parameters *params);
+
+int qtnf_cmd_resp_parse(struct qtnf_bus *bus, struct sk_buff *resp_skb);
+int qtnf_cmd_resp_check(const struct qtnf_vif *vif,
+ const struct sk_buff *resp_skb, u16 cmd_id,
+ u16 *result, const u8 **payload, size_t *payload_size);
+int qtnf_cmd_send_scan(struct qtnf_wmac *mac);
+int qtnf_cmd_send_connect(struct qtnf_vif *vif,
+ struct cfg80211_connect_params *sme);
+int qtnf_cmd_send_disconnect(struct qtnf_vif *vif,
+ u16 reason_code);
+int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif,
+ bool up);
+
+#endif /* QLINK_COMMANDS_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c
new file mode 100644
index 0000000..f053532
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -0,0 +1,618 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/if_ether.h>
+
+#include "core.h"
+#include "bus.h"
+#include "trans.h"
+#include "commands.h"
+#include "cfg80211.h"
+#include "event.h"
+#include "util.h"
+
+#define QTNF_DMP_MAX_LEN 48
+#define QTNF_PRIMARY_VIF_IDX 0
+
+struct qtnf_frame_meta_info {
+ u8 magic_s;
+ u8 ifidx;
+ u8 macid;
+ u8 magic_e;
+} __packed;
+
+struct qtnf_wmac *qtnf_core_get_mac(const struct qtnf_bus *bus, u8 macid)
+{
+ struct qtnf_wmac *mac = NULL;
+
+ if (unlikely(macid >= QTNF_MAX_MAC)) {
+ pr_err("invalid MAC index %u\n", macid);
+ return NULL;
+ }
+
+ mac = bus->mac[macid];
+
+ if (unlikely(!mac)) {
+ pr_err("MAC%u: not initialized\n", macid);
+ return NULL;
+ }
+
+ return mac;
+}
+
+/* Netdev handler for open.
+ */
+static int qtnf_netdev_open(struct net_device *ndev)
+{
+ netif_carrier_off(ndev);
+ qtnf_netdev_updown(ndev, 1);
+ return 0;
+}
+
+/* Netdev handler for close.
+ */
+static int qtnf_netdev_close(struct net_device *ndev)
+{
+ netif_carrier_off(ndev);
+ qtnf_virtual_intf_cleanup(ndev);
+ qtnf_netdev_updown(ndev, 0);
+ return 0;
+}
+
+/* Netdev handler for data transmission.
+ */
+static int
+qtnf_netdev_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ struct qtnf_vif *vif;
+ struct qtnf_wmac *mac;
+
+ vif = qtnf_netdev_get_priv(ndev);
+
+ if (unlikely(skb->dev != ndev)) {
+ pr_err_ratelimited("invalid skb->dev");
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+
+ if (unlikely(vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)) {
+ pr_err_ratelimited("%s: VIF not initialized\n", ndev->name);
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+
+ mac = vif->mac;
+ if (unlikely(!mac)) {
+ pr_err_ratelimited("%s: NULL mac pointer", ndev->name);
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+
+ if (!skb->len || (skb->len > ETH_FRAME_LEN)) {
+ pr_err_ratelimited("%s: invalid skb len %d\n", ndev->name,
+ skb->len);
+ dev_kfree_skb_any(skb);
+ ndev->stats.tx_dropped++;
+ return 0;
+ }
+
+ /* tx path is enabled: reset vif timeout */
+ vif->cons_tx_timeout_cnt = 0;
+
+ return qtnf_bus_data_tx(mac->bus, skb);
+}
+
+/* Netdev handler for getting stats.
+ */
+static struct net_device_stats *qtnf_netdev_get_stats(struct net_device *dev)
+{
+ return &dev->stats;
+}
+
+/* Netdev handler for transmission timeout.
+ */
+static void qtnf_netdev_tx_timeout(struct net_device *ndev)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
+ struct qtnf_wmac *mac;
+ struct qtnf_bus *bus;
+
+ if (unlikely(!vif || !vif->mac || !vif->mac->bus))
+ return;
+
+ mac = vif->mac;
+ bus = mac->bus;
+
+ pr_warn("VIF%u.%u: Tx timeout- %lu\n", mac->macid, vif->vifid, jiffies);
+
+ qtnf_bus_data_tx_timeout(bus, ndev);
+ ndev->stats.tx_errors++;
+
+ if (++vif->cons_tx_timeout_cnt > QTNF_TX_TIMEOUT_TRSHLD) {
+ pr_err("Tx timeout threshold exceeded !\n");
+ pr_err("schedule interface %s reset !\n", netdev_name(ndev));
+ queue_work(bus->workqueue, &vif->reset_work);
+ }
+}
+
+/* Network device ops handlers */
+const struct net_device_ops qtnf_netdev_ops = {
+ .ndo_open = qtnf_netdev_open,
+ .ndo_stop = qtnf_netdev_close,
+ .ndo_start_xmit = qtnf_netdev_hard_start_xmit,
+ .ndo_tx_timeout = qtnf_netdev_tx_timeout,
+ .ndo_get_stats = qtnf_netdev_get_stats,
+};
+
+static int qtnf_mac_init_single_band(struct wiphy *wiphy,
+ struct qtnf_wmac *mac,
+ enum nl80211_band band)
+{
+ int ret;
+
+ wiphy->bands[band] = kzalloc(sizeof(*wiphy->bands[band]), GFP_KERNEL);
+ if (!wiphy->bands[band])
+ return -ENOMEM;
+
+ wiphy->bands[band]->band = band;
+
+ ret = qtnf_cmd_get_mac_chan_info(mac, wiphy->bands[band]);
+ if (ret) {
+ pr_err("MAC%u: band %u: failed to get chans info: %d\n",
+ mac->macid, band, ret);
+ return ret;
+ }
+
+ qtnf_band_init_rates(wiphy->bands[band]);
+ qtnf_band_setup_htvht_caps(&mac->macinfo, wiphy->bands[band]);
+
+ return 0;
+}
+
+static int qtnf_mac_init_bands(struct qtnf_wmac *mac)
+{
+ struct wiphy *wiphy = priv_to_wiphy(mac);
+ int ret = 0;
+
+ if (mac->macinfo.bands_cap & QLINK_BAND_2GHZ) {
+ ret = qtnf_mac_init_single_band(wiphy, mac, NL80211_BAND_2GHZ);
+ if (ret)
+ goto out;
+ }
+
+ if (mac->macinfo.bands_cap & QLINK_BAND_5GHZ) {
+ ret = qtnf_mac_init_single_band(wiphy, mac, NL80211_BAND_5GHZ);
+ if (ret)
+ goto out;
+ }
+
+ if (mac->macinfo.bands_cap & QLINK_BAND_60GHZ)
+ ret = qtnf_mac_init_single_band(wiphy, mac, NL80211_BAND_60GHZ);
+
+out:
+ return ret;
+}
+
+struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac)
+{
+ struct qtnf_vif *vif;
+ int i;
+
+ for (i = 0; i < QTNF_MAX_INTF; i++) {
+ vif = &mac->iflist[i];
+ if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)
+ return vif;
+ }
+
+ return NULL;
+}
+
+struct qtnf_vif *qtnf_mac_get_base_vif(struct qtnf_wmac *mac)
+{
+ struct qtnf_vif *vif;
+
+ vif = &mac->iflist[QTNF_PRIMARY_VIF_IDX];
+
+ if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)
+ return NULL;
+
+ return vif;
+}
+
+static void qtnf_vif_reset_handler(struct work_struct *work)
+{
+ struct qtnf_vif *vif = container_of(work, struct qtnf_vif, reset_work);
+
+ rtnl_lock();
+
+ if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) {
+ rtnl_unlock();
+ return;
+ }
+
+ /* stop tx completely */
+ netif_tx_stop_all_queues(vif->netdev);
+ if (netif_carrier_ok(vif->netdev))
+ netif_carrier_off(vif->netdev);
+
+ qtnf_cfg80211_vif_reset(vif);
+
+ rtnl_unlock();
+}
+
+static void qtnf_mac_init_primary_intf(struct qtnf_wmac *mac)
+{
+ struct qtnf_vif *vif = &mac->iflist[QTNF_PRIMARY_VIF_IDX];
+
+ vif->wdev.iftype = NL80211_IFTYPE_AP;
+ vif->bss_priority = QTNF_DEF_BSS_PRIORITY;
+ vif->wdev.wiphy = priv_to_wiphy(mac);
+ INIT_WORK(&vif->reset_work, qtnf_vif_reset_handler);
+ vif->cons_tx_timeout_cnt = 0;
+}
+
+static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus,
+ unsigned int macid)
+{
+ struct wiphy *wiphy;
+ struct qtnf_wmac *mac;
+ unsigned int i;
+
+ wiphy = qtnf_wiphy_allocate(bus);
+ if (!wiphy)
+ return ERR_PTR(-ENOMEM);
+
+ mac = wiphy_priv(wiphy);
+
+ mac->macid = macid;
+ mac->bus = bus;
+
+ for (i = 0; i < QTNF_MAX_INTF; i++) {
+ memset(&mac->iflist[i], 0, sizeof(struct qtnf_vif));
+ mac->iflist[i].wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+ mac->iflist[i].mac = mac;
+ mac->iflist[i].vifid = i;
+ qtnf_sta_list_init(&mac->iflist[i].sta_list);
+ }
+
+ qtnf_mac_init_primary_intf(mac);
+ bus->mac[macid] = mac;
+
+ return mac;
+}
+
+int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *vif,
+ const char *name, unsigned char name_assign_type,
+ enum nl80211_iftype iftype)
+{
+ struct wiphy *wiphy = priv_to_wiphy(mac);
+ struct net_device *dev;
+ void *qdev_vif;
+ int ret;
+
+ dev = alloc_netdev_mqs(sizeof(struct qtnf_vif *), name,
+ name_assign_type, ether_setup, 1, 1);
+ if (!dev) {
+ memset(&vif->wdev, 0, sizeof(vif->wdev));
+ vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+ return -ENOMEM;
+ }
+
+ vif->netdev = dev;
+
+ dev->netdev_ops = &qtnf_netdev_ops;
+ dev->needs_free_netdev = true;
+ dev_net_set(dev, wiphy_net(wiphy));
+ dev->ieee80211_ptr = &vif->wdev;
+ dev->ieee80211_ptr->iftype = iftype;
+ ether_addr_copy(dev->dev_addr, vif->mac_addr);
+ SET_NETDEV_DEV(dev, wiphy_dev(wiphy));
+ dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+ dev->watchdog_timeo = QTNF_DEF_WDOG_TIMEOUT;
+ dev->tx_queue_len = 100;
+
+ qdev_vif = netdev_priv(dev);
+ *((void **)qdev_vif) = vif;
+
+ SET_NETDEV_DEV(dev, mac->bus->dev);
+
+ ret = register_netdevice(dev);
+ if (ret) {
+ free_netdev(dev);
+ vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+ }
+
+ return ret;
+}
+
+static void qtnf_core_mac_detach(struct qtnf_bus *bus, unsigned int macid)
+{
+ struct qtnf_wmac *mac;
+ struct wiphy *wiphy;
+ struct qtnf_vif *vif;
+ unsigned int i;
+ enum nl80211_band band;
+
+ mac = bus->mac[macid];
+
+ if (!mac)
+ return;
+
+ wiphy = priv_to_wiphy(mac);
+
+ for (i = 0; i < QTNF_MAX_INTF; i++) {
+ vif = &mac->iflist[i];
+ rtnl_lock();
+ if (vif->netdev &&
+ vif->wdev.iftype != NL80211_IFTYPE_UNSPECIFIED) {
+ qtnf_virtual_intf_cleanup(vif->netdev);
+ qtnf_del_virtual_intf(wiphy, &vif->wdev);
+ }
+ rtnl_unlock();
+ qtnf_sta_list_free(&vif->sta_list);
+ }
+
+ if (mac->wiphy_registered)
+ wiphy_unregister(wiphy);
+
+ for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; ++band) {
+ if (!wiphy->bands[band])
+ continue;
+
+ kfree(wiphy->bands[band]->channels);
+ wiphy->bands[band]->n_channels = 0;
+
+ kfree(wiphy->bands[band]);
+ wiphy->bands[band] = NULL;
+ }
+
+ kfree(mac->macinfo.limits);
+ kfree(wiphy->iface_combinations);
+ wiphy_free(wiphy);
+ bus->mac[macid] = NULL;
+}
+
+static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid)
+{
+ struct qtnf_wmac *mac;
+ struct qtnf_vif *vif;
+ int ret;
+
+ if (!(bus->hw_info.mac_bitmap & BIT(macid))) {
+ pr_info("MAC%u is not active in FW\n", macid);
+ return 0;
+ }
+
+ mac = qtnf_core_mac_alloc(bus, macid);
+ if (IS_ERR(mac)) {
+ pr_err("MAC%u allocation failed\n", macid);
+ return PTR_ERR(mac);
+ }
+
+ ret = qtnf_cmd_get_mac_info(mac);
+ if (ret) {
+ pr_err("MAC%u: failed to get info\n", macid);
+ goto error;
+ }
+
+ vif = qtnf_mac_get_base_vif(mac);
+ if (!vif) {
+ pr_err("MAC%u: primary VIF is not ready\n", macid);
+ ret = -EFAULT;
+ goto error;
+ }
+
+ ret = qtnf_cmd_send_add_intf(vif, NL80211_IFTYPE_AP, vif->mac_addr);
+ if (ret) {
+ pr_err("MAC%u: failed to add VIF\n", macid);
+ goto error;
+ }
+
+ ret = qtnf_cmd_send_get_phy_params(mac);
+ if (ret) {
+ pr_err("MAC%u: failed to get PHY settings\n", macid);
+ goto error;
+ }
+
+ ret = qtnf_mac_init_bands(mac);
+ if (ret) {
+ pr_err("MAC%u: failed to init bands\n", macid);
+ goto error;
+ }
+
+ ret = qtnf_wiphy_register(&bus->hw_info, mac);
+ if (ret) {
+ pr_err("MAC%u: wiphy registration failed\n", macid);
+ goto error;
+ }
+
+ mac->wiphy_registered = 1;
+
+ rtnl_lock();
+
+ ret = qtnf_core_net_attach(mac, vif, "wlan%d", NET_NAME_ENUM,
+ NL80211_IFTYPE_AP);
+ rtnl_unlock();
+
+ if (ret) {
+ pr_err("MAC%u: failed to attach netdev\n", macid);
+ vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+ vif->netdev = NULL;
+ goto error;
+ }
+
+ pr_debug("MAC%u initialized\n", macid);
+
+ return 0;
+
+error:
+ qtnf_core_mac_detach(bus, macid);
+ return ret;
+}
+
+int qtnf_core_attach(struct qtnf_bus *bus)
+{
+ unsigned int i;
+ int ret;
+
+ qtnf_trans_init(bus);
+
+ bus->fw_state = QTNF_FW_STATE_BOOT_DONE;
+ qtnf_bus_data_rx_start(bus);
+
+ bus->workqueue = alloc_ordered_workqueue("QTNF_BUS", 0);
+ if (!bus->workqueue) {
+ pr_err("failed to alloc main workqueue\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ INIT_WORK(&bus->event_work, qtnf_event_work_handler);
+
+ ret = qtnf_cmd_send_init_fw(bus);
+ if (ret) {
+ pr_err("failed to init FW: %d\n", ret);
+ goto error;
+ }
+
+ bus->fw_state = QTNF_FW_STATE_ACTIVE;
+
+ ret = qtnf_cmd_get_hw_info(bus);
+ if (ret) {
+ pr_err("failed to get HW info: %d\n", ret);
+ goto error;
+ }
+
+ if (bus->hw_info.ql_proto_ver != QLINK_PROTO_VER) {
+ pr_err("qlink version mismatch %u != %u\n",
+ QLINK_PROTO_VER, bus->hw_info.ql_proto_ver);
+ ret = -EPROTONOSUPPORT;
+ goto error;
+ }
+
+ if (bus->hw_info.num_mac > QTNF_MAX_MAC) {
+ pr_err("no support for number of MACs=%u\n",
+ bus->hw_info.num_mac);
+ ret = -ERANGE;
+ goto error;
+ }
+
+ for (i = 0; i < bus->hw_info.num_mac; i++) {
+ ret = qtnf_core_mac_attach(bus, i);
+
+ if (ret) {
+ pr_err("MAC%u: attach failed: %d\n", i, ret);
+ goto error;
+ }
+ }
+
+ return 0;
+
+error:
+ qtnf_core_detach(bus);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(qtnf_core_attach);
+
+void qtnf_core_detach(struct qtnf_bus *bus)
+{
+ unsigned int macid;
+
+ qtnf_bus_data_rx_stop(bus);
+
+ for (macid = 0; macid < QTNF_MAX_MAC; macid++)
+ qtnf_core_mac_detach(bus, macid);
+
+ if (bus->fw_state == QTNF_FW_STATE_ACTIVE)
+ qtnf_cmd_send_deinit_fw(bus);
+
+ bus->fw_state = QTNF_FW_STATE_DEAD;
+
+ if (bus->workqueue) {
+ flush_workqueue(bus->workqueue);
+ destroy_workqueue(bus->workqueue);
+ }
+
+ qtnf_trans_free(bus);
+}
+EXPORT_SYMBOL_GPL(qtnf_core_detach);
+
+static inline int qtnf_is_frame_meta_magic_valid(struct qtnf_frame_meta_info *m)
+{
+ return m->magic_s == 0xAB && m->magic_e == 0xBA;
+}
+
+struct net_device *qtnf_classify_skb(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+ struct qtnf_frame_meta_info *meta;
+ struct net_device *ndev = NULL;
+ struct qtnf_wmac *mac;
+ struct qtnf_vif *vif;
+
+ meta = (struct qtnf_frame_meta_info *)
+ (skb_tail_pointer(skb) - sizeof(*meta));
+
+ if (unlikely(!qtnf_is_frame_meta_magic_valid(meta))) {
+ pr_err_ratelimited("invalid magic 0x%x:0x%x\n",
+ meta->magic_s, meta->magic_e);
+ goto out;
+ }
+
+ if (unlikely(meta->macid >= QTNF_MAX_MAC)) {
+ pr_err_ratelimited("invalid mac(%u)\n", meta->macid);
+ goto out;
+ }
+
+ if (unlikely(meta->ifidx >= QTNF_MAX_INTF)) {
+ pr_err_ratelimited("invalid vif(%u)\n", meta->ifidx);
+ goto out;
+ }
+
+ mac = bus->mac[meta->macid];
+
+ if (unlikely(!mac)) {
+ pr_err_ratelimited("mac(%d) does not exist\n", meta->macid);
+ goto out;
+ }
+
+ vif = &mac->iflist[meta->ifidx];
+
+ if (unlikely(vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)) {
+ pr_err_ratelimited("vif(%u) does not exists\n", meta->ifidx);
+ goto out;
+ }
+
+ ndev = vif->netdev;
+
+ if (unlikely(!ndev)) {
+ pr_err_ratelimited("netdev for wlan%u.%u does not exists\n",
+ meta->macid, meta->ifidx);
+ goto out;
+ }
+
+ __skb_trim(skb, skb->len - sizeof(*meta));
+
+out:
+ return ndev;
+}
+EXPORT_SYMBOL_GPL(qtnf_classify_skb);
+
+MODULE_AUTHOR("Quantenna Communications");
+MODULE_DESCRIPTION("Quantenna 802.11 wireless LAN FullMAC driver.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
new file mode 100644
index 0000000..a616434
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _QTN_FMAC_CORE_H_
+#define _QTN_FMAC_CORE_H_
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/semaphore.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <net/sock.h>
+#include <net/lib80211.h>
+#include <net/cfg80211.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+#include <linux/ctype.h>
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+
+#include "qlink.h"
+#include "trans.h"
+
+#undef pr_fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
+
+#define QTNF_MAX_SSID_LIST_LENGTH 2
+#define QTNF_MAX_VSIE_LEN 255
+#define QTNF_MAX_ALPHA_LEN 2
+#define QTNF_MAX_INTF 8
+#define QTNF_MAX_EVENT_QUEUE_LEN 255
+#define QTNF_DEFAULT_BG_SCAN_PERIOD 300
+#define QTNF_MAX_BG_SCAN_PERIOD 0xffff
+
+#define QTNF_DEF_BSS_PRIORITY 0
+#define QTNF_DEF_WDOG_TIMEOUT 5
+#define QTNF_TX_TIMEOUT_TRSHLD 100
+
+#define QTNF_STATE_AP_CONFIG BIT(2)
+#define QTNF_STATE_AP_START BIT(1)
+
+extern const struct net_device_ops qtnf_netdev_ops;
+struct qtnf_bus;
+struct qtnf_vif;
+
+struct qtnf_bss_config {
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+ u8 bssid[ETH_ALEN];
+ size_t ssid_len;
+ u8 dtim;
+ u16 bcn_period;
+ u16 auth_type;
+ bool privacy;
+ enum nl80211_mfp mfp;
+ struct cfg80211_chan_def chandef;
+ struct cfg80211_crypto_settings crypto;
+ u16 bg_scan_period;
+ u32 connect_flags;
+};
+
+struct qtnf_sta_node {
+ struct list_head list;
+ u8 mac_addr[ETH_ALEN];
+};
+
+struct qtnf_sta_list {
+ struct list_head head;
+ atomic_t size;
+};
+
+enum qtnf_sta_state {
+ QTNF_STA_DISCONNECTED,
+ QTNF_STA_CONNECTING,
+ QTNF_STA_CONNECTED
+};
+
+struct qtnf_vif {
+ struct wireless_dev wdev;
+ u8 vifid;
+ u8 bss_priority;
+ u8 bss_status;
+ enum qtnf_sta_state sta_state;
+ u16 mgmt_frames_bitmask;
+ struct net_device *netdev;
+ struct qtnf_wmac *mac;
+ u8 mac_addr[ETH_ALEN];
+ struct work_struct reset_work;
+ struct qtnf_bss_config bss_cfg;
+ struct qtnf_sta_list sta_list;
+ unsigned long cons_tx_timeout_cnt;
+};
+
+struct qtnf_mac_info {
+ u8 bands_cap;
+ u8 phymode_cap;
+ u8 dev_mac[ETH_ALEN];
+ u8 num_tx_chain;
+ u8 num_rx_chain;
+ u16 max_ap_assoc_sta;
+ u32 frag_thr;
+ u32 rts_thr;
+ u8 lretry_limit;
+ u8 sretry_limit;
+ u8 coverage_class;
+ u8 radar_detect_widths;
+ struct ieee80211_ht_cap ht_cap;
+ struct ieee80211_vht_cap vht_cap;
+ struct ieee80211_iface_limit *limits;
+ size_t n_limits;
+};
+
+struct qtnf_wmac {
+ u8 macid;
+ u8 wiphy_registered;
+ u8 macaddr[ETH_ALEN];
+ struct qtnf_bus *bus;
+ struct qtnf_mac_info macinfo;
+ struct qtnf_vif iflist[QTNF_MAX_INTF];
+ struct cfg80211_scan_request *scan_req;
+};
+
+struct qtnf_hw_info {
+ u8 num_mac;
+ u8 mac_bitmap;
+ u8 alpha2_code[QTNF_MAX_ALPHA_LEN];
+ u32 fw_ver;
+ u16 ql_proto_ver;
+ u8 total_tx_chain;
+ u8 total_rx_chain;
+ u32 hw_capab;
+};
+
+struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac);
+struct qtnf_vif *qtnf_mac_get_base_vif(struct qtnf_wmac *mac);
+struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus);
+int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *priv,
+ const char *name, unsigned char name_assign_type,
+ enum nl80211_iftype iftype);
+void qtnf_main_work_queue(struct work_struct *work);
+int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed);
+int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac);
+
+struct qtnf_wmac *qtnf_core_get_mac(const struct qtnf_bus *bus, u8 macid);
+struct net_device *qtnf_classify_skb(struct qtnf_bus *bus, struct sk_buff *skb);
+struct net_device *qtnf_classify_skb_no_mbss(struct qtnf_bus *bus,
+ struct sk_buff *skb);
+
+void qtnf_virtual_intf_cleanup(struct net_device *ndev);
+
+void qtnf_netdev_updown(struct net_device *ndev, bool up);
+
+static inline struct qtnf_vif *qtnf_netdev_get_priv(struct net_device *dev)
+{
+ return *((void **)netdev_priv(dev));
+}
+
+#endif /* _QTN_FMAC_CORE_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/debug.c b/drivers/net/wireless/quantenna/qtnfmac/debug.c
new file mode 100644
index 0000000..9f826b9
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/debug.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "debug.h"
+
+#undef pr_fmt
+#define pr_fmt(fmt) "qtnfmac dbg: %s: " fmt, __func__
+
+void qtnf_debugfs_init(struct qtnf_bus *bus, const char *name)
+{
+ bus->dbg_dir = debugfs_create_dir(name, NULL);
+
+ if (IS_ERR_OR_NULL(bus->dbg_dir)) {
+ pr_warn("failed to create debugfs root dir\n");
+ bus->dbg_dir = NULL;
+ }
+}
+
+void qtnf_debugfs_remove(struct qtnf_bus *bus)
+{
+ debugfs_remove_recursive(bus->dbg_dir);
+ bus->dbg_dir = NULL;
+}
+
+void qtnf_debugfs_add_entry(struct qtnf_bus *bus, const char *name,
+ int (*fn)(struct seq_file *seq, void *data))
+{
+ struct dentry *entry;
+
+ entry = debugfs_create_devm_seqfile(bus->dev, name, bus->dbg_dir, fn);
+ if (IS_ERR_OR_NULL(entry))
+ pr_warn("failed to add entry (%s)\n", name);
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/debug.h b/drivers/net/wireless/quantenna/qtnfmac/debug.h
new file mode 100644
index 0000000..d6dd12b5
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/debug.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _QTN_FMAC_DEBUG_H_
+#define _QTN_FMAC_DEBUG_H_
+
+#include <linux/debugfs.h>
+
+#include "core.h"
+#include "bus.h"
+
+#ifdef CONFIG_DEBUG_FS
+
+void qtnf_debugfs_init(struct qtnf_bus *bus, const char *name);
+void qtnf_debugfs_remove(struct qtnf_bus *bus);
+void qtnf_debugfs_add_entry(struct qtnf_bus *bus, const char *name,
+ int (*fn)(struct seq_file *seq, void *data));
+
+#else
+
+static inline void qtnf_debugfs_init(struct qtnf_bus *bus, const char *name)
+{
+}
+
+static inline void qtnf_debugfs_remove(struct qtnf_bus *bus)
+{
+}
+
+static inline void
+qtnf_debugfs_add_entry(struct qtnf_bus *bus, const char *name,
+ int (*fn)(struct seq_file *seq, void *data))
+{
+}
+
+#endif /* CONFIG_DEBUG_FS */
+
+#endif /* _QTN_FMAC_DEBUG_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
new file mode 100644
index 0000000..9b61e9a
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "cfg80211.h"
+#include "core.h"
+#include "qlink.h"
+#include "bus.h"
+#include "trans.h"
+#include "util.h"
+#include "event.h"
+
+static int
+qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif,
+ const struct qlink_event_sta_assoc *sta_assoc,
+ u16 len)
+{
+ const u8 *sta_addr;
+ u16 frame_control;
+ struct station_info sinfo = { 0 };
+ size_t payload_len;
+ u16 tlv_type;
+ u16 tlv_value_len;
+ size_t tlv_full_len;
+ const struct qlink_tlv_hdr *tlv;
+
+ if (unlikely(len < sizeof(*sta_assoc))) {
+ pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
+ mac->macid, vif->vifid, len, sizeof(*sta_assoc));
+ return -EINVAL;
+ }
+
+ if (vif->wdev.iftype != NL80211_IFTYPE_AP) {
+ pr_err("VIF%u.%u: STA_ASSOC event when not in AP mode\n",
+ mac->macid, vif->vifid);
+ return -EPROTO;
+ }
+
+ if (!(vif->bss_status & QTNF_STATE_AP_START)) {
+ pr_err("VIF%u.%u: STA_ASSOC event when AP is not started\n",
+ mac->macid, vif->vifid);
+ return -EPROTO;
+ }
+
+ sta_addr = sta_assoc->sta_addr;
+ frame_control = le16_to_cpu(sta_assoc->frame_control);
+
+ pr_debug("VIF%u.%u: MAC:%pM FC:%x\n", mac->macid, vif->vifid, sta_addr,
+ frame_control);
+
+ qtnf_sta_list_add(&vif->sta_list, sta_addr);
+
+ sinfo.assoc_req_ies = NULL;
+ sinfo.assoc_req_ies_len = 0;
+
+ payload_len = len - sizeof(*sta_assoc);
+ tlv = (struct qlink_tlv_hdr *)sta_assoc->ies;
+
+ while (payload_len >= sizeof(struct qlink_tlv_hdr)) {
+ tlv_type = le16_to_cpu(tlv->type);
+ tlv_value_len = le16_to_cpu(tlv->len);
+ tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
+
+ if (tlv_full_len > payload_len) {
+ pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n",
+ mac->macid, vif->vifid, tlv_type,
+ tlv_value_len);
+ return -EINVAL;
+ }
+
+ if (tlv_type == QTN_TLV_ID_IE_SET) {
+ sinfo.assoc_req_ies = tlv->val;
+ sinfo.assoc_req_ies_len = tlv_value_len;
+ }
+
+ payload_len -= tlv_full_len;
+ tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
+ }
+
+ if (payload_len) {
+ pr_warn("VIF%u.%u: malformed TLV buf; bytes left: %zu\n",
+ mac->macid, vif->vifid, payload_len);
+ return -EINVAL;
+ }
+
+ cfg80211_new_sta(vif->netdev, sta_assoc->sta_addr, &sinfo,
+ GFP_KERNEL);
+
+ return 0;
+}
+
+static int
+qtnf_event_handle_sta_deauth(struct qtnf_wmac *mac, struct qtnf_vif *vif,
+ const struct qlink_event_sta_deauth *sta_deauth,
+ u16 len)
+{
+ const u8 *sta_addr;
+ u16 reason;
+
+ if (unlikely(len < sizeof(*sta_deauth))) {
+ pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
+ mac->macid, vif->vifid, len,
+ sizeof(struct qlink_event_sta_deauth));
+ return -EINVAL;
+ }
+
+ if (vif->wdev.iftype != NL80211_IFTYPE_AP) {
+ pr_err("VIF%u.%u: STA_DEAUTH event when not in AP mode\n",
+ mac->macid, vif->vifid);
+ return -EPROTO;
+ }
+
+ if (!(vif->bss_status & QTNF_STATE_AP_START)) {
+ pr_err("VIF%u.%u: STA_DEAUTH event when AP is not started\n",
+ mac->macid, vif->vifid);
+ return -EPROTO;
+ }
+
+ sta_addr = sta_deauth->sta_addr;
+ reason = le16_to_cpu(sta_deauth->reason);
+
+ pr_debug("VIF%u.%u: MAC:%pM reason:%x\n", mac->macid, vif->vifid,
+ sta_addr, reason);
+
+ if (qtnf_sta_list_del(&vif->sta_list, sta_addr))
+ cfg80211_del_sta(vif->netdev, sta_deauth->sta_addr,
+ GFP_KERNEL);
+
+ return 0;
+}
+
+static int
+qtnf_event_handle_bss_join(struct qtnf_vif *vif,
+ const struct qlink_event_bss_join *join_info,
+ u16 len)
+{
+ if (unlikely(len < sizeof(*join_info))) {
+ pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
+ vif->mac->macid, vif->vifid, len,
+ sizeof(struct qlink_event_bss_join));
+ return -EINVAL;
+ }
+
+ if (vif->wdev.iftype != NL80211_IFTYPE_STATION) {
+ pr_err("VIF%u.%u: BSS_JOIN event when not in STA mode\n",
+ vif->mac->macid, vif->vifid);
+ return -EPROTO;
+ }
+
+ if (vif->sta_state != QTNF_STA_CONNECTING) {
+ pr_err("VIF%u.%u: BSS_JOIN event when STA is not connecting\n",
+ vif->mac->macid, vif->vifid);
+ return -EPROTO;
+ }
+
+ pr_debug("VIF%u.%u: BSSID:%pM\n", vif->mac->macid, vif->vifid,
+ join_info->bssid);
+
+ cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, NULL,
+ 0, le16_to_cpu(join_info->status), GFP_KERNEL);
+
+ if (le16_to_cpu(join_info->status) == WLAN_STATUS_SUCCESS) {
+ vif->sta_state = QTNF_STA_CONNECTED;
+ netif_carrier_on(vif->netdev);
+ } else {
+ vif->sta_state = QTNF_STA_DISCONNECTED;
+ }
+
+ return 0;
+}
+
+static int
+qtnf_event_handle_bss_leave(struct qtnf_vif *vif,
+ const struct qlink_event_bss_leave *leave_info,
+ u16 len)
+{
+ if (unlikely(len < sizeof(*leave_info))) {
+ pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
+ vif->mac->macid, vif->vifid, len,
+ sizeof(struct qlink_event_bss_leave));
+ return -EINVAL;
+ }
+
+ if (vif->wdev.iftype != NL80211_IFTYPE_STATION) {
+ pr_err("VIF%u.%u: BSS_LEAVE event when not in STA mode\n",
+ vif->mac->macid, vif->vifid);
+ return -EPROTO;
+ }
+
+ if (vif->sta_state != QTNF_STA_CONNECTED) {
+ pr_err("VIF%u.%u: BSS_LEAVE event when STA is not connected\n",
+ vif->mac->macid, vif->vifid);
+ return -EPROTO;
+ }
+
+ pr_debug("VIF%u.%u: disconnected\n", vif->mac->macid, vif->vifid);
+
+ cfg80211_disconnected(vif->netdev, leave_info->reason, NULL, 0, 0,
+ GFP_KERNEL);
+
+ vif->sta_state = QTNF_STA_DISCONNECTED;
+ netif_carrier_off(vif->netdev);
+
+ return 0;
+}
+
+static int
+qtnf_event_handle_mgmt_received(struct qtnf_vif *vif,
+ const struct qlink_event_rxmgmt *rxmgmt,
+ u16 len)
+{
+ const size_t min_len = sizeof(*rxmgmt) +
+ sizeof(struct ieee80211_hdr_3addr);
+ const struct ieee80211_hdr_3addr *frame = (void *)rxmgmt->frame_data;
+ const u16 frame_len = len - sizeof(*rxmgmt);
+ enum nl80211_rxmgmt_flags flags = 0;
+
+ if (unlikely(len < min_len)) {
+ pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
+ vif->mac->macid, vif->vifid, len, min_len);
+ return -EINVAL;
+ }
+
+ if (le32_to_cpu(rxmgmt->flags) & QLINK_RXMGMT_FLAG_ANSWERED)
+ flags |= NL80211_RXMGMT_FLAG_ANSWERED;
+
+ pr_debug("%s LEN:%u FC:%.4X SA:%pM\n", vif->netdev->name, frame_len,
+ le16_to_cpu(frame->frame_control), frame->addr2);
+
+ cfg80211_rx_mgmt(&vif->wdev, le32_to_cpu(rxmgmt->freq),
+ le32_to_cpu(rxmgmt->sig_dbm), rxmgmt->frame_data,
+ frame_len, flags);
+
+ return 0;
+}
+
+static int
+qtnf_event_handle_scan_results(struct qtnf_vif *vif,
+ const struct qlink_event_scan_result *sr,
+ u16 len)
+{
+ struct cfg80211_bss *bss;
+ struct ieee80211_channel *channel;
+ struct wiphy *wiphy = priv_to_wiphy(vif->mac);
+ enum cfg80211_bss_frame_type frame_type;
+ size_t payload_len;
+ u16 tlv_type;
+ u16 tlv_value_len;
+ size_t tlv_full_len;
+ const struct qlink_tlv_hdr *tlv;
+
+ const u8 *ies = NULL;
+ size_t ies_len = 0;
+
+ if (len < sizeof(*sr)) {
+ pr_err("VIF%u.%u: payload is too short\n", vif->mac->macid,
+ vif->vifid);
+ return -EINVAL;
+ }
+
+ channel = ieee80211_get_channel(wiphy, le16_to_cpu(sr->freq));
+ if (!channel) {
+ pr_err("VIF%u.%u: channel at %u MHz not found\n",
+ vif->mac->macid, vif->vifid, le16_to_cpu(sr->freq));
+ return -EINVAL;
+ }
+
+ switch (sr->frame_type) {
+ case QLINK_BSS_FTYPE_BEACON:
+ frame_type = CFG80211_BSS_FTYPE_BEACON;
+ break;
+ case QLINK_BSS_FTYPE_PRESP:
+ frame_type = CFG80211_BSS_FTYPE_PRESP;
+ break;
+ default:
+ frame_type = CFG80211_BSS_FTYPE_UNKNOWN;
+ }
+
+ payload_len = len - sizeof(*sr);
+ tlv = (struct qlink_tlv_hdr *)sr->payload;
+
+ while (payload_len >= sizeof(struct qlink_tlv_hdr)) {
+ tlv_type = le16_to_cpu(tlv->type);
+ tlv_value_len = le16_to_cpu(tlv->len);
+ tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
+
+ if (tlv_full_len > payload_len) {
+ pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n",
+ vif->mac->macid, vif->vifid, tlv_type,
+ tlv_value_len);
+ return -EINVAL;
+ }
+
+ if (tlv_type == QTN_TLV_ID_IE_SET) {
+ ies = tlv->val;
+ ies_len = tlv_value_len;
+ }
+
+ payload_len -= tlv_full_len;
+ tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
+ }
+
+ if (payload_len) {
+ pr_warn("VIF%u.%u: malformed TLV buf; bytes left: %zu\n",
+ vif->mac->macid, vif->vifid, payload_len);
+ return -EINVAL;
+ }
+
+ bss = cfg80211_inform_bss(wiphy, channel, frame_type,
+ sr->bssid, get_unaligned_le64(&sr->tsf),
+ le16_to_cpu(sr->capab),
+ le16_to_cpu(sr->bintval), ies, ies_len,
+ sr->signal, GFP_KERNEL);
+ if (!bss)
+ return -ENOMEM;
+
+ cfg80211_put_bss(wiphy, bss);
+
+ return 0;
+}
+
+static int
+qtnf_event_handle_scan_complete(struct qtnf_wmac *mac,
+ const struct qlink_event_scan_complete *status,
+ u16 len)
+{
+ if (len < sizeof(*status)) {
+ pr_err("MAC%u: payload is too short\n", mac->macid);
+ return -EINVAL;
+ }
+
+ qtnf_scan_done(mac, le32_to_cpu(status->flags) & QLINK_SCAN_ABORTED);
+
+ return 0;
+}
+
+static int qtnf_event_parse(struct qtnf_wmac *mac,
+ const struct sk_buff *event_skb)
+{
+ const struct qlink_event *event;
+ struct qtnf_vif *vif = NULL;
+ int ret = -1;
+ u16 event_id;
+ u16 event_len;
+
+ event = (const struct qlink_event *)event_skb->data;
+ event_id = le16_to_cpu(event->event_id);
+ event_len = le16_to_cpu(event->mhdr.len);
+
+ if (likely(event->vifid < QTNF_MAX_INTF)) {
+ vif = &mac->iflist[event->vifid];
+ } else {
+ pr_err("invalid vif(%u)\n", event->vifid);
+ return -EINVAL;
+ }
+
+ switch (event_id) {
+ case QLINK_EVENT_STA_ASSOCIATED:
+ ret = qtnf_event_handle_sta_assoc(mac, vif, (const void *)event,
+ event_len);
+ break;
+ case QLINK_EVENT_STA_DEAUTH:
+ ret = qtnf_event_handle_sta_deauth(mac, vif,
+ (const void *)event,
+ event_len);
+ break;
+ case QLINK_EVENT_MGMT_RECEIVED:
+ ret = qtnf_event_handle_mgmt_received(vif, (const void *)event,
+ event_len);
+ break;
+ case QLINK_EVENT_SCAN_RESULTS:
+ ret = qtnf_event_handle_scan_results(vif, (const void *)event,
+ event_len);
+ break;
+ case QLINK_EVENT_SCAN_COMPLETE:
+ ret = qtnf_event_handle_scan_complete(mac, (const void *)event,
+ event_len);
+ break;
+ case QLINK_EVENT_BSS_JOIN:
+ ret = qtnf_event_handle_bss_join(vif, (const void *)event,
+ event_len);
+ break;
+ case QLINK_EVENT_BSS_LEAVE:
+ ret = qtnf_event_handle_bss_leave(vif, (const void *)event,
+ event_len);
+ break;
+ default:
+ pr_warn("unknown event type: %x\n", event_id);
+ break;
+ }
+
+ return ret;
+}
+
+static int qtnf_event_process_skb(struct qtnf_bus *bus,
+ const struct sk_buff *skb)
+{
+ const struct qlink_event *event;
+ struct qtnf_wmac *mac;
+ int res;
+
+ if (unlikely(!skb || skb->len < sizeof(*event))) {
+ pr_err("invalid event buffer\n");
+ return -EINVAL;
+ }
+
+ event = (struct qlink_event *)skb->data;
+
+ mac = qtnf_core_get_mac(bus, event->macid);
+
+ pr_debug("new event id:%x len:%u mac:%u vif:%u\n",
+ le16_to_cpu(event->event_id), le16_to_cpu(event->mhdr.len),
+ event->macid, event->vifid);
+
+ if (unlikely(!mac))
+ return -ENXIO;
+
+ qtnf_bus_lock(bus);
+ res = qtnf_event_parse(mac, skb);
+ qtnf_bus_unlock(bus);
+
+ return res;
+}
+
+void qtnf_event_work_handler(struct work_struct *work)
+{
+ struct qtnf_bus *bus = container_of(work, struct qtnf_bus, event_work);
+ struct sk_buff_head *event_queue = &bus->trans.event_queue;
+ struct sk_buff *current_event_skb = skb_dequeue(event_queue);
+
+ while (current_event_skb) {
+ qtnf_event_process_skb(bus, current_event_skb);
+ dev_kfree_skb_any(current_event_skb);
+ current_event_skb = skb_dequeue(event_queue);
+ }
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.h b/drivers/net/wireless/quantenna/qtnfmac/event.h
new file mode 100644
index 0000000..ae759b6
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _QTN_FMAC_EVENT_H_
+#define _QTN_FMAC_EVENT_H_
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "qlink.h"
+
+void qtnf_event_work_handler(struct work_struct *work);
+
+#endif /* _QTN_FMAC_EVENT_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
new file mode 100644
index 0000000..7fc4f0d
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
@@ -0,0 +1,1378 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/crc32.h>
+#include <linux/spinlock.h>
+
+#include "qtn_hw_ids.h"
+#include "pcie_bus_priv.h"
+#include "core.h"
+#include "bus.h"
+#include "debug.h"
+
+static bool use_msi = true;
+module_param(use_msi, bool, 0644);
+MODULE_PARM_DESC(use_msi, "set 0 to use legacy interrupt");
+
+static unsigned int tx_bd_size_param = 256;
+module_param(tx_bd_size_param, uint, 0644);
+MODULE_PARM_DESC(tx_bd_size_param, "Tx descriptors queue size");
+
+static unsigned int rx_bd_size_param = 256;
+module_param(rx_bd_size_param, uint, 0644);
+MODULE_PARM_DESC(rx_bd_size_param, "Rx descriptors queue size");
+
+static unsigned int rx_bd_reserved_param = 16;
+module_param(rx_bd_reserved_param, uint, 0644);
+MODULE_PARM_DESC(rx_bd_reserved_param, "Reserved RX descriptors");
+
+static u8 flashboot = 1;
+module_param(flashboot, byte, 0644);
+MODULE_PARM_DESC(flashboot, "set to 0 to use FW binary file on FS");
+
+#define DRV_NAME "qtnfmac_pearl_pcie"
+
+static inline void qtnf_non_posted_write(u32 val, void __iomem *basereg)
+{
+ writel(val, basereg);
+
+ /* flush posted write */
+ readl(basereg);
+}
+
+static inline void qtnf_init_hdp_irqs(struct qtnf_pcie_bus_priv *priv)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->irq_lock, flags);
+ priv->pcie_irq_mask = (PCIE_HDP_INT_RX_BITS | PCIE_HDP_INT_TX_BITS);
+ spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static inline void qtnf_enable_hdp_irqs(struct qtnf_pcie_bus_priv *priv)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->irq_lock, flags);
+ writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base));
+ spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static inline void qtnf_disable_hdp_irqs(struct qtnf_pcie_bus_priv *priv)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->irq_lock, flags);
+ writel(0x0, PCIE_HDP_INT_EN(priv->pcie_reg_base));
+ spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static inline void qtnf_en_rxdone_irq(struct qtnf_pcie_bus_priv *priv)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->irq_lock, flags);
+ priv->pcie_irq_mask |= PCIE_HDP_INT_RX_BITS;
+ writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base));
+ spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static inline void qtnf_dis_rxdone_irq(struct qtnf_pcie_bus_priv *priv)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->irq_lock, flags);
+ priv->pcie_irq_mask &= ~PCIE_HDP_INT_RX_BITS;
+ writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base));
+ spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static inline void qtnf_en_txdone_irq(struct qtnf_pcie_bus_priv *priv)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->irq_lock, flags);
+ priv->pcie_irq_mask |= PCIE_HDP_INT_TX_BITS;
+ writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base));
+ spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static inline void qtnf_dis_txdone_irq(struct qtnf_pcie_bus_priv *priv)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->irq_lock, flags);
+ priv->pcie_irq_mask &= ~PCIE_HDP_INT_TX_BITS;
+ writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base));
+ spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static int qtnf_pcie_init_irq(struct qtnf_pcie_bus_priv *priv)
+{
+ struct pci_dev *pdev = priv->pdev;
+
+ /* fall back to legacy INTx interrupts by default */
+ priv->msi_enabled = 0;
+
+ /* check if MSI capability is available */
+ if (use_msi) {
+ if (!pci_enable_msi(pdev)) {
+ pr_debug("MSI interrupt enabled\n");
+ priv->msi_enabled = 1;
+ } else {
+ pr_warn("failed to enable MSI interrupts");
+ }
+ }
+
+ if (!priv->msi_enabled) {
+ pr_warn("legacy PCIE interrupts enabled\n");
+ pci_intx(pdev, 1);
+ }
+
+ return 0;
+}
+
+static void qtnf_deassert_intx(struct qtnf_pcie_bus_priv *priv)
+{
+ void __iomem *reg = priv->sysctl_bar + PEARL_PCIE_CFG0_OFFSET;
+ u32 cfg;
+
+ cfg = readl(reg);
+ cfg &= ~PEARL_ASSERT_INTX;
+ qtnf_non_posted_write(cfg, reg);
+}
+
+static void qtnf_ipc_gen_ep_int(void *arg)
+{
+ const struct qtnf_pcie_bus_priv *priv = arg;
+ const u32 data = QTN_PEARL_IPC_IRQ_WORD(QTN_PEARL_LHOST_IPC_IRQ);
+ void __iomem *reg = priv->sysctl_bar +
+ QTN_PEARL_SYSCTL_LHOST_IRQ_OFFSET;
+
+ qtnf_non_posted_write(data, reg);
+}
+
+static void __iomem *qtnf_map_bar(struct qtnf_pcie_bus_priv *priv, u8 index)
+{
+ void __iomem *vaddr;
+ dma_addr_t busaddr;
+ size_t len;
+ int ret;
+
+ ret = pcim_iomap_regions(priv->pdev, 1 << index, DRV_NAME);
+ if (ret)
+ return IOMEM_ERR_PTR(ret);
+
+ busaddr = pci_resource_start(priv->pdev, index);
+ vaddr = pcim_iomap_table(priv->pdev)[index];
+ len = pci_resource_len(priv->pdev, index);
+
+ pr_debug("BAR%u vaddr=0x%p busaddr=%pad len=%u\n",
+ index, vaddr, &busaddr, (int)len);
+
+ return vaddr;
+}
+
+static void qtnf_pcie_control_rx_callback(void *arg, const u8 *buf, size_t len)
+{
+ struct qtnf_pcie_bus_priv *priv = arg;
+ struct qtnf_bus *bus = pci_get_drvdata(priv->pdev);
+ struct sk_buff *skb;
+
+ if (unlikely(len == 0)) {
+ pr_warn("zero length packet received\n");
+ return;
+ }
+
+ skb = __dev_alloc_skb(len, GFP_KERNEL);
+
+ if (unlikely(!skb)) {
+ pr_err("failed to allocate skb\n");
+ return;
+ }
+
+ skb_put_data(skb, buf, len);
+
+ qtnf_trans_handle_rx_ctl_packet(bus, skb);
+}
+
+static int qtnf_pcie_init_shm_ipc(struct qtnf_pcie_bus_priv *priv)
+{
+ struct qtnf_shm_ipc_region __iomem *ipc_tx_reg;
+ struct qtnf_shm_ipc_region __iomem *ipc_rx_reg;
+ const struct qtnf_shm_ipc_int ipc_int = { qtnf_ipc_gen_ep_int, priv };
+ const struct qtnf_shm_ipc_rx_callback rx_callback = {
+ qtnf_pcie_control_rx_callback, priv };
+
+ ipc_tx_reg = &priv->bda->bda_shm_reg1;
+ ipc_rx_reg = &priv->bda->bda_shm_reg2;
+
+ qtnf_shm_ipc_init(&priv->shm_ipc_ep_in, QTNF_SHM_IPC_OUTBOUND,
+ ipc_tx_reg, priv->workqueue,
+ &ipc_int, &rx_callback);
+ qtnf_shm_ipc_init(&priv->shm_ipc_ep_out, QTNF_SHM_IPC_INBOUND,
+ ipc_rx_reg, priv->workqueue,
+ &ipc_int, &rx_callback);
+
+ return 0;
+}
+
+static void qtnf_pcie_free_shm_ipc(struct qtnf_pcie_bus_priv *priv)
+{
+ qtnf_shm_ipc_free(&priv->shm_ipc_ep_in);
+ qtnf_shm_ipc_free(&priv->shm_ipc_ep_out);
+}
+
+static int qtnf_pcie_init_memory(struct qtnf_pcie_bus_priv *priv)
+{
+ int ret = -ENOMEM;
+
+ priv->sysctl_bar = qtnf_map_bar(priv, QTN_SYSCTL_BAR);
+ if (IS_ERR_OR_NULL(priv->sysctl_bar)) {
+ pr_err("failed to map BAR%u\n", QTN_SYSCTL_BAR);
+ return ret;
+ }
+
+ priv->dmareg_bar = qtnf_map_bar(priv, QTN_DMA_BAR);
+ if (IS_ERR_OR_NULL(priv->dmareg_bar)) {
+ pr_err("failed to map BAR%u\n", QTN_DMA_BAR);
+ return ret;
+ }
+
+ priv->epmem_bar = qtnf_map_bar(priv, QTN_SHMEM_BAR);
+ if (IS_ERR_OR_NULL(priv->epmem_bar)) {
+ pr_err("failed to map BAR%u\n", QTN_SHMEM_BAR);
+ return ret;
+ }
+
+ priv->pcie_reg_base = priv->dmareg_bar;
+ priv->bda = priv->epmem_bar;
+ writel(priv->msi_enabled, &priv->bda->bda_rc_msi_enabled);
+
+ return 0;
+}
+
+static int
+qtnf_pcie_init_dma_mask(struct qtnf_pcie_bus_priv *priv, u64 dma_mask)
+{
+ int ret;
+
+ ret = dma_supported(&priv->pdev->dev, dma_mask);
+ if (!ret) {
+ pr_err("DMA mask %llu not supported\n", dma_mask);
+ return ret;
+ }
+
+ ret = pci_set_dma_mask(priv->pdev, dma_mask);
+ if (ret) {
+ pr_err("failed to set DMA mask %llu\n", dma_mask);
+ return ret;
+ }
+
+ ret = pci_set_consistent_dma_mask(priv->pdev, dma_mask);
+ if (ret) {
+ pr_err("failed to set consistent DMA mask %llu\n", dma_mask);
+ return ret;
+ }
+
+ return ret;
+}
+
+static void qtnf_tune_pcie_mps(struct qtnf_pcie_bus_priv *priv)
+{
+ struct pci_dev *pdev = priv->pdev;
+ struct pci_dev *parent;
+ int mps_p, mps_o, mps_m, mps;
+ int ret;
+
+ /* current mps */
+ mps_o = pcie_get_mps(pdev);
+
+ /* maximum supported mps */
+ mps_m = 128 << pdev->pcie_mpss;
+
+ /* suggested new mps value */
+ mps = mps_m;
+
+ if (pdev->bus && pdev->bus->self) {
+ /* parent (bus) mps */
+ parent = pdev->bus->self;
+
+ if (pci_is_pcie(parent)) {
+ mps_p = pcie_get_mps(parent);
+ mps = min(mps_m, mps_p);
+ }
+ }
+
+ ret = pcie_set_mps(pdev, mps);
+ if (ret) {
+ pr_err("failed to set mps to %d, keep using current %d\n",
+ mps, mps_o);
+ priv->mps = mps_o;
+ return;
+ }
+
+ pr_debug("set mps to %d (was %d, max %d)\n", mps, mps_o, mps_m);
+ priv->mps = mps;
+}
+
+static int qtnf_is_state(__le32 __iomem *reg, u32 state)
+{
+ u32 s = readl(reg);
+
+ return s & state;
+}
+
+static void qtnf_set_state(__le32 __iomem *reg, u32 state)
+{
+ u32 s = readl(reg);
+
+ qtnf_non_posted_write(state | s, reg);
+}
+
+static void qtnf_clear_state(__le32 __iomem *reg, u32 state)
+{
+ u32 s = readl(reg);
+
+ qtnf_non_posted_write(s & ~state, reg);
+}
+
+static int qtnf_poll_state(__le32 __iomem *reg, u32 state, u32 delay_in_ms)
+{
+ u32 timeout = 0;
+
+ while ((qtnf_is_state(reg, state) == 0)) {
+ usleep_range(1000, 1200);
+ if (++timeout > delay_in_ms)
+ return -1;
+ }
+
+ return 0;
+}
+
+static int alloc_skb_array(struct qtnf_pcie_bus_priv *priv)
+{
+ struct sk_buff **vaddr;
+ int len;
+
+ len = priv->tx_bd_num * sizeof(*priv->tx_skb) +
+ priv->rx_bd_num * sizeof(*priv->rx_skb);
+ vaddr = devm_kzalloc(&priv->pdev->dev, len, GFP_KERNEL);
+
+ if (!vaddr)
+ return -ENOMEM;
+
+ priv->tx_skb = vaddr;
+
+ vaddr += priv->tx_bd_num;
+ priv->rx_skb = vaddr;
+
+ return 0;
+}
+
+static int alloc_bd_table(struct qtnf_pcie_bus_priv *priv)
+{
+ dma_addr_t paddr;
+ void *vaddr;
+ int len;
+
+ len = priv->tx_bd_num * sizeof(struct qtnf_tx_bd) +
+ priv->rx_bd_num * sizeof(struct qtnf_rx_bd);
+
+ vaddr = dmam_alloc_coherent(&priv->pdev->dev, len, &paddr, GFP_KERNEL);
+ if (!vaddr)
+ return -ENOMEM;
+
+ /* tx bd */
+
+ memset(vaddr, 0, len);
+
+ priv->bd_table_vaddr = vaddr;
+ priv->bd_table_paddr = paddr;
+ priv->bd_table_len = len;
+
+ priv->tx_bd_vbase = vaddr;
+ priv->tx_bd_pbase = paddr;
+
+ pr_debug("TX descriptor table: vaddr=0x%p paddr=%pad\n", vaddr, &paddr);
+
+ priv->tx_bd_reclaim_start = 0;
+ priv->tx_bd_index = 0;
+ priv->tx_queue_len = 0;
+
+ /* rx bd */
+
+ vaddr = ((struct qtnf_tx_bd *)vaddr) + priv->tx_bd_num;
+ paddr += priv->tx_bd_num * sizeof(struct qtnf_tx_bd);
+
+ priv->rx_bd_vbase = vaddr;
+ priv->rx_bd_pbase = paddr;
+
+ writel(QTN_HOST_LO32(paddr),
+ PCIE_HDP_TX_HOST_Q_BASE_L(priv->pcie_reg_base));
+ writel(QTN_HOST_HI32(paddr),
+ PCIE_HDP_TX_HOST_Q_BASE_H(priv->pcie_reg_base));
+ writel(priv->rx_bd_num | (sizeof(struct qtnf_rx_bd)) << 16,
+ PCIE_HDP_TX_HOST_Q_SZ_CTRL(priv->pcie_reg_base));
+
+ priv->hw_txproc_wr_ptr = priv->rx_bd_num - rx_bd_reserved_param;
+
+ writel(priv->hw_txproc_wr_ptr,
+ PCIE_HDP_TX_HOST_Q_WR_PTR(priv->pcie_reg_base));
+
+ pr_debug("RX descriptor table: vaddr=0x%p paddr=%pad\n", vaddr, &paddr);
+
+ priv->rx_bd_index = 0;
+
+ return 0;
+}
+
+static int skb2rbd_attach(struct qtnf_pcie_bus_priv *priv, u16 rx_bd_index)
+{
+ struct qtnf_rx_bd *rxbd;
+ struct sk_buff *skb;
+ dma_addr_t paddr;
+
+ skb = __dev_alloc_skb(SKB_BUF_SIZE + NET_IP_ALIGN,
+ GFP_ATOMIC);
+ if (!skb) {
+ priv->rx_skb[rx_bd_index] = NULL;
+ return -ENOMEM;
+ }
+
+ priv->rx_skb[rx_bd_index] = skb;
+
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ rxbd = &priv->rx_bd_vbase[rx_bd_index];
+
+ paddr = pci_map_single(priv->pdev, skb->data,
+ SKB_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(priv->pdev, paddr)) {
+ pr_err("skb DMA mapping error: %pad\n", &paddr);
+ return -ENOMEM;
+ }
+
+ writel(QTN_HOST_LO32(paddr),
+ PCIE_HDP_HHBM_BUF_PTR(priv->pcie_reg_base));
+ writel(QTN_HOST_HI32(paddr),
+ PCIE_HDP_HHBM_BUF_PTR_H(priv->pcie_reg_base));
+
+ /* keep rx skb paddrs in rx buffer descriptors for cleanup purposes */
+ rxbd->addr = cpu_to_le32(QTN_HOST_LO32(paddr));
+ rxbd->addr_h = cpu_to_le32(QTN_HOST_HI32(paddr));
+
+ rxbd->info = 0x0;
+
+ return 0;
+}
+
+static int alloc_rx_buffers(struct qtnf_pcie_bus_priv *priv)
+{
+ u16 i;
+ int ret = 0;
+
+ memset(priv->rx_bd_vbase, 0x0,
+ priv->rx_bd_num * sizeof(struct qtnf_rx_bd));
+
+ for (i = 0; i < priv->rx_bd_num; i++) {
+ ret = skb2rbd_attach(priv, i);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+/* all rx/tx activity should have ceased before calling this function */
+static void free_xfer_buffers(void *data)
+{
+ struct qtnf_pcie_bus_priv *priv = (struct qtnf_pcie_bus_priv *)data;
+ struct qtnf_rx_bd *rxbd;
+ dma_addr_t paddr;
+ int i;
+
+ /* free rx buffers */
+ for (i = 0; i < priv->rx_bd_num; i++) {
+ if (priv->rx_skb[i]) {
+ rxbd = &priv->rx_bd_vbase[i];
+ paddr = QTN_HOST_ADDR(le32_to_cpu(rxbd->addr_h),
+ le32_to_cpu(rxbd->addr));
+ pci_unmap_single(priv->pdev, paddr, SKB_BUF_SIZE,
+ PCI_DMA_FROMDEVICE);
+
+ dev_kfree_skb_any(priv->rx_skb[i]);
+ }
+ }
+
+ /* free tx buffers */
+ for (i = 0; i < priv->tx_bd_num; i++) {
+ if (priv->tx_skb[i]) {
+ dev_kfree_skb_any(priv->tx_skb[i]);
+ priv->tx_skb[i] = NULL;
+ }
+ }
+}
+
+static int qtnf_pcie_init_xfer(struct qtnf_pcie_bus_priv *priv)
+{
+ int ret;
+
+ priv->tx_bd_num = tx_bd_size_param;
+ priv->rx_bd_num = rx_bd_size_param;
+
+ ret = alloc_skb_array(priv);
+ if (ret) {
+ pr_err("failed to allocate skb array\n");
+ return ret;
+ }
+
+ ret = alloc_bd_table(priv);
+ if (ret) {
+ pr_err("failed to allocate bd table\n");
+ return ret;
+ }
+
+ ret = alloc_rx_buffers(priv);
+ if (ret) {
+ pr_err("failed to allocate rx buffers\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+static int qtnf_pcie_data_tx_reclaim(struct qtnf_pcie_bus_priv *priv)
+{
+ struct qtnf_tx_bd *txbd;
+ struct sk_buff *skb;
+ dma_addr_t paddr;
+ int last_sent;
+ int count;
+ int i;
+
+ last_sent = readl(PCIE_HDP_RX0DMA_CNT(priv->pcie_reg_base))
+ % priv->tx_bd_num;
+ i = priv->tx_bd_reclaim_start;
+ count = 0;
+
+ while (i != last_sent) {
+ skb = priv->tx_skb[i];
+ if (!skb)
+ break;
+
+ txbd = &priv->tx_bd_vbase[i];
+ paddr = QTN_HOST_ADDR(le32_to_cpu(txbd->addr_h),
+ le32_to_cpu(txbd->addr));
+ pci_unmap_single(priv->pdev, paddr, skb->len, PCI_DMA_TODEVICE);
+
+ if (skb->dev) {
+ skb->dev->stats.tx_packets++;
+ skb->dev->stats.tx_bytes += skb->len;
+
+ if (netif_queue_stopped(skb->dev))
+ netif_wake_queue(skb->dev);
+ }
+
+ dev_kfree_skb_any(skb);
+ priv->tx_skb[i] = NULL;
+ priv->tx_queue_len--;
+ count++;
+
+ if (++i >= priv->tx_bd_num)
+ i = 0;
+ }
+
+ priv->tx_bd_reclaim_start = i;
+ priv->tx_reclaim_done += count;
+ priv->tx_reclaim_req++;
+
+ return count;
+}
+
+static bool qtnf_tx_queue_ready(struct qtnf_pcie_bus_priv *priv)
+{
+ if (priv->tx_queue_len >= priv->tx_bd_num - 1) {
+ pr_err_ratelimited("reclaim full Tx queue\n");
+ qtnf_pcie_data_tx_reclaim(priv);
+
+ if (priv->tx_queue_len >= priv->tx_bd_num - 1) {
+ priv->tx_full_count++;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+ struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+ dma_addr_t txbd_paddr, skb_paddr;
+ struct qtnf_tx_bd *txbd;
+ unsigned long flags;
+ int len, i;
+ u32 info;
+ int ret = 0;
+
+ spin_lock_irqsave(&priv->tx_lock, flags);
+
+ priv->tx_done_count++;
+
+ if (!qtnf_tx_queue_ready(priv)) {
+ if (skb->dev)
+ netif_stop_queue(skb->dev);
+
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+ return NETDEV_TX_BUSY;
+ }
+
+ i = priv->tx_bd_index;
+ priv->tx_skb[i] = skb;
+ len = skb->len;
+
+ skb_paddr = pci_map_single(priv->pdev, skb->data,
+ skb->len, PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(priv->pdev, skb_paddr)) {
+ pr_err("skb DMA mapping error: %pad\n", &skb_paddr);
+ ret = -ENOMEM;
+ goto tx_done;
+ }
+
+ txbd = &priv->tx_bd_vbase[i];
+ txbd->addr = cpu_to_le32(QTN_HOST_LO32(skb_paddr));
+ txbd->addr_h = cpu_to_le32(QTN_HOST_HI32(skb_paddr));
+
+ info = (len & QTN_PCIE_TX_DESC_LEN_MASK) << QTN_PCIE_TX_DESC_LEN_SHIFT;
+ txbd->info = cpu_to_le32(info);
+
+ /* sync up all descriptor updates before passing them to EP */
+ dma_wmb();
+
+ /* write new TX descriptor to PCIE_RX_FIFO on EP */
+ txbd_paddr = priv->tx_bd_pbase + i * sizeof(struct qtnf_tx_bd);
+ writel(QTN_HOST_LO32(txbd_paddr),
+ PCIE_HDP_HOST_WR_DESC0(priv->pcie_reg_base));
+ writel(QTN_HOST_HI32(txbd_paddr),
+ PCIE_HDP_HOST_WR_DESC0_H(priv->pcie_reg_base));
+
+ if (++i >= priv->tx_bd_num)
+ i = 0;
+
+ priv->tx_bd_index = i;
+ priv->tx_queue_len++;
+
+tx_done:
+ if (ret && skb) {
+ pr_err_ratelimited("drop skb\n");
+ if (skb->dev)
+ skb->dev->stats.tx_dropped++;
+ dev_kfree_skb_any(skb);
+ }
+
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+
+ return NETDEV_TX_OK;
+}
+
+static int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+ struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+
+ return qtnf_shm_ipc_send(&priv->shm_ipc_ep_in, skb->data, skb->len);
+}
+
+static irqreturn_t qtnf_interrupt(int irq, void *data)
+{
+ struct qtnf_bus *bus = (struct qtnf_bus *)data;
+ struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+ u32 status;
+
+ priv->pcie_irq_count++;
+ status = readl(PCIE_HDP_INT_STATUS(priv->pcie_reg_base));
+
+ qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_in);
+ qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_out);
+
+ if (!(status & priv->pcie_irq_mask))
+ goto irq_done;
+
+ if (status & PCIE_HDP_INT_RX_BITS) {
+ priv->pcie_irq_rx_count++;
+ qtnf_dis_rxdone_irq(priv);
+ napi_schedule(&bus->mux_napi);
+ }
+
+ if (status & PCIE_HDP_INT_TX_BITS) {
+ priv->pcie_irq_tx_count++;
+ qtnf_dis_txdone_irq(priv);
+ tasklet_hi_schedule(&priv->reclaim_tq);
+ }
+
+irq_done:
+ /* H/W workaround: clean all bits, not only enabled */
+ qtnf_non_posted_write(~0U, PCIE_HDP_INT_STATUS(priv->pcie_reg_base));
+
+ if (!priv->msi_enabled)
+ qtnf_deassert_intx(priv);
+
+ return IRQ_HANDLED;
+}
+
+static inline void hw_txproc_wr_ptr_inc(struct qtnf_pcie_bus_priv *priv)
+{
+ u32 index;
+
+ index = priv->hw_txproc_wr_ptr;
+
+ if (++index >= priv->rx_bd_num)
+ index = 0;
+
+ priv->hw_txproc_wr_ptr = index;
+}
+
+static int qtnf_rx_poll(struct napi_struct *napi, int budget)
+{
+ struct qtnf_bus *bus = container_of(napi, struct qtnf_bus, mux_napi);
+ struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+ struct net_device *ndev = NULL;
+ struct sk_buff *skb = NULL;
+ int processed = 0;
+ struct qtnf_rx_bd *rxbd;
+ dma_addr_t skb_paddr;
+ u32 descw;
+ u16 index;
+ int ret;
+
+ index = priv->rx_bd_index;
+ rxbd = &priv->rx_bd_vbase[index];
+
+ descw = le32_to_cpu(rxbd->info);
+
+ while ((descw & QTN_TXDONE_MASK) && (processed < budget)) {
+ skb = priv->rx_skb[index];
+
+ if (likely(skb)) {
+ skb_put(skb, QTN_GET_LEN(descw));
+
+ skb_paddr = QTN_HOST_ADDR(le32_to_cpu(rxbd->addr_h),
+ le32_to_cpu(rxbd->addr));
+ pci_unmap_single(priv->pdev, skb_paddr, SKB_BUF_SIZE,
+ PCI_DMA_FROMDEVICE);
+
+ ndev = qtnf_classify_skb(bus, skb);
+ if (likely(ndev)) {
+ ndev->stats.rx_packets++;
+ ndev->stats.rx_bytes += skb->len;
+
+ skb->protocol = eth_type_trans(skb, ndev);
+ netif_receive_skb(skb);
+ } else {
+ pr_debug("drop untagged skb\n");
+ bus->mux_dev.stats.rx_dropped++;
+ dev_kfree_skb_any(skb);
+ }
+
+ processed++;
+ } else {
+ pr_err("missing rx_skb[%d]\n", index);
+ }
+
+ /* attached rx buffer is passed upstream: map a new one */
+ ret = skb2rbd_attach(priv, index);
+ if (likely(!ret)) {
+ if (++index >= priv->rx_bd_num)
+ index = 0;
+
+ priv->rx_bd_index = index;
+ hw_txproc_wr_ptr_inc(priv);
+
+ rxbd = &priv->rx_bd_vbase[index];
+ descw = le32_to_cpu(rxbd->info);
+ } else {
+ pr_err("failed to allocate new rx_skb[%d]\n", index);
+ break;
+ }
+
+ writel(priv->hw_txproc_wr_ptr,
+ PCIE_HDP_TX_HOST_Q_WR_PTR(priv->pcie_reg_base));
+ }
+
+ if (processed < budget) {
+ napi_complete(napi);
+ qtnf_en_rxdone_irq(priv);
+ }
+
+ return processed;
+}
+
+static void
+qtnf_pcie_data_tx_timeout(struct qtnf_bus *bus, struct net_device *ndev)
+{
+ struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+
+ tasklet_hi_schedule(&priv->reclaim_tq);
+}
+
+static void qtnf_pcie_data_rx_start(struct qtnf_bus *bus)
+{
+ struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+
+ qtnf_enable_hdp_irqs(priv);
+ napi_enable(&bus->mux_napi);
+}
+
+static void qtnf_pcie_data_rx_stop(struct qtnf_bus *bus)
+{
+ struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+
+ napi_disable(&bus->mux_napi);
+ qtnf_disable_hdp_irqs(priv);
+}
+
+static const struct qtnf_bus_ops qtnf_pcie_bus_ops = {
+ /* control path methods */
+ .control_tx = qtnf_pcie_control_tx,
+
+ /* data path methods */
+ .data_tx = qtnf_pcie_data_tx,
+ .data_tx_timeout = qtnf_pcie_data_tx_timeout,
+ .data_rx_start = qtnf_pcie_data_rx_start,
+ .data_rx_stop = qtnf_pcie_data_rx_stop,
+};
+
+static int qtnf_ep_fw_send(struct qtnf_pcie_bus_priv *priv, uint32_t size,
+ int blk, const u8 *pblk, const u8 *fw)
+{
+ struct pci_dev *pdev = priv->pdev;
+ struct qtnf_bus *bus = pci_get_drvdata(pdev);
+
+ struct qtnf_pcie_fw_hdr *hdr;
+ u8 *pdata;
+
+ int hds = sizeof(*hdr);
+ struct sk_buff *skb = NULL;
+ int len = 0;
+ int ret;
+
+ skb = __dev_alloc_skb(QTN_PCIE_FW_BUFSZ, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ skb->len = QTN_PCIE_FW_BUFSZ;
+ skb->dev = NULL;
+
+ hdr = (struct qtnf_pcie_fw_hdr *)skb->data;
+ memcpy(hdr->boardflg, QTN_PCIE_BOARDFLG, strlen(QTN_PCIE_BOARDFLG));
+ hdr->fwsize = cpu_to_le32(size);
+ hdr->seqnum = cpu_to_le32(blk);
+
+ if (blk)
+ hdr->type = cpu_to_le32(QTN_FW_DSUB);
+ else
+ hdr->type = cpu_to_le32(QTN_FW_DBEGIN);
+
+ pdata = skb->data + hds;
+
+ len = QTN_PCIE_FW_BUFSZ - hds;
+ if (pblk >= (fw + size - len)) {
+ len = fw + size - pblk;
+ hdr->type = cpu_to_le32(QTN_FW_DEND);
+ }
+
+ hdr->pktlen = cpu_to_le32(len);
+ memcpy(pdata, pblk, len);
+ hdr->crc = cpu_to_le32(~crc32(0, pdata, len));
+
+ ret = qtnf_pcie_data_tx(bus, skb);
+
+ return (ret == NETDEV_TX_OK) ? len : 0;
+}
+
+static int
+qtnf_ep_fw_load(struct qtnf_pcie_bus_priv *priv, const u8 *fw, u32 fw_size)
+{
+ int blk_size = QTN_PCIE_FW_BUFSZ - sizeof(struct qtnf_pcie_fw_hdr);
+ int blk_count = fw_size / blk_size + ((fw_size % blk_size) ? 1 : 0);
+ const u8 *pblk = fw;
+ int threshold = 0;
+ int blk = 0;
+ int len;
+
+ pr_debug("FW upload started: fw_addr=0x%p size=%d\n", fw, fw_size);
+
+ while (blk < blk_count) {
+ if (++threshold > 10000) {
+ pr_err("FW upload failed: too many retries\n");
+ return -ETIMEDOUT;
+ }
+
+ len = qtnf_ep_fw_send(priv, fw_size, blk, pblk, fw);
+ if (len <= 0)
+ continue;
+
+ if (!((blk + 1) & QTN_PCIE_FW_DLMASK) ||
+ (blk == (blk_count - 1))) {
+ qtnf_set_state(&priv->bda->bda_rc_state,
+ QTN_RC_FW_SYNC);
+ if (qtnf_poll_state(&priv->bda->bda_ep_state,
+ QTN_EP_FW_SYNC,
+ QTN_FW_DL_TIMEOUT_MS)) {
+ pr_err("FW upload failed: SYNC timed out\n");
+ return -ETIMEDOUT;
+ }
+
+ qtnf_clear_state(&priv->bda->bda_ep_state,
+ QTN_EP_FW_SYNC);
+
+ if (qtnf_is_state(&priv->bda->bda_ep_state,
+ QTN_EP_FW_RETRY)) {
+ if (blk == (blk_count - 1)) {
+ int last_round =
+ blk_count & QTN_PCIE_FW_DLMASK;
+ blk -= last_round;
+ pblk -= ((last_round - 1) *
+ blk_size + len);
+ } else {
+ blk -= QTN_PCIE_FW_DLMASK;
+ pblk -= QTN_PCIE_FW_DLMASK * blk_size;
+ }
+
+ qtnf_clear_state(&priv->bda->bda_ep_state,
+ QTN_EP_FW_RETRY);
+
+ pr_warn("FW upload retry: block #%d\n", blk);
+ continue;
+ }
+
+ qtnf_pcie_data_tx_reclaim(priv);
+ }
+
+ pblk += len;
+ blk++;
+ }
+
+ pr_debug("FW upload completed: totally sent %d blocks\n", blk);
+ return 0;
+}
+
+static void qtnf_firmware_load(const struct firmware *fw, void *context)
+{
+ struct qtnf_pcie_bus_priv *priv = (void *)context;
+ struct pci_dev *pdev = priv->pdev;
+ struct qtnf_bus *bus = pci_get_drvdata(pdev);
+ int ret;
+
+ if (!fw) {
+ pr_err("failed to get firmware %s\n", bus->fwname);
+ goto fw_load_err;
+ }
+
+ ret = qtnf_ep_fw_load(priv, fw->data, fw->size);
+ if (ret) {
+ pr_err("FW upload error\n");
+ goto fw_load_err;
+ }
+
+ if (qtnf_poll_state(&priv->bda->bda_ep_state, QTN_EP_FW_DONE,
+ QTN_FW_DL_TIMEOUT_MS)) {
+ pr_err("FW bringup timed out\n");
+ goto fw_load_err;
+ }
+
+ bus->fw_state = QTNF_FW_STATE_FW_DNLD_DONE;
+ pr_info("firmware is up and running\n");
+
+fw_load_err:
+
+ if (fw)
+ release_firmware(fw);
+
+ complete(&bus->request_firmware_complete);
+}
+
+static int qtnf_bringup_fw(struct qtnf_bus *bus)
+{
+ struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+ struct pci_dev *pdev = priv->pdev;
+ int ret;
+ u32 state = QTN_RC_FW_LOADRDY | QTN_RC_FW_QLINK;
+
+ if (flashboot)
+ state |= QTN_RC_FW_FLASHBOOT;
+
+ qtnf_set_state(&priv->bda->bda_rc_state, state);
+
+ if (qtnf_poll_state(&priv->bda->bda_ep_state, QTN_EP_FW_LOADRDY,
+ QTN_FW_DL_TIMEOUT_MS)) {
+ pr_err("card is not ready\n");
+ return -ETIMEDOUT;
+ }
+
+ qtnf_clear_state(&priv->bda->bda_ep_state, QTN_EP_FW_LOADRDY);
+
+ if (flashboot) {
+ pr_info("Booting FW from flash\n");
+
+ if (!qtnf_poll_state(&priv->bda->bda_ep_state, QTN_EP_FW_DONE,
+ QTN_FW_DL_TIMEOUT_MS))
+ bus->fw_state = QTNF_FW_STATE_FW_DNLD_DONE;
+
+ return 0;
+ }
+
+ pr_info("starting firmware upload: %s\n", bus->fwname);
+
+ ret = request_firmware_nowait(THIS_MODULE, 1, bus->fwname, &pdev->dev,
+ GFP_KERNEL, priv, qtnf_firmware_load);
+ if (ret < 0)
+ pr_err("request_firmware_nowait error %d\n", ret);
+ else
+ ret = 1;
+
+ return ret;
+}
+
+static void qtnf_reclaim_tasklet_fn(unsigned long data)
+{
+ struct qtnf_pcie_bus_priv *priv = (void *)data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ qtnf_pcie_data_tx_reclaim(priv);
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+ qtnf_en_txdone_irq(priv);
+}
+
+static int qtnf_dbg_mps_show(struct seq_file *s, void *data)
+{
+ struct qtnf_bus *bus = dev_get_drvdata(s->private);
+ struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+ seq_printf(s, "%d\n", priv->mps);
+
+ return 0;
+}
+
+static int qtnf_dbg_msi_show(struct seq_file *s, void *data)
+{
+ struct qtnf_bus *bus = dev_get_drvdata(s->private);
+ struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+ seq_printf(s, "%u\n", priv->msi_enabled);
+
+ return 0;
+}
+
+static int qtnf_dbg_irq_stats(struct seq_file *s, void *data)
+{
+ struct qtnf_bus *bus = dev_get_drvdata(s->private);
+ struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+ seq_printf(s, "pcie_irq_count(%u)\n", priv->pcie_irq_count);
+ seq_printf(s, "pcie_irq_tx_count(%u)\n", priv->pcie_irq_tx_count);
+ seq_printf(s, "pcie_irq_rx_count(%u)\n", priv->pcie_irq_rx_count);
+
+ return 0;
+}
+
+static int qtnf_dbg_hdp_stats(struct seq_file *s, void *data)
+{
+ struct qtnf_bus *bus = dev_get_drvdata(s->private);
+ struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+ seq_printf(s, "tx_full_count(%u)\n", priv->tx_full_count);
+ seq_printf(s, "tx_done_count(%u)\n", priv->tx_done_count);
+ seq_printf(s, "tx_reclaim_done(%u)\n", priv->tx_reclaim_done);
+ seq_printf(s, "tx_reclaim_req(%u)\n", priv->tx_reclaim_req);
+ seq_printf(s, "tx_bd_reclaim_start(%u)\n", priv->tx_bd_reclaim_start);
+ seq_printf(s, "tx_bd_index(%u)\n", priv->tx_bd_index);
+ seq_printf(s, "rx_bd_index(%u)\n", priv->rx_bd_index);
+ seq_printf(s, "tx_queue_len(%u)\n", priv->tx_queue_len);
+
+ return 0;
+}
+
+static int qtnf_dbg_shm_stats(struct seq_file *s, void *data)
+{
+ struct qtnf_bus *bus = dev_get_drvdata(s->private);
+ struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+ seq_printf(s, "shm_ipc_ep_in.tx_packet_count(%zu)\n",
+ priv->shm_ipc_ep_in.tx_packet_count);
+ seq_printf(s, "shm_ipc_ep_in.rx_packet_count(%zu)\n",
+ priv->shm_ipc_ep_in.rx_packet_count);
+ seq_printf(s, "shm_ipc_ep_out.tx_packet_count(%zu)\n",
+ priv->shm_ipc_ep_out.tx_timeout_count);
+ seq_printf(s, "shm_ipc_ep_out.rx_packet_count(%zu)\n",
+ priv->shm_ipc_ep_out.rx_packet_count);
+
+ return 0;
+}
+
+static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct qtnf_pcie_bus_priv *pcie_priv;
+ struct qtnf_bus *bus;
+ int ret;
+
+ bus = devm_kzalloc(&pdev->dev,
+ sizeof(*bus) + sizeof(*pcie_priv), GFP_KERNEL);
+ if (!bus) {
+ ret = -ENOMEM;
+ goto err_init;
+ }
+
+ pcie_priv = get_bus_priv(bus);
+
+ pci_set_drvdata(pdev, bus);
+ bus->bus_ops = &qtnf_pcie_bus_ops;
+ bus->dev = &pdev->dev;
+ bus->fw_state = QTNF_FW_STATE_RESET;
+ pcie_priv->pdev = pdev;
+
+ strcpy(bus->fwname, QTN_PCI_PEARL_FW_NAME);
+ init_completion(&bus->request_firmware_complete);
+ mutex_init(&bus->bus_lock);
+ spin_lock_init(&pcie_priv->irq_lock);
+ spin_lock_init(&pcie_priv->tx_lock);
+
+ /* init stats */
+ pcie_priv->tx_full_count = 0;
+ pcie_priv->tx_done_count = 0;
+ pcie_priv->pcie_irq_count = 0;
+ pcie_priv->pcie_irq_rx_count = 0;
+ pcie_priv->pcie_irq_tx_count = 0;
+ pcie_priv->tx_reclaim_done = 0;
+ pcie_priv->tx_reclaim_req = 0;
+
+ pcie_priv->workqueue = create_singlethread_workqueue("QTNF_PEARL_PCIE");
+ if (!pcie_priv->workqueue) {
+ pr_err("failed to alloc bus workqueue\n");
+ ret = -ENODEV;
+ goto err_priv;
+ }
+
+ if (!pci_is_pcie(pdev)) {
+ pr_err("device %s is not PCI Express\n", pci_name(pdev));
+ ret = -EIO;
+ goto err_base;
+ }
+
+ qtnf_tune_pcie_mps(pcie_priv);
+
+ ret = pcim_enable_device(pdev);
+ if (ret) {
+ pr_err("failed to init PCI device %x\n", pdev->device);
+ goto err_base;
+ } else {
+ pr_debug("successful init of PCI device %x\n", pdev->device);
+ }
+
+ pcim_pin_device(pdev);
+ pci_set_master(pdev);
+
+ ret = qtnf_pcie_init_irq(pcie_priv);
+ if (ret < 0) {
+ pr_err("irq init failed\n");
+ goto err_base;
+ }
+
+ ret = qtnf_pcie_init_memory(pcie_priv);
+ if (ret < 0) {
+ pr_err("PCIE memory init failed\n");
+ goto err_base;
+ }
+
+ ret = qtnf_pcie_init_shm_ipc(pcie_priv);
+ if (ret < 0) {
+ pr_err("PCIE SHM IPC init failed\n");
+ goto err_base;
+ }
+
+ ret = qtnf_pcie_init_dma_mask(pcie_priv, DMA_BIT_MASK(32));
+ if (ret) {
+ pr_err("PCIE DMA mask init failed\n");
+ goto err_base;
+ }
+
+ ret = devm_add_action(&pdev->dev, free_xfer_buffers, (void *)pcie_priv);
+ if (ret) {
+ pr_err("custom release callback init failed\n");
+ goto err_base;
+ }
+
+ ret = qtnf_pcie_init_xfer(pcie_priv);
+ if (ret) {
+ pr_err("PCIE xfer init failed\n");
+ goto err_base;
+ }
+
+ /* init default irq settings */
+ qtnf_init_hdp_irqs(pcie_priv);
+
+ /* start with disabled irqs */
+ qtnf_disable_hdp_irqs(pcie_priv);
+
+ ret = devm_request_irq(&pdev->dev, pdev->irq, &qtnf_interrupt, 0,
+ "qtnf_pcie_irq", (void *)bus);
+ if (ret) {
+ pr_err("failed to request pcie irq %d\n", pdev->irq);
+ goto err_base;
+ }
+
+ tasklet_init(&pcie_priv->reclaim_tq, qtnf_reclaim_tasklet_fn,
+ (unsigned long)pcie_priv);
+ init_dummy_netdev(&bus->mux_dev);
+ netif_napi_add(&bus->mux_dev, &bus->mux_napi,
+ qtnf_rx_poll, 10);
+
+ ret = qtnf_bringup_fw(bus);
+ if (ret < 0)
+ goto err_bringup_fw;
+ else if (ret)
+ wait_for_completion(&bus->request_firmware_complete);
+
+ if (bus->fw_state != QTNF_FW_STATE_FW_DNLD_DONE) {
+ pr_err("failed to start FW\n");
+ goto err_bringup_fw;
+ }
+
+ if (qtnf_poll_state(&pcie_priv->bda->bda_ep_state, QTN_EP_FW_QLINK_DONE,
+ QTN_FW_QLINK_TIMEOUT_MS)) {
+ pr_err("FW runtime failure\n");
+ goto err_bringup_fw;
+ }
+
+ ret = qtnf_core_attach(bus);
+ if (ret) {
+ pr_err("failed to attach core\n");
+ goto err_bringup_fw;
+ }
+
+ qtnf_debugfs_init(bus, DRV_NAME);
+ qtnf_debugfs_add_entry(bus, "mps", qtnf_dbg_mps_show);
+ qtnf_debugfs_add_entry(bus, "msi_enabled", qtnf_dbg_msi_show);
+ qtnf_debugfs_add_entry(bus, "hdp_stats", qtnf_dbg_hdp_stats);
+ qtnf_debugfs_add_entry(bus, "irq_stats", qtnf_dbg_irq_stats);
+ qtnf_debugfs_add_entry(bus, "shm_stats", qtnf_dbg_shm_stats);
+
+ return 0;
+
+err_bringup_fw:
+ netif_napi_del(&bus->mux_napi);
+
+err_base:
+ flush_workqueue(pcie_priv->workqueue);
+ destroy_workqueue(pcie_priv->workqueue);
+
+err_priv:
+ pci_set_drvdata(pdev, NULL);
+
+err_init:
+ return ret;
+}
+
+static void qtnf_pcie_remove(struct pci_dev *pdev)
+{
+ struct qtnf_pcie_bus_priv *priv;
+ struct qtnf_bus *bus;
+
+ bus = pci_get_drvdata(pdev);
+ if (!bus)
+ return;
+
+ priv = get_bus_priv(bus);
+
+ qtnf_core_detach(bus);
+ netif_napi_del(&bus->mux_napi);
+
+ flush_workqueue(priv->workqueue);
+ destroy_workqueue(priv->workqueue);
+ tasklet_kill(&priv->reclaim_tq);
+
+ qtnf_debugfs_remove(bus);
+
+ qtnf_pcie_free_shm_ipc(priv);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int qtnf_pcie_suspend(struct device *dev)
+{
+ return -EOPNOTSUPP;
+}
+
+static int qtnf_pcie_resume(struct device *dev)
+{
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM_SLEEP
+/* Power Management Hooks */
+static SIMPLE_DEV_PM_OPS(qtnf_pcie_pm_ops, qtnf_pcie_suspend,
+ qtnf_pcie_resume);
+#endif
+
+static struct pci_device_id qtnf_pcie_devid_table[] = {
+ {
+ PCIE_VENDOR_ID_QUANTENNA, PCIE_DEVICE_ID_QTN_PEARL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ },
+ { },
+};
+
+MODULE_DEVICE_TABLE(pci, qtnf_pcie_devid_table);
+
+static struct pci_driver qtnf_pcie_drv_data = {
+ .name = DRV_NAME,
+ .id_table = qtnf_pcie_devid_table,
+ .probe = qtnf_pcie_probe,
+ .remove = qtnf_pcie_remove,
+#ifdef CONFIG_PM_SLEEP
+ .driver = {
+ .pm = &qtnf_pcie_pm_ops,
+ },
+#endif
+};
+
+static int __init qtnf_pcie_register(void)
+{
+ pr_info("register Quantenna QSR10g FullMAC PCIE driver\n");
+ return pci_register_driver(&qtnf_pcie_drv_data);
+}
+
+static void __exit qtnf_pcie_exit(void)
+{
+ pr_info("unregister Quantenna QSR10g FullMAC PCIE driver\n");
+ pci_unregister_driver(&qtnf_pcie_drv_data);
+}
+
+module_init(qtnf_pcie_register);
+module_exit(qtnf_pcie_exit);
+
+MODULE_AUTHOR("Quantenna Communications");
+MODULE_DESCRIPTION("Quantenna QSR10g PCIe bus driver for 802.11 wireless LAN.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h
new file mode 100644
index 0000000..2a897db
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _QTN_FMAC_PCIE_H_
+#define _QTN_FMAC_PCIE_H_
+
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+
+#include "pcie_regs_pearl.h"
+#include "pcie_ipc.h"
+#include "shm_ipc.h"
+
+struct bus;
+
+struct qtnf_pcie_bus_priv {
+ struct pci_dev *pdev;
+
+ /* lock for irq configuration changes */
+ spinlock_t irq_lock;
+
+ /* lock for tx operations */
+ spinlock_t tx_lock;
+ u8 msi_enabled;
+ int mps;
+
+ struct workqueue_struct *workqueue;
+ struct tasklet_struct reclaim_tq;
+
+ void __iomem *sysctl_bar;
+ void __iomem *epmem_bar;
+ void __iomem *dmareg_bar;
+
+ struct qtnf_shm_ipc shm_ipc_ep_in;
+ struct qtnf_shm_ipc shm_ipc_ep_out;
+
+ struct qtnf_pcie_bda __iomem *bda;
+ void __iomem *pcie_reg_base;
+
+ u16 tx_bd_num;
+ u16 rx_bd_num;
+
+ struct sk_buff **tx_skb;
+ struct sk_buff **rx_skb;
+
+ struct qtnf_tx_bd *tx_bd_vbase;
+ dma_addr_t tx_bd_pbase;
+
+ struct qtnf_rx_bd *rx_bd_vbase;
+ dma_addr_t rx_bd_pbase;
+
+ dma_addr_t bd_table_paddr;
+ void *bd_table_vaddr;
+ u32 bd_table_len;
+
+ u32 hw_txproc_wr_ptr;
+
+ u16 tx_bd_reclaim_start;
+ u16 tx_bd_index;
+ u32 tx_queue_len;
+
+ u16 rx_bd_index;
+
+ u32 pcie_irq_mask;
+
+ /* diagnostics stats */
+ u32 pcie_irq_count;
+ u32 pcie_irq_rx_count;
+ u32 pcie_irq_tx_count;
+ u32 tx_full_count;
+ u32 tx_done_count;
+ u32 tx_reclaim_done;
+ u32 tx_reclaim_req;
+};
+
+#endif /* _QTN_FMAC_PCIE_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_ipc.h b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_ipc.h
new file mode 100644
index 0000000..e00d508
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_ipc.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _QTN_FMAC_PCIE_IPC_H_
+#define _QTN_FMAC_PCIE_IPC_H_
+
+#include <linux/types.h>
+
+#include "shm_ipc_defs.h"
+
+/* bitmap for EP status and flags: updated by EP, read by RC */
+#define QTN_EP_HAS_UBOOT BIT(0)
+#define QTN_EP_HAS_FIRMWARE BIT(1)
+#define QTN_EP_REQ_UBOOT BIT(2)
+#define QTN_EP_REQ_FIRMWARE BIT(3)
+#define QTN_EP_ERROR_UBOOT BIT(4)
+#define QTN_EP_ERROR_FIRMWARE BIT(5)
+
+#define QTN_EP_FW_LOADRDY BIT(8)
+#define QTN_EP_FW_SYNC BIT(9)
+#define QTN_EP_FW_RETRY BIT(10)
+#define QTN_EP_FW_QLINK_DONE BIT(15)
+#define QTN_EP_FW_DONE BIT(16)
+
+/* bitmap for RC status and flags: updated by RC, read by EP */
+#define QTN_RC_PCIE_LINK BIT(0)
+#define QTN_RC_NET_LINK BIT(1)
+#define QTN_RC_FW_FLASHBOOT BIT(5)
+#define QTN_RC_FW_QLINK BIT(7)
+#define QTN_RC_FW_LOADRDY BIT(8)
+#define QTN_RC_FW_SYNC BIT(9)
+
+/* state transition timeouts */
+#define QTN_FW_DL_TIMEOUT_MS 3000
+#define QTN_FW_QLINK_TIMEOUT_MS 30000
+
+#define PCIE_HDP_INT_RX_BITS (0 \
+ | PCIE_HDP_INT_EP_TXDMA \
+ | PCIE_HDP_INT_EP_TXEMPTY \
+ )
+
+#define PCIE_HDP_INT_TX_BITS (0 \
+ | PCIE_HDP_INT_EP_RXDMA \
+ )
+
+#if BITS_PER_LONG == 64
+#define QTN_HOST_HI32(a) ((u32)(((u64)a) >> 32))
+#define QTN_HOST_LO32(a) ((u32)(((u64)a) & 0xffffffffUL))
+#define QTN_HOST_ADDR(h, l) ((((u64)h) << 32) | ((u64)l))
+#elif BITS_PER_LONG == 32
+#define QTN_HOST_HI32(a) 0
+#define QTN_HOST_LO32(a) ((u32)(((u32)a) & 0xffffffffUL))
+#define QTN_HOST_ADDR(h, l) ((u32)l)
+#else
+#error Unexpected BITS_PER_LONG value
+#endif
+
+#define QTN_SYSCTL_BAR 0
+#define QTN_SHMEM_BAR 2
+#define QTN_DMA_BAR 3
+
+#define QTN_PCIE_BDA_VERSION 0x1002
+
+#define PCIE_BDA_NAMELEN 32
+#define PCIE_HHBM_MAX_SIZE 512
+
+#define SKB_BUF_SIZE 2048
+
+#define QTN_PCIE_BOARDFLG "PCIEQTN"
+#define QTN_PCIE_FW_DLMASK 0xF
+#define QTN_PCIE_FW_BUFSZ 2048
+
+#define QTN_ENET_ADDR_LENGTH 6
+
+#define QTN_TXDONE_MASK ((u32)0x80000000)
+#define QTN_GET_LEN(x) ((x) & 0xFFFF)
+
+#define QTN_PCIE_TX_DESC_LEN_MASK 0xFFFF
+#define QTN_PCIE_TX_DESC_LEN_SHIFT 0
+#define QTN_PCIE_TX_DESC_PORT_MASK 0xF
+#define QTN_PCIE_TX_DESC_PORT_SHIFT 16
+#define QTN_PCIE_TX_DESC_TQE_BIT BIT(24)
+
+#define QTN_EP_LHOST_TQE_PORT 4
+
+enum qtnf_pcie_bda_ipc_flags {
+ QTN_PCIE_IPC_FLAG_HBM_MAGIC = BIT(0),
+ QTN_PCIE_IPC_FLAG_SHM_PIO = BIT(1),
+};
+
+struct qtnf_pcie_bda {
+ __le16 bda_len;
+ __le16 bda_version;
+ __le32 bda_pci_endian;
+ __le32 bda_ep_state;
+ __le32 bda_rc_state;
+ __le32 bda_dma_mask;
+ __le32 bda_msi_addr;
+ __le32 bda_flashsz;
+ u8 bda_boardname[PCIE_BDA_NAMELEN];
+ __le32 bda_rc_msi_enabled;
+ __le32 bda_hhbm_list[PCIE_HHBM_MAX_SIZE];
+ __le32 bda_dsbw_start_index;
+ __le32 bda_dsbw_end_index;
+ __le32 bda_dsbw_total_bytes;
+ __le32 bda_rc_tx_bd_base;
+ __le32 bda_rc_tx_bd_num;
+ u8 bda_pcie_mac[QTN_ENET_ADDR_LENGTH];
+ struct qtnf_shm_ipc_region bda_shm_reg1 __aligned(4096); /* host TX */
+ struct qtnf_shm_ipc_region bda_shm_reg2 __aligned(4096); /* host RX */
+} __packed;
+
+struct qtnf_tx_bd {
+ __le32 addr;
+ __le32 addr_h;
+ __le32 info;
+ __le32 info_h;
+} __packed;
+
+struct qtnf_rx_bd {
+ __le32 addr;
+ __le32 addr_h;
+ __le32 info;
+ __le32 info_h;
+ __le32 next_ptr;
+ __le32 next_ptr_h;
+} __packed;
+
+enum qtnf_fw_loadtype {
+ QTN_FW_DBEGIN,
+ QTN_FW_DSUB,
+ QTN_FW_DEND,
+ QTN_FW_CTRL
+};
+
+struct qtnf_pcie_fw_hdr {
+ u8 boardflg[8];
+ __le32 fwsize;
+ __le32 seqnum;
+ __le32 type;
+ __le32 pktlen;
+ __le32 crc;
+} __packed;
+
+#endif /* _QTN_FMAC_PCIE_IPC_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_regs_pearl.h b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_regs_pearl.h
new file mode 100644
index 0000000..78715b8
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_regs_pearl.h
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2015 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __PEARL_PCIE_H
+#define __PEARL_PCIE_H
+
+#define PCIE_GEN2_BASE (0xe9000000)
+#define PCIE_GEN3_BASE (0xe7000000)
+
+#define PEARL_CUR_PCIE_BASE (PCIE_GEN2_BASE)
+#define PCIE_HDP_OFFSET (0x2000)
+
+#define PCIE_HDP_CTRL(base) ((base) + 0x2c00)
+#define PCIE_HDP_AXI_CTRL(base) ((base) + 0x2c04)
+#define PCIE_HDP_HOST_WR_DESC0(base) ((base) + 0x2c10)
+#define PCIE_HDP_HOST_WR_DESC0_H(base) ((base) + 0x2c14)
+#define PCIE_HDP_HOST_WR_DESC1(base) ((base) + 0x2c18)
+#define PCIE_HDP_HOST_WR_DESC1_H(base) ((base) + 0x2c1c)
+#define PCIE_HDP_HOST_WR_DESC2(base) ((base) + 0x2c20)
+#define PCIE_HDP_HOST_WR_DESC2_H(base) ((base) + 0x2c24)
+#define PCIE_HDP_HOST_WR_DESC3(base) ((base) + 0x2c28)
+#define PCIE_HDP_HOST_WR_DESC4_H(base) ((base) + 0x2c2c)
+#define PCIE_HDP_RX_INT_CTRL(base) ((base) + 0x2c30)
+#define PCIE_HDP_TX_INT_CTRL(base) ((base) + 0x2c34)
+#define PCIE_HDP_INT_STATUS(base) ((base) + 0x2c38)
+#define PCIE_HDP_INT_EN(base) ((base) + 0x2c3c)
+#define PCIE_HDP_RX_DESC0_PTR(base) ((base) + 0x2c40)
+#define PCIE_HDP_RX_DESC0_NOE(base) ((base) + 0x2c44)
+#define PCIE_HDP_RX_DESC1_PTR(base) ((base) + 0x2c48)
+#define PCIE_HDP_RX_DESC1_NOE(base) ((base) + 0x2c4c)
+#define PCIE_HDP_RX_DESC2_PTR(base) ((base) + 0x2c50)
+#define PCIE_HDP_RX_DESC2_NOE(base) ((base) + 0x2c54)
+#define PCIE_HDP_RX_DESC3_PTR(base) ((base) + 0x2c58)
+#define PCIE_HDP_RX_DESC3_NOE(base) ((base) + 0x2c5c)
+
+#define PCIE_HDP_TX0_BASE_ADDR(base) ((base) + 0x2c60)
+#define PCIE_HDP_TX1_BASE_ADDR(base) ((base) + 0x2c64)
+#define PCIE_HDP_TX0_Q_CTRL(base) ((base) + 0x2c70)
+#define PCIE_HDP_TX1_Q_CTRL(base) ((base) + 0x2c74)
+#define PCIE_HDP_CFG0(base) ((base) + 0x2c80)
+#define PCIE_HDP_CFG1(base) ((base) + 0x2c84)
+#define PCIE_HDP_CFG2(base) ((base) + 0x2c88)
+#define PCIE_HDP_CFG3(base) ((base) + 0x2c8c)
+#define PCIE_HDP_CFG4(base) ((base) + 0x2c90)
+#define PCIE_HDP_CFG5(base) ((base) + 0x2c94)
+#define PCIE_HDP_CFG6(base) ((base) + 0x2c98)
+#define PCIE_HDP_CFG7(base) ((base) + 0x2c9c)
+#define PCIE_HDP_CFG8(base) ((base) + 0x2ca0)
+#define PCIE_HDP_CFG9(base) ((base) + 0x2ca4)
+#define PCIE_HDP_CFG10(base) ((base) + 0x2ca8)
+#define PCIE_HDP_CFG11(base) ((base) + 0x2cac)
+#define PCIE_INT(base) ((base) + 0x2cb0)
+#define PCIE_INT_MASK(base) ((base) + 0x2cb4)
+#define PCIE_MSI_MASK(base) ((base) + 0x2cb8)
+#define PCIE_MSI_PNDG(base) ((base) + 0x2cbc)
+#define PCIE_PRI_CFG(base) ((base) + 0x2cc0)
+#define PCIE_PHY_CR(base) ((base) + 0x2cc4)
+#define PCIE_HDP_CTAG_CTRL(base) ((base) + 0x2cf4)
+#define PCIE_HDP_HHBM_BUF_PTR(base) ((base) + 0x2d00)
+#define PCIE_HDP_HHBM_BUF_PTR_H(base) ((base) + 0x2d04)
+#define PCIE_HDP_HHBM_BUF_FIFO_NOE(base) ((base) + 0x2d04)
+#define PCIE_HDP_RX0DMA_CNT(base) ((base) + 0x2d10)
+#define PCIE_HDP_RX1DMA_CNT(base) ((base) + 0x2d14)
+#define PCIE_HDP_RX2DMA_CNT(base) ((base) + 0x2d18)
+#define PCIE_HDP_RX3DMA_CNT(base) ((base) + 0x2d1c)
+#define PCIE_HDP_TX0DMA_CNT(base) ((base) + 0x2d20)
+#define PCIE_HDP_TX1DMA_CNT(base) ((base) + 0x2d24)
+#define PCIE_HDP_RXDMA_CTRL(base) ((base) + 0x2d28)
+#define PCIE_HDP_TX_HOST_Q_SZ_CTRL(base) ((base) + 0x2d2c)
+#define PCIE_HDP_TX_HOST_Q_BASE_L(base) ((base) + 0x2d30)
+#define PCIE_HDP_TX_HOST_Q_BASE_H(base) ((base) + 0x2d34)
+#define PCIE_HDP_TX_HOST_Q_WR_PTR(base) ((base) + 0x2d38)
+#define PCIE_HDP_TX_HOST_Q_RD_PTR(base) ((base) + 0x2d3c)
+#define PCIE_HDP_TX_HOST_Q_STS(base) ((base) + 0x2d40)
+
+/* Host HBM pool registers */
+#define PCIE_HHBM_CSR_REG(base) ((base) + 0x2e00)
+#define PCIE_HHBM_Q_BASE_REG(base) ((base) + 0x2e04)
+#define PCIE_HHBM_Q_LIMIT_REG(base) ((base) + 0x2e08)
+#define PCIE_HHBM_Q_WR_REG(base) ((base) + 0x2e0c)
+#define PCIE_HHBM_Q_RD_REG(base) ((base) + 0x2e10)
+#define PCIE_HHBM_POOL_DATA_0_H(base) ((base) + 0x2e90)
+#define PCIE_HHBM_CONFIG(base) ((base) + 0x2f9c)
+#define PCIE_HHBM_POOL_REQ_0(base) ((base) + 0x2f10)
+#define PCIE_HHBM_POOL_DATA_0(base) ((base) + 0x2f40)
+#define PCIE_HHBM_WATERMARK_MASKED_INT(base) ((base) + 0x2f68)
+#define PCIE_HHBM_WATERMARK_INT(base) ((base) + 0x2f6c)
+#define PCIE_HHBM_POOL_WATERMARK(base) ((base) + 0x2f70)
+#define PCIE_HHBM_POOL_OVERFLOW_CNT(base) ((base) + 0x2f90)
+#define PCIE_HHBM_POOL_UNDERFLOW_CNT(base) ((base) + 0x2f94)
+#define HBM_INT_STATUS(base) ((base) + 0x2f9c)
+#define PCIE_HHBM_POOL_CNFIG(base) ((base) + 0x2f9c)
+
+/* host HBM bit field definition */
+#define HHBM_CONFIG_SOFT_RESET (BIT(8))
+#define HHBM_WR_REQ (BIT(0))
+#define HHBM_RD_REQ (BIT(1))
+#define HHBM_DONE (BIT(31))
+
+/* offsets for dual PCIE */
+#define PCIE_PORT_LINK_CTL(base) ((base) + 0x0710)
+#define PCIE_GEN2_CTL(base) ((base) + 0x080C)
+#define PCIE_GEN3_OFF(base) ((base) + 0x0890)
+#define PCIE_ATU_CTRL1(base) ((base) + 0x0904)
+#define PCIE_ATU_CTRL2(base) ((base) + 0x0908)
+#define PCIE_ATU_BASE_LOW(base) ((base) + 0x090C)
+#define PCIE_ATU_BASE_HIGH(base) ((base) + 0x0910)
+#define PCIE_ATU_BASE_LIMIT(base) ((base) + 0x0914)
+#define PCIE_ATU_TGT_LOW(base) ((base) + 0x0918)
+#define PCIE_ATU_TGT_HIGH(base) ((base) + 0x091C)
+#define PCIE_DMA_WR_ENABLE(base) ((base) + 0x097C)
+#define PCIE_DMA_WR_CHWTLOW(base) ((base) + 0x0988)
+#define PCIE_DMA_WR_CHWTHIG(base) ((base) + 0x098C)
+#define PCIE_DMA_WR_INTSTS(base) ((base) + 0x09BC)
+#define PCIE_DMA_WR_INTMASK(base) ((base) + 0x09C4)
+#define PCIE_DMA_WR_INTCLER(base) ((base) + 0x09C8)
+#define PCIE_DMA_WR_DONE_IMWR_ADDR_L(base) ((base) + 0x09D0)
+#define PCIE_DMA_WR_DONE_IMWR_ADDR_H(base) ((base) + 0x09D4)
+#define PCIE_DMA_WR_ABORT_IMWR_ADDR_L(base) ((base) + 0x09D8)
+#define PCIE_DMA_WR_ABORT_IMWR_ADDR_H(base) ((base) + 0x09DC)
+#define PCIE_DMA_WR_IMWR_DATA(base) ((base) + 0x09E0)
+#define PCIE_DMA_WR_LL_ERR_EN(base) ((base) + 0x0A00)
+#define PCIE_DMA_WR_DOORBELL(base) ((base) + 0x0980)
+#define PCIE_DMA_RD_ENABLE(base) ((base) + 0x099C)
+#define PCIE_DMA_RD_DOORBELL(base) ((base) + 0x09A0)
+#define PCIE_DMA_RD_CHWTLOW(base) ((base) + 0x09A8)
+#define PCIE_DMA_RD_CHWTHIG(base) ((base) + 0x09AC)
+#define PCIE_DMA_RD_INTSTS(base) ((base) + 0x0A10)
+#define PCIE_DMA_RD_INTMASK(base) ((base) + 0x0A18)
+#define PCIE_DMA_RD_INTCLER(base) ((base) + 0x0A1C)
+#define PCIE_DMA_RD_ERR_STS_L(base) ((base) + 0x0A24)
+#define PCIE_DMA_RD_ERR_STS_H(base) ((base) + 0x0A28)
+#define PCIE_DMA_RD_LL_ERR_EN(base) ((base) + 0x0A34)
+#define PCIE_DMA_RD_DONE_IMWR_ADDR_L(base) ((base) + 0x0A3C)
+#define PCIE_DMA_RD_DONE_IMWR_ADDR_H(base) ((base) + 0x0A40)
+#define PCIE_DMA_RD_ABORT_IMWR_ADDR_L(base) ((base) + 0x0A44)
+#define PCIE_DMA_RD_ABORT_IMWR_ADDR_H(base) ((base) + 0x0A48)
+#define PCIE_DMA_RD_IMWR_DATA(base) ((base) + 0x0A4C)
+#define PCIE_DMA_CHNL_CONTEXT(base) ((base) + 0x0A6C)
+#define PCIE_DMA_CHNL_CNTRL(base) ((base) + 0x0A70)
+#define PCIE_DMA_XFR_SIZE(base) ((base) + 0x0A78)
+#define PCIE_DMA_SAR_LOW(base) ((base) + 0x0A7C)
+#define PCIE_DMA_SAR_HIGH(base) ((base) + 0x0A80)
+#define PCIE_DMA_DAR_LOW(base) ((base) + 0x0A84)
+#define PCIE_DMA_DAR_HIGH(base) ((base) + 0x0A88)
+#define PCIE_DMA_LLPTR_LOW(base) ((base) + 0x0A8C)
+#define PCIE_DMA_LLPTR_HIGH(base) ((base) + 0x0A90)
+#define PCIE_DMA_WRLL_ERR_ENB(base) ((base) + 0x0A00)
+#define PCIE_DMA_RDLL_ERR_ENB(base) ((base) + 0x0A34)
+#define PCIE_DMABD_CHNL_CNTRL(base) ((base) + 0x8000)
+#define PCIE_DMABD_XFR_SIZE(base) ((base) + 0x8004)
+#define PCIE_DMABD_SAR_LOW(base) ((base) + 0x8008)
+#define PCIE_DMABD_SAR_HIGH(base) ((base) + 0x800c)
+#define PCIE_DMABD_DAR_LOW(base) ((base) + 0x8010)
+#define PCIE_DMABD_DAR_HIGH(base) ((base) + 0x8014)
+#define PCIE_DMABD_LLPTR_LOW(base) ((base) + 0x8018)
+#define PCIE_DMABD_LLPTR_HIGH(base) ((base) + 0x801c)
+#define PCIE_WRDMA0_CHNL_CNTRL(base) ((base) + 0x8000)
+#define PCIE_WRDMA0_XFR_SIZE(base) ((base) + 0x8004)
+#define PCIE_WRDMA0_SAR_LOW(base) ((base) + 0x8008)
+#define PCIE_WRDMA0_SAR_HIGH(base) ((base) + 0x800c)
+#define PCIE_WRDMA0_DAR_LOW(base) ((base) + 0x8010)
+#define PCIE_WRDMA0_DAR_HIGH(base) ((base) + 0x8014)
+#define PCIE_WRDMA0_LLPTR_LOW(base) ((base) + 0x8018)
+#define PCIE_WRDMA0_LLPTR_HIGH(base) ((base) + 0x801c)
+#define PCIE_WRDMA1_CHNL_CNTRL(base) ((base) + 0x8020)
+#define PCIE_WRDMA1_XFR_SIZE(base) ((base) + 0x8024)
+#define PCIE_WRDMA1_SAR_LOW(base) ((base) + 0x8028)
+#define PCIE_WRDMA1_SAR_HIGH(base) ((base) + 0x802c)
+#define PCIE_WRDMA1_DAR_LOW(base) ((base) + 0x8030)
+#define PCIE_WRDMA1_DAR_HIGH(base) ((base) + 0x8034)
+#define PCIE_WRDMA1_LLPTR_LOW(base) ((base) + 0x8038)
+#define PCIE_WRDMA1_LLPTR_HIGH(base) ((base) + 0x803c)
+#define PCIE_RDDMA0_CHNL_CNTRL(base) ((base) + 0x8040)
+#define PCIE_RDDMA0_XFR_SIZE(base) ((base) + 0x8044)
+#define PCIE_RDDMA0_SAR_LOW(base) ((base) + 0x8048)
+#define PCIE_RDDMA0_SAR_HIGH(base) ((base) + 0x804c)
+#define PCIE_RDDMA0_DAR_LOW(base) ((base) + 0x8050)
+#define PCIE_RDDMA0_DAR_HIGH(base) ((base) + 0x8054)
+#define PCIE_RDDMA0_LLPTR_LOW(base) ((base) + 0x8058)
+#define PCIE_RDDMA0_LLPTR_HIGH(base) ((base) + 0x805c)
+#define PCIE_RDDMA1_CHNL_CNTRL(base) ((base) + 0x8060)
+#define PCIE_RDDMA1_XFR_SIZE(base) ((base) + 0x8064)
+#define PCIE_RDDMA1_SAR_LOW(base) ((base) + 0x8068)
+#define PCIE_RDDMA1_SAR_HIGH(base) ((base) + 0x806c)
+#define PCIE_RDDMA1_DAR_LOW(base) ((base) + 0x8070)
+#define PCIE_RDDMA1_DAR_HIGH(base) ((base) + 0x8074)
+#define PCIE_RDDMA1_LLPTR_LOW(base) ((base) + 0x8078)
+#define PCIE_RDDMA1_LLPTR_HIGH(base) ((base) + 0x807c)
+
+#define PCIE_ID(base) ((base) + 0x0000)
+#define PCIE_CMD(base) ((base) + 0x0004)
+#define PCIE_BAR(base, n) ((base) + 0x0010 + ((n) << 2))
+#define PCIE_CAP_PTR(base) ((base) + 0x0034)
+#define PCIE_MSI_LBAR(base) ((base) + 0x0054)
+#define PCIE_MSI_CTRL(base) ((base) + 0x0050)
+#define PCIE_MSI_ADDR_L(base) ((base) + 0x0054)
+#define PCIE_MSI_ADDR_H(base) ((base) + 0x0058)
+#define PCIE_MSI_DATA(base) ((base) + 0x005C)
+#define PCIE_MSI_MASK_BIT(base) ((base) + 0x0060)
+#define PCIE_MSI_PEND_BIT(base) ((base) + 0x0064)
+#define PCIE_DEVCAP(base) ((base) + 0x0074)
+#define PCIE_DEVCTLSTS(base) ((base) + 0x0078)
+
+#define PCIE_CMDSTS(base) ((base) + 0x0004)
+#define PCIE_LINK_STAT(base) ((base) + 0x80)
+#define PCIE_LINK_CTL2(base) ((base) + 0xa0)
+#define PCIE_ASPM_L1_CTRL(base) ((base) + 0x70c)
+#define PCIE_ASPM_LINK_CTRL(base) (PCIE_LINK_STAT)
+#define PCIE_ASPM_L1_SUBSTATE_TIMING(base) ((base) + 0xB44)
+#define PCIE_L1SUB_CTRL1(base) ((base) + 0x150)
+#define PCIE_PMCSR(base) ((base) + 0x44)
+#define PCIE_CFG_SPACE_LIMIT(base) ((base) + 0x100)
+
+/* PCIe link defines */
+#define PEARL_PCIE_LINKUP (0x7)
+#define PEARL_PCIE_DATA_LINK (BIT(0))
+#define PEARL_PCIE_PHY_LINK (BIT(1))
+#define PEARL_PCIE_LINK_RST (BIT(3))
+#define PEARL_PCIE_FATAL_ERR (BIT(5))
+#define PEARL_PCIE_NONFATAL_ERR (BIT(6))
+
+/* PCIe Lane defines */
+#define PCIE_G2_LANE_X1 ((BIT(0)) << 16)
+#define PCIE_G2_LANE_X2 ((BIT(0) | BIT(1)) << 16)
+
+/* PCIe DLL link enable */
+#define PCIE_DLL_LINK_EN ((BIT(0)) << 5)
+
+#define PCIE_LINK_GEN1 (BIT(0))
+#define PCIE_LINK_GEN2 (BIT(1))
+#define PCIE_LINK_GEN3 (BIT(2))
+#define PCIE_LINK_MODE(x) (((x) >> 16) & 0x7)
+
+#define MSI_EN (BIT(0))
+#define MSI_64_EN (BIT(7))
+#define PCIE_MSI_ADDR_OFFSET(a) ((a) & 0xFFFF)
+#define PCIE_MSI_ADDR_ALIGN(a) ((a) & (~0xFFFF))
+
+#define PCIE_BAR_MASK(base, n) ((base) + 0x1010 + ((n) << 2))
+#define PCIE_MAX_BAR (6)
+
+#define PCIE_ATU_VIEW(base) ((base) + 0x0900)
+#define PCIE_ATU_CTL1(base) ((base) + 0x0904)
+#define PCIE_ATU_CTL2(base) ((base) + 0x0908)
+#define PCIE_ATU_LBAR(base) ((base) + 0x090c)
+#define PCIE_ATU_UBAR(base) ((base) + 0x0910)
+#define PCIE_ATU_LAR(base) ((base) + 0x0914)
+#define PCIE_ATU_LTAR(base) ((base) + 0x0918)
+#define PCIE_ATU_UTAR(base) ((base) + 0x091c)
+
+#define PCIE_MSI_ADDR_LOWER(base) ((base) + 0x0820)
+#define PCIE_MSI_ADDR_UPPER(base) ((base) + 0x0824)
+#define PCIE_MSI_ENABLE(base) ((base) + 0x0828)
+#define PCIE_MSI_MASK_RC(base) ((base) + 0x082c)
+#define PCIE_MSI_STATUS(base) ((base) + 0x0830)
+#define PEARL_PCIE_MSI_REGION (0xce000000)
+#define PEARL_PCIE_MSI_DATA (0)
+#define PCIE_MSI_GPIO(base) ((base) + 0x0888)
+
+#define PCIE_HDP_HOST_QUEUE_FULL (BIT(17))
+#define USE_BAR_MATCH_MODE
+#define PCIE_ATU_OB_REGION (BIT(0))
+#define PCIE_ATU_EN_REGION (BIT(31))
+#define PCIE_ATU_EN_MATCH (BIT(30))
+#define PCIE_BASE_REGION (0xb0000000)
+#define PCIE_MEM_MAP_SIZE (512 * 1024)
+
+#define PCIE_OB_REG_REGION (0xcf000000)
+#define PCIE_CONFIG_REGION (0xcf000000)
+#define PCIE_CONFIG_SIZE (4096)
+#define PCIE_CONFIG_CH (1)
+
+/* inbound mapping */
+#define PCIE_IB_BAR0 (0x00000000) /* ddr */
+#define PCIE_IB_BAR0_CH (0)
+#define PCIE_IB_BAR3 (0xe0000000) /* sys_reg */
+#define PCIE_IB_BAR3_CH (1)
+
+/* outbound mapping */
+#define PCIE_MEM_CH (0)
+#define PCIE_REG_CH (1)
+#define PCIE_MEM_REGION (0xc0000000)
+#define PCIE_MEM_SIZE (0x000fffff)
+#define PCIE_MEM_TAR (0x80000000)
+
+#define PCIE_MSI_REGION (0xce000000)
+#define PCIE_MSI_SIZE (KBYTE(4) - 1)
+#define PCIE_MSI_CH (1)
+
+/* size of config region */
+#define PCIE_CFG_SIZE (0x0000ffff)
+
+#define PCIE_ATU_DIR_IB (BIT(31))
+#define PCIE_ATU_DIR_OB (0)
+#define PCIE_ATU_DIR_CFG (2)
+#define PCIE_ATU_DIR_MATCH_IB (BIT(31) | BIT(30))
+
+#define PCIE_DMA_WR_0 (0)
+#define PCIE_DMA_WR_1 (1)
+#define PCIE_DMA_RD_0 (2)
+#define PCIE_DMA_RD_1 (3)
+
+#define PCIE_DMA_CHNL_CNTRL_CB (BIT(0))
+#define PCIE_DMA_CHNL_CNTRL_TCB (BIT(1))
+#define PCIE_DMA_CHNL_CNTRL_LLP (BIT(2))
+#define PCIE_DMA_CHNL_CNTRL_LIE (BIT(3))
+#define PCIE_DMA_CHNL_CNTRL_RIE (BIT(4))
+#define PCIE_DMA_CHNL_CNTRL_CSS (BIT(8))
+#define PCIE_DMA_CHNL_CNTRL_LLE (BIT(9))
+#define PCIE_DMA_CHNL_CNTRL_TLP (BIT(26))
+
+#define PCIE_DMA_CHNL_CONTEXT_RD (BIT(31))
+#define PCIE_DMA_CHNL_CONTEXT_WR (0)
+#define PCIE_MAX_BAR (6)
+
+/* PCIe HDP interrupt status definition */
+#define PCIE_HDP_INT_EP_RXDMA (BIT(0))
+#define PCIE_HDP_INT_HBM_UF (BIT(1))
+#define PCIE_HDP_INT_RX_LEN_ERR (BIT(2))
+#define PCIE_HDP_INT_RX_HDR_LEN_ERR (BIT(3))
+#define PCIE_HDP_INT_EP_TXDMA (BIT(12))
+#define PCIE_HDP_INT_EP_TXEMPTY (BIT(15))
+#define PCIE_HDP_INT_IPC (BIT(29))
+
+/* PCIe interrupt status definition */
+#define PCIE_INT_MSI (BIT(24))
+#define PCIE_INT_INTX (BIT(23))
+
+/* PCIe legacy INTx */
+#define PEARL_PCIE_CFG0_OFFSET (0x6C)
+#define PEARL_ASSERT_INTX (BIT(9))
+
+/* SYS CTL regs */
+#define QTN_PEARL_SYSCTL_LHOST_IRQ_OFFSET (0x001C)
+
+#define QTN_PEARL_IPC_IRQ_WORD(irq) (BIT(irq) | BIT(irq + 16))
+#define QTN_PEARL_LHOST_IPC_IRQ (6)
+
+#endif /* __PEARL_PCIE_H */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
new file mode 100644
index 0000000..6eafc15
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -0,0 +1,901 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _QTN_QLINK_H_
+#define _QTN_QLINK_H_
+
+#include <linux/ieee80211.h>
+
+#define QLINK_PROTO_VER 3
+
+#define QLINK_MACID_RSVD 0xFF
+#define QLINK_VIFID_RSVD 0xFF
+
+/* Common QLINK protocol messages definitions.
+ */
+
+/**
+ * enum qlink_msg_type - QLINK message types
+ *
+ * Used to distinguish between message types of QLINK protocol.
+ *
+ * @QLINK_MSG_TYPE_CMD: Message is carrying data of a command sent from
+ * driver to wireless hardware.
+ * @QLINK_MSG_TYPE_CMDRSP: Message is carrying data of a response to a command.
+ * Sent from wireless HW to driver in reply to previously issued command.
+ * @QLINK_MSG_TYPE_EVENT: Data for an event originated in wireless hardware and
+ * sent asynchronously to driver.
+ */
+enum qlink_msg_type {
+ QLINK_MSG_TYPE_CMD = 1,
+ QLINK_MSG_TYPE_CMDRSP = 2,
+ QLINK_MSG_TYPE_EVENT = 3
+};
+
+/**
+ * struct qlink_msg_header - common QLINK protocol message header
+ *
+ * Portion of QLINK protocol header common for all message types.
+ *
+ * @type: Message type, one of &enum qlink_msg_type.
+ * @len: Total length of message including all headers.
+ */
+struct qlink_msg_header {
+ __le16 type;
+ __le16 len;
+} __packed;
+
+/* Generic definitions of data and information carried in QLINK messages
+ */
+
+enum qlink_hw_capab {
+ QLINK_HW_SUPPORTS_REG_UPDATE = BIT(0),
+};
+
+enum qlink_phy_mode {
+ QLINK_PHYMODE_BGN = BIT(0),
+ QLINK_PHYMODE_AN = BIT(1),
+ QLINK_PHYMODE_AC = BIT(2),
+};
+
+enum qlink_iface_type {
+ QLINK_IFTYPE_AP = 1,
+ QLINK_IFTYPE_STATION = 2,
+ QLINK_IFTYPE_ADHOC = 3,
+ QLINK_IFTYPE_MONITOR = 4,
+ QLINK_IFTYPE_WDS = 5,
+};
+
+/**
+ * struct qlink_intf_info - information on virtual interface.
+ *
+ * Data describing a single virtual interface.
+ *
+ * @if_type: Mode of interface operation, one of &enum qlink_iface_type
+ * @flags: interface flagsmap.
+ * @mac_addr: MAC address of virtual interface.
+ */
+struct qlink_intf_info {
+ __le16 if_type;
+ __le16 flags;
+ u8 mac_addr[ETH_ALEN];
+ u8 rsvd[2];
+} __packed;
+
+enum qlink_sta_flags {
+ QLINK_STA_FLAG_INVALID = 0,
+ QLINK_STA_FLAG_AUTHORIZED = BIT(0),
+ QLINK_STA_FLAG_SHORT_PREAMBLE = BIT(1),
+ QLINK_STA_FLAG_WME = BIT(2),
+ QLINK_STA_FLAG_MFP = BIT(3),
+ QLINK_STA_FLAG_AUTHENTICATED = BIT(4),
+ QLINK_STA_FLAG_TDLS_PEER = BIT(5),
+ QLINK_STA_FLAG_ASSOCIATED = BIT(6),
+};
+
+enum qlink_channel_width {
+ QLINK_CHAN_WIDTH_5 = BIT(0),
+ QLINK_CHAN_WIDTH_10 = BIT(1),
+ QLINK_CHAN_WIDTH_20_NOHT = BIT(2),
+ QLINK_CHAN_WIDTH_20 = BIT(3),
+ QLINK_CHAN_WIDTH_40 = BIT(4),
+ QLINK_CHAN_WIDTH_80 = BIT(5),
+ QLINK_CHAN_WIDTH_80P80 = BIT(6),
+ QLINK_CHAN_WIDTH_160 = BIT(7),
+};
+
+/* QLINK Command messages related definitions
+ */
+
+/**
+ * enum qlink_cmd_type - list of supported commands
+ *
+ * Commands are QLINK messages of type @QLINK_MSG_TYPE_CMD, sent by driver to
+ * wireless network device for processing. Device is expected to send back a
+ * reply message of type &QLINK_MSG_TYPE_CMDRSP, containing at least command
+ * execution status (one of &enum qlink_cmd_result) at least. Reply message
+ * may also contain data payload specific to the command type.
+ *
+ * @QLINK_CMD_CHANS_INFO_GET: for the specified MAC and specified band, get
+ * number of operational channels and information on each of the channel.
+ * This command is generic to a specified MAC, interface index must be set
+ * to QLINK_VIFID_RSVD in command header.
+ */
+enum qlink_cmd_type {
+ QLINK_CMD_FW_INIT = 0x0001,
+ QLINK_CMD_FW_DEINIT = 0x0002,
+ QLINK_CMD_REGISTER_MGMT = 0x0003,
+ QLINK_CMD_SEND_MGMT_FRAME = 0x0004,
+ QLINK_CMD_MGMT_SET_APPIE = 0x0005,
+ QLINK_CMD_PHY_PARAMS_GET = 0x0011,
+ QLINK_CMD_PHY_PARAMS_SET = 0x0012,
+ QLINK_CMD_GET_HW_INFO = 0x0013,
+ QLINK_CMD_MAC_INFO = 0x0014,
+ QLINK_CMD_ADD_INTF = 0x0015,
+ QLINK_CMD_DEL_INTF = 0x0016,
+ QLINK_CMD_CHANGE_INTF = 0x0017,
+ QLINK_CMD_UPDOWN_INTF = 0x0018,
+ QLINK_CMD_REG_REGION = 0x0019,
+ QLINK_CMD_CHANS_INFO_GET = 0x001A,
+ QLINK_CMD_CONFIG_AP = 0x0020,
+ QLINK_CMD_START_AP = 0x0021,
+ QLINK_CMD_STOP_AP = 0x0022,
+ QLINK_CMD_GET_STA_INFO = 0x0030,
+ QLINK_CMD_ADD_KEY = 0x0040,
+ QLINK_CMD_DEL_KEY = 0x0041,
+ QLINK_CMD_SET_DEFAULT_KEY = 0x0042,
+ QLINK_CMD_SET_DEFAULT_MGMT_KEY = 0x0043,
+ QLINK_CMD_CHANGE_STA = 0x0051,
+ QLINK_CMD_DEL_STA = 0x0052,
+ QLINK_CMD_SCAN = 0x0053,
+ QLINK_CMD_CONNECT = 0x0060,
+ QLINK_CMD_DISCONNECT = 0x0061,
+};
+
+/**
+ * struct qlink_cmd - QLINK command message header
+ *
+ * Header used for QLINK messages of QLINK_MSG_TYPE_CMD type.
+ *
+ * @mhdr: Common QLINK message header.
+ * @cmd_id: command id, one of &enum qlink_cmd_type.
+ * @seq_num: sequence number of command message, used for matching with
+ * response message.
+ * @macid: index of physical radio device the command is destined to or
+ * QLINK_MACID_RSVD if not applicable.
+ * @vifid: index of virtual wireless interface on specified @macid the command
+ * is destined to or QLINK_VIFID_RSVD if not applicable.
+ */
+struct qlink_cmd {
+ struct qlink_msg_header mhdr;
+ __le16 cmd_id;
+ __le16 seq_num;
+ u8 rsvd[2];
+ u8 macid;
+ u8 vifid;
+} __packed;
+
+/**
+ * struct qlink_cmd_manage_intf - interface management command
+ *
+ * Data for interface management commands QLINK_CMD_ADD_INTF, QLINK_CMD_DEL_INTF
+ * and QLINK_CMD_CHANGE_INTF.
+ *
+ * @intf_info: interface description.
+ */
+struct qlink_cmd_manage_intf {
+ struct qlink_cmd chdr;
+ struct qlink_intf_info intf_info;
+} __packed;
+
+enum qlink_mgmt_frame_type {
+ QLINK_MGMT_FRAME_ASSOC_REQ = 0x00,
+ QLINK_MGMT_FRAME_ASSOC_RESP = 0x01,
+ QLINK_MGMT_FRAME_REASSOC_REQ = 0x02,
+ QLINK_MGMT_FRAME_REASSOC_RESP = 0x03,
+ QLINK_MGMT_FRAME_PROBE_REQ = 0x04,
+ QLINK_MGMT_FRAME_PROBE_RESP = 0x05,
+ QLINK_MGMT_FRAME_BEACON = 0x06,
+ QLINK_MGMT_FRAME_ATIM = 0x07,
+ QLINK_MGMT_FRAME_DISASSOC = 0x08,
+ QLINK_MGMT_FRAME_AUTH = 0x09,
+ QLINK_MGMT_FRAME_DEAUTH = 0x0A,
+ QLINK_MGMT_FRAME_ACTION = 0x0B,
+
+ QLINK_MGMT_FRAME_TYPE_COUNT
+};
+
+/**
+ * struct qlink_cmd_mgmt_frame_register - data for QLINK_CMD_REGISTER_MGMT
+ *
+ * @frame_type: MGMT frame type the registration request describes, one of
+ * &enum qlink_mgmt_frame_type.
+ * @do_register: 0 - unregister, otherwise register for reception of specified
+ * MGMT frame type.
+ */
+struct qlink_cmd_mgmt_frame_register {
+ struct qlink_cmd chdr;
+ __le16 frame_type;
+ u8 do_register;
+} __packed;
+
+enum qlink_mgmt_frame_tx_flags {
+ QLINK_MGMT_FRAME_TX_FLAG_NONE = 0,
+ QLINK_MGMT_FRAME_TX_FLAG_OFFCHAN = BIT(0),
+ QLINK_MGMT_FRAME_TX_FLAG_NO_CCK = BIT(1),
+ QLINK_MGMT_FRAME_TX_FLAG_ACK_NOWAIT = BIT(2),
+};
+
+/**
+ * struct qlink_cmd_mgmt_frame_tx - data for QLINK_CMD_SEND_MGMT_FRAME command
+ *
+ * @cookie: opaque request identifier.
+ * @freq: Frequency to use for frame transmission.
+ * @flags: Transmission flags, one of &enum qlink_mgmt_frame_tx_flags.
+ * @frame_data: frame to transmit.
+ */
+struct qlink_cmd_mgmt_frame_tx {
+ struct qlink_cmd chdr;
+ __le32 cookie;
+ __le16 freq;
+ __le16 flags;
+ u8 frame_data[0];
+} __packed;
+
+/**
+ * struct qlink_cmd_mgmt_append_ie - data for QLINK_CMD_MGMT_SET_APPIE command
+ *
+ * @type: type of MGMT frame to appent requested IEs to, one of
+ * &enum qlink_mgmt_frame_type.
+ * @flags: for future use.
+ * @ie_data: IEs data to append.
+ */
+struct qlink_cmd_mgmt_append_ie {
+ struct qlink_cmd chdr;
+ u8 type;
+ u8 flags;
+ u8 ie_data[0];
+} __packed;
+
+/**
+ * struct qlink_cmd_get_sta_info - data for QLINK_CMD_GET_STA_INFO command
+ *
+ * @sta_addr: MAC address of the STA statistics is requested for.
+ */
+struct qlink_cmd_get_sta_info {
+ struct qlink_cmd chdr;
+ u8 sta_addr[ETH_ALEN];
+} __packed;
+
+/**
+ * struct qlink_cmd_add_key - data for QLINK_CMD_ADD_KEY command.
+ *
+ * @key_index: index of the key being installed.
+ * @pairwise: whether to use pairwise key.
+ * @addr: MAC address of a STA key is being installed to.
+ * @cipher: cipher suite.
+ * @key_data: key data itself.
+ */
+struct qlink_cmd_add_key {
+ struct qlink_cmd chdr;
+ u8 key_index;
+ u8 pairwise;
+ u8 addr[ETH_ALEN];
+ __le32 cipher;
+ u8 key_data[0];
+} __packed;
+
+/**
+ * struct qlink_cmd_del_key_req - data for QLINK_CMD_DEL_KEY command
+ *
+ * @key_index: index of the key being removed.
+ * @pairwise: whether to use pairwise key.
+ * @addr: MAC address of a STA for which a key is removed.
+ */
+struct qlink_cmd_del_key {
+ struct qlink_cmd chdr;
+ u8 key_index;
+ u8 pairwise;
+ u8 addr[ETH_ALEN];
+} __packed;
+
+/**
+ * struct qlink_cmd_set_def_key - data for QLINK_CMD_SET_DEFAULT_KEY command
+ *
+ * @key_index: index of the key to be set as default one.
+ * @unicast: key is unicast.
+ * @multicast: key is multicast.
+ */
+struct qlink_cmd_set_def_key {
+ struct qlink_cmd chdr;
+ u8 key_index;
+ u8 unicast;
+ u8 multicast;
+} __packed;
+
+/**
+ * struct qlink_cmd_set_def_mgmt_key - data for QLINK_CMD_SET_DEFAULT_MGMT_KEY
+ *
+ * @key_index: index of the key to be set as default MGMT key.
+ */
+struct qlink_cmd_set_def_mgmt_key {
+ struct qlink_cmd chdr;
+ u8 key_index;
+} __packed;
+
+/**
+ * struct qlink_cmd_change_sta - data for QLINK_CMD_CHANGE_STA command
+ *
+ * @sta_flags_mask: STA flags mask, bitmap of &enum qlink_sta_flags
+ * @sta_flags_set: STA flags values, bitmap of &enum qlink_sta_flags
+ * @sta_addr: address of the STA for which parameters are set.
+ */
+struct qlink_cmd_change_sta {
+ struct qlink_cmd chdr;
+ __le32 sta_flags_mask;
+ __le32 sta_flags_set;
+ u8 sta_addr[ETH_ALEN];
+} __packed;
+
+/**
+ * struct qlink_cmd_del_sta - data for QLINK_CMD_DEL_STA command.
+ *
+ * See &struct station_del_parameters
+ */
+struct qlink_cmd_del_sta {
+ struct qlink_cmd chdr;
+ __le16 reason_code;
+ u8 subtype;
+ u8 sta_addr[ETH_ALEN];
+} __packed;
+
+enum qlink_sta_connect_flags {
+ QLINK_STA_CONNECT_DISABLE_HT = BIT(0),
+ QLINK_STA_CONNECT_DISABLE_VHT = BIT(1),
+ QLINK_STA_CONNECT_USE_RRM = BIT(2),
+};
+
+/**
+ * struct qlink_cmd_connect - data for QLINK_CMD_CONNECT command
+ *
+ * @flags: for future use.
+ * @freq: center frequence of a channel which should be used to connect.
+ * @bg_scan_period: period of background scan.
+ * @bssid: BSSID of the BSS to connect to.
+ * @payload: variable portion of connection request.
+ */
+struct qlink_cmd_connect {
+ struct qlink_cmd chdr;
+ __le32 flags;
+ __le16 freq;
+ __le16 bg_scan_period;
+ u8 bssid[ETH_ALEN];
+ u8 payload[0];
+} __packed;
+
+/**
+ * struct qlink_cmd_disconnect - data for QLINK_CMD_DISCONNECT command
+ *
+ * @reason: code of the reason of disconnect, see &enum ieee80211_reasoncode.
+ */
+struct qlink_cmd_disconnect {
+ struct qlink_cmd chdr;
+ __le16 reason;
+} __packed;
+
+/**
+ * struct qlink_cmd_updown - data for QLINK_CMD_UPDOWN_INTF command
+ *
+ * @if_up: bring specified interface DOWN (if_up==0) or UP (otherwise).
+ * Interface is specified in common command header @chdr.
+ */
+struct qlink_cmd_updown {
+ struct qlink_cmd chdr;
+ u8 if_up;
+} __packed;
+
+/**
+ * enum qlink_band - a list of frequency bands
+ *
+ * @QLINK_BAND_2GHZ: 2.4GHz band
+ * @QLINK_BAND_5GHZ: 5GHz band
+ * @QLINK_BAND_60GHZ: 60GHz band
+ */
+enum qlink_band {
+ QLINK_BAND_2GHZ = BIT(0),
+ QLINK_BAND_5GHZ = BIT(1),
+ QLINK_BAND_60GHZ = BIT(2),
+};
+
+/**
+ * struct qlink_cmd_chans_info_get - data for QLINK_CMD_CHANS_INFO_GET command
+ *
+ * @band: a PHY band for which channels info is needed, one of @enum qlink_band
+ */
+struct qlink_cmd_chans_info_get {
+ struct qlink_cmd chdr;
+ u8 band;
+} __packed;
+
+/* QLINK Command Responses messages related definitions
+ */
+
+enum qlink_cmd_result {
+ QLINK_CMD_RESULT_OK = 0,
+ QLINK_CMD_RESULT_INVALID,
+ QLINK_CMD_RESULT_ENOTSUPP,
+ QLINK_CMD_RESULT_ENOTFOUND,
+};
+
+/**
+ * struct qlink_resp - QLINK command response message header
+ *
+ * Header used for QLINK messages of QLINK_MSG_TYPE_CMDRSP type.
+ *
+ * @mhdr: see &struct qlink_msg_header.
+ * @cmd_id: command ID the response corresponds to, one of &enum qlink_cmd_type.
+ * @seq_num: sequence number of command message, used for matching with
+ * response message.
+ * @result: result of the command execution, one of &enum qlink_cmd_result.
+ * @macid: index of physical radio device the response is sent from or
+ * QLINK_MACID_RSVD if not applicable.
+ * @vifid: index of virtual wireless interface on specified @macid the response
+ * is sent from or QLINK_VIFID_RSVD if not applicable.
+ */
+struct qlink_resp {
+ struct qlink_msg_header mhdr;
+ __le16 cmd_id;
+ __le16 seq_num;
+ __le16 result;
+ u8 macid;
+ u8 vifid;
+} __packed;
+
+/**
+ * struct qlink_resp_get_mac_info - response for QLINK_CMD_MAC_INFO command
+ *
+ * Data describing specific physical device providing wireless MAC
+ * functionality.
+ *
+ * @dev_mac: MAC address of physical WMAC device (used for first BSS on
+ * specified WMAC).
+ * @num_tx_chain: Number of transmit chains used by WMAC.
+ * @num_rx_chain: Number of receive chains used by WMAC.
+ * @vht_cap: VHT capabilities.
+ * @ht_cap: HT capabilities.
+ * @bands_cap: wireless bands WMAC can operate in, bitmap of &enum qlink_band.
+ * @phymode_cap: PHY modes WMAC can operate in, bitmap of &enum qlink_phy_mode.
+ * @max_ap_assoc_sta: Maximum number of associations supported by WMAC.
+ * @radar_detect_widths: bitmask of channels BW for which WMAC can detect radar.
+ * @var_info: variable-length WMAC info data.
+ */
+struct qlink_resp_get_mac_info {
+ struct qlink_resp rhdr;
+ u8 dev_mac[ETH_ALEN];
+ u8 num_tx_chain;
+ u8 num_rx_chain;
+ struct ieee80211_vht_cap vht_cap;
+ struct ieee80211_ht_cap ht_cap;
+ u8 bands_cap;
+ u8 phymode_cap;
+ __le16 max_ap_assoc_sta;
+ __le16 radar_detect_widths;
+ u8 var_info[0];
+} __packed;
+
+/**
+ * struct qlink_resp_get_hw_info - response for QLINK_CMD_GET_HW_INFO command
+ *
+ * Description of wireless hardware capabilities and features.
+ *
+ * @fw_ver: wireless hardware firmware version.
+ * @hw_capab: Bitmap of capabilities supported by firmware.
+ * @ql_proto_ver: Version of QLINK protocol used by firmware.
+ * @country_code: country code ID firmware is configured to.
+ * @num_mac: Number of separate physical radio devices provided by hardware.
+ * @mac_bitmap: Bitmap of MAC IDs that are active and can be used in firmware.
+ * @total_tx_chains: total number of transmit chains used by device.
+ * @total_rx_chains: total number of receive chains.
+ */
+struct qlink_resp_get_hw_info {
+ struct qlink_resp rhdr;
+ __le32 fw_ver;
+ __le32 hw_capab;
+ __le16 ql_proto_ver;
+ u8 alpha2_code[2];
+ u8 num_mac;
+ u8 mac_bitmap;
+ u8 total_tx_chain;
+ u8 total_rx_chain;
+} __packed;
+
+/**
+ * struct qlink_resp_manage_intf - response for interface management commands
+ *
+ * Response data for QLINK_CMD_ADD_INTF and QLINK_CMD_CHANGE_INTF commands.
+ *
+ * @rhdr: Common Command Response message header.
+ * @intf_info: interface description.
+ */
+struct qlink_resp_manage_intf {
+ struct qlink_resp rhdr;
+ struct qlink_intf_info intf_info;
+} __packed;
+
+/**
+ * struct qlink_resp_get_sta_info - response for QLINK_CMD_GET_STA_INFO command
+ *
+ * Response data containing statistics for specified STA.
+ *
+ * @sta_addr: MAC address of STA the response carries statistic for.
+ * @info: statistics for specified STA.
+ */
+struct qlink_resp_get_sta_info {
+ struct qlink_resp rhdr;
+ u8 sta_addr[ETH_ALEN];
+ u8 info[0];
+} __packed;
+
+/**
+ * struct qlink_resp_get_chan_info - response for QLINK_CMD_CHANS_INFO_GET cmd
+ *
+ * @band: frequency band to which channels belong to, one of @enum qlink_band.
+ * @num_chans: total number of channels info data contained in reply data.
+ * @info: variable-length channels info.
+ */
+struct qlink_resp_get_chan_info {
+ struct qlink_resp rhdr;
+ u8 band;
+ u8 num_chans;
+ u8 rsvd[2];
+ u8 info[0];
+} __packed;
+
+/**
+ * struct qlink_resp_phy_params - response for QLINK_CMD_PHY_PARAMS_GET command
+ *
+ * @info: variable-length array of PHY params.
+ */
+struct qlink_resp_phy_params {
+ struct qlink_resp rhdr;
+ u8 info[0];
+} __packed;
+
+/* QLINK Events messages related definitions
+ */
+
+enum qlink_event_type {
+ QLINK_EVENT_STA_ASSOCIATED = 0x0021,
+ QLINK_EVENT_STA_DEAUTH = 0x0022,
+ QLINK_EVENT_MGMT_RECEIVED = 0x0023,
+ QLINK_EVENT_SCAN_RESULTS = 0x0024,
+ QLINK_EVENT_SCAN_COMPLETE = 0x0025,
+ QLINK_EVENT_BSS_JOIN = 0x0026,
+ QLINK_EVENT_BSS_LEAVE = 0x0027,
+};
+
+/**
+ * struct qlink_event - QLINK event message header
+ *
+ * Header used for QLINK messages of QLINK_MSG_TYPE_EVENT type.
+ *
+ * @mhdr: Common QLINK message header.
+ * @event_id: Specifies specific event ID, one of &enum qlink_event_type.
+ * @macid: index of physical radio device the event was generated on or
+ * QLINK_MACID_RSVD if not applicable.
+ * @vifid: index of virtual wireless interface on specified @macid the event
+ * was generated on or QLINK_VIFID_RSVD if not applicable.
+ */
+struct qlink_event {
+ struct qlink_msg_header mhdr;
+ __le16 event_id;
+ u8 macid;
+ u8 vifid;
+} __packed;
+
+/**
+ * struct qlink_event_sta_assoc - data for QLINK_EVENT_STA_ASSOCIATED event
+ *
+ * @sta_addr: Address of a STA for which new association event was generated
+ * @frame_control: control bits from 802.11 ASSOC_REQUEST header.
+ * @payload: IEs from association request.
+ */
+struct qlink_event_sta_assoc {
+ struct qlink_event ehdr;
+ u8 sta_addr[ETH_ALEN];
+ __le16 frame_control;
+ u8 ies[0];
+} __packed;
+
+/**
+ * struct qlink_event_sta_deauth - data for QLINK_EVENT_STA_DEAUTH event
+ *
+ * @sta_addr: Address of a deauthenticated STA.
+ * @reason: reason for deauthentication.
+ */
+struct qlink_event_sta_deauth {
+ struct qlink_event ehdr;
+ u8 sta_addr[ETH_ALEN];
+ __le16 reason;
+} __packed;
+
+/**
+ * struct qlink_event_bss_join - data for QLINK_EVENT_BSS_JOIN event
+ *
+ * @bssid: BSSID of a BSS which interface tried to joined.
+ * @status: status of joining attempt, see &enum ieee80211_statuscode.
+ */
+struct qlink_event_bss_join {
+ struct qlink_event ehdr;
+ u8 bssid[ETH_ALEN];
+ __le16 status;
+} __packed;
+
+/**
+ * struct qlink_event_bss_leave - data for QLINK_EVENT_BSS_LEAVE event
+ *
+ * @reason: reason of disconnecting from BSS.
+ */
+struct qlink_event_bss_leave {
+ struct qlink_event ehdr;
+ u16 reason;
+} __packed;
+
+enum qlink_rxmgmt_flags {
+ QLINK_RXMGMT_FLAG_ANSWERED = 1 << 0,
+};
+
+/**
+ * struct qlink_event_rxmgmt - data for QLINK_EVENT_MGMT_RECEIVED event
+ *
+ * @freq: Frequency on which the frame was received in MHz.
+ * @sig_dbm: signal strength in dBm.
+ * @flags: bitmap of &enum qlink_rxmgmt_flags.
+ * @frame_data: data of Rx'd frame itself.
+ */
+struct qlink_event_rxmgmt {
+ struct qlink_event ehdr;
+ __le32 freq;
+ __le32 sig_dbm;
+ __le32 flags;
+ u8 frame_data[0];
+} __packed;
+
+enum qlink_frame_type {
+ QLINK_BSS_FTYPE_UNKNOWN,
+ QLINK_BSS_FTYPE_BEACON,
+ QLINK_BSS_FTYPE_PRESP,
+};
+
+/**
+ * struct qlink_event_scan_result - data for QLINK_EVENT_SCAN_RESULTS event
+ *
+ * @tsf: TSF timestamp indicating when scan results were generated.
+ * @freq: Center frequency of the channel where BSS for which the scan result
+ * event was generated was discovered.
+ * @capab: capabilities field.
+ * @bintval: beacon interval announced by discovered BSS.
+ * @signal: signal strength.
+ * @frame_type: frame type used to get scan result, see &enum qlink_frame_type.
+ * @bssid: BSSID announced by discovered BSS.
+ * @ssid_len: length of SSID announced by BSS.
+ * @ssid: SSID announced by discovered BSS.
+ * @payload: IEs that are announced by discovered BSS in its MGMt frames.
+ */
+struct qlink_event_scan_result {
+ struct qlink_event ehdr;
+ __le64 tsf;
+ __le16 freq;
+ __le16 capab;
+ __le16 bintval;
+ s8 signal;
+ u8 frame_type;
+ u8 bssid[ETH_ALEN];
+ u8 ssid_len;
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+ u8 payload[0];
+} __packed;
+
+/**
+ * enum qlink_scan_complete_flags - indicates result of scan request.
+ *
+ * @QLINK_SCAN_NONE: Scan request was processed.
+ * @QLINK_SCAN_ABORTED: Scan was aborted.
+ */
+enum qlink_scan_complete_flags {
+ QLINK_SCAN_NONE = 0,
+ QLINK_SCAN_ABORTED = BIT(0),
+};
+
+/**
+ * struct qlink_event_scan_complete - data for QLINK_EVENT_SCAN_COMPLETE event
+ *
+ * @flags: flags indicating the status of pending scan request,
+ * see &enum qlink_scan_complete_flags.
+ */
+struct qlink_event_scan_complete {
+ struct qlink_event ehdr;
+ __le32 flags;
+} __packed;
+
+/* QLINK TLVs (Type-Length Values) definitions
+ */
+
+enum qlink_tlv_id {
+ QTN_TLV_ID_FRAG_THRESH = 0x0201,
+ QTN_TLV_ID_RTS_THRESH = 0x0202,
+ QTN_TLV_ID_SRETRY_LIMIT = 0x0203,
+ QTN_TLV_ID_LRETRY_LIMIT = 0x0204,
+ QTN_TLV_ID_BCN_PERIOD = 0x0205,
+ QTN_TLV_ID_DTIM = 0x0206,
+ QTN_TLV_ID_CHANNEL = 0x020F,
+ QTN_TLV_ID_COVERAGE_CLASS = 0x0213,
+ QTN_TLV_ID_IFACE_LIMIT = 0x0214,
+ QTN_TLV_ID_NUM_IFACE_COMB = 0x0215,
+ QTN_TLV_ID_STA_BASIC_COUNTERS = 0x0300,
+ QTN_TLV_ID_STA_GENERIC_INFO = 0x0301,
+ QTN_TLV_ID_KEY = 0x0302,
+ QTN_TLV_ID_SEQ = 0x0303,
+ QTN_TLV_ID_CRYPTO = 0x0304,
+ QTN_TLV_ID_IE_SET = 0x0305,
+};
+
+struct qlink_tlv_hdr {
+ __le16 type;
+ __le16 len;
+ u8 val[0];
+} __packed;
+
+struct qlink_iface_limit {
+ __le16 max_num;
+ __le16 type_mask;
+} __packed;
+
+struct qlink_iface_comb_num {
+ __le16 iface_comb_num;
+} __packed;
+
+struct qlink_sta_stat_basic_counters {
+ __le64 rx_bytes;
+ __le64 tx_bytes;
+ __le64 rx_beacons;
+ __le32 rx_packets;
+ __le32 tx_packets;
+ __le32 rx_dropped;
+ __le32 tx_failed;
+} __packed;
+
+enum qlink_sta_info_rate_flags {
+ QLINK_STA_INFO_RATE_FLAG_INVALID = 0,
+ QLINK_STA_INFO_RATE_FLAG_HT_MCS = BIT(0),
+ QLINK_STA_INFO_RATE_FLAG_VHT_MCS = BIT(1),
+ QLINK_STA_INFO_RATE_FLAG_SHORT_GI = BIT(2),
+ QLINK_STA_INFO_RATE_FLAG_60G = BIT(3),
+};
+
+enum qlink_sta_info_rate_bw {
+ QLINK_STA_INFO_RATE_BW_5 = 0,
+ QLINK_STA_INFO_RATE_BW_10 = 1,
+ QLINK_STA_INFO_RATE_BW_20 = 2,
+ QLINK_STA_INFO_RATE_BW_40 = 3,
+ QLINK_STA_INFO_RATE_BW_80 = 4,
+ QLINK_STA_INFO_RATE_BW_160 = 5,
+};
+
+/**
+ * struct qlink_sta_info_rate - STA rate statistics
+ *
+ * @rate: data rate in Mbps.
+ * @flags: bitmap of &enum qlink_sta_flags.
+ * @mcs: 802.11-defined MCS index.
+ * nss: Number of Spatial Streams.
+ * @bw: bandwidth, one of &enum qlink_sta_info_rate_bw.
+ */
+struct qlink_sta_info_rate {
+ __le16 rate;
+ u8 flags;
+ u8 mcs;
+ u8 nss;
+ u8 bw;
+} __packed;
+
+struct qlink_sta_info_state {
+ __le32 mask;
+ __le32 value;
+} __packed;
+
+#define QLINK_RSSI_OFFSET 120
+
+struct qlink_sta_info_generic {
+ struct qlink_sta_info_state state;
+ __le32 connected_time;
+ __le32 inactive_time;
+ struct qlink_sta_info_rate rx_rate;
+ struct qlink_sta_info_rate tx_rate;
+ u8 rssi;
+ u8 rssi_avg;
+} __packed;
+
+struct qlink_tlv_frag_rts_thr {
+ struct qlink_tlv_hdr hdr;
+ __le16 thr;
+} __packed;
+
+struct qlink_tlv_rlimit {
+ struct qlink_tlv_hdr hdr;
+ u8 rlimit;
+} __packed;
+
+struct qlink_tlv_cclass {
+ struct qlink_tlv_hdr hdr;
+ u8 cclass;
+} __packed;
+
+enum qlink_dfs_state {
+ QLINK_DFS_USABLE,
+ QLINK_DFS_UNAVAILABLE,
+ QLINK_DFS_AVAILABLE,
+};
+
+enum qlink_channel_flags {
+ QLINK_CHAN_DISABLED = BIT(0),
+ QLINK_CHAN_NO_IR = BIT(1),
+ QLINK_CHAN_RADAR = BIT(3),
+ QLINK_CHAN_NO_HT40PLUS = BIT(4),
+ QLINK_CHAN_NO_HT40MINUS = BIT(5),
+ QLINK_CHAN_NO_OFDM = BIT(6),
+ QLINK_CHAN_NO_80MHZ = BIT(7),
+ QLINK_CHAN_NO_160MHZ = BIT(8),
+ QLINK_CHAN_INDOOR_ONLY = BIT(9),
+ QLINK_CHAN_IR_CONCURRENT = BIT(10),
+ QLINK_CHAN_NO_20MHZ = BIT(11),
+ QLINK_CHAN_NO_10MHZ = BIT(12),
+};
+
+struct qlink_tlv_channel {
+ struct qlink_tlv_hdr hdr;
+ __le16 hw_value;
+ __le16 center_freq;
+ __le32 flags;
+ u8 band;
+ u8 max_antenna_gain;
+ u8 max_power;
+ u8 max_reg_power;
+ __le32 dfs_cac_ms;
+ u8 dfs_state;
+ u8 beacon_found;
+ u8 rsvd[2];
+} __packed;
+
+#define QLINK_MAX_NR_CIPHER_SUITES 5
+#define QLINK_MAX_NR_AKM_SUITES 2
+
+struct qlink_auth_encr {
+ __le32 wpa_versions;
+ __le32 cipher_group;
+ __le32 n_ciphers_pairwise;
+ __le32 ciphers_pairwise[QLINK_MAX_NR_CIPHER_SUITES];
+ __le32 n_akm_suites;
+ __le32 akm_suites[QLINK_MAX_NR_AKM_SUITES];
+ __le16 control_port_ethertype;
+ u8 auth_type;
+ u8 privacy;
+ u8 mfp;
+ u8 control_port;
+ u8 control_port_no_encrypt;
+} __packed;
+
+#endif /* _QTN_QLINK_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
new file mode 100644
index 0000000..49ae652
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/nl80211.h>
+
+#include "qlink_util.h"
+
+u16 qlink_iface_type_mask_to_nl(u16 qlink_mask)
+{
+ u16 result = 0;
+
+ if (qlink_mask & QLINK_IFTYPE_AP)
+ result |= BIT(NL80211_IFTYPE_AP);
+
+ if (qlink_mask & QLINK_IFTYPE_STATION)
+ result |= BIT(NL80211_IFTYPE_STATION);
+
+ if (qlink_mask & QLINK_IFTYPE_ADHOC)
+ result |= BIT(NL80211_IFTYPE_ADHOC);
+
+ if (qlink_mask & QLINK_IFTYPE_MONITOR)
+ result |= BIT(NL80211_IFTYPE_MONITOR);
+
+ if (qlink_mask & QLINK_IFTYPE_WDS)
+ result |= BIT(NL80211_IFTYPE_WDS);
+
+ return result;
+}
+
+u8 qlink_chan_width_mask_to_nl(u16 qlink_mask)
+{
+ u8 result = 0;
+
+ if (qlink_mask & QLINK_CHAN_WIDTH_5)
+ result |= BIT(NL80211_CHAN_WIDTH_5);
+
+ if (qlink_mask & QLINK_CHAN_WIDTH_10)
+ result |= BIT(NL80211_CHAN_WIDTH_10);
+
+ if (qlink_mask & QLINK_CHAN_WIDTH_20_NOHT)
+ result |= BIT(NL80211_CHAN_WIDTH_20_NOHT);
+
+ if (qlink_mask & QLINK_CHAN_WIDTH_20)
+ result |= BIT(NL80211_CHAN_WIDTH_20);
+
+ if (qlink_mask & QLINK_CHAN_WIDTH_40)
+ result |= BIT(NL80211_CHAN_WIDTH_40);
+
+ if (qlink_mask & QLINK_CHAN_WIDTH_80)
+ result |= BIT(NL80211_CHAN_WIDTH_80);
+
+ if (qlink_mask & QLINK_CHAN_WIDTH_80P80)
+ result |= BIT(NL80211_CHAN_WIDTH_80P80);
+
+ if (qlink_mask & QLINK_CHAN_WIDTH_160)
+ result |= BIT(NL80211_CHAN_WIDTH_160);
+
+ return result;
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
new file mode 100644
index 0000000..90d7d09
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _QTN_FMAC_QLINK_UTIL_H_
+#define _QTN_FMAC_QLINK_UTIL_H_
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+
+#include "qlink.h"
+
+static inline void qtnf_cmd_skb_put_action(struct sk_buff *skb, u16 action)
+{
+ __le16 *buf_ptr;
+
+ buf_ptr = skb_put(skb, sizeof(action));
+ *buf_ptr = cpu_to_le16(action);
+}
+
+static inline void
+qtnf_cmd_skb_put_buffer(struct sk_buff *skb, const u8 *buf_src, size_t len)
+{
+ skb_put_data(skb, buf_src, len);
+}
+
+static inline void qtnf_cmd_skb_put_tlv_arr(struct sk_buff *skb,
+ u16 tlv_id, const u8 arr[],
+ size_t arr_len)
+{
+ struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr) + arr_len);
+
+ hdr->type = cpu_to_le16(tlv_id);
+ hdr->len = cpu_to_le16(arr_len);
+ memcpy(hdr->val, arr, arr_len);
+}
+
+static inline void qtnf_cmd_skb_put_tlv_u8(struct sk_buff *skb, u16 tlv_id,
+ u8 value)
+{
+ struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr) + sizeof(value));
+
+ hdr->type = cpu_to_le16(tlv_id);
+ hdr->len = cpu_to_le16(sizeof(value));
+ *hdr->val = value;
+}
+
+static inline void qtnf_cmd_skb_put_tlv_u16(struct sk_buff *skb,
+ u16 tlv_id, u16 value)
+{
+ struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr) + sizeof(value));
+ __le16 tmp = cpu_to_le16(value);
+
+ hdr->type = cpu_to_le16(tlv_id);
+ hdr->len = cpu_to_le16(sizeof(value));
+ memcpy(hdr->val, &tmp, sizeof(tmp));
+}
+
+u16 qlink_iface_type_mask_to_nl(u16 qlink_mask);
+u8 qlink_chan_width_mask_to_nl(u16 qlink_mask);
+
+#endif /* _QTN_FMAC_QLINK_UTIL_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h b/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h
new file mode 100644
index 0000000..c4ad40d
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _QTN_HW_IDS_H_
+#define _QTN_HW_IDS_H_
+
+#include <linux/pci_ids.h>
+
+#define PCIE_VENDOR_ID_QUANTENNA (0x1bb5)
+
+/* PCIE Device IDs */
+
+#define PCIE_DEVICE_ID_QTN_PEARL (0x0008)
+
+/* FW names */
+
+#define QTN_PCI_PEARL_FW_NAME "qtn/fmac_qsr10g.img"
+
+#endif /* _QTN_HW_IDS_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c
new file mode 100644
index 0000000..aa106dd
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+#include "shm_ipc.h"
+
+#undef pr_fmt
+#define pr_fmt(fmt) "qtnfmac shm_ipc: %s: " fmt, __func__
+
+static bool qtnf_shm_ipc_has_new_data(struct qtnf_shm_ipc *ipc)
+{
+ const u32 flags = readl(&ipc->shm_region->headroom.hdr.flags);
+
+ return (flags & QTNF_SHM_IPC_NEW_DATA);
+}
+
+static void qtnf_shm_handle_new_data(struct qtnf_shm_ipc *ipc)
+{
+ size_t size;
+ bool rx_buff_ok = true;
+ struct qtnf_shm_ipc_region_header __iomem *shm_reg_hdr;
+
+ shm_reg_hdr = &ipc->shm_region->headroom.hdr;
+
+ size = readw(&shm_reg_hdr->data_len);
+
+ if (unlikely(size == 0 || size > QTN_IPC_MAX_DATA_SZ)) {
+ pr_err("wrong rx packet size: %zu\n", size);
+ rx_buff_ok = false;
+ } else {
+ memcpy_fromio(ipc->rx_data, ipc->shm_region->data, size);
+ }
+
+ writel(QTNF_SHM_IPC_ACK, &shm_reg_hdr->flags);
+ readl(&shm_reg_hdr->flags); /* flush PCIe write */
+
+ ipc->interrupt.fn(ipc->interrupt.arg);
+
+ if (likely(rx_buff_ok)) {
+ ipc->rx_packet_count++;
+ ipc->rx_callback.fn(ipc->rx_callback.arg, ipc->rx_data, size);
+ }
+}
+
+static void qtnf_shm_ipc_irq_work(struct work_struct *work)
+{
+ struct qtnf_shm_ipc *ipc = container_of(work, struct qtnf_shm_ipc,
+ irq_work);
+
+ while (qtnf_shm_ipc_has_new_data(ipc))
+ qtnf_shm_handle_new_data(ipc);
+}
+
+static void qtnf_shm_ipc_irq_inbound_handler(struct qtnf_shm_ipc *ipc)
+{
+ u32 flags;
+
+ flags = readl(&ipc->shm_region->headroom.hdr.flags);
+
+ if (flags & QTNF_SHM_IPC_NEW_DATA)
+ queue_work(ipc->workqueue, &ipc->irq_work);
+}
+
+static void qtnf_shm_ipc_irq_outbound_handler(struct qtnf_shm_ipc *ipc)
+{
+ u32 flags;
+
+ if (!READ_ONCE(ipc->waiting_for_ack))
+ return;
+
+ flags = readl(&ipc->shm_region->headroom.hdr.flags);
+
+ if (flags & QTNF_SHM_IPC_ACK) {
+ WRITE_ONCE(ipc->waiting_for_ack, 0);
+ complete(&ipc->tx_completion);
+ }
+}
+
+int qtnf_shm_ipc_init(struct qtnf_shm_ipc *ipc,
+ enum qtnf_shm_ipc_direction direction,
+ struct qtnf_shm_ipc_region __iomem *shm_region,
+ struct workqueue_struct *workqueue,
+ const struct qtnf_shm_ipc_int *interrupt,
+ const struct qtnf_shm_ipc_rx_callback *rx_callback)
+{
+ BUILD_BUG_ON(offsetof(struct qtnf_shm_ipc_region, data) !=
+ QTN_IPC_REG_HDR_SZ);
+ BUILD_BUG_ON(sizeof(struct qtnf_shm_ipc_region) > QTN_IPC_REG_SZ);
+
+ ipc->shm_region = shm_region;
+ ipc->direction = direction;
+ ipc->interrupt = *interrupt;
+ ipc->rx_callback = *rx_callback;
+ ipc->tx_packet_count = 0;
+ ipc->rx_packet_count = 0;
+ ipc->workqueue = workqueue;
+ ipc->waiting_for_ack = 0;
+ ipc->tx_timeout_count = 0;
+
+ switch (direction) {
+ case QTNF_SHM_IPC_OUTBOUND:
+ ipc->irq_handler = qtnf_shm_ipc_irq_outbound_handler;
+ break;
+ case QTNF_SHM_IPC_INBOUND:
+ ipc->irq_handler = qtnf_shm_ipc_irq_inbound_handler;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ INIT_WORK(&ipc->irq_work, qtnf_shm_ipc_irq_work);
+ init_completion(&ipc->tx_completion);
+
+ return 0;
+}
+
+void qtnf_shm_ipc_free(struct qtnf_shm_ipc *ipc)
+{
+ complete_all(&ipc->tx_completion);
+}
+
+int qtnf_shm_ipc_send(struct qtnf_shm_ipc *ipc, const u8 *buf, size_t size)
+{
+ int ret = 0;
+ struct qtnf_shm_ipc_region_header __iomem *shm_reg_hdr;
+
+ shm_reg_hdr = &ipc->shm_region->headroom.hdr;
+
+ if (unlikely(size > QTN_IPC_MAX_DATA_SZ))
+ return -E2BIG;
+
+ ipc->tx_packet_count++;
+
+ writew(size, &shm_reg_hdr->data_len);
+ memcpy_toio(ipc->shm_region->data, buf, size);
+
+ /* sync previous writes before proceeding */
+ dma_wmb();
+
+ WRITE_ONCE(ipc->waiting_for_ack, 1);
+
+ /* sync previous memory write before announcing new data ready */
+ wmb();
+
+ writel(QTNF_SHM_IPC_NEW_DATA, &shm_reg_hdr->flags);
+ readl(&shm_reg_hdr->flags); /* flush PCIe write */
+
+ ipc->interrupt.fn(ipc->interrupt.arg);
+
+ if (!wait_for_completion_timeout(&ipc->tx_completion,
+ QTN_SHM_IPC_ACK_TIMEOUT)) {
+ ret = -ETIMEDOUT;
+ ipc->tx_timeout_count++;
+ pr_err("TX ACK timeout\n");
+ }
+
+ /* now we're not waiting for ACK even in case of timeout */
+ WRITE_ONCE(ipc->waiting_for_ack, 0);
+
+ return ret;
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h
new file mode 100644
index 0000000..453dd64
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _QTN_FMAC_SHM_IPC_H_
+#define _QTN_FMAC_SHM_IPC_H_
+
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
+#include "shm_ipc_defs.h"
+
+#define QTN_SHM_IPC_ACK_TIMEOUT (2 * HZ)
+
+struct qtnf_shm_ipc_int {
+ void (*fn)(void *arg);
+ void *arg;
+};
+
+struct qtnf_shm_ipc_rx_callback {
+ void (*fn)(void *arg, const u8 *buf, size_t len);
+ void *arg;
+};
+
+enum qtnf_shm_ipc_direction {
+ QTNF_SHM_IPC_OUTBOUND = BIT(0),
+ QTNF_SHM_IPC_INBOUND = BIT(1),
+};
+
+struct qtnf_shm_ipc {
+ struct qtnf_shm_ipc_region __iomem *shm_region;
+ enum qtnf_shm_ipc_direction direction;
+ size_t tx_packet_count;
+ size_t rx_packet_count;
+
+ size_t tx_timeout_count;
+
+ u8 waiting_for_ack;
+
+ u8 rx_data[QTN_IPC_MAX_DATA_SZ] __aligned(sizeof(u32));
+
+ struct qtnf_shm_ipc_int interrupt;
+ struct qtnf_shm_ipc_rx_callback rx_callback;
+
+ void (*irq_handler)(struct qtnf_shm_ipc *ipc);
+
+ struct workqueue_struct *workqueue;
+ struct work_struct irq_work;
+ struct completion tx_completion;
+};
+
+int qtnf_shm_ipc_init(struct qtnf_shm_ipc *ipc,
+ enum qtnf_shm_ipc_direction direction,
+ struct qtnf_shm_ipc_region __iomem *shm_region,
+ struct workqueue_struct *workqueue,
+ const struct qtnf_shm_ipc_int *interrupt,
+ const struct qtnf_shm_ipc_rx_callback *rx_callback);
+void qtnf_shm_ipc_free(struct qtnf_shm_ipc *ipc);
+int qtnf_shm_ipc_send(struct qtnf_shm_ipc *ipc, const u8 *buf, size_t size);
+
+static inline void qtnf_shm_ipc_irq_handler(struct qtnf_shm_ipc *ipc)
+{
+ ipc->irq_handler(ipc);
+}
+
+#endif /* _QTN_FMAC_SHM_IPC_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h
new file mode 100644
index 0000000..95a5f89
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _QTN_FMAC_SHM_IPC_DEFS_H_
+#define _QTN_FMAC_SHM_IPC_DEFS_H_
+
+#include <linux/types.h>
+
+#define QTN_IPC_REG_HDR_SZ (32)
+#define QTN_IPC_REG_SZ (4096)
+#define QTN_IPC_MAX_DATA_SZ (QTN_IPC_REG_SZ - QTN_IPC_REG_HDR_SZ)
+
+enum qtnf_shm_ipc_region_flags {
+ QTNF_SHM_IPC_NEW_DATA = BIT(0),
+ QTNF_SHM_IPC_ACK = BIT(1),
+};
+
+struct qtnf_shm_ipc_region_header {
+ __le32 flags;
+ __le16 data_len;
+} __packed;
+
+union qtnf_shm_ipc_region_headroom {
+ struct qtnf_shm_ipc_region_header hdr;
+ u8 headroom[QTN_IPC_REG_HDR_SZ];
+} __packed;
+
+struct qtnf_shm_ipc_region {
+ union qtnf_shm_ipc_region_headroom headroom;
+ u8 data[QTN_IPC_MAX_DATA_SZ];
+} __packed;
+
+#endif /* _QTN_FMAC_SHM_IPC_DEFS_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/trans.c b/drivers/net/wireless/quantenna/qtnfmac/trans.c
new file mode 100644
index 0000000..ccddfeb
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/trans.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+
+#include "core.h"
+#include "commands.h"
+#include "event.h"
+#include "bus.h"
+
+#define QTNF_DEF_SYNC_CMD_TIMEOUT (5 * HZ)
+
+int qtnf_trans_send_cmd_with_resp(struct qtnf_bus *bus, struct sk_buff *cmd_skb,
+ struct sk_buff **response_skb)
+{
+ struct qtnf_cmd_ctl_node *ctl_node = &bus->trans.curr_cmd;
+ struct qlink_cmd *cmd = (void *)cmd_skb->data;
+ int ret = 0;
+ long status;
+ bool resp_not_handled = true;
+ struct sk_buff *resp_skb = NULL;
+
+ if (unlikely(!response_skb))
+ return -EFAULT;
+
+ spin_lock(&ctl_node->resp_lock);
+ ctl_node->seq_num++;
+ cmd->seq_num = cpu_to_le16(ctl_node->seq_num);
+ WARN(ctl_node->resp_skb, "qtnfmac: response skb not empty\n");
+ ctl_node->waiting_for_resp = true;
+ spin_unlock(&ctl_node->resp_lock);
+
+ ret = qtnf_bus_control_tx(bus, cmd_skb);
+ dev_kfree_skb(cmd_skb);
+
+ if (unlikely(ret))
+ goto out;
+
+ status = wait_for_completion_interruptible_timeout(
+ &ctl_node->cmd_resp_completion,
+ QTNF_DEF_SYNC_CMD_TIMEOUT);
+
+ spin_lock(&ctl_node->resp_lock);
+ resp_not_handled = ctl_node->waiting_for_resp;
+ resp_skb = ctl_node->resp_skb;
+ ctl_node->resp_skb = NULL;
+ ctl_node->waiting_for_resp = false;
+ spin_unlock(&ctl_node->resp_lock);
+
+ if (unlikely(status <= 0)) {
+ if (status == 0) {
+ ret = -ETIMEDOUT;
+ pr_err("response timeout\n");
+ } else {
+ ret = -EINTR;
+ pr_debug("interrupted\n");
+ }
+ }
+
+ if (unlikely(!resp_skb || resp_not_handled)) {
+ if (!ret)
+ ret = -EFAULT;
+
+ goto out;
+ }
+
+ ret = 0;
+ *response_skb = resp_skb;
+
+out:
+ if (unlikely(resp_skb && resp_not_handled))
+ dev_kfree_skb(resp_skb);
+
+ return ret;
+}
+
+static void qtnf_trans_signal_cmdresp(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+ struct qtnf_cmd_ctl_node *ctl_node = &bus->trans.curr_cmd;
+ const struct qlink_resp *resp = (const struct qlink_resp *)skb->data;
+ const u16 recvd_seq_num = le16_to_cpu(resp->seq_num);
+
+ spin_lock(&ctl_node->resp_lock);
+
+ if (unlikely(!ctl_node->waiting_for_resp)) {
+ pr_err("unexpected response\n");
+ goto out_err;
+ }
+
+ if (unlikely(recvd_seq_num != ctl_node->seq_num)) {
+ pr_err("seq num mismatch\n");
+ goto out_err;
+ }
+
+ ctl_node->resp_skb = skb;
+ ctl_node->waiting_for_resp = false;
+
+ spin_unlock(&ctl_node->resp_lock);
+
+ complete(&ctl_node->cmd_resp_completion);
+ return;
+
+out_err:
+ spin_unlock(&ctl_node->resp_lock);
+ dev_kfree_skb(skb);
+}
+
+static int qtnf_trans_event_enqueue(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+ struct qtnf_qlink_transport *trans = &bus->trans;
+
+ if (likely(skb_queue_len(&trans->event_queue) <
+ trans->event_queue_max_len)) {
+ skb_queue_tail(&trans->event_queue, skb);
+ queue_work(bus->workqueue, &bus->event_work);
+ } else {
+ pr_warn("event dropped due to queue overflow\n");
+ dev_kfree_skb(skb);
+ return -1;
+ }
+
+ return 0;
+}
+
+void qtnf_trans_init(struct qtnf_bus *bus)
+{
+ struct qtnf_qlink_transport *trans = &bus->trans;
+
+ init_completion(&trans->curr_cmd.cmd_resp_completion);
+ spin_lock_init(&trans->curr_cmd.resp_lock);
+
+ spin_lock(&trans->curr_cmd.resp_lock);
+ trans->curr_cmd.seq_num = 0;
+ trans->curr_cmd.waiting_for_resp = false;
+ trans->curr_cmd.resp_skb = NULL;
+ spin_unlock(&trans->curr_cmd.resp_lock);
+
+ /* Init event handling related fields */
+ skb_queue_head_init(&trans->event_queue);
+ trans->event_queue_max_len = QTNF_MAX_EVENT_QUEUE_LEN;
+}
+
+static void qtnf_trans_free_events(struct qtnf_bus *bus)
+{
+ struct sk_buff_head *event_queue = &bus->trans.event_queue;
+ struct sk_buff *current_event_skb = skb_dequeue(event_queue);
+
+ while (current_event_skb) {
+ dev_kfree_skb_any(current_event_skb);
+ current_event_skb = skb_dequeue(event_queue);
+ }
+}
+
+void qtnf_trans_free(struct qtnf_bus *bus)
+{
+ if (!bus) {
+ pr_err("invalid bus pointer\n");
+ return;
+ }
+
+ qtnf_trans_free_events(bus);
+}
+
+int qtnf_trans_handle_rx_ctl_packet(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+ const struct qlink_msg_header *header = (void *)skb->data;
+ int ret = -1;
+
+ if (unlikely(skb->len < sizeof(*header))) {
+ pr_warn("packet is too small: %u\n", skb->len);
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ if (unlikely(skb->len != le16_to_cpu(header->len))) {
+ pr_warn("cmd reply length mismatch: %u != %u\n",
+ skb->len, le16_to_cpu(header->len));
+ dev_kfree_skb(skb);
+ return -EFAULT;
+ }
+
+ switch (le16_to_cpu(header->type)) {
+ case QLINK_MSG_TYPE_CMDRSP:
+ if (unlikely(skb->len < sizeof(struct qlink_cmd))) {
+ pr_warn("cmd reply too short: %u\n", skb->len);
+ dev_kfree_skb(skb);
+ break;
+ }
+
+ qtnf_trans_signal_cmdresp(bus, skb);
+ break;
+ case QLINK_MSG_TYPE_EVENT:
+ if (unlikely(skb->len < sizeof(struct qlink_event))) {
+ pr_warn("event too short: %u\n", skb->len);
+ dev_kfree_skb(skb);
+ break;
+ }
+
+ ret = qtnf_trans_event_enqueue(bus, skb);
+ break;
+ default:
+ pr_warn("unknown packet type: %x\n", le16_to_cpu(header->type));
+ dev_kfree_skb(skb);
+ break;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(qtnf_trans_handle_rx_ctl_packet);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/trans.h b/drivers/net/wireless/quantenna/qtnfmac/trans.h
new file mode 100644
index 0000000..9a473e0
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/trans.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _QTN_FMAC_TRANS_H_
+#define _QTN_FMAC_TRANS_H_
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/mutex.h>
+
+#include "qlink.h"
+
+#define QTNF_CMD_FLAG_RESP_REQ BIT(0)
+
+#define QTNF_MAX_CMD_BUF_SIZE 2048
+#define QTNF_DEF_CMD_HROOM 4
+
+struct qtnf_bus;
+
+struct qtnf_cmd_ctl_node {
+ struct completion cmd_resp_completion;
+ struct sk_buff *resp_skb;
+ u16 seq_num;
+ bool waiting_for_resp;
+ spinlock_t resp_lock; /* lock for resp_skb & waiting_for_resp changes */
+};
+
+struct qtnf_qlink_transport {
+ struct qtnf_cmd_ctl_node curr_cmd;
+ struct sk_buff_head event_queue;
+ size_t event_queue_max_len;
+};
+
+void qtnf_trans_init(struct qtnf_bus *bus);
+void qtnf_trans_free(struct qtnf_bus *bus);
+
+int qtnf_trans_send_next_cmd(struct qtnf_bus *bus);
+int qtnf_trans_handle_rx_ctl_packet(struct qtnf_bus *bus, struct sk_buff *skb);
+int qtnf_trans_send_cmd_with_resp(struct qtnf_bus *bus,
+ struct sk_buff *cmd_skb,
+ struct sk_buff **response_skb);
+
+#endif /* _QTN_FMAC_TRANS_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/util.c b/drivers/net/wireless/quantenna/qtnfmac/util.c
new file mode 100644
index 0000000..ed38e87
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/util.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "util.h"
+
+void qtnf_sta_list_init(struct qtnf_sta_list *list)
+{
+ if (unlikely(!list))
+ return;
+
+ INIT_LIST_HEAD(&list->head);
+ atomic_set(&list->size, 0);
+}
+
+struct qtnf_sta_node *qtnf_sta_list_lookup(struct qtnf_sta_list *list,
+ const u8 *mac)
+{
+ struct qtnf_sta_node *node;
+
+ if (unlikely(!mac))
+ return NULL;
+
+ list_for_each_entry(node, &list->head, list) {
+ if (ether_addr_equal(node->mac_addr, mac))
+ return node;
+ }
+
+ return NULL;
+}
+
+struct qtnf_sta_node *qtnf_sta_list_lookup_index(struct qtnf_sta_list *list,
+ size_t index)
+{
+ struct qtnf_sta_node *node;
+
+ if (qtnf_sta_list_size(list) <= index)
+ return NULL;
+
+ list_for_each_entry(node, &list->head, list) {
+ if (index-- == 0)
+ return node;
+ }
+
+ return NULL;
+}
+
+struct qtnf_sta_node *qtnf_sta_list_add(struct qtnf_sta_list *list,
+ const u8 *mac)
+{
+ struct qtnf_sta_node *node;
+
+ if (unlikely(!mac))
+ return NULL;
+
+ node = qtnf_sta_list_lookup(list, mac);
+
+ if (node)
+ goto done;
+
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
+ if (unlikely(!node))
+ goto done;
+
+ ether_addr_copy(node->mac_addr, mac);
+ list_add_tail(&node->list, &list->head);
+ atomic_inc(&list->size);
+
+done:
+ return node;
+}
+
+bool qtnf_sta_list_del(struct qtnf_sta_list *list, const u8 *mac)
+{
+ struct qtnf_sta_node *node;
+ bool ret = false;
+
+ node = qtnf_sta_list_lookup(list, mac);
+
+ if (node) {
+ list_del(&node->list);
+ atomic_dec(&list->size);
+ kfree(node);
+ ret = true;
+ }
+
+ return ret;
+}
+
+void qtnf_sta_list_free(struct qtnf_sta_list *list)
+{
+ struct qtnf_sta_node *node, *tmp;
+
+ atomic_set(&list->size, 0);
+
+ list_for_each_entry_safe(node, tmp, &list->head, list) {
+ list_del(&node->list);
+ kfree(node);
+ }
+
+ INIT_LIST_HEAD(&list->head);
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/util.h b/drivers/net/wireless/quantenna/qtnfmac/util.h
new file mode 100644
index 0000000..0359eae
--- /dev/null
+++ b/drivers/net/wireless/quantenna/qtnfmac/util.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015 Quantenna Communications
+ *
+ * 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 QTNFMAC_UTIL_H
+#define QTNFMAC_UTIL_H
+
+#include <linux/kernel.h>
+#include "core.h"
+
+void qtnf_sta_list_init(struct qtnf_sta_list *list);
+
+struct qtnf_sta_node *qtnf_sta_list_lookup(struct qtnf_sta_list *list,
+ const u8 *mac);
+struct qtnf_sta_node *qtnf_sta_list_lookup_index(struct qtnf_sta_list *list,
+ size_t index);
+struct qtnf_sta_node *qtnf_sta_list_add(struct qtnf_sta_list *list,
+ const u8 *mac);
+bool qtnf_sta_list_del(struct qtnf_sta_list *list, const u8 *mac);
+
+void qtnf_sta_list_free(struct qtnf_sta_list *list);
+
+static inline size_t qtnf_sta_list_size(const struct qtnf_sta_list *list)
+{
+ return atomic_read(&list->size);
+}
+
+static inline bool qtnf_sta_list_empty(const struct qtnf_sta_list *list)
+{
+ return list_empty(&list->head);
+}
+
+#endif /* QTNFMAC_UTIL_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
index 1987443..0bc8b02 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
@@ -77,10 +77,11 @@ static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,
mutex_unlock(&rt2x00dev->csr_mutex);
}
-static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u8 *value)
+static u8 rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word)
{
u32 reg;
+ u8 value;
mutex_lock(&rt2x00dev->csr_mutex);
@@ -103,9 +104,11 @@ static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
WAIT_FOR_BBP(rt2x00dev, &reg);
}
- *value = rt2x00_get_field32(reg, BBPCSR_VALUE);
+ value = rt2x00_get_field32(reg, BBPCSR_VALUE);
mutex_unlock(&rt2x00dev->csr_mutex);
+
+ return value;
}
static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -138,7 +141,7 @@ static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR21);
eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN);
eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT);
@@ -202,7 +205,7 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, GPIOCSR);
return rt2x00_get_field32(reg, GPIOCSR_VAL0);
}
@@ -215,7 +218,7 @@ static void rt2400pci_brightness_set(struct led_classdev *led_cdev,
unsigned int enabled = brightness != LED_OFF;
u32 reg;
- rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
+ reg = rt2x00mmio_register_read(led->rt2x00dev, LEDCSR);
if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
@@ -233,7 +236,7 @@ static int rt2400pci_blink_set(struct led_classdev *led_cdev,
container_of(led_cdev, struct rt2x00_led, led_dev);
u32 reg;
- rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
+ reg = rt2x00mmio_register_read(led->rt2x00dev, LEDCSR);
rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
@@ -266,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.
*/
- rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RXCSR0);
rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
@@ -295,14 +298,14 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
* Enable beacon config
*/
bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
- rt2x00mmio_register_read(rt2x00dev, BCNCSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, BCNCSR1);
rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg);
/*
* Enable synchronisation.
*/
- rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
}
@@ -330,35 +333,35 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
preamble_mask = erp->short_preamble << 3;
- rt2x00mmio_register_read(rt2x00dev, TXCSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR1);
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);
rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg);
- rt2x00mmio_register_read(rt2x00dev, ARCSR2, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, ARCSR2);
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));
rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg);
- rt2x00mmio_register_read(rt2x00dev, ARCSR3, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, ARCSR3);
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));
rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg);
- rt2x00mmio_register_read(rt2x00dev, ARCSR4, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, ARCSR4);
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));
rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg);
- rt2x00mmio_register_read(rt2x00dev, ARCSR5, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, ARCSR5);
rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
@@ -370,23 +373,23 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
if (changed & BSS_CHANGED_ERP_SLOT) {
- rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR11);
rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
- rt2x00mmio_register_read(rt2x00dev, CSR18, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR18);
rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
rt2x00mmio_register_write(rt2x00dev, CSR18, reg);
- rt2x00mmio_register_read(rt2x00dev, CSR19, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR19);
rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
rt2x00mmio_register_write(rt2x00dev, CSR19, reg);
}
if (changed & BSS_CHANGED_BEACON_INT) {
- rt2x00mmio_register_read(rt2x00dev, CSR12, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR12);
rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
erp->beacon_int * 16);
rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
@@ -408,8 +411,8 @@ static void rt2400pci_config_ant(struct rt2x00_dev *rt2x00dev,
BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
ant->tx == ANTENNA_SW_DIVERSITY);
- rt2400pci_bbp_read(rt2x00dev, 4, &r4);
- rt2400pci_bbp_read(rt2x00dev, 1, &r1);
+ r4 = rt2400pci_bbp_read(rt2x00dev, 4);
+ r1 = rt2400pci_bbp_read(rt2x00dev, 1);
/*
* Configure the TX antenna.
@@ -495,7 +498,7 @@ static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
/*
* Clear false CRC during channel switch.
*/
- rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1);
+ rf->rf1 = rt2x00mmio_register_read(rt2x00dev, CNT0);
}
static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower)
@@ -508,7 +511,7 @@ static void rt2400pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR11);
rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
libconf->conf->long_frame_max_tx_count);
rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
@@ -525,7 +528,7 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
u32 reg;
if (state == STATE_SLEEP) {
- rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR20);
rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
(rt2x00dev->beacon_int - 20) * 16);
rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
@@ -538,7 +541,7 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
} else {
- rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR20);
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
}
@@ -566,7 +569,7 @@ static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR11);
rt2x00_set_field32(&reg, CSR11_CWMIN, cw_min);
rt2x00_set_field32(&reg, CSR11_CWMAX, cw_max);
rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
@@ -584,13 +587,13 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
/*
* Update FCS error count from register.
*/
- rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CNT0);
qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
- rt2400pci_bbp_read(rt2x00dev, 39, &bbp);
+ bbp = rt2400pci_bbp_read(rt2x00dev, 39);
qual->false_cca = bbp;
}
@@ -639,12 +642,12 @@ static void rt2400pci_start_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RXCSR0);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
rt2x00_set_field32(&reg, CSR14_TBCN, 1);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
@@ -662,17 +665,17 @@ static void rt2400pci_kick_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_AC_VO:
- rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_AC_VI:
- rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_ATIM:
- rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
@@ -690,17 +693,17 @@ static void rt2400pci_stop_queue(struct data_queue *queue)
case QID_AC_VO:
case QID_AC_VI:
case QID_ATIM:
- rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_RX:
- rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RXCSR0);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(&reg, CSR14_TBCN, 0);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
@@ -725,11 +728,11 @@ static bool rt2400pci_get_entry_state(struct queue_entry *entry)
u32 word;
if (entry->queue->qid == QID_RX) {
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
} else {
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
rt2x00_get_field32(word, TXD_W0_VALID));
@@ -743,19 +746,19 @@ static void rt2400pci_clear_entry(struct queue_entry *entry)
u32 word;
if (entry->queue->qid == QID_RX) {
- rt2x00_desc_read(entry_priv->desc, 2, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 2);
rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->skb->len);
rt2x00_desc_write(entry_priv->desc, 2, word);
- rt2x00_desc_read(entry_priv->desc, 1, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 1);
rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
rt2x00_desc_write(entry_priv->desc, 1, word);
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
rt2x00_desc_write(entry_priv->desc, 0, word);
} else {
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
rt2x00_set_field32(&word, TXD_W0_VALID, 0);
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
rt2x00_desc_write(entry_priv->desc, 0, word);
@@ -770,7 +773,7 @@ static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
/*
* Initialize registers.
*/
- rt2x00mmio_register_read(rt2x00dev, TXCSR2, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR2);
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);
@@ -778,36 +781,36 @@ static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg);
entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
- rt2x00mmio_register_read(rt2x00dev, TXCSR3, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR3);
rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
entry_priv->desc_dma);
rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg);
entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
- rt2x00mmio_register_read(rt2x00dev, TXCSR5, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR5);
rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
entry_priv->desc_dma);
rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg);
entry_priv = rt2x00dev->atim->entries[0].priv_data;
- rt2x00mmio_register_read(rt2x00dev, TXCSR4, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR4);
rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
entry_priv->desc_dma);
rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg);
entry_priv = rt2x00dev->bcn->entries[0].priv_data;
- rt2x00mmio_register_read(rt2x00dev, TXCSR6, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR6);
rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
entry_priv->desc_dma);
rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg);
- rt2x00mmio_register_read(rt2x00dev, RXCSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RXCSR1);
rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg);
entry_priv = rt2x00dev->rx->entries[0].priv_data;
- rt2x00mmio_register_read(rt2x00dev, RXCSR2, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RXCSR2);
rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
entry_priv->desc_dma);
rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg);
@@ -824,18 +827,18 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00023f20);
rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002);
- rt2x00mmio_register_read(rt2x00dev, TIMECSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TIMECSR);
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);
rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg);
- rt2x00mmio_register_read(rt2x00dev, CSR9, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR9);
rt2x00_set_field32(&reg, CSR9_MAX_FRAME_UNIT,
(rt2x00dev->rx->data_size / 128));
rt2x00mmio_register_write(rt2x00dev, CSR9, reg);
- rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
rt2x00_set_field32(&reg, CSR14_TBCN, 0);
@@ -848,14 +851,14 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00mmio_register_write(rt2x00dev, CNT3, 0x3f080000);
- rt2x00mmio_register_read(rt2x00dev, ARCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, ARCSR0);
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);
rt2x00mmio_register_write(rt2x00dev, ARCSR0, reg);
- rt2x00mmio_register_read(rt2x00dev, RXCSR3, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RXCSR3);
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 */
@@ -872,24 +875,24 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00217223);
rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518);
- rt2x00mmio_register_read(rt2x00dev, MACCSR2, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MACCSR2);
rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg);
- rt2x00mmio_register_read(rt2x00dev, RALINKCSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RALINKCSR);
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);
rt2x00mmio_register_write(rt2x00dev, RALINKCSR, reg);
- rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR1);
rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 1);
rt2x00_set_field32(&reg, CSR1_BBP_RESET, 0);
rt2x00_set_field32(&reg, CSR1_HOST_READY, 0);
rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
- rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR1);
rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 0);
rt2x00_set_field32(&reg, CSR1_HOST_READY, 1);
rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
@@ -899,8 +902,8 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
*/
- rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
- rt2x00mmio_register_read(rt2x00dev, CNT4, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CNT0);
+ reg = rt2x00mmio_register_read(rt2x00dev, CNT4);
return 0;
}
@@ -911,7 +914,7 @@ static int rt2400pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
u8 value;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2400pci_bbp_read(rt2x00dev, 0, &value);
+ value = rt2400pci_bbp_read(rt2x00dev, 0);
if ((value != 0xff) && (value != 0x00))
return 0;
udelay(REGISTER_BUSY_DELAY);
@@ -947,7 +950,7 @@ static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2400pci_bbp_write(rt2x00dev, 31, 0x00);
for (i = 0; i < EEPROM_BBP_SIZE; i++) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i);
if (eeprom != 0xffff && eeprom != 0x0000) {
reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
@@ -974,7 +977,7 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
* should clear the register to assure a clean state.
*/
if (state == STATE_RADIO_IRQ_ON) {
- rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR7);
rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
}
@@ -984,7 +987,7 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
- rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, mask);
@@ -1037,7 +1040,7 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
put_to_sleep = (state != STATE_AWAKE);
- rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, PWRCSR1);
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);
@@ -1050,7 +1053,7 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
* device has entered the correct state.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg2);
+ reg2 = rt2x00mmio_register_read(rt2x00dev, PWRCSR1);
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)
@@ -1110,16 +1113,16 @@ static void rt2400pci_write_tx_desc(struct queue_entry *entry,
/*
* Start writing the descriptor words.
*/
- rt2x00_desc_read(txd, 1, &word);
+ word = rt2x00_desc_read(txd, 1);
rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
rt2x00_desc_write(txd, 1, word);
- rt2x00_desc_read(txd, 2, &word);
+ word = rt2x00_desc_read(txd, 2);
rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, txdesc->length);
rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, txdesc->length);
rt2x00_desc_write(txd, 2, word);
- rt2x00_desc_read(txd, 3, &word);
+ word = rt2x00_desc_read(txd, 3);
rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal);
rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5);
rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1);
@@ -1128,7 +1131,7 @@ static void rt2400pci_write_tx_desc(struct queue_entry *entry,
rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1);
rt2x00_desc_write(txd, 3, word);
- rt2x00_desc_read(txd, 4, &word);
+ word = rt2x00_desc_read(txd, 4);
rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW,
txdesc->u.plcp.length_low);
rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8);
@@ -1144,7 +1147,7 @@ static void rt2400pci_write_tx_desc(struct queue_entry *entry,
* the device, whereby the device may take hold of the TXD before we
* finished updating it.
*/
- rt2x00_desc_read(txd, 0, &word);
+ word = rt2x00_desc_read(txd, 0);
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
rt2x00_set_field32(&word, TXD_W0_VALID, 1);
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
@@ -1180,7 +1183,7 @@ 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.
*/
- rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
@@ -1225,10 +1228,10 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry,
u32 rx_low;
u32 rx_high;
- rt2x00_desc_read(entry_priv->desc, 0, &word0);
- rt2x00_desc_read(entry_priv->desc, 2, &word2);
- rt2x00_desc_read(entry_priv->desc, 3, &word3);
- rt2x00_desc_read(entry_priv->desc, 4, &word4);
+ word0 = rt2x00_desc_read(entry_priv->desc, 0);
+ word2 = rt2x00_desc_read(entry_priv->desc, 2);
+ word3 = rt2x00_desc_read(entry_priv->desc, 3);
+ word4 = rt2x00_desc_read(entry_priv->desc, 4);
if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
@@ -1282,7 +1285,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
while (!rt2x00queue_empty(queue)) {
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
entry_priv = entry->priv_data;
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
!rt2x00_get_field32(word, TXD_W0_VALID))
@@ -1320,7 +1323,7 @@ static inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
rt2x00_set_field32(&reg, irq_field, 0);
rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
@@ -1345,7 +1348,7 @@ static void rt2400pci_txstatus_tasklet(unsigned long data)
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
@@ -1381,7 +1384,7 @@ 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.
*/
- rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR7);
rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
if (!reg)
@@ -1419,7 +1422,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
*/
spin_lock(&rt2x00dev->irqmask_lock);
- rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
reg |= mask;
rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
@@ -1440,7 +1443,7 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
u16 word;
u8 *mac;
- rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR21);
eeprom.data = rt2x00dev;
eeprom.register_read = rt2400pci_eepromregister_read;
@@ -1461,7 +1464,7 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
rt2x00lib_set_mac_address(rt2x00dev, mac);
- rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
if (word == 0xffff) {
rt2x00_err(rt2x00dev, "Invalid EEPROM data detected\n");
return -EINVAL;
@@ -1479,13 +1482,13 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Read EEPROM word for configuration.
*/
- rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
/*
* Identify RF chipset.
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
- rt2x00mmio_register_read(rt2x00dev, CSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR0);
rt2x00_set_chip(rt2x00dev, RT2460, value,
rt2x00_get_field32(reg, CSR0_REVISION));
@@ -1630,7 +1633,7 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
- rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, GPIOCSR);
rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg);
@@ -1692,9 +1695,9 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw,
u64 tsf;
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, CSR17, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR17);
tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32;
- rt2x00mmio_register_read(rt2x00dev, CSR16, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR16);
tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER);
return tsf;
@@ -1705,7 +1708,7 @@ static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)
struct rt2x00_dev *rt2x00dev = hw->priv;
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, CSR15, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR15);
return rt2x00_get_field32(reg, CSR15_BEACON_SENT);
}
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
index 791434d..1ff5434 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
@@ -77,10 +77,11 @@ static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev,
mutex_unlock(&rt2x00dev->csr_mutex);
}
-static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u8 *value)
+static u8 rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word)
{
u32 reg;
+ u8 value;
mutex_lock(&rt2x00dev->csr_mutex);
@@ -103,9 +104,11 @@ static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
WAIT_FOR_BBP(rt2x00dev, &reg);
}
- *value = rt2x00_get_field32(reg, BBPCSR_VALUE);
+ value = rt2x00_get_field32(reg, BBPCSR_VALUE);
mutex_unlock(&rt2x00dev->csr_mutex);
+
+ return value;
}
static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -138,7 +141,7 @@ static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR21);
eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN);
eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT);
@@ -202,7 +205,7 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, GPIOCSR);
return rt2x00_get_field32(reg, GPIOCSR_VAL0);
}
@@ -215,7 +218,7 @@ static void rt2500pci_brightness_set(struct led_classdev *led_cdev,
unsigned int enabled = brightness != LED_OFF;
u32 reg;
- rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
+ reg = rt2x00mmio_register_read(led->rt2x00dev, LEDCSR);
if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
@@ -233,7 +236,7 @@ static int rt2500pci_blink_set(struct led_classdev *led_cdev,
container_of(led_cdev, struct rt2x00_led, led_dev);
u32 reg;
- rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
+ reg = rt2x00mmio_register_read(led->rt2x00dev, LEDCSR);
rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
@@ -267,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.
*/
- rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RXCSR0);
rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
@@ -300,7 +303,7 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
* Enable beacon config
*/
bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
- rt2x00mmio_register_read(rt2x00dev, BCNCSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, BCNCSR1);
rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
rt2x00_set_field32(&reg, BCNCSR1_BEACON_CWMIN, queue->cw_min);
rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg);
@@ -308,7 +311,7 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
/*
* Enable synchronisation.
*/
- rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
}
@@ -335,35 +338,35 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
preamble_mask = erp->short_preamble << 3;
- rt2x00mmio_register_read(rt2x00dev, TXCSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR1);
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);
rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg);
- rt2x00mmio_register_read(rt2x00dev, ARCSR2, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, ARCSR2);
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));
rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg);
- rt2x00mmio_register_read(rt2x00dev, ARCSR3, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, ARCSR3);
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));
rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg);
- rt2x00mmio_register_read(rt2x00dev, ARCSR4, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, ARCSR4);
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));
rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg);
- rt2x00mmio_register_read(rt2x00dev, ARCSR5, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, ARCSR5);
rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
@@ -375,23 +378,23 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
if (changed & BSS_CHANGED_ERP_SLOT) {
- rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR11);
rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
- rt2x00mmio_register_read(rt2x00dev, CSR18, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR18);
rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
rt2x00mmio_register_write(rt2x00dev, CSR18, reg);
- rt2x00mmio_register_read(rt2x00dev, CSR19, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR19);
rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
rt2x00mmio_register_write(rt2x00dev, CSR19, reg);
}
if (changed & BSS_CHANGED_BEACON_INT) {
- rt2x00mmio_register_read(rt2x00dev, CSR12, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR12);
rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
erp->beacon_int * 16);
rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
@@ -415,9 +418,9 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
ant->tx == ANTENNA_SW_DIVERSITY);
- rt2x00mmio_register_read(rt2x00dev, BBPCSR1, &reg);
- rt2500pci_bbp_read(rt2x00dev, 14, &r14);
- rt2500pci_bbp_read(rt2x00dev, 2, &r2);
+ reg = rt2x00mmio_register_read(rt2x00dev, BBPCSR1);
+ r14 = rt2500pci_bbp_read(rt2x00dev, 14);
+ r2 = rt2500pci_bbp_read(rt2x00dev, 2);
/*
* Configure the TX antenna.
@@ -538,7 +541,7 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
/*
* Clear false CRC during channel switch.
*/
- rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1);
+ rf->rf1 = rt2x00mmio_register_read(rt2x00dev, CNT0);
}
static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev,
@@ -546,7 +549,7 @@ static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev,
{
u32 rf3;
- rt2x00_rf_read(rt2x00dev, 3, &rf3);
+ rf3 = rt2x00_rf_read(rt2x00dev, 3);
rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
rt2500pci_rf_write(rt2x00dev, 3, rf3);
}
@@ -556,7 +559,7 @@ static void rt2500pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR11);
rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
libconf->conf->long_frame_max_tx_count);
rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
@@ -573,7 +576,7 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
u32 reg;
if (state == STATE_SLEEP) {
- rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR20);
rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
(rt2x00dev->beacon_int - 20) * 16);
rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
@@ -586,7 +589,7 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
} else {
- rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR20);
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
}
@@ -622,13 +625,13 @@ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev,
/*
* Update FCS error count from register.
*/
- rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CNT0);
qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
- rt2x00mmio_register_read(rt2x00dev, CNT3, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CNT3);
qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA);
}
@@ -728,12 +731,12 @@ static void rt2500pci_start_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RXCSR0);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
rt2x00_set_field32(&reg, CSR14_TBCN, 1);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
@@ -751,17 +754,17 @@ static void rt2500pci_kick_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_AC_VO:
- rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_AC_VI:
- rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_ATIM:
- rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
@@ -779,17 +782,17 @@ static void rt2500pci_stop_queue(struct data_queue *queue)
case QID_AC_VO:
case QID_AC_VI:
case QID_ATIM:
- rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_RX:
- rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RXCSR0);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(&reg, CSR14_TBCN, 0);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
@@ -814,11 +817,11 @@ static bool rt2500pci_get_entry_state(struct queue_entry *entry)
u32 word;
if (entry->queue->qid == QID_RX) {
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
} else {
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
rt2x00_get_field32(word, TXD_W0_VALID));
@@ -832,15 +835,15 @@ static void rt2500pci_clear_entry(struct queue_entry *entry)
u32 word;
if (entry->queue->qid == QID_RX) {
- rt2x00_desc_read(entry_priv->desc, 1, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 1);
rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
rt2x00_desc_write(entry_priv->desc, 1, word);
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
rt2x00_desc_write(entry_priv->desc, 0, word);
} else {
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
rt2x00_set_field32(&word, TXD_W0_VALID, 0);
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
rt2x00_desc_write(entry_priv->desc, 0, word);
@@ -855,7 +858,7 @@ static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
/*
* Initialize registers.
*/
- rt2x00mmio_register_read(rt2x00dev, TXCSR2, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR2);
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);
@@ -863,36 +866,36 @@ static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg);
entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
- rt2x00mmio_register_read(rt2x00dev, TXCSR3, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR3);
rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
entry_priv->desc_dma);
rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg);
entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
- rt2x00mmio_register_read(rt2x00dev, TXCSR5, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR5);
rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
entry_priv->desc_dma);
rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg);
entry_priv = rt2x00dev->atim->entries[0].priv_data;
- rt2x00mmio_register_read(rt2x00dev, TXCSR4, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR4);
rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
entry_priv->desc_dma);
rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg);
entry_priv = rt2x00dev->bcn->entries[0].priv_data;
- rt2x00mmio_register_read(rt2x00dev, TXCSR6, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR6);
rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
entry_priv->desc_dma);
rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg);
- rt2x00mmio_register_read(rt2x00dev, RXCSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RXCSR1);
rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg);
entry_priv = rt2x00dev->rx->entries[0].priv_data;
- rt2x00mmio_register_read(rt2x00dev, RXCSR2, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RXCSR2);
rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
entry_priv->desc_dma);
rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg);
@@ -909,13 +912,13 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00020002);
rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002);
- rt2x00mmio_register_read(rt2x00dev, TIMECSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TIMECSR);
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);
rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg);
- rt2x00mmio_register_read(rt2x00dev, CSR9, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR9);
rt2x00_set_field32(&reg, CSR9_MAX_FRAME_UNIT,
rt2x00dev->rx->data_size / 128);
rt2x00mmio_register_write(rt2x00dev, CSR9, reg);
@@ -923,11 +926,11 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
/*
* Always use CWmin and CWmax set in descriptor.
*/
- rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR11);
rt2x00_set_field32(&reg, CSR11_CW_SELECT, 0);
rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
- rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
rt2x00_set_field32(&reg, CSR14_TBCN, 0);
@@ -940,7 +943,7 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00mmio_register_write(rt2x00dev, CNT3, 0);
- rt2x00mmio_register_read(rt2x00dev, TXCSR8, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXCSR8);
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);
@@ -951,28 +954,28 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, TXCSR8_BBP_ID3_VALID, 1);
rt2x00mmio_register_write(rt2x00dev, TXCSR8, reg);
- rt2x00mmio_register_read(rt2x00dev, ARTCSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, ARTCSR0);
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);
rt2x00mmio_register_write(rt2x00dev, ARTCSR0, reg);
- rt2x00mmio_register_read(rt2x00dev, ARTCSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, ARTCSR1);
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);
rt2x00mmio_register_write(rt2x00dev, ARTCSR1, reg);
- rt2x00mmio_register_read(rt2x00dev, ARTCSR2, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, ARTCSR2);
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);
rt2x00mmio_register_write(rt2x00dev, ARTCSR2, reg);
- rt2x00mmio_register_read(rt2x00dev, RXCSR3, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RXCSR3);
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 */
@@ -983,7 +986,7 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, RXCSR3_BBP_ID3_VALID, 1);
rt2x00mmio_register_write(rt2x00dev, RXCSR3, reg);
- rt2x00mmio_register_read(rt2x00dev, PCICSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, PCICSR);
rt2x00_set_field32(&reg, PCICSR_BIG_ENDIAN, 0);
rt2x00_set_field32(&reg, PCICSR_RX_TRESHOLD, 0);
rt2x00_set_field32(&reg, PCICSR_TX_TRESHOLD, 3);
@@ -1004,11 +1007,11 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00213223);
rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518);
- rt2x00mmio_register_read(rt2x00dev, MACCSR2, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MACCSR2);
rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg);
- rt2x00mmio_register_read(rt2x00dev, RALINKCSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RALINKCSR);
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);
@@ -1021,13 +1024,13 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00mmio_register_write(rt2x00dev, TXACKCSR0, 0x00000020);
- rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR1);
rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 1);
rt2x00_set_field32(&reg, CSR1_BBP_RESET, 0);
rt2x00_set_field32(&reg, CSR1_HOST_READY, 0);
rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
- rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR1);
rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 0);
rt2x00_set_field32(&reg, CSR1_HOST_READY, 1);
rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
@@ -1037,8 +1040,8 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
*/
- rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
- rt2x00mmio_register_read(rt2x00dev, CNT4, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CNT0);
+ reg = rt2x00mmio_register_read(rt2x00dev, CNT4);
return 0;
}
@@ -1049,7 +1052,7 @@ static int rt2500pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
u8 value;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2500pci_bbp_read(rt2x00dev, 0, &value);
+ value = rt2500pci_bbp_read(rt2x00dev, 0);
if ((value != 0xff) && (value != 0x00))
return 0;
udelay(REGISTER_BUSY_DELAY);
@@ -1101,7 +1104,7 @@ static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2500pci_bbp_write(rt2x00dev, 62, 0x10);
for (i = 0; i < EEPROM_BBP_SIZE; i++) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i);
if (eeprom != 0xffff && eeprom != 0x0000) {
reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
@@ -1128,7 +1131,7 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
* should clear the register to assure a clean state.
*/
if (state == STATE_RADIO_IRQ_ON) {
- rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR7);
rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
}
@@ -1138,7 +1141,7 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
- rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, mask);
@@ -1190,7 +1193,7 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
put_to_sleep = (state != STATE_AWAKE);
- rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, PWRCSR1);
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);
@@ -1203,7 +1206,7 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
* device has entered the correct state.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg2);
+ reg2 = rt2x00mmio_register_read(rt2x00dev, PWRCSR1);
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)
@@ -1263,18 +1266,18 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,
/*
* Start writing the descriptor words.
*/
- rt2x00_desc_read(txd, 1, &word);
+ word = rt2x00_desc_read(txd, 1);
rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
rt2x00_desc_write(txd, 1, word);
- rt2x00_desc_read(txd, 2, &word);
+ word = rt2x00_desc_read(txd, 2);
rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);
rt2x00_set_field32(&word, TXD_W2_AIFS, entry->queue->aifs);
rt2x00_set_field32(&word, TXD_W2_CWMIN, entry->queue->cw_min);
rt2x00_set_field32(&word, TXD_W2_CWMAX, entry->queue->cw_max);
rt2x00_desc_write(txd, 2, word);
- rt2x00_desc_read(txd, 3, &word);
+ word = rt2x00_desc_read(txd, 3);
rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal);
rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.service);
rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW,
@@ -1283,7 +1286,7 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,
txdesc->u.plcp.length_high);
rt2x00_desc_write(txd, 3, word);
- rt2x00_desc_read(txd, 10, &word);
+ word = rt2x00_desc_read(txd, 10);
rt2x00_set_field32(&word, TXD_W10_RTS,
test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
rt2x00_desc_write(txd, 10, word);
@@ -1293,7 +1296,7 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,
* the device, whereby the device may take hold of the TXD before we
* finished updating it.
*/
- rt2x00_desc_read(txd, 0, &word);
+ word = rt2x00_desc_read(txd, 0);
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
rt2x00_set_field32(&word, TXD_W0_VALID, 1);
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
@@ -1332,7 +1335,7 @@ 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.
*/
- rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
@@ -1368,8 +1371,8 @@ static void rt2500pci_fill_rxdone(struct queue_entry *entry,
u32 word0;
u32 word2;
- rt2x00_desc_read(entry_priv->desc, 0, &word0);
- rt2x00_desc_read(entry_priv->desc, 2, &word2);
+ word0 = rt2x00_desc_read(entry_priv->desc, 0);
+ word2 = rt2x00_desc_read(entry_priv->desc, 2);
if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
@@ -1410,7 +1413,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
while (!rt2x00queue_empty(queue)) {
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
entry_priv = entry->priv_data;
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
!rt2x00_get_field32(word, TXD_W0_VALID))
@@ -1448,7 +1451,7 @@ static inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
rt2x00_set_field32(&reg, irq_field, 0);
rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
@@ -1473,7 +1476,7 @@ static void rt2500pci_txstatus_tasklet(unsigned long data)
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
@@ -1509,7 +1512,7 @@ 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.
*/
- rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR7);
rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
if (!reg)
@@ -1547,7 +1550,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
*/
spin_lock(&rt2x00dev->irqmask_lock);
- rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
reg |= mask;
rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
@@ -1566,7 +1569,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
u16 word;
u8 *mac;
- rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR21);
eeprom.data = rt2x00dev;
eeprom.register_read = rt2500pci_eepromregister_read;
@@ -1587,7 +1590,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
rt2x00lib_set_mac_address(rt2x00dev, mac);
- rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
@@ -1603,7 +1606,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);
@@ -1612,7 +1615,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
DEFAULT_RSSI_OFFSET);
@@ -1633,13 +1636,13 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Read EEPROM word for configuration.
*/
- rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
/*
* Identify RF chipset.
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
- rt2x00mmio_register_read(rt2x00dev, CSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR0);
rt2x00_set_chip(rt2x00dev, RT2560, value,
rt2x00_get_field32(reg, CSR0_REVISION));
@@ -1689,14 +1692,14 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Check if the BBP tuning should be enabled.
*/
- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
if (!rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE))
__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
/*
* Read the RSSI <-> dBm offset information.
*/
- rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET);
rt2x00dev->rssi_offset =
rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI);
@@ -1955,7 +1958,7 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
- rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, GPIOCSR);
rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg);
@@ -1991,9 +1994,9 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw,
u64 tsf;
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, CSR17, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR17);
tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32;
- rt2x00mmio_register_read(rt2x00dev, CSR16, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR16);
tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER);
return tsf;
@@ -2004,7 +2007,7 @@ static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)
struct rt2x00_dev *rt2x00dev = hw->priv;
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, CSR15, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CSR15);
return rt2x00_get_field32(reg, CSR15_BEACON_SENT);
}
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
index 0d2670a..529e059 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
@@ -55,26 +55,24 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
* If the csr_mutex is already held then the _lock variants must
* be used instead.
*/
-static void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- u16 *value)
+static u16 rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset)
{
__le16 reg;
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
&reg, sizeof(reg));
- *value = le16_to_cpu(reg);
+ return le16_to_cpu(reg);
}
-static void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- u16 *value)
+static u16 rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset)
{
__le16 reg;
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
&reg, sizeof(reg), REGISTER_TIMEOUT);
- *value = le16_to_cpu(reg);
+ return le16_to_cpu(reg);
}
static void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
@@ -114,7 +112,7 @@ static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
unsigned int i;
for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
- rt2500usb_register_read_lock(rt2x00dev, offset, reg);
+ *reg = rt2500usb_register_read_lock(rt2x00dev, offset);
if (!rt2x00_get_field16(*reg, field))
return 1;
udelay(REGISTER_BUSY_DELAY);
@@ -155,10 +153,11 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
mutex_unlock(&rt2x00dev->csr_mutex);
}
-static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u8 *value)
+static u8 rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word)
{
u16 reg;
+ u8 value;
mutex_lock(&rt2x00dev->csr_mutex);
@@ -178,12 +177,14 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
if (WAIT_FOR_BBP(rt2x00dev, &reg))
- rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg);
+ reg = rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7);
}
- *value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
+ value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
mutex_unlock(&rt2x00dev->csr_mutex);
+
+ return value;
}
static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -216,14 +217,10 @@ static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
}
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-static void _rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- u32 *value)
+static u32 _rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset)
{
- u16 tmp;
-
- rt2500usb_register_read(rt2x00dev, offset, &tmp);
- *value = tmp;
+ return rt2500usb_register_read(rt2x00dev, offset);
}
static void _rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
@@ -271,7 +268,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u16 reg;
- rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, MAC_CSR19);
return rt2x00_get_field16(reg, MAC_CSR19_VAL7);
}
@@ -284,7 +281,7 @@ static void rt2500usb_brightness_set(struct led_classdev *led_cdev,
unsigned int enabled = brightness != LED_OFF;
u16 reg;
- rt2500usb_register_read(led->rt2x00dev, MAC_CSR20, &reg);
+ reg = rt2500usb_register_read(led->rt2x00dev, MAC_CSR20);
if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
rt2x00_set_field16(&reg, MAC_CSR20_LINK, enabled);
@@ -302,7 +299,7 @@ static int rt2500usb_blink_set(struct led_classdev *led_cdev,
container_of(led_cdev, struct rt2x00_led, led_dev);
u16 reg;
- rt2500usb_register_read(led->rt2x00dev, MAC_CSR21, &reg);
+ reg = rt2500usb_register_read(led->rt2x00dev, MAC_CSR21);
rt2x00_set_field16(&reg, MAC_CSR21_ON_PERIOD, *delay_on);
rt2x00_set_field16(&reg, MAC_CSR21_OFF_PERIOD, *delay_off);
rt2500usb_register_write(led->rt2x00dev, MAC_CSR21, reg);
@@ -356,7 +353,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
*/
mask = TXRX_CSR0_KEY_ID.bit_mask;
- rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR0);
curr_cipher = rt2x00_get_field16(reg, TXRX_CSR0_ALGORITHM);
reg &= mask;
@@ -395,7 +392,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
* TXRX_CSR0_KEY_ID contains only single-bit fields to indicate
* a particular key is valid.
*/
- rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR0);
rt2x00_set_field16(&reg, TXRX_CSR0_ALGORITHM, crypto->cipher);
rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
@@ -421,7 +418,7 @@ static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev,
* and broadcast frames will always be accepted since
* there is no filter for it at this time.
*/
- rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2);
rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL,
@@ -453,7 +450,7 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
* Enable beacon config
*/
bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
- rt2500usb_register_read(rt2x00dev, TXRX_CSR20, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR20);
rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET, bcn_preload >> 6);
rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW,
2 * (conf->type != NL80211_IFTYPE_STATION));
@@ -462,11 +459,11 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
/*
* Enable synchronisation.
*/
- rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR18);
rt2x00_set_field16(&reg, TXRX_CSR18_OFFSET, 0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
- rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19);
rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, conf->sync);
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
}
@@ -487,7 +484,7 @@ static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
u16 reg;
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR10);
rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
!!erp->short_preamble);
rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
@@ -498,7 +495,7 @@ static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
erp->basic_rates);
if (changed & BSS_CHANGED_BEACON_INT) {
- rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR18);
rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
erp->beacon_int * 4);
rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
@@ -526,10 +523,10 @@ static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev,
BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
ant->tx == ANTENNA_SW_DIVERSITY);
- rt2500usb_bbp_read(rt2x00dev, 2, &r2);
- rt2500usb_bbp_read(rt2x00dev, 14, &r14);
- rt2500usb_register_read(rt2x00dev, PHY_CSR5, &csr5);
- rt2500usb_register_read(rt2x00dev, PHY_CSR6, &csr6);
+ r2 = rt2500usb_bbp_read(rt2x00dev, 2);
+ r14 = rt2500usb_bbp_read(rt2x00dev, 14);
+ csr5 = rt2500usb_register_read(rt2x00dev, PHY_CSR5);
+ csr6 = rt2500usb_register_read(rt2x00dev, PHY_CSR6);
/*
* Configure the TX antenna.
@@ -629,7 +626,7 @@ static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev,
{
u32 rf3;
- rt2x00_rf_read(rt2x00dev, 3, &rf3);
+ rf3 = rt2x00_rf_read(rt2x00dev, 3);
rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
rt2500usb_rf_write(rt2x00dev, 3, rf3);
}
@@ -643,7 +640,7 @@ static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev,
u16 reg;
if (state == STATE_SLEEP) {
- rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, MAC_CSR18);
rt2x00_set_field16(&reg, MAC_CSR18_DELAY_AFTER_BEACON,
rt2x00dev->beacon_int - 20);
rt2x00_set_field16(&reg, MAC_CSR18_BEACONS_BEFORE_WAKEUP,
@@ -656,7 +653,7 @@ static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 1);
rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
} else {
- rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, MAC_CSR18);
rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 0);
rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
}
@@ -690,13 +687,13 @@ static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev,
/*
* Update FCS error count from register.
*/
- rt2500usb_register_read(rt2x00dev, STA_CSR0, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, STA_CSR0);
qual->rx_failed = rt2x00_get_field16(reg, STA_CSR0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
- rt2500usb_register_read(rt2x00dev, STA_CSR3, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, STA_CSR3);
qual->false_cca = rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR);
}
@@ -706,19 +703,19 @@ static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
u16 eeprom;
u16 value;
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24);
value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R24_LOW);
rt2500usb_bbp_write(rt2x00dev, 24, value);
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25);
value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R25_LOW);
rt2500usb_bbp_write(rt2x00dev, 25, value);
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61);
value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R61_LOW);
rt2500usb_bbp_write(rt2x00dev, 61, value);
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC);
value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_VGCUPPER);
rt2500usb_bbp_write(rt2x00dev, 17, value);
@@ -735,12 +732,12 @@ static void rt2500usb_start_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2);
rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
break;
case QID_BEACON:
- rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19);
rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
@@ -758,12 +755,12 @@ static void rt2500usb_stop_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2);
rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 1);
rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
break;
case QID_BEACON:
- rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19);
rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
@@ -786,54 +783,54 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00usb_vendor_request_sw(rt2x00dev, USB_SINGLE_WRITE, 0x0308,
0x00f0, REGISTER_TIMEOUT);
- rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2);
rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 1);
rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x1111);
rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x1e11);
- rt2500usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, MAC_CSR1);
rt2x00_set_field16(&reg, MAC_CSR1_SOFT_RESET, 1);
rt2x00_set_field16(&reg, MAC_CSR1_BBP_RESET, 1);
rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 0);
rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2500usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, MAC_CSR1);
rt2x00_set_field16(&reg, MAC_CSR1_SOFT_RESET, 0);
rt2x00_set_field16(&reg, MAC_CSR1_BBP_RESET, 0);
rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 0);
rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2500usb_register_read(rt2x00dev, TXRX_CSR5, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR5);
rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID0, 13);
rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID0_VALID, 1);
rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID1, 12);
rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID1_VALID, 1);
rt2500usb_register_write(rt2x00dev, TXRX_CSR5, reg);
- rt2500usb_register_read(rt2x00dev, TXRX_CSR6, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR6);
rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID0, 10);
rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID0_VALID, 1);
rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID1, 11);
rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID1_VALID, 1);
rt2500usb_register_write(rt2x00dev, TXRX_CSR6, reg);
- rt2500usb_register_read(rt2x00dev, TXRX_CSR7, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR7);
rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID0, 7);
rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID0_VALID, 1);
rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID1, 6);
rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID1_VALID, 1);
rt2500usb_register_write(rt2x00dev, TXRX_CSR7, reg);
- rt2500usb_register_read(rt2x00dev, TXRX_CSR8, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR8);
rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID0, 5);
rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID0_VALID, 1);
rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID1, 0);
rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID1_VALID, 0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR8, reg);
- rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19);
rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, 0);
rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
@@ -846,14 +843,14 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
return -EBUSY;
- rt2500usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, MAC_CSR1);
rt2x00_set_field16(&reg, MAC_CSR1_SOFT_RESET, 0);
rt2x00_set_field16(&reg, MAC_CSR1_BBP_RESET, 0);
rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 1);
rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
if (rt2x00_rev(rt2x00dev) >= RT2570_VERSION_C) {
- rt2500usb_register_read(rt2x00dev, PHY_CSR2, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, PHY_CSR2);
rt2x00_set_field16(&reg, PHY_CSR2_LNA, 0);
} else {
reg = 0;
@@ -867,26 +864,26 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2500usb_register_write(rt2x00dev, MAC_CSR15, 0x01ee);
rt2500usb_register_write(rt2x00dev, MAC_CSR16, 0x0000);
- rt2500usb_register_read(rt2x00dev, MAC_CSR8, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, MAC_CSR8);
rt2x00_set_field16(&reg, MAC_CSR8_MAX_FRAME_UNIT,
rt2x00dev->rx->data_size);
rt2500usb_register_write(rt2x00dev, MAC_CSR8, reg);
- rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR0);
rt2x00_set_field16(&reg, TXRX_CSR0_ALGORITHM, CIPHER_NONE);
rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, 0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg);
- rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, MAC_CSR18);
rt2x00_set_field16(&reg, MAC_CSR18_DELAY_AFTER_BEACON, 90);
rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
- rt2500usb_register_read(rt2x00dev, PHY_CSR4, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, PHY_CSR4);
rt2x00_set_field16(&reg, PHY_CSR4_LOW_RF_LE, 1);
rt2500usb_register_write(rt2x00dev, PHY_CSR4, reg);
- rt2500usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR1);
rt2x00_set_field16(&reg, TXRX_CSR1_AUTO_SEQUENCE, 1);
rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg);
@@ -899,7 +896,7 @@ static int rt2500usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
u8 value;
for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
- rt2500usb_bbp_read(rt2x00dev, 0, &value);
+ value = rt2500usb_bbp_read(rt2x00dev, 0);
if ((value != 0xff) && (value != 0x00))
return 0;
udelay(REGISTER_BUSY_DELAY);
@@ -952,7 +949,7 @@ static int rt2500usb_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2500usb_bbp_write(rt2x00dev, 75, 0xff);
for (i = 0; i < EEPROM_BBP_SIZE; i++) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i);
if (eeprom != 0xffff && eeprom != 0x0000) {
reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
@@ -1018,7 +1015,7 @@ static int rt2500usb_set_state(struct rt2x00_dev *rt2x00dev,
* device has entered the correct state.
*/
for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
- rt2500usb_register_read(rt2x00dev, MAC_CSR17, &reg2);
+ reg2 = rt2500usb_register_read(rt2x00dev, MAC_CSR17);
bbp_state = rt2x00_get_field16(reg2, MAC_CSR17_BBP_CURR_STATE);
rf_state = rt2x00_get_field16(reg2, MAC_CSR17_RF_CURR_STATE);
if (bbp_state == state && rf_state == state)
@@ -1077,7 +1074,7 @@ static void rt2500usb_write_tx_desc(struct queue_entry *entry,
/*
* Start writing the descriptor words.
*/
- rt2x00_desc_read(txd, 0, &word);
+ word = rt2x00_desc_read(txd, 0);
rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit);
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
@@ -1095,14 +1092,14 @@ static void rt2500usb_write_tx_desc(struct queue_entry *entry,
rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
rt2x00_desc_write(txd, 0, word);
- rt2x00_desc_read(txd, 1, &word);
+ word = rt2x00_desc_read(txd, 1);
rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
rt2x00_set_field32(&word, TXD_W1_AIFS, entry->queue->aifs);
rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
rt2x00_desc_write(txd, 1, word);
- rt2x00_desc_read(txd, 2, &word);
+ word = rt2x00_desc_read(txd, 2);
rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
@@ -1143,7 +1140,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry,
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19);
rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
@@ -1250,8 +1247,8 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry,
/*
* It is now safe to read the descriptor on all architectures.
*/
- rt2x00_desc_read(rxd, 0, &word0);
- rt2x00_desc_read(rxd, 1, &word1);
+ word0 = rt2x00_desc_read(rxd, 0);
+ word1 = rt2x00_desc_read(rxd, 1);
if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
@@ -1263,8 +1260,8 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry,
rxdesc->cipher_status = RX_CRYPTO_FAIL_KEY;
if (rxdesc->cipher != CIPHER_NONE) {
- _rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]);
- _rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]);
+ rxdesc->iv[0] = _rt2x00_desc_read(rxd, 2);
+ rxdesc->iv[1] = _rt2x00_desc_read(rxd, 3);
rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
/* ICV is located at the end of frame */
@@ -1342,7 +1339,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
rt2x00lib_set_mac_address(rt2x00dev, mac);
- rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
@@ -1358,7 +1355,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);
@@ -1367,7 +1364,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
DEFAULT_RSSI_OFFSET);
@@ -1376,7 +1373,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_BBPTUNE_THRESHOLD, 45);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE, word);
@@ -1387,10 +1384,10 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
* Switch lower vgc bound to current BBP R17 value,
* lower the value a bit for better quality.
*/
- rt2500usb_bbp_read(rt2x00dev, 17, &bbp);
+ bbp = rt2500usb_bbp_read(rt2x00dev, 17);
bbp -= 6;
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
@@ -1401,7 +1398,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_LOW, 0x48);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41);
@@ -1409,7 +1406,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r17: 0x%04x\n", word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_LOW, 0x40);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_HIGH, 0x80);
@@ -1417,7 +1414,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r24: 0x%04x\n", word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_LOW, 0x40);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_HIGH, 0x50);
@@ -1425,7 +1422,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r25: 0x%04x\n", word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_LOW, 0x60);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_HIGH, 0x6d);
@@ -1445,13 +1442,13 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Read EEPROM word for configuration.
*/
- rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
/*
* Identify RF chipset.
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
- rt2500usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, MAC_CSR0);
rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
if (((reg & 0xfff0) != 0) || ((reg & 0x0000000f) == 0)) {
@@ -1511,7 +1508,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Read the RSSI <-> dBm offset information.
*/
- rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET);
rt2x00dev->rssi_offset =
rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI);
@@ -1776,7 +1773,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
- rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
+ reg = rt2500usb_register_read(rt2x00dev, MAC_CSR19);
rt2x00_set_field16(&reg, MAC_CSR19_DIR0, 0);
rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index d11c7b2..6e2e760 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -110,10 +110,10 @@ static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
mutex_unlock(&rt2x00dev->csr_mutex);
}
-static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u8 *value)
+static u8 rt2800_bbp_read(struct rt2x00_dev *rt2x00dev, const unsigned int word)
{
u32 reg;
+ u8 value;
mutex_lock(&rt2x00dev->csr_mutex);
@@ -137,9 +137,11 @@ static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev,
WAIT_FOR_BBP(rt2x00dev, &reg);
}
- *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE);
+ value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE);
mutex_unlock(&rt2x00dev->csr_mutex);
+
+ return value;
}
static void rt2800_rfcsr_write(struct rt2x00_dev *rt2x00dev,
@@ -203,10 +205,11 @@ static void rt2800_rfcsr_write_dccal(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write_bank(rt2x00dev, 7, reg, value);
}
-static void rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u8 *value)
+static u8 rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word)
{
u32 reg;
+ u8 value;
mutex_lock(&rt2x00dev->csr_mutex);
@@ -232,7 +235,7 @@ static void rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev,
WAIT_FOR_RFCSR_MT7620(rt2x00dev, &reg);
}
- *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA_MT7620);
+ value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA_MT7620);
break;
default:
@@ -247,17 +250,19 @@ static void rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev,
WAIT_FOR_RFCSR(rt2x00dev, &reg);
}
- *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA);
+ value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA);
break;
}
mutex_unlock(&rt2x00dev->csr_mutex);
+
+ return value;
}
-static void rt2800_rfcsr_read_bank(struct rt2x00_dev *rt2x00dev, const u8 bank,
- const unsigned int reg, u8 *value)
+static u8 rt2800_rfcsr_read_bank(struct rt2x00_dev *rt2x00dev, const u8 bank,
+ const unsigned int reg)
{
- rt2800_rfcsr_read(rt2x00dev, (reg | (bank << 6)), value);
+ return rt2800_rfcsr_read(rt2x00dev, (reg | (bank << 6)));
}
static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -405,13 +410,13 @@ static void *rt2800_eeprom_addr(struct rt2x00_dev *rt2x00dev,
return rt2x00_eeprom_addr(rt2x00dev, index);
}
-static void rt2800_eeprom_read(struct rt2x00_dev *rt2x00dev,
- const enum rt2800_eeprom_word word, u16 *data)
+static u16 rt2800_eeprom_read(struct rt2x00_dev *rt2x00dev,
+ const enum rt2800_eeprom_word word)
{
unsigned int index;
index = rt2800_eeprom_word_index(rt2x00dev, word);
- rt2x00_eeprom_read(rt2x00dev, index, data);
+ return rt2x00_eeprom_read(rt2x00dev, index);
}
static void rt2800_eeprom_write(struct rt2x00_dev *rt2x00dev,
@@ -423,15 +428,14 @@ static void rt2800_eeprom_write(struct rt2x00_dev *rt2x00dev,
rt2x00_eeprom_write(rt2x00dev, index, data);
}
-static void rt2800_eeprom_read_from_array(struct rt2x00_dev *rt2x00dev,
- const enum rt2800_eeprom_word array,
- unsigned int offset,
- u16 *data)
+static u16 rt2800_eeprom_read_from_array(struct rt2x00_dev *rt2x00dev,
+ const enum rt2800_eeprom_word array,
+ unsigned int offset)
{
unsigned int index;
index = rt2800_eeprom_word_index(rt2x00dev, array);
- rt2x00_eeprom_read(rt2x00dev, index + offset, data);
+ return rt2x00_eeprom_read(rt2x00dev, index + offset);
}
static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
@@ -439,7 +443,7 @@ static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
u32 reg;
int i, count;
- rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL);
rt2x00_set_field32(&reg, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
rt2x00_set_field32(&reg, FRC_WL_ANT_SET, 1);
rt2x00_set_field32(&reg, WLAN_CLK_EN, 0);
@@ -454,7 +458,7 @@ static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
* Check PLL_LD & XTAL_RDY.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, CMB_CTRL);
if (rt2x00_get_field32(reg, PLL_LD) &&
rt2x00_get_field32(reg, XTAL_RDY))
break;
@@ -477,7 +481,7 @@ static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
count = 0;
}
- rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL);
rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 0);
rt2x00_set_field32(&reg, WLAN_CLK_EN, 1);
rt2x00_set_field32(&reg, WLAN_RESET, 1);
@@ -532,7 +536,7 @@ int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev)
u32 reg;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+ reg = rt2800_register_read(rt2x00dev, MAC_CSR0);
if (reg && reg != ~0)
return 0;
msleep(1);
@@ -553,7 +557,7 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
* before timing out.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG);
if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
!rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))
return 0;
@@ -570,7 +574,7 @@ void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
@@ -720,7 +724,7 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
- rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, AUX_CTRL);
rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
rt2800_register_write(rt2x00dev, AUX_CTRL, reg);
@@ -739,7 +743,7 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
* Wait for device to stabilize.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, PBF_SYS_CTRL);
if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))
break;
msleep(1);
@@ -781,7 +785,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
/*
* Initialize TX Info descriptor
*/
- rt2x00_desc_read(txwi, 0, &word);
+ word = rt2x00_desc_read(txwi, 0);
rt2x00_set_field32(&word, TXWI_W0_FRAG,
test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
rt2x00_set_field32(&word, TXWI_W0_MIMO_PS,
@@ -803,7 +807,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode);
rt2x00_desc_write(txwi, 0, word);
- rt2x00_desc_read(txwi, 1, &word);
+ word = rt2x00_desc_read(txwi, 1);
rt2x00_set_field32(&word, TXWI_W1_ACK,
test_bit(ENTRY_TXD_ACK, &txdesc->flags));
rt2x00_set_field32(&word, TXWI_W1_NSEQ,
@@ -843,16 +847,16 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)
u8 offset2;
if (rt2x00dev->curr_band == NL80211_BAND_2GHZ) {
- rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG);
offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0);
offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1);
- rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2);
offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_OFFSET2);
} else {
- rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A);
offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET0);
offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET1);
- rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2);
offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_OFFSET2);
}
@@ -881,12 +885,12 @@ void rt2800_process_rxwi(struct queue_entry *entry,
__le32 *rxwi = (__le32 *) entry->skb->data;
u32 word;
- rt2x00_desc_read(rxwi, 0, &word);
+ word = rt2x00_desc_read(rxwi, 0);
rxdesc->cipher = rt2x00_get_field32(word, RXWI_W0_UDF);
rxdesc->size = rt2x00_get_field32(word, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
- rt2x00_desc_read(rxwi, 1, &word);
+ word = rt2x00_desc_read(rxwi, 1);
if (rt2x00_get_field32(word, RXWI_W1_SHORT_GI))
rxdesc->enc_flags |= RX_ENC_FLAG_SHORT_GI;
@@ -907,7 +911,7 @@ void rt2800_process_rxwi(struct queue_entry *entry,
if (rxdesc->rate_mode == RATE_MODE_CCK)
rxdesc->signal &= ~0x8;
- rt2x00_desc_read(rxwi, 2, &word);
+ word = rt2x00_desc_read(rxwi, 2);
/*
* Convert descriptor AGC value to RSSI value.
@@ -968,7 +972,7 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
* Obtain the status about this packet.
*/
txdesc.flags = 0;
- rt2x00_desc_read(txwi, 0, &word);
+ word = rt2x00_desc_read(txwi, 0);
mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
ampdu = rt2x00_get_field32(word, TXWI_W0_AMPDU);
@@ -1093,7 +1097,7 @@ static void rt2800_update_beacons_setup(struct rt2x00_dev *rt2x00dev)
/*
* H/W sends up to MAC_BSSID_DW1_BSS_BCN_NUM + 1 consecutive beacons.
*/
- rt2800_register_read(rt2x00dev, MAC_BSSID_DW1, &bssid_dw1);
+ bssid_dw1 = rt2800_register_read(rt2x00dev, MAC_BSSID_DW1);
rt2x00_set_field32(&bssid_dw1, MAC_BSSID_DW1_BSS_BCN_NUM,
bcn_num > 0 ? bcn_num - 1 : 0);
rt2800_register_write(rt2x00dev, MAC_BSSID_DW1, bssid_dw1);
@@ -1112,7 +1116,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, BCN_TIME_CFG);
orig_reg = reg;
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
@@ -1202,7 +1206,7 @@ void rt2800_clear_beacon(struct queue_entry *entry)
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &orig_reg);
+ orig_reg = rt2800_register_read(rt2x00dev, BCN_TIME_CFG);
reg = orig_reg;
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
@@ -1275,10 +1279,10 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
u32 reg;
if (rt2x00_rt(rt2x00dev, RT3290)) {
- rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL);
return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
} else {
- rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, GPIO_CTRL);
return rt2x00_get_field32(reg, GPIO_CTRL_VAL2);
}
}
@@ -1303,7 +1307,7 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev,
/* Check for SoC (SOC devices don't support MCU requests) */
if (rt2x00_is_soc(led->rt2x00dev)) {
- rt2800_register_read(led->rt2x00dev, LED_CFG, &reg);
+ reg = rt2800_register_read(led->rt2x00dev, LED_CFG);
/* Set LED Polarity */
rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, polarity);
@@ -1392,7 +1396,7 @@ static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
* The BSS Idx numbers is split in a main value of 3 bits,
* and a extended field for adding one additional bit to the value.
*/
- rt2800_register_read(rt2x00dev, offset, &reg);
+ reg = rt2800_register_read(rt2x00dev, offset);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7));
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
(bssidx & 0x8) >> 3);
@@ -1410,7 +1414,7 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);
if (crypto->cmd == SET_KEY) {
- rt2800_register_read(rt2x00dev, offset, &reg);
+ reg = rt2800_register_read(rt2x00dev, offset);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB,
!!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE));
/*
@@ -1426,7 +1430,7 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
rt2800_register_write(rt2x00dev, offset, reg);
} else {
/* Delete the cipher without touching the bssidx */
- rt2800_register_read(rt2x00dev, offset, &reg);
+ reg = rt2800_register_read(rt2x00dev, offset);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB, 0);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER, 0);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT, 0);
@@ -1482,7 +1486,7 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);
- rt2800_register_read(rt2x00dev, offset, &reg);
+ reg = rt2800_register_read(rt2x00dev, offset);
rt2x00_set_field32(&reg, field,
(crypto->cmd == SET_KEY) * crypto->cipher);
rt2800_register_write(rt2x00dev, offset, reg);
@@ -1548,7 +1552,7 @@ static void rt2800_set_max_psdu_len(struct rt2x00_dev *rt2x00dev)
max_psdu = min(drv_data->max_psdu, i);
- rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, MAX_LEN_CFG);
rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, max_psdu);
rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg);
}
@@ -1640,7 +1644,7 @@ void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
* and broadcast frames will always be accepted since
* there is no filter for it at this time.
*/
- rt2800_register_read(rt2x00dev, RX_FILTER_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, RX_FILTER_CFG);
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CRC_ERROR,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PHY_ERROR,
@@ -1684,7 +1688,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
/*
* Enable synchronisation.
*/
- rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, BCN_TIME_CFG);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
@@ -1692,14 +1696,14 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
/*
* Tune beacon queue transmit parameters for AP mode
*/
- rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG);
rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 0);
rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 1);
rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 0);
rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
} else {
- rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG);
rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 4);
rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 2);
rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
@@ -1818,22 +1822,22 @@ static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,
gf20_mode = gf40_mode = 1;
/* Update HT protection config */
- rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, MM20_PROT_CFG);
rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, mm20_rate);
rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, mm20_mode);
rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
- rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, MM40_PROT_CFG);
rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, mm40_rate);
rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, mm40_mode);
rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
- rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, GF20_PROT_CFG);
rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, gf20_rate);
rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, gf20_mode);
rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
- rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, GF40_PROT_CFG);
rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, gf40_rate);
rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, gf40_mode);
rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
@@ -1845,14 +1849,14 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
u32 reg;
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, AUTO_RSP_CFG);
rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE,
!!erp->short_preamble);
rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
}
if (changed & BSS_CHANGED_ERP_CTS_PROT) {
- rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, OFDM_PROT_CFG);
rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL,
erp->cts_protection ? 2 : 0);
rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
@@ -1865,18 +1869,18 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
}
if (changed & BSS_CHANGED_ERP_SLOT) {
- rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG);
rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME,
erp->slot_time);
rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
- rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, XIFS_TIME_CFG);
rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
}
if (changed & BSS_CHANGED_BEACON_INT) {
- rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, BCN_TIME_CFG);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
erp->beacon_int * 16);
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
@@ -1893,7 +1897,7 @@ static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev)
u16 eeprom;
u8 led_ctrl, led_g_mode, led_r_mode;
- rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+ reg = rt2800_register_read(rt2x00dev, GPIO_SWITCH);
if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) {
rt2x00_set_field32(&reg, GPIO_SWITCH_0, 1);
rt2x00_set_field32(&reg, GPIO_SWITCH_1, 1);
@@ -1903,12 +1907,12 @@ static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev)
}
rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
- rt2800_register_read(rt2x00dev, LED_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, LED_CFG);
led_g_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 3 : 0;
led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3;
if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) ||
led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) {
- rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ);
led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE);
if (led_ctrl == 0 || led_ctrl > 0x40) {
rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, led_g_mode);
@@ -1929,14 +1933,14 @@ static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev,
u8 gpio_bit3 = (ant == ANTENNA_A) ? 0 : 1;
if (rt2x00_is_pci(rt2x00dev)) {
- rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ reg = rt2800_register_read(rt2x00dev, E2PROM_CSR);
rt2x00_set_field32(&reg, E2PROM_CSR_DATA_CLOCK, eesk_pin);
rt2800_register_write(rt2x00dev, E2PROM_CSR, reg);
} else if (rt2x00_is_usb(rt2x00dev))
rt2800_mcu_request(rt2x00dev, MCU_ANT_SELECT, 0xff,
eesk_pin, 0);
- rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, GPIO_CTRL);
rt2x00_set_field32(&reg, GPIO_CTRL_DIR3, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_VAL3, gpio_bit3);
rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
@@ -1948,8 +1952,8 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
u8 r3;
u16 eeprom;
- rt2800_bbp_read(rt2x00dev, 1, &r1);
- rt2800_bbp_read(rt2x00dev, 3, &r3);
+ r1 = rt2800_bbp_read(rt2x00dev, 1);
+ r3 = rt2800_bbp_read(rt2x00dev, 3);
if (rt2x00_rt(rt2x00dev, RT3572) &&
rt2x00_has_cap_bt_coexist(rt2x00dev))
@@ -1983,8 +1987,8 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT3390)) {
- rt2800_eeprom_read(rt2x00dev,
- EEPROM_NIC_CONF1, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev,
+ EEPROM_NIC_CONF1);
if (rt2x00_get_field16(eeprom,
EEPROM_NIC_CONF1_ANT_DIVERSITY))
rt2800_set_ant_diversity(rt2x00dev,
@@ -2027,28 +2031,28 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev,
short lna_gain;
if (libconf->rf.channel <= 14) {
- rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_LNA);
lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG);
} else if (libconf->rf.channel <= 64) {
- rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_LNA);
lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);
} else if (libconf->rf.channel <= 128) {
if (rt2x00_rt(rt2x00dev, RT3593)) {
- rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2);
lna_gain = rt2x00_get_field16(eeprom,
EEPROM_EXT_LNA2_A1);
} else {
- rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2);
lna_gain = rt2x00_get_field16(eeprom,
EEPROM_RSSI_BG2_LNA_A1);
}
} else {
if (rt2x00_rt(rt2x00dev, RT3593)) {
- rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2);
lna_gain = rt2x00_get_field16(eeprom,
EEPROM_EXT_LNA2_A2);
} else {
- rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2);
lna_gain = rt2x00_get_field16(eeprom,
EEPROM_RSSI_A2_LNA_A2);
}
@@ -2072,7 +2076,7 @@ static void rt2800_freq_cal_mode1(struct rt2x00_dev *rt2x00dev)
freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE);
freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND);
- rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 17);
prev_rfcsr = rfcsr;
rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset);
@@ -2174,23 +2178,23 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
- rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 3);
rt2x00_set_field8(&rfcsr, RFCSR3_K, rf->rf3);
rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 6);
rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2);
rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 12);
rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, info->default_power1);
rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 13);
rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2);
rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD,
rt2x00dev->default_ant.rx_chain_num <= 1);
@@ -2203,7 +2207,7 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
rt2x00dev->default_ant.tx_chain_num <= 2);
rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 23);
rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
@@ -2220,19 +2224,19 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
}
}
- rt2800_rfcsr_read(rt2x00dev, 24, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 24);
rt2x00_set_field8(&rfcsr, RFCSR24_TX_CALIB, calib_tx);
rt2800_rfcsr_write(rt2x00dev, 24, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 31);
rt2x00_set_field8(&rfcsr, RFCSR31_RX_CALIB, calib_rx);
rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 7);
rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 30);
rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
@@ -2262,7 +2266,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3);
- rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 6);
rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2);
if (rf->channel <= 14)
rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 2);
@@ -2270,14 +2274,14 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 1);
rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 5, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 5);
if (rf->channel <= 14)
rt2x00_set_field8(&rfcsr, RFCSR5_R1, 1);
else
rt2x00_set_field8(&rfcsr, RFCSR5_R1, 2);
rt2800_rfcsr_write(rt2x00dev, 5, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 12);
if (rf->channel <= 14) {
rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3);
rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
@@ -2290,7 +2294,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
}
rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 13);
if (rf->channel <= 14) {
rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3);
rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
@@ -2303,7 +2307,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
}
rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
@@ -2336,7 +2340,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
}
rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 23);
rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
@@ -2366,7 +2370,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
} else {
- rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 7);
rt2x00_set_field8(&rfcsr, RFCSR7_BIT2, 1);
rt2x00_set_field8(&rfcsr, RFCSR7_BIT3, 0);
rt2x00_set_field8(&rfcsr, RFCSR7_BIT4, 1);
@@ -2399,7 +2403,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 29, 0x9f);
}
- rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, GPIO_CTRL);
rt2x00_set_field32(&reg, GPIO_CTRL_DIR7, 0);
if (rf->channel <= 14)
rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 1);
@@ -2407,7 +2411,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 0);
rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
- rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 7);
rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
}
@@ -2425,12 +2429,12 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
const bool txbf_enabled = false; /* TODO */
/* TODO: use TX{0,1,2}FinePowerControl values from EEPROM */
- rt2800_bbp_read(rt2x00dev, 109, &bbp);
+ bbp = rt2800_bbp_read(rt2x00dev, 109);
rt2x00_set_field8(&bbp, BBP109_TX0_POWER, 0);
rt2x00_set_field8(&bbp, BBP109_TX1_POWER, 0);
rt2800_bbp_write(rt2x00dev, 109, bbp);
- rt2800_bbp_read(rt2x00dev, 110, &bbp);
+ bbp = rt2800_bbp_read(rt2x00dev, 110);
rt2x00_set_field8(&bbp, BBP110_TX2_POWER, 0);
rt2800_bbp_write(rt2x00dev, 110, bbp);
@@ -2450,11 +2454,11 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3 & 0xf);
- rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 11);
rt2x00_set_field8(&rfcsr, RFCSR11_R, (rf->rf2 & 0x3));
rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 11);
rt2x00_set_field8(&rfcsr, RFCSR11_PLL_IDOH, 1);
if (rf->channel <= 14)
rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 1);
@@ -2462,7 +2466,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 2);
rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 53, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 53);
if (rf->channel <= 14) {
rfcsr = 0;
rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER,
@@ -2477,7 +2481,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
}
rt2800_rfcsr_write(rt2x00dev, 53, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 55, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 55);
if (rf->channel <= 14) {
rfcsr = 0;
rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER,
@@ -2492,7 +2496,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
}
rt2800_rfcsr_write(rt2x00dev, 55, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 54, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 54);
if (rf->channel <= 14) {
rfcsr = 0;
rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER,
@@ -2507,7 +2511,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
}
rt2800_rfcsr_write(rt2x00dev, 54, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
@@ -2559,7 +2563,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
/* NOTE: the reference driver does not writes the new value
* back to RFCSR 32
*/
- rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 32);
rt2x00_set_field8(&rfcsr, RFCSR32_TX_AGC_FC, txrx_agc_fc);
if (rf->channel <= 14)
@@ -2568,34 +2572,34 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
rfcsr = 0x80;
rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 30);
rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, txrx_h20m);
rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, txrx_h20m);
rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
/* Band selection */
- rt2800_rfcsr_read(rt2x00dev, 36, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 36);
if (rf->channel <= 14)
rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1);
else
rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0);
rt2800_rfcsr_write(rt2x00dev, 36, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 34, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 34);
if (rf->channel <= 14)
rfcsr = 0x3c;
else
rfcsr = 0x20;
rt2800_rfcsr_write(rt2x00dev, 34, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 12);
if (rf->channel <= 14)
rfcsr = 0x1a;
else
rfcsr = 0x12;
rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 6);
if (rf->channel >= 1 && rf->channel <= 14)
rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1);
else if (rf->channel >= 36 && rf->channel <= 64)
@@ -2606,7 +2610,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1);
rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 30);
rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
@@ -2620,11 +2624,11 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 13, 0x23);
}
- rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 51);
rt2x00_set_field8(&rfcsr, RFCSR51_BITS01, 1);
rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 51);
if (rf->channel <= 14) {
rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 5);
rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 3);
@@ -2634,7 +2638,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
}
rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 49);
if (rf->channel <= 14)
rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 3);
else
@@ -2645,11 +2649,11 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 50);
rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO1_EN, 0);
rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 57, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 57);
if (rf->channel <= 14)
rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x1b);
else
@@ -2665,7 +2669,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
}
/* Initiate VCO calibration */
- rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 3);
if (rf->channel <= 14) {
rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
} else {
@@ -2721,11 +2725,11 @@ static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
- rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 11);
rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 49);
if (info->default_power1 > POWER_BOUND)
rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND);
else
@@ -2775,7 +2779,7 @@ static void rt2800_config_channel_rf3322(struct rt2x00_dev *rt2x00dev,
rt2800_freq_cal_mode1(rt2x00dev);
- rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
@@ -2806,11 +2810,11 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
- rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 11);
rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 49);
if (info->default_power1 > POWER_BOUND)
rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND);
else
@@ -2818,7 +2822,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
if (rt2x00_rt(rt2x00dev, RT5392)) {
- rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 50);
if (info->default_power2 > POWER_BOUND)
rt2x00_set_field8(&rfcsr, RFCSR50_TX, POWER_BOUND);
else
@@ -2827,7 +2831,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
}
- rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
if (rt2x00_rt(rt2x00dev, RT5392)) {
rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
@@ -2911,7 +2915,7 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
const bool is_11b = false;
const bool is_type_ep = false;
- rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ reg = rt2800_register_read(rt2x00dev, LDO_CFG0);
rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL,
(rf->channel > 14 || conf_is_ht40(conf)) ? 5 : 0);
rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
@@ -2919,13 +2923,13 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
/* Order of values on rf_channel entry: N, K, mod, R */
rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1 & 0xff);
- rt2800_rfcsr_read(rt2x00dev, 9, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 9);
rt2x00_set_field8(&rfcsr, RFCSR9_K, rf->rf2 & 0xf);
rt2x00_set_field8(&rfcsr, RFCSR9_N, (rf->rf1 & 0x100) >> 8);
rt2x00_set_field8(&rfcsr, RFCSR9_MOD, ((rf->rf3 - 8) & 0x4) >> 2);
rt2800_rfcsr_write(rt2x00dev, 9, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 11);
rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf4 - 1);
rt2x00_set_field8(&rfcsr, RFCSR11_MOD, (rf->rf3 - 8) & 0x3);
rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
@@ -3093,7 +3097,7 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
ep_reg = 0x3;
}
- rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 49);
if (info->default_power1 > power_bound)
rt2x00_set_field8(&rfcsr, RFCSR49_TX, power_bound);
else
@@ -3102,7 +3106,7 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field8(&rfcsr, RFCSR49_EP, ep_reg);
rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 50);
if (info->default_power2 > power_bound)
rt2x00_set_field8(&rfcsr, RFCSR50_TX, power_bound);
else
@@ -3111,7 +3115,7 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field8(&rfcsr, RFCSR50_EP, ep_reg);
rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
@@ -3144,7 +3148,7 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
rt2800_freq_cal_mode1(rt2x00dev);
/* TODO merge with others */
- rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 3);
rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
@@ -3186,7 +3190,7 @@ static void rt2800_config_channel_rf7620(struct rt2x00_dev *rt2x00dev,
/* Rdiv setting (set 0x03 if Xtal==20)
* R13[1:0]
*/
- rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 13);
rt2x00_set_field8(&rfcsr, RFCSR13_RDIV_MT7620,
rt2800_clk_is_20mhz(rt2x00dev) ? 3 : 0);
rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
@@ -3195,25 +3199,25 @@ static void rt2800_config_channel_rf7620(struct rt2x00_dev *rt2x00dev,
* R20[7:0] in rf->rf1
* R21[0] always 0
*/
- rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 20);
rfcsr = (rf->rf1 & 0x00ff);
rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 21);
rt2x00_set_field8(&rfcsr, RFCSR21_BIT1, 0);
rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
/* K setting (always 0)
* R16[3:0] (RF PLL freq selection)
*/
- rt2800_rfcsr_read(rt2x00dev, 16, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 16);
rt2x00_set_field8(&rfcsr, RFCSR16_RF_PLL_FREQ_SEL_MT7620, 0);
rt2800_rfcsr_write(rt2x00dev, 16, rfcsr);
/* D setting (always 0)
* R22[2:0] (D=15, R22[2:0]=<111>)
*/
- rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 22);
rt2x00_set_field8(&rfcsr, RFCSR22_FREQPLAN_D_MT7620, 0);
rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
@@ -3222,40 +3226,40 @@ static void rt2800_config_channel_rf7620(struct rt2x00_dev *rt2x00dev,
* R18<7:0> in rf->rf3
* R19<1:0> in rf->rf4
*/
- rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 17);
rfcsr = rf->rf2;
rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 18, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 18);
rfcsr = rf->rf3;
rt2800_rfcsr_write(rt2x00dev, 18, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 19, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 19);
rt2x00_set_field8(&rfcsr, RFCSR19_K, rf->rf4);
rt2800_rfcsr_write(rt2x00dev, 19, rfcsr);
/* Default: XO=20MHz , SDM mode */
- rt2800_rfcsr_read(rt2x00dev, 16, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 16);
rt2x00_set_field8(&rfcsr, RFCSR16_SDM_MODE_MT7620, 0x80);
rt2800_rfcsr_write(rt2x00dev, 16, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 21);
rt2x00_set_field8(&rfcsr, RFCSR21_BIT8, 1);
rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
rt2x00_set_field8(&rfcsr, RFCSR1_TX2_EN_MT7620,
rt2x00dev->default_ant.tx_chain_num != 1);
rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 2);
rt2x00_set_field8(&rfcsr, RFCSR2_TX2_EN_MT7620,
rt2x00dev->default_ant.tx_chain_num != 1);
rt2x00_set_field8(&rfcsr, RFCSR2_RX2_EN_MT7620,
rt2x00dev->default_ant.rx_chain_num != 1);
rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 42, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 42);
rt2x00_set_field8(&rfcsr, RFCSR42_TX2_EN_MT7620,
rt2x00dev->default_ant.tx_chain_num != 1);
rt2800_rfcsr_write(rt2x00dev, 42, rfcsr);
@@ -3283,7 +3287,7 @@ static void rt2800_config_channel_rf7620(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x28);
}
- rt2800_rfcsr_read(rt2x00dev, 28, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 28);
rt2x00_set_field8(&rfcsr, RFCSR28_CH11_HT40,
conf_is_ht40(conf) && (rf->channel == 11));
rt2800_rfcsr_write(rt2x00dev, 28, rfcsr);
@@ -3296,36 +3300,36 @@ static void rt2800_config_channel_rf7620(struct rt2x00_dev *rt2x00dev,
rx_agc_fc = drv_data->rx_calibration_bw20;
tx_agc_fc = drv_data->tx_calibration_bw20;
}
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 6, &rfcsr);
+ rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 5, 6);
rfcsr &= (~0x3F);
rfcsr |= rx_agc_fc;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 6, rfcsr);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 7, &rfcsr);
+ rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 5, 7);
rfcsr &= (~0x3F);
rfcsr |= rx_agc_fc;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 7, rfcsr);
- rt2800_rfcsr_read_bank(rt2x00dev, 7, 6, &rfcsr);
+ rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 7, 6);
rfcsr &= (~0x3F);
rfcsr |= rx_agc_fc;
rt2800_rfcsr_write_bank(rt2x00dev, 7, 6, rfcsr);
- rt2800_rfcsr_read_bank(rt2x00dev, 7, 7, &rfcsr);
+ rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 7, 7);
rfcsr &= (~0x3F);
rfcsr |= rx_agc_fc;
rt2800_rfcsr_write_bank(rt2x00dev, 7, 7, rfcsr);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 58, &rfcsr);
+ rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 5, 58);
rfcsr &= (~0x3F);
rfcsr |= tx_agc_fc;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 58, rfcsr);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 59, &rfcsr);
+ rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 5, 59);
rfcsr &= (~0x3F);
rfcsr |= tx_agc_fc;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 59, rfcsr);
- rt2800_rfcsr_read_bank(rt2x00dev, 7, 58, &rfcsr);
+ rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 7, 58);
rfcsr &= (~0x3F);
rfcsr |= tx_agc_fc;
rt2800_rfcsr_write_bank(rt2x00dev, 7, 58, rfcsr);
- rt2800_rfcsr_read_bank(rt2x00dev, 7, 59, &rfcsr);
+ rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 7, 59);
rfcsr &= (~0x3F);
rfcsr |= tx_agc_fc;
rt2800_rfcsr_write_bank(rt2x00dev, 7, 59, rfcsr);
@@ -3350,34 +3354,33 @@ static void rt2800_config_alc(struct rt2x00_dev *rt2x00dev,
if (max_power > 0x2f)
max_power = 0x2f;
- rt2800_register_read(rt2x00dev, TX_ALC_CFG_0, &reg);
+ reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_0);
rt2x00_set_field32(&reg, TX_ALC_CFG_0_CH_INIT_0, power_level);
rt2x00_set_field32(&reg, TX_ALC_CFG_0_CH_INIT_1, power_level);
rt2x00_set_field32(&reg, TX_ALC_CFG_0_LIMIT_0, max_power);
rt2x00_set_field32(&reg, TX_ALC_CFG_0_LIMIT_1, max_power);
- rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_INTERNAL_TX_ALC)) {
/* init base power by eeprom target power */
- rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_INIT,
- &target_power);
+ target_power = rt2800_eeprom_read(rt2x00dev,
+ EEPROM_TXPOWER_INIT);
rt2x00_set_field32(&reg, TX_ALC_CFG_0_CH_INIT_0, target_power);
rt2x00_set_field32(&reg, TX_ALC_CFG_0_CH_INIT_1, target_power);
}
rt2800_register_write(rt2x00dev, TX_ALC_CFG_0, reg);
- rt2800_register_read(rt2x00dev, TX_ALC_CFG_1, &reg);
+ reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_1);
rt2x00_set_field32(&reg, TX_ALC_CFG_1_TX_TEMP_COMP, 0);
rt2800_register_write(rt2x00dev, TX_ALC_CFG_1, reg);
/* Save MAC SYS CTRL registers */
- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &mac_sys_ctrl);
+ mac_sys_ctrl = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
/* Disable Tx/Rx */
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0);
/* Check MAC Tx/Rx idle */
for (i = 0; i < 10000; i++) {
- rt2800_register_read(rt2x00dev, MAC_STATUS_CFG,
- &mac_status);
+ mac_status = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG);
if (mac_status & 0x3)
usleep_range(50, 200);
else
@@ -3388,7 +3391,7 @@ static void rt2800_config_alc(struct rt2x00_dev *rt2x00dev,
rt2x00_warn(rt2x00dev, "Wait MAC Status to MAX !!!\n");
if (chan->center_freq > 2457) {
- rt2800_bbp_read(rt2x00dev, 30, &bbp);
+ bbp = rt2800_bbp_read(rt2x00dev, 30);
bbp = 0x40;
rt2800_bbp_write(rt2x00dev, 30, bbp);
rt2800_rfcsr_write(rt2x00dev, 39, 0);
@@ -3397,7 +3400,7 @@ static void rt2800_config_alc(struct rt2x00_dev *rt2x00dev,
else
rt2800_rfcsr_write(rt2x00dev, 42, 0x7b);
} else {
- rt2800_bbp_read(rt2x00dev, 30, &bbp);
+ bbp = rt2800_bbp_read(rt2x00dev, 30);
bbp = 0x1f;
rt2800_bbp_write(rt2x00dev, 30, bbp);
rt2800_rfcsr_write(rt2x00dev, 39, 0x80);
@@ -3418,7 +3421,7 @@ static void rt2800_bbp_write_with_rx_chain(struct rt2x00_dev *rt2x00dev,
u8 chain, reg;
for (chain = 0; chain < rt2x00dev->default_ant.rx_chain_num; chain++) {
- rt2800_bbp_read(rt2x00dev, 27, &reg);
+ reg = rt2800_bbp_read(rt2x00dev, 27);
rt2x00_set_field8(&reg, BBP27_RX_CHAIN_SEL, chain);
rt2800_bbp_write(rt2x00dev, 27, reg);
@@ -3597,7 +3600,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2x00_rf(rt2x00dev, RF5372) ||
rt2x00_rf(rt2x00dev, RF5390) ||
rt2x00_rf(rt2x00dev, RF5392)) {
- rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 30);
if (rt2x00_rf(rt2x00dev, RF3322)) {
rt2x00_set_field8(&rfcsr, RF3322_RFCSR30_TX_H20M,
conf_is_ht40(conf));
@@ -3611,7 +3614,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
}
rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 3);
rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
}
@@ -3690,7 +3693,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2800_bbp_write(rt2x00dev, 75, 0x50);
}
- rt2800_register_read(rt2x00dev, TX_BAND_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, TX_BAND_CFG);
rt2x00_set_field32(&reg, TX_BAND_CFG_HT40_MINUS, conf_is_ht40_minus(conf));
rt2x00_set_field32(&reg, TX_BAND_CFG_A, rf->channel > 14);
rt2x00_set_field32(&reg, TX_BAND_CFG_BG, rf->channel <= 14);
@@ -3699,7 +3702,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
if (rt2x00_rt(rt2x00dev, RT3572))
rt2800_rfcsr_write(rt2x00dev, 8, 0);
- rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin);
+ tx_pin = rt2800_register_read(rt2x00dev, TX_PIN_CFG);
switch (rt2x00dev->default_ant.tx_chain_num) {
case 3:
@@ -3765,7 +3768,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
}
if (rt2x00_rt(rt2x00dev, RT3593)) {
- rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, GPIO_CTRL);
/* Band selection */
if (rt2x00_is_usb(rt2x00dev) ||
@@ -3832,11 +3835,11 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2800_iq_calibrate(rt2x00dev, rf->channel);
}
- rt2800_bbp_read(rt2x00dev, 4, &bbp);
+ bbp = rt2800_bbp_read(rt2x00dev, 4);
rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
rt2800_bbp_write(rt2x00dev, 4, bbp);
- rt2800_bbp_read(rt2x00dev, 3, &bbp);
+ bbp = rt2800_bbp_read(rt2x00dev, 3);
rt2x00_set_field8(&bbp, BBP3_HT40_MINUS, conf_is_ht40_minus(conf));
rt2800_bbp_write(rt2x00dev, 3, bbp);
@@ -3857,16 +3860,16 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
/*
* Clear channel statistic counters
*/
- rt2800_register_read(rt2x00dev, CH_IDLE_STA, &reg);
- rt2800_register_read(rt2x00dev, CH_BUSY_STA, &reg);
- rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &reg);
+ reg = rt2800_register_read(rt2x00dev, CH_IDLE_STA);
+ reg = rt2800_register_read(rt2x00dev, CH_BUSY_STA);
+ reg = rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC);
/*
* Clear update flag
*/
if (rt2x00_rt(rt2x00dev, RT3352) ||
rt2x00_rt(rt2x00dev, RT5350)) {
- rt2800_bbp_read(rt2x00dev, 49, &bbp);
+ bbp = rt2800_bbp_read(rt2x00dev, 49);
rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0);
rt2800_bbp_write(rt2x00dev, 49, bbp);
}
@@ -3883,7 +3886,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
/*
* First check if temperature compensation is supported.
*/
- rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
if (!rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC))
return 0;
@@ -3896,62 +3899,62 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
* Example TSSI bounds 0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00
*/
if (rt2x00dev->curr_band == NL80211_BAND_2GHZ) {
- rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1);
tssi_bounds[0] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_BG1_MINUS4);
tssi_bounds[1] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_BG1_MINUS3);
- rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2);
tssi_bounds[2] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_BG2_MINUS2);
tssi_bounds[3] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_BG2_MINUS1);
- rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3);
tssi_bounds[4] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_BG3_REF);
tssi_bounds[5] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_BG3_PLUS1);
- rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4);
tssi_bounds[6] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_BG4_PLUS2);
tssi_bounds[7] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_BG4_PLUS3);
- rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5);
tssi_bounds[8] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_BG5_PLUS4);
step = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_BG5_AGC_STEP);
} else {
- rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1);
tssi_bounds[0] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_A1_MINUS4);
tssi_bounds[1] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_A1_MINUS3);
- rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2);
tssi_bounds[2] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_A2_MINUS2);
tssi_bounds[3] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_A2_MINUS1);
- rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3);
tssi_bounds[4] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_A3_REF);
tssi_bounds[5] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_A3_PLUS1);
- rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4);
tssi_bounds[6] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_A4_PLUS2);
tssi_bounds[7] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_A4_PLUS3);
- rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5);
tssi_bounds[8] = rt2x00_get_field16(eeprom,
EEPROM_TSSI_BOUND_A5_PLUS4);
@@ -3968,7 +3971,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
/*
* Read current TSSI (BBP 49).
*/
- rt2800_bbp_read(rt2x00dev, 49, &current_tssi);
+ current_tssi = rt2800_bbp_read(rt2x00dev, 49);
/*
* Compare TSSI value (BBP49) with the compensation boundaries
@@ -3997,7 +4000,7 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev,
u8 comp_type;
int comp_value = 0;
- rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA);
/*
* HT40 compensation not required.
@@ -4075,13 +4078,13 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
* .11b data rate need add additional 4dbm
* when calculating eirp txpower.
*/
- rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
- 1, &eeprom);
+ eeprom = rt2800_eeprom_read_from_array(rt2x00dev,
+ EEPROM_TXPOWER_BYRATE,
+ 1);
criterion = rt2x00_get_field16(eeprom,
EEPROM_TXPOWER_BYRATE_RATE0);
- rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER,
- &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER);
if (band == NL80211_BAND_2GHZ)
eirp_txpower_criterion = rt2x00_get_field16(eeprom,
@@ -4150,8 +4153,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
offset += 8;
/* read the next four txpower values */
- rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
- offset, &eeprom);
+ eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+ offset);
/* CCK 1MBS,2MBS */
txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4198,8 +4201,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
TX_PWR_CFG_0_EXT_OFDM12_CH2, txpower);
/* read the next four txpower values */
- rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
- offset + 1, &eeprom);
+ eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+ offset + 1);
/* OFDM 24MBS,36MBS */
txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4235,8 +4238,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
TX_PWR_CFG_7_OFDM54_CH2, txpower);
/* read the next four txpower values */
- rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
- offset + 2, &eeprom);
+ eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+ offset + 2);
/* MCS 0,1 */
txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4283,8 +4286,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
TX_PWR_CFG_2_EXT_MCS6_CH2, txpower);
/* read the next four txpower values */
- rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
- offset + 3, &eeprom);
+ eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+ offset + 3);
/* MCS 7 */
txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4331,8 +4334,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
TX_PWR_CFG_3_EXT_MCS12_CH2, txpower);
/* read the next four txpower values */
- rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
- offset + 4, &eeprom);
+ eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+ offset + 4);
/* MCS 14 */
txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4379,8 +4382,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
TX_PWR_CFG_5_MCS18_CH2, txpower);
/* read the next four txpower values */
- rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
- offset + 5, &eeprom);
+ eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+ offset + 5);
/* MCS 20,21 */
txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4416,8 +4419,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
TX_PWR_CFG_8_MCS23_CH2, txpower);
/* read the next four txpower values */
- rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
- offset + 6, &eeprom);
+ eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+ offset + 6);
/* STBC, MCS 0,1 */
txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4460,8 +4463,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
txpower);
/* read the next four txpower values */
- rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
- offset + 7, &eeprom);
+ eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+ offset + 7);
/* STBC, MCS 7 */
txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4541,8 +4544,9 @@ static void rt2800_config_txpower_rt6352(struct rt2x00_dev *rt2x00dev,
* board vendors expected when they populated the EEPROM...
*/
for (i = 0; i < 5; i++) {
- rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
- i * 2, &eeprom);
+ eeprom = rt2800_eeprom_read_from_array(rt2x00dev,
+ EEPROM_TXPOWER_BYRATE,
+ i * 2);
data = eeprom;
@@ -4558,8 +4562,9 @@ static void rt2800_config_txpower_rt6352(struct rt2x00_dev *rt2x00dev,
gdata |= (t << 8);
- rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
- (i * 2) + 1, &eeprom);
+ eeprom = rt2800_eeprom_read_from_array(rt2x00dev,
+ EEPROM_TXPOWER_BYRATE,
+ (i * 2) + 1);
t = eeprom & 0x3f;
if (t == 32)
@@ -4601,26 +4606,26 @@ static void rt2800_config_txpower_rt6352(struct rt2x00_dev *rt2x00dev,
/* For OFDM 54MBS use value from OFDM 48MBS */
pwreg = 0;
- rt2800_register_read(rt2x00dev, TX_PWR_CFG_1, &reg);
+ reg = rt2800_register_read(rt2x00dev, TX_PWR_CFG_1);
t = rt2x00_get_field32(reg, TX_PWR_CFG_1B_48MBS);
rt2x00_set_field32(&pwreg, TX_PWR_CFG_7B_54MBS, t);
/* For MCS 7 use value from MCS 6 */
- rt2800_register_read(rt2x00dev, TX_PWR_CFG_2, &reg);
+ reg = rt2800_register_read(rt2x00dev, TX_PWR_CFG_2);
t = rt2x00_get_field32(reg, TX_PWR_CFG_2B_MCS6_MCS7);
rt2x00_set_field32(&pwreg, TX_PWR_CFG_7B_MCS7, t);
rt2800_register_write(rt2x00dev, TX_PWR_CFG_7, pwreg);
/* For MCS 15 use value from MCS 14 */
pwreg = 0;
- rt2800_register_read(rt2x00dev, TX_PWR_CFG_3, &reg);
+ reg = rt2800_register_read(rt2x00dev, TX_PWR_CFG_3);
t = rt2x00_get_field32(reg, TX_PWR_CFG_3B_MCS14);
rt2x00_set_field32(&pwreg, TX_PWR_CFG_8B_MCS15, t);
rt2800_register_write(rt2x00dev, TX_PWR_CFG_8, pwreg);
/* For STBC MCS 7 use value from STBC MCS 6 */
pwreg = 0;
- rt2800_register_read(rt2x00dev, TX_PWR_CFG_4, &reg);
+ reg = rt2800_register_read(rt2x00dev, TX_PWR_CFG_4);
t = rt2x00_get_field32(reg, TX_PWR_CFG_4B_STBC_MCS6);
rt2x00_set_field32(&pwreg, TX_PWR_CFG_9B_STBC_MCS7, t);
rt2800_register_write(rt2x00dev, TX_PWR_CFG_9, pwreg);
@@ -4702,7 +4707,7 @@ static void rt2800_config_txpower_rt28xx(struct rt2x00_dev *rt2x00dev,
} else {
power_ctrl = 0;
}
- rt2800_bbp_read(rt2x00dev, 1, &r1);
+ r1 = rt2800_bbp_read(rt2x00dev, 1);
rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);
rt2800_bbp_write(rt2x00dev, 1, r1);
@@ -4713,11 +4718,12 @@ static void rt2800_config_txpower_rt28xx(struct rt2x00_dev *rt2x00dev,
if (offset > TX_PWR_CFG_4)
break;
- rt2800_register_read(rt2x00dev, offset, &reg);
+ reg = rt2800_register_read(rt2x00dev, offset);
/* read the next four txpower values */
- rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
- i, &eeprom);
+ eeprom = rt2800_eeprom_read_from_array(rt2x00dev,
+ EEPROM_TXPOWER_BYRATE,
+ i);
is_rate_b = i ? 0 : 1;
/*
@@ -4765,8 +4771,9 @@ static void rt2800_config_txpower_rt28xx(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE3, txpower);
/* read the next four txpower values */
- rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
- i + 1, &eeprom);
+ eeprom = rt2800_eeprom_read_from_array(rt2x00dev,
+ EEPROM_TXPOWER_BYRATE,
+ i + 1);
is_rate_b = 0;
/*
@@ -4853,7 +4860,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
* periodically to adjust the frequency to be precision.
*/
- rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin);
+ tx_pin = rt2800_register_read(rt2x00dev, TX_PIN_CFG);
tx_pin &= TX_PIN_CFG_PA_PE_DISABLE;
rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
@@ -4864,7 +4871,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
case RF3022:
case RF3320:
case RF3052:
- rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 7);
rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
break;
@@ -4879,7 +4886,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
case RF5390:
case RF5392:
case RF5592:
- rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 3);
rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
min_sleep = 1000;
@@ -4887,7 +4894,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
case RF7620:
rt2800_rfcsr_write(rt2x00dev, 5, 0x40);
rt2800_rfcsr_write(rt2x00dev, 4, 0x0C);
- rt2800_rfcsr_read(rt2x00dev, 4, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 4);
rt2x00_set_field8(&rfcsr, RFCSR4_VCOCAL_EN, 1);
rt2800_rfcsr_write(rt2x00dev, 4, rfcsr);
min_sleep = 2000;
@@ -4901,7 +4908,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
if (min_sleep > 0)
usleep_range(min_sleep, min_sleep * 2);
- rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin);
+ tx_pin = rt2800_register_read(rt2x00dev, TX_PIN_CFG);
if (rt2x00dev->rf_channel <= 14) {
switch (rt2x00dev->default_ant.tx_chain_num) {
case 3:
@@ -4975,7 +4982,7 @@ static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2800_register_read(rt2x00dev, TX_RTY_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, TX_RTY_CFG);
rt2x00_set_field32(&reg, TX_RTY_CFG_SHORT_RTY_LIMIT,
libconf->conf->short_frame_max_tx_count);
rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT,
@@ -4994,7 +5001,7 @@ static void rt2800_config_ps(struct rt2x00_dev *rt2x00dev,
if (state == STATE_SLEEP) {
rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0);
- rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG);
rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5);
rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE,
libconf->conf->listen_interval - 1);
@@ -5003,7 +5010,7 @@ static void rt2800_config_ps(struct rt2x00_dev *rt2x00dev,
rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
} else {
- rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG);
rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
@@ -5046,7 +5053,7 @@ void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual)
/*
* Update FCS error count from register.
*/
- rt2800_register_read(rt2x00dev, RX_STA_CNT0, &reg);
+ reg = rt2800_register_read(rt2x00dev, RX_STA_CNT0);
qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR);
}
EXPORT_SYMBOL_GPL(rt2800_link_stats);
@@ -5175,7 +5182,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
- rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, BCN_TIME_CFG);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL, 1600);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, 0);
@@ -5186,43 +5193,43 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_config_filter(rt2x00dev, FIF_ALLMULTI);
- rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG);
rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME, 9);
rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
if (rt2x00_rt(rt2x00dev, RT3290)) {
- rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL);
if (rt2x00_get_field32(reg, WLAN_EN) == 1) {
rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 1);
rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
}
- rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, CMB_CTRL);
if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) {
rt2x00_set_field32(&reg, LDO0_EN, 1);
rt2x00_set_field32(&reg, LDO_BGSEL, 3);
rt2800_register_write(rt2x00dev, CMB_CTRL, reg);
}
- rt2800_register_read(rt2x00dev, OSC_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, OSC_CTRL);
rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
rt2x00_set_field32(&reg, OSC_CAL_REQ, 1);
rt2x00_set_field32(&reg, OSC_REF_CYCLE, 0x27);
rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
- rt2800_register_read(rt2x00dev, COEX_CFG0, &reg);
+ reg = rt2800_register_read(rt2x00dev, COEX_CFG0);
rt2x00_set_field32(&reg, COEX_CFG_ANT, 0x5e);
rt2800_register_write(rt2x00dev, COEX_CFG0, reg);
- rt2800_register_read(rt2x00dev, COEX_CFG2, &reg);
+ reg = rt2800_register_read(rt2x00dev, COEX_CFG2);
rt2x00_set_field32(&reg, BT_COEX_CFG1, 0x00);
rt2x00_set_field32(&reg, BT_COEX_CFG0, 0x17);
rt2x00_set_field32(&reg, WL_COEX_CFG1, 0x93);
rt2x00_set_field32(&reg, WL_COEX_CFG0, 0x7f);
rt2800_register_write(rt2x00dev, COEX_CFG2, reg);
- rt2800_register_read(rt2x00dev, PLL_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, PLL_CTRL);
rt2x00_set_field32(&reg, PLL_CONTROL, 1);
rt2800_register_write(rt2x00dev, PLL_CTRL, reg);
}
@@ -5243,8 +5250,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
- rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
- &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
rt2800_register_write(rt2x00dev, TX_SW_CFG2,
0x0000002c);
@@ -5279,8 +5285,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
if (rt2x00_rt_rev_lt(rt2x00dev, RT3593, REV_RT3593E)) {
- rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
- &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
if (rt2x00_get_field16(eeprom,
EEPROM_NIC_CONF1_DAC_TEST))
rt2800_register_write(rt2x00dev, TX_SW_CFG2,
@@ -5319,7 +5324,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
0x3630363A);
rt2800_register_write(rt2x00dev, TX1_RF_GAIN_CORRECT,
0x3630363A);
- rt2800_register_read(rt2x00dev, TX_ALC_CFG_1, &reg);
+ reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_1);
rt2x00_set_field32(&reg, TX_ALC_CFG_1_ROS_BUSY_EN, 0);
rt2800_register_write(rt2x00dev, TX_ALC_CFG_1, reg);
} else {
@@ -5327,7 +5332,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
}
- rt2800_register_read(rt2x00dev, TX_LINK_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, TX_LINK_CFG);
rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32);
rt2x00_set_field32(&reg, TX_LINK_CFG_MFB_ENABLE, 0);
rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0);
@@ -5338,13 +5343,13 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFS, 0);
rt2800_register_write(rt2x00dev, TX_LINK_CFG, reg);
- rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG);
rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9);
rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 32);
rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10);
rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
- rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, MAX_LEN_CFG);
rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
if (rt2x00_is_usb(rt2x00dev)) {
drv_data->max_psdu = 3;
@@ -5360,7 +5365,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_MPDU, 10);
rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg);
- rt2800_register_read(rt2x00dev, LED_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, LED_CFG);
rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, 70);
rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, 30);
rt2x00_set_field32(&reg, LED_CFG_SLOW_BLINK_PERIOD, 3);
@@ -5372,7 +5377,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f);
- rt2800_register_read(rt2x00dev, TX_RTY_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, TX_RTY_CFG);
rt2x00_set_field32(&reg, TX_RTY_CFG_SHORT_RTY_LIMIT, 2);
rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT, 2);
rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_THRE, 2000);
@@ -5381,7 +5386,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1);
rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg);
- rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, AUTO_RSP_CFG);
rt2x00_set_field32(&reg, AUTO_RSP_CFG_AUTORESPONDER, 1);
rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY, 1);
rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MMODE, 1);
@@ -5391,7 +5396,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0);
rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
- rt2800_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, CCK_PROT_CFG);
rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_RATE, 3);
rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_CTRL, 0);
rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_NAV_SHORT, 1);
@@ -5404,7 +5409,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, CCK_PROT_CFG_RTS_TH_EN, 1);
rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);
- rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, OFDM_PROT_CFG);
rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_RATE, 3);
rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL, 0);
rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_NAV_SHORT, 1);
@@ -5417,7 +5422,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, OFDM_PROT_CFG_RTS_TH_EN, 1);
rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
- rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, MM20_PROT_CFG);
rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, 0x4004);
rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, 1);
rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_NAV_SHORT, 1);
@@ -5430,7 +5435,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, MM20_PROT_CFG_RTS_TH_EN, 0);
rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
- rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, MM40_PROT_CFG);
rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, 0x4084);
rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, 1);
rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_NAV_SHORT, 1);
@@ -5443,7 +5448,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, MM40_PROT_CFG_RTS_TH_EN, 0);
rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
- rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, GF20_PROT_CFG);
rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, 0x4004);
rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, 1);
rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_NAV_SHORT, 1);
@@ -5456,7 +5461,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, GF20_PROT_CFG_RTS_TH_EN, 0);
rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
- rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, GF40_PROT_CFG);
rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, 0x4084);
rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, 1);
rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_NAV_SHORT, 1);
@@ -5472,7 +5477,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
if (rt2x00_is_usb(rt2x00dev)) {
rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
- rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
@@ -5489,7 +5494,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
* The legacy driver also sets TXOP_CTRL_CFG_RESERVED_TRUN_EN to 1
* although it is reserved.
*/
- rt2800_register_read(rt2x00dev, TXOP_CTRL_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, TXOP_CTRL_CFG);
rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TIMEOUT_TRUN_EN, 1);
rt2x00_set_field32(&reg, TXOP_CTRL_CFG_AC_TRUN_EN, 1);
rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN, 1);
@@ -5505,7 +5510,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
- rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, TX_RTS_CFG);
rt2x00_set_field32(&reg, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 7);
rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES,
IEEE80211_MAX_RTS_THRESHOLD);
@@ -5521,7 +5526,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
* connection problems with 11g + CTS protection. Hence, use the same
* defaults as the Ralink driver: 16 for both, CCK and OFDM SIFS.
*/
- rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, XIFS_TIME_CFG);
rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, 16);
rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, 16);
rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4);
@@ -5551,16 +5556,16 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_clear_beacon_register(rt2x00dev, i);
if (rt2x00_is_usb(rt2x00dev)) {
- rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
+ reg = rt2800_register_read(rt2x00dev, US_CYC_CNT);
rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, 30);
rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
} else if (rt2x00_is_pcie(rt2x00dev)) {
- rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
+ reg = rt2800_register_read(rt2x00dev, US_CYC_CNT);
rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, 125);
rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
}
- rt2800_register_read(rt2x00dev, HT_FBK_CFG0, &reg);
+ reg = rt2800_register_read(rt2x00dev, HT_FBK_CFG0);
rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS0FBK, 0);
rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS1FBK, 0);
rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS2FBK, 1);
@@ -5571,7 +5576,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS7FBK, 6);
rt2800_register_write(rt2x00dev, HT_FBK_CFG0, reg);
- rt2800_register_read(rt2x00dev, HT_FBK_CFG1, &reg);
+ reg = rt2800_register_read(rt2x00dev, HT_FBK_CFG1);
rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS8FBK, 8);
rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS9FBK, 8);
rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS10FBK, 9);
@@ -5582,7 +5587,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS15FBK, 14);
rt2800_register_write(rt2x00dev, HT_FBK_CFG1, reg);
- rt2800_register_read(rt2x00dev, LG_FBK_CFG0, &reg);
+ reg = rt2800_register_read(rt2x00dev, LG_FBK_CFG0);
rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS0FBK, 8);
rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS1FBK, 8);
rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS2FBK, 9);
@@ -5593,7 +5598,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS7FBK, 14);
rt2800_register_write(rt2x00dev, LG_FBK_CFG0, reg);
- rt2800_register_read(rt2x00dev, LG_FBK_CFG1, &reg);
+ reg = rt2800_register_read(rt2x00dev, LG_FBK_CFG1);
rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS0FBK, 0);
rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS1FBK, 0);
rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS2FBK, 1);
@@ -5603,7 +5608,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
/*
* Do not force the BA window size, we use the TXWI to set it
*/
- rt2800_register_read(rt2x00dev, AMPDU_BA_WINSIZE, &reg);
+ reg = rt2800_register_read(rt2x00dev, AMPDU_BA_WINSIZE);
rt2x00_set_field32(&reg, AMPDU_BA_WINSIZE_FORCE_WINSIZE_ENABLE, 0);
rt2x00_set_field32(&reg, AMPDU_BA_WINSIZE_FORCE_WINSIZE, 0);
rt2800_register_write(rt2x00dev, AMPDU_BA_WINSIZE, reg);
@@ -5613,24 +5618,24 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
*/
- rt2800_register_read(rt2x00dev, RX_STA_CNT0, &reg);
- rt2800_register_read(rt2x00dev, RX_STA_CNT1, &reg);
- rt2800_register_read(rt2x00dev, RX_STA_CNT2, &reg);
- rt2800_register_read(rt2x00dev, TX_STA_CNT0, &reg);
- rt2800_register_read(rt2x00dev, TX_STA_CNT1, &reg);
- rt2800_register_read(rt2x00dev, TX_STA_CNT2, &reg);
+ reg = rt2800_register_read(rt2x00dev, RX_STA_CNT0);
+ reg = rt2800_register_read(rt2x00dev, RX_STA_CNT1);
+ reg = rt2800_register_read(rt2x00dev, RX_STA_CNT2);
+ reg = rt2800_register_read(rt2x00dev, TX_STA_CNT0);
+ reg = rt2800_register_read(rt2x00dev, TX_STA_CNT1);
+ reg = rt2800_register_read(rt2x00dev, TX_STA_CNT2);
/*
* Setup leadtime for pre tbtt interrupt to 6ms
*/
- rt2800_register_read(rt2x00dev, INT_TIMER_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, INT_TIMER_CFG);
rt2x00_set_field32(&reg, INT_TIMER_CFG_PRE_TBTT_TIMER, 6 << 4);
rt2800_register_write(rt2x00dev, INT_TIMER_CFG, reg);
/*
* Set up channel statistics timer
*/
- rt2800_register_read(rt2x00dev, CH_TIME_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, CH_TIME_CFG);
rt2x00_set_field32(&reg, CH_TIME_CFG_EIFS_BUSY, 1);
rt2x00_set_field32(&reg, CH_TIME_CFG_NAV_BUSY, 1);
rt2x00_set_field32(&reg, CH_TIME_CFG_RX_BUSY, 1);
@@ -5647,7 +5652,7 @@ static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)
u32 reg;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2800_register_read(rt2x00dev, MAC_STATUS_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG);
if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY))
return 0;
@@ -5672,7 +5677,7 @@ static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
msleep(1);
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2800_bbp_read(rt2x00dev, 0, &value);
+ value = rt2800_bbp_read(rt2x00dev, 0);
if ((value != 0xff) && (value != 0x00))
return 0;
udelay(REGISTER_BUSY_DELAY);
@@ -5686,7 +5691,7 @@ static void rt2800_bbp4_mac_if_ctrl(struct rt2x00_dev *rt2x00dev)
{
u8 value;
- rt2800_bbp_read(rt2x00dev, 4, &value);
+ value = rt2800_bbp_read(rt2x00dev, 4);
rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
rt2800_bbp_write(rt2x00dev, 4, value);
}
@@ -5743,8 +5748,8 @@ static void rt2800_disable_unused_dac_adc(struct rt2x00_dev *rt2x00dev)
u16 eeprom;
u8 value;
- rt2800_bbp_read(rt2x00dev, 138, &value);
- rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+ value = rt2800_bbp_read(rt2x00dev, 138);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
value |= 0x20;
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
@@ -5927,12 +5932,12 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 155, 0x3b);
rt2800_bbp_write(rt2x00dev, 253, 0x04);
- rt2800_bbp_read(rt2x00dev, 47, &value);
+ value = rt2800_bbp_read(rt2x00dev, 47);
rt2x00_set_field8(&value, BBP47_TSSI_ADC6, 1);
rt2800_bbp_write(rt2x00dev, 47, value);
/* Use 5-bit ADC for Acquisition and 8-bit ADC for data */
- rt2800_bbp_read(rt2x00dev, 3, &value);
+ value = rt2800_bbp_read(rt2x00dev, 3);
rt2x00_set_field8(&value, BBP3_ADC_MODE_SWITCH, 1);
rt2x00_set_field8(&value, BBP3_ADC_INIT_MODE, 1);
rt2800_bbp_write(rt2x00dev, 3, value);
@@ -6191,7 +6196,7 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
rt2800_disable_unused_dac_adc(rt2x00dev);
- rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
div_mode = rt2x00_get_field16(eeprom,
EEPROM_NIC_CONF1_ANT_DIVERSITY);
ant = (div_mode == 3) ? 1 : 0;
@@ -6200,7 +6205,7 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
if (rt2x00_has_cap_bt_coexist(rt2x00dev)) {
u32 reg;
- rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, GPIO_CTRL);
rt2x00_set_field32(&reg, GPIO_CTRL_DIR3, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_DIR6, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_VAL3, 0);
@@ -6219,7 +6224,7 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 154, 0); /* Clear previously selected antenna */
}
- rt2800_bbp_read(rt2x00dev, 152, &value);
+ value = rt2800_bbp_read(rt2x00dev, 152);
if (ant == 0)
rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1);
else
@@ -6237,7 +6242,7 @@ static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev)
rt2800_init_bbp_early(rt2x00dev);
- rt2800_bbp_read(rt2x00dev, 105, &value);
+ value = rt2800_bbp_read(rt2x00dev, 105);
rt2x00_set_field8(&value, BBP105_MLD,
rt2x00dev->default_ant.rx_chain_num == 2);
rt2800_bbp_write(rt2x00dev, 105, value);
@@ -6277,10 +6282,10 @@ static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev)
rt2800_bbp4_mac_if_ctrl(rt2x00dev);
- rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
div_mode = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY);
ant = (div_mode == 3) ? 1 : 0;
- rt2800_bbp_read(rt2x00dev, 152, &value);
+ value = rt2800_bbp_read(rt2x00dev, 152);
if (ant == 0) {
/* Main antenna */
rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1);
@@ -6291,7 +6296,7 @@ static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 152, value);
if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) {
- rt2800_bbp_read(rt2x00dev, 254, &value);
+ value = rt2800_bbp_read(rt2x00dev, 254);
rt2x00_set_field8(&value, BBP254_BIT7, 1);
rt2800_bbp_write(rt2x00dev, 254, value);
}
@@ -6317,11 +6322,10 @@ static void rt2800_bbp_dcoc_write(struct rt2x00_dev *rt2x00dev,
rt2800_bbp_write(rt2x00dev, 159, value);
}
-static void rt2800_bbp_dcoc_read(struct rt2x00_dev *rt2x00dev,
- const u8 reg, u8 *value)
+static u8 rt2800_bbp_dcoc_read(struct rt2x00_dev *rt2x00dev, const u8 reg)
{
rt2800_bbp_write(rt2x00dev, 158, reg);
- rt2800_bbp_read(rt2x00dev, 159, value);
+ return rt2800_bbp_read(rt2x00dev, 159);
}
static void rt2800_init_bbp_6352(struct rt2x00_dev *rt2x00dev)
@@ -6329,7 +6333,7 @@ static void rt2800_init_bbp_6352(struct rt2x00_dev *rt2x00dev)
u8 bbp;
/* Apply Maximum Likelihood Detection (MLD) for 2 stream case */
- rt2800_bbp_read(rt2x00dev, 105, &bbp);
+ bbp = rt2800_bbp_read(rt2x00dev, 105);
rt2x00_set_field8(&bbp, BBP105_MLD,
rt2x00dev->default_ant.rx_chain_num == 2);
rt2800_bbp_write(rt2x00dev, 105, bbp);
@@ -6338,7 +6342,7 @@ static void rt2800_init_bbp_6352(struct rt2x00_dev *rt2x00dev)
rt2800_bbp4_mac_if_ctrl(rt2x00dev);
/* Fix I/Q swap issue */
- rt2800_bbp_read(rt2x00dev, 1, &bbp);
+ bbp = rt2800_bbp_read(rt2x00dev, 1);
bbp |= 0x04;
rt2800_bbp_write(rt2x00dev, 1, bbp);
@@ -6578,8 +6582,8 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
}
for (i = 0; i < EEPROM_BBP_SIZE; i++) {
- rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_BBP_START, i,
- &eeprom);
+ eeprom = rt2800_eeprom_read_from_array(rt2x00dev,
+ EEPROM_BBP_START, i);
if (eeprom != 0xffff && eeprom != 0x0000) {
reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
@@ -6593,7 +6597,7 @@ static void rt2800_led_open_drain_enable(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2800_register_read(rt2x00dev, OPT_14_CSR, &reg);
+ reg = rt2800_register_read(rt2x00dev, OPT_14_CSR);
rt2x00_set_field32(&reg, OPT_14_CSR_BIT0, 1);
rt2800_register_write(rt2x00dev, OPT_14_CSR, reg);
}
@@ -6611,15 +6615,15 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, bool bw40,
rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);
- rt2800_bbp_read(rt2x00dev, 4, &bbp);
+ bbp = rt2800_bbp_read(rt2x00dev, 4);
rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40);
rt2800_bbp_write(rt2x00dev, 4, bbp);
- rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 31);
rt2x00_set_field8(&rfcsr, RFCSR31_RX_H20M, bw40);
rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 22);
rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1);
rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
@@ -6632,7 +6636,7 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, bool bw40,
rt2800_bbp_write(rt2x00dev, 25, 0x90);
msleep(1);
- rt2800_bbp_read(rt2x00dev, 55, &passband);
+ passband = rt2800_bbp_read(rt2x00dev, 55);
if (passband)
break;
}
@@ -6646,7 +6650,7 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, bool bw40,
rt2800_bbp_write(rt2x00dev, 25, 0x90);
msleep(1);
- rt2800_bbp_read(rt2x00dev, 55, &stopband);
+ stopband = rt2800_bbp_read(rt2x00dev, 55);
if ((passband - stopband) <= filter_target) {
rfcsr24++;
@@ -6668,7 +6672,7 @@ static void rt2800_rf_init_calibration(struct rt2x00_dev *rt2x00dev,
{
u8 rfcsr;
- rt2800_rfcsr_read(rt2x00dev, rf_reg, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, rf_reg);
rt2x00_set_field8(&rfcsr, FIELD8(0x80), 1);
rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr);
msleep(1);
@@ -6702,22 +6706,22 @@ static void rt2800_rx_filter_calibration(struct rt2x00_dev *rt2x00dev)
/*
* 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);
+ drv_data->bbp25 = rt2800_bbp_read(rt2x00dev, 25);
+ drv_data->bbp26 = rt2800_bbp_read(rt2x00dev, 26);
/*
* Set back to initial state
*/
rt2800_bbp_write(rt2x00dev, 24, 0);
- rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 22);
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);
+ bbp = rt2800_bbp_read(rt2x00dev, 4);
rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
rt2800_bbp_write(rt2x00dev, 4, bbp);
}
@@ -6728,7 +6732,7 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
u8 min_gain, rfcsr, bbp;
u16 eeprom;
- rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 17);
rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);
if (rt2x00_rt(rt2x00dev, RT3070) ||
@@ -6749,8 +6753,8 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt(rt2x00dev, RT3090)) {
/* Turn off unused DAC1 and ADC1 to reduce power consumption */
- rt2800_bbp_read(rt2x00dev, 138, &bbp);
- rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+ bbp = rt2800_bbp_read(rt2x00dev, 138);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0);
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)
@@ -6759,7 +6763,7 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
}
if (rt2x00_rt(rt2x00dev, RT3070)) {
- rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 27);
if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F))
rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3);
else
@@ -6771,7 +6775,7 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
} else if (rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3390)) {
- rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
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);
@@ -6779,15 +6783,15 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 15, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 15);
rt2x00_set_field8(&rfcsr, RFCSR15_TX_LO2_EN, 0);
rt2800_rfcsr_write(rt2x00dev, 15, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 20);
rt2x00_set_field8(&rfcsr, RFCSR20_RX_LO1_EN, 0);
rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 21);
rt2x00_set_field8(&rfcsr, RFCSR21_RX_LO2_EN, 0);
rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
}
@@ -6799,30 +6803,30 @@ static void rt2800_normal_mode_setup_3593(struct rt2x00_dev *rt2x00dev)
u8 rfcsr;
u8 tx_gain;
- rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 50);
rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO2_EN, 0);
rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 51);
tx_gain = rt2x00_get_field8(drv_data->txmixer_gain_24g,
RFCSR17_TXMIXER_GAIN);
rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, tx_gain);
rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 38);
rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0);
rt2800_rfcsr_write(rt2x00dev, 38, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 39, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 39);
rt2x00_set_field8(&rfcsr, RFCSR39_RX_LO2_EN, 0);
rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
- rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 30);
rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
@@ -6835,25 +6839,25 @@ static void rt2800_normal_mode_setup_5xxx(struct rt2x00_dev *rt2x00dev)
u16 eeprom;
/* Turn off unused DAC1 and ADC1 to reduce power consumption */
- rt2800_bbp_read(rt2x00dev, 138, &reg);
- rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+ reg = rt2800_bbp_read(rt2x00dev, 138);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0);
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);
+ reg = rt2800_rfcsr_read(rt2x00dev, 38);
rt2x00_set_field8(&reg, RFCSR38_RX_LO1_EN, 0);
rt2800_rfcsr_write(rt2x00dev, 38, reg);
- rt2800_rfcsr_read(rt2x00dev, 39, &reg);
+ reg = rt2800_rfcsr_read(rt2x00dev, 39);
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);
+ reg = rt2800_rfcsr_read(rt2x00dev, 30);
rt2x00_set_field8(&reg, RFCSR30_RX_VCM, 2);
rt2800_rfcsr_write(rt2x00dev, 30, reg);
}
@@ -6926,7 +6930,7 @@ static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);
if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
- rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ reg = rt2800_register_read(rt2x00dev, LDO_CFG0);
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);
@@ -6934,16 +6938,15 @@ static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev)
rt2x00_rt(rt2x00dev, RT3090)) {
rt2800_rfcsr_write(rt2x00dev, 31, 0x14);
- rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 6);
rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
- rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ reg = rt2800_register_read(rt2x00dev, LDO_CFG0);
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)) {
- rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
- &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
else
@@ -6951,7 +6954,7 @@ static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev)
}
rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
- rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+ reg = rt2800_register_read(rt2x00dev, GPIO_SWITCH);
rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
}
@@ -7020,7 +7023,7 @@ static void rt2800_init_rfcsr_3290(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
- rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 29);
rt2x00_set_field8(&rfcsr, RFCSR29_RSSI_GAIN, 3);
rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
@@ -7166,7 +7169,7 @@ static void rt2800_init_rfcsr_3390(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 30, 0x20);
rt2800_rfcsr_write(rt2x00dev, 31, 0x0f);
- rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+ reg = rt2800_register_read(rt2x00dev, GPIO_SWITCH);
rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
@@ -7218,16 +7221,16 @@ static void rt2800_init_rfcsr_3572(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 30, 0x09);
rt2800_rfcsr_write(rt2x00dev, 31, 0x10);
- rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 6);
rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
- rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ reg = rt2800_register_read(rt2x00dev, LDO_CFG0);
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);
+ reg = rt2800_register_read(rt2x00dev, LDO_CFG0);
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);
@@ -7242,7 +7245,7 @@ static void rt3593_post_bbp_init(struct rt2x00_dev *rt2x00dev)
u8 bbp;
bool txbf_enabled = false; /* FIXME */
- rt2800_bbp_read(rt2x00dev, 105, &bbp);
+ bbp = rt2800_bbp_read(rt2x00dev, 105);
if (rt2x00dev->default_ant.rx_chain_num == 1)
rt2x00_set_field8(&bbp, BBP105_MLD, 0);
else
@@ -7291,7 +7294,7 @@ static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev)
u8 rfcsr;
/* Disable GPIO #4 and #7 function for LAN PE control */
- rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+ reg = rt2800_register_read(rt2x00dev, GPIO_SWITCH);
rt2x00_set_field32(&reg, GPIO_SWITCH_4, 0);
rt2x00_set_field32(&reg, GPIO_SWITCH_7, 0);
rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
@@ -7332,22 +7335,22 @@ static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev)
/* Initiate calibration */
/* TODO: use rt2800_rf_init_calibration ? */
- rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 2);
rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
rt2800_freq_cal_mode1(rt2x00dev);
- rt2800_rfcsr_read(rt2x00dev, 18, &rfcsr);
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 18);
rt2x00_set_field8(&rfcsr, RFCSR18_XO_TUNE_BYPASS, 1);
rt2800_rfcsr_write(rt2x00dev, 18, rfcsr);
- rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ reg = rt2800_register_read(rt2x00dev, LDO_CFG0);
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);
usleep_range(1000, 1500);
- rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ reg = rt2800_register_read(rt2x00dev, LDO_CFG0);
rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
@@ -7356,8 +7359,8 @@ static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev)
drv_data->calibration_bw40 = 0x2f;
/* 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);
+ drv_data->bbp25 = rt2800_bbp_read(rt2x00dev, 25);
+ drv_data->bbp26 = rt2800_bbp_read(rt2x00dev, 26);
rt2800_led_open_drain_enable(rt2x00dev);
rt2800_normal_mode_setup_3593(rt2x00dev);
@@ -7651,19 +7654,19 @@ static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
{
u8 bbp_val;
- rt2800_bbp_read(rt2x00dev, 21, &bbp_val);
+ bbp_val = rt2800_bbp_read(rt2x00dev, 21);
bbp_val |= 0x1;
rt2800_bbp_write(rt2x00dev, 21, bbp_val);
usleep_range(100, 200);
if (set_bw) {
- rt2800_bbp_read(rt2x00dev, 4, &bbp_val);
+ bbp_val = rt2800_bbp_read(rt2x00dev, 4);
rt2x00_set_field8(&bbp_val, BBP4_BANDWIDTH, 2 * is_ht40);
rt2800_bbp_write(rt2x00dev, 4, bbp_val);
usleep_range(100, 200);
}
- rt2800_bbp_read(rt2x00dev, 21, &bbp_val);
+ bbp_val = rt2800_bbp_read(rt2x00dev, 21);
bbp_val &= (~0x1);
rt2800_bbp_write(rt2x00dev, 21, bbp_val);
usleep_range(100, 200);
@@ -7680,7 +7683,7 @@ static int rt2800_rf_lp_config(struct rt2x00_dev *rt2x00dev, bool btxcal)
rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x06);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 17, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 17);
rf_val |= 0x80;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 17, rf_val);
@@ -7688,11 +7691,11 @@ static int rt2800_rf_lp_config(struct rt2x00_dev *rt2x00dev, bool btxcal)
rt2800_rfcsr_write_bank(rt2x00dev, 5, 18, 0xC1);
rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, 0x20);
rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, 0x02);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 3, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 3);
rf_val &= (~0x3F);
rf_val |= 0x3F;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 3, rf_val);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 4, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4);
rf_val &= (~0x3F);
rf_val |= 0x3F;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, rf_val);
@@ -7701,11 +7704,11 @@ static int rt2800_rf_lp_config(struct rt2x00_dev *rt2x00dev, bool btxcal)
rt2800_rfcsr_write_bank(rt2x00dev, 5, 18, 0xF1);
rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, 0x18);
rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, 0x02);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 3, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 3);
rf_val &= (~0x3F);
rf_val |= 0x34;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 3, rf_val);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 4, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4);
rf_val &= (~0x3F);
rf_val |= 0x34;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, rf_val);
@@ -7725,14 +7728,14 @@ static char rt2800_lp_tx_filter_bw_cal(struct rt2x00_dev *rt2x00dev)
cnt = 0;
do {
usleep_range(500, 2000);
- rt2800_bbp_read(rt2x00dev, 159, &bbp_val);
+ bbp_val = rt2800_bbp_read(rt2x00dev, 159);
if (bbp_val == 0x02 || cnt == 20)
break;
cnt++;
} while (cnt < 20);
- rt2800_bbp_dcoc_read(rt2x00dev, 0x39, &bbp_val);
+ bbp_val = rt2800_bbp_dcoc_read(rt2x00dev, 0x39);
cal_val = bbp_val & 0x7F;
if (cal_val >= 0x40)
cal_val -= 128;
@@ -7761,67 +7764,67 @@ static void rt2800_bw_filter_calibration(struct rt2x00_dev *rt2x00dev,
u32 MAC_RF_CONTROL0, MAC_RF_BYPASS0;
/* Save MAC registers */
- rt2800_register_read(rt2x00dev, RF_CONTROL0, &MAC_RF_CONTROL0);
- rt2800_register_read(rt2x00dev, RF_BYPASS0, &MAC_RF_BYPASS0);
+ MAC_RF_CONTROL0 = rt2800_register_read(rt2x00dev, RF_CONTROL0);
+ MAC_RF_BYPASS0 = rt2800_register_read(rt2x00dev, RF_BYPASS0);
/* save BBP registers */
- rt2800_bbp_read(rt2x00dev, 23, &savebbpr23);
+ savebbpr23 = rt2800_bbp_read(rt2x00dev, 23);
- rt2800_bbp_dcoc_read(rt2x00dev, 0, &savebbp159r0);
- rt2800_bbp_dcoc_read(rt2x00dev, 2, &savebbp159r2);
+ savebbp159r0 = rt2800_bbp_dcoc_read(rt2x00dev, 0);
+ savebbp159r2 = rt2800_bbp_dcoc_read(rt2x00dev, 2);
/* Save RF registers */
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 0, &saverfb5r00);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 1, &saverfb5r01);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 3, &saverfb5r03);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 4, &saverfb5r04);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 5, &saverfb5r05);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 6, &saverfb5r06);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 7, &saverfb5r07);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 8, &saverfb5r08);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 17, &saverfb5r17);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 18, &saverfb5r18);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 19, &saverfb5r19);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 20, &saverfb5r20);
-
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 37, &saverfb5r37);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 38, &saverfb5r38);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 39, &saverfb5r39);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 40, &saverfb5r40);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 41, &saverfb5r41);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 42, &saverfb5r42);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 43, &saverfb5r43);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 44, &saverfb5r44);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 45, &saverfb5r45);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 46, &saverfb5r46);
-
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 58, &saverfb5r58);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 59, &saverfb5r59);
-
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 0, &rf_val);
+ saverfb5r00 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 0);
+ saverfb5r01 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 1);
+ saverfb5r03 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 3);
+ saverfb5r04 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4);
+ saverfb5r05 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 5);
+ saverfb5r06 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 6);
+ saverfb5r07 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 7);
+ saverfb5r08 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 8);
+ saverfb5r17 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 17);
+ saverfb5r18 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 18);
+ saverfb5r19 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 19);
+ saverfb5r20 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 20);
+
+ saverfb5r37 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 37);
+ saverfb5r38 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 38);
+ saverfb5r39 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 39);
+ saverfb5r40 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 40);
+ saverfb5r41 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 41);
+ saverfb5r42 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 42);
+ saverfb5r43 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 43);
+ saverfb5r44 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 44);
+ saverfb5r45 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 45);
+ saverfb5r46 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 46);
+
+ saverfb5r58 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 58);
+ saverfb5r59 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 59);
+
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 0);
rf_val |= 0x3;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 0, rf_val);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 1, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 1);
rf_val |= 0x1;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 1, rf_val);
cnt = 0;
do {
usleep_range(500, 2000);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 1, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 1);
if (((rf_val & 0x1) == 0x00) || (cnt == 40))
break;
cnt++;
} while (cnt < 40);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 0, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 0);
rf_val &= (~0x3);
rf_val |= 0x1;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 0, rf_val);
/* I-3 */
- rt2800_bbp_read(rt2x00dev, 23, &bbp_val);
+ bbp_val = rt2800_bbp_read(rt2x00dev, 23);
bbp_val &= (~0x1F);
bbp_val |= 0x10;
rt2800_bbp_write(rt2x00dev, 23, bbp_val);
@@ -7844,7 +7847,7 @@ static void rt2800_bw_filter_calibration(struct rt2x00_dev *rt2x00dev,
filter_target = rx_filter_target_40m;
}
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 8, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 8);
rf_val &= (~0x04);
if (loop == 1)
rf_val |= 0x4;
@@ -7856,25 +7859,25 @@ static void rt2800_bw_filter_calibration(struct rt2x00_dev *rt2x00dev,
rt2800_rf_lp_config(rt2x00dev, btxcal);
if (btxcal) {
tx_agc_fc = 0;
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 58, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 58);
rf_val &= (~0x7F);
rt2800_rfcsr_write_bank(rt2x00dev, 5, 58, rf_val);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 59, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 59);
rf_val &= (~0x7F);
rt2800_rfcsr_write_bank(rt2x00dev, 5, 59, rf_val);
} else {
rx_agc_fc = 0;
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 6, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 6);
rf_val &= (~0x7F);
rt2800_rfcsr_write_bank(rt2x00dev, 5, 6, rf_val);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 7, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 7);
rf_val &= (~0x7F);
rt2800_rfcsr_write_bank(rt2x00dev, 5, 7, rf_val);
}
usleep_range(1000, 2000);
- rt2800_bbp_dcoc_read(rt2x00dev, 2, &bbp_val);
+ bbp_val = rt2800_bbp_dcoc_read(rt2x00dev, 2);
bbp_val &= (~0x6);
rt2800_bbp_dcoc_write(rt2x00dev, 2, bbp_val);
@@ -7882,25 +7885,25 @@ static void rt2800_bw_filter_calibration(struct rt2x00_dev *rt2x00dev,
cal_r32_init = rt2800_lp_tx_filter_bw_cal(rt2x00dev);
- rt2800_bbp_dcoc_read(rt2x00dev, 2, &bbp_val);
+ bbp_val = rt2800_bbp_dcoc_read(rt2x00dev, 2);
bbp_val |= 0x6;
rt2800_bbp_dcoc_write(rt2x00dev, 2, bbp_val);
do_cal:
if (btxcal) {
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 58, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 58);
rf_val &= (~0x7F);
rf_val |= tx_agc_fc;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 58, rf_val);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 59, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 59);
rf_val &= (~0x7F);
rf_val |= tx_agc_fc;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 59, rf_val);
} else {
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 6, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 6);
rf_val &= (~0x7F);
rf_val |= rx_agc_fc;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 6, rf_val);
- rt2800_rfcsr_read_bank(rt2x00dev, 5, 7, &rf_val);
+ rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 7);
rf_val &= (~0x7F);
rf_val |= rx_agc_fc;
rt2800_rfcsr_write_bank(rt2x00dev, 5, 7, rf_val);
@@ -7980,7 +7983,7 @@ do_cal:
rt2800_bbp_dcoc_write(rt2x00dev, 0, savebbp159r0);
rt2800_bbp_dcoc_write(rt2x00dev, 2, savebbp159r2);
- rt2800_bbp_read(rt2x00dev, 4, &bbp_val);
+ bbp_val = rt2800_bbp_read(rt2x00dev, 4);
rt2x00_set_field8(&bbp_val, BBP4_BANDWIDTH,
2 * test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags));
rt2800_bbp_write(rt2x00dev, 4, bbp_val);
@@ -8355,20 +8358,20 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Enable RX.
*/
- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
udelay(50);
- rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
@@ -8376,15 +8379,15 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Initialize LED control
*/
- rt2800_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word);
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF);
rt2800_mcu_request(rt2x00dev, MCU_LED_AG_CONF, 0xff,
word & 0xff, (word >> 8) & 0xff);
- rt2800_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word);
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF);
rt2800_mcu_request(rt2x00dev, MCU_LED_ACT_CONF, 0xff,
word & 0xff, (word >> 8) & 0xff);
- rt2800_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word);
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY);
rt2800_mcu_request(rt2x00dev, MCU_LED_LED_POLARITY, 0xff,
word & 0xff, (word >> 8) & 0xff);
@@ -8401,7 +8404,7 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)
/* Wait for DMA, ignore error */
rt2800_wait_wpdma_ready(rt2x00dev);
- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 0);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
@@ -8418,7 +8421,7 @@ int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
else
efuse_ctrl_reg = EFUSE_CTRL;
- rt2800_register_read(rt2x00dev, efuse_ctrl_reg, &reg);
+ reg = rt2800_register_read(rt2x00dev, efuse_ctrl_reg);
return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
}
EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
@@ -8447,7 +8450,7 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
}
mutex_lock(&rt2x00dev->csr_mutex);
- rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, &reg);
+ reg = rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg);
rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
@@ -8456,14 +8459,14 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
/* Wait until the EEPROM has been loaded */
rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, &reg);
/* Apparently the data is read from end to start */
- rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, &reg);
+ reg = rt2800_register_read_lock(rt2x00dev, efuse_data3_reg);
/* The returned value is in CPU order, but eeprom is le */
*(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
- rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, &reg);
+ reg = rt2800_register_read_lock(rt2x00dev, efuse_data2_reg);
*(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
- rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, &reg);
+ reg = rt2800_register_read_lock(rt2x00dev, efuse_data1_reg);
*(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
- rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, &reg);
+ reg = rt2800_register_read_lock(rt2x00dev, efuse_data0_reg);
*(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);
mutex_unlock(&rt2x00dev->csr_mutex);
@@ -8487,7 +8490,7 @@ static u8 rt2800_get_txmixer_gain_24g(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt(rt2x00dev, RT3593))
return 0;
- rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG);
if ((word & 0x00ff) != 0x00ff)
return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL);
@@ -8501,7 +8504,7 @@ static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt(rt2x00dev, RT3593))
return 0;
- rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word);
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A);
if ((word & 0x00ff) != 0x00ff)
return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL);
@@ -8529,7 +8532,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2800_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
rt2x00lib_set_mac_address(rt2x00dev, mac);
- rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word);
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2);
rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1);
@@ -8546,7 +8549,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
}
- rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word);
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_HW_RADIO, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC, 0);
@@ -8567,7 +8570,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
}
- rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ);
if ((word & 0x00ff) == 0x00ff) {
rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
@@ -8589,10 +8592,10 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
* lna0 as correct value. Note that EEPROM_LNA
* is never validated.
*/
- rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &word);
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_LNA);
default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0);
- rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG);
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10)
rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0);
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10)
@@ -8601,7 +8604,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
drv_data->txmixer_gain_24g = rt2800_get_txmixer_gain_24g(rt2x00dev);
- rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2);
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
if (!rt2x00_rt(rt2x00dev, RT3593)) {
@@ -8614,14 +8617,14 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
drv_data->txmixer_gain_5g = rt2800_get_txmixer_gain_5g(rt2x00dev);
- rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A);
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)
rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0);
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10)
rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0);
rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word);
- rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2);
if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
if (!rt2x00_rt(rt2x00dev, RT3593)) {
@@ -8633,7 +8636,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
if (rt2x00_rt(rt2x00dev, RT3593)) {
- rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &word);
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2);
if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0x00 ||
rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff)
rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1,
@@ -8657,7 +8660,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Read EEPROM word for configuration.
*/
- rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0);
/*
* Identify RF chipset by EEPROM value
@@ -8668,7 +8671,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392) ||
rt2x00_rt(rt2x00dev, RT6352))
- rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
+ rf = rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID);
else if (rt2x00_rt(rt2x00dev, RT3352))
rf = RF3322;
else if (rt2x00_rt(rt2x00dev, RT5350))
@@ -8717,7 +8720,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00dev->default_ant.rx_chain_num =
rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH);
- rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
if (rt2x00_rt(rt2x00dev, RT3070) ||
rt2x00_rt(rt2x00dev, RT3090) ||
@@ -8771,7 +8774,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Read frequency offset and RF programming sequence.
*/
- rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ);
rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
/*
@@ -8788,7 +8791,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Check if support EIRP tx power limit feature.
*/
- rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER);
if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) <
EIRP_MAX_TX_POWER_LIMIT)
@@ -8797,7 +8800,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Detect if device uses internal or external PA
*/
- rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
if (rt2x00_rt(rt2x00dev, RT3352)) {
if (rt2x00_get_field16(eeprom,
@@ -9239,7 +9242,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
break;
case RF5592:
- rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, &reg);
+ reg = rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX);
if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) {
spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40);
spec->channels = rf_vals_5592_xtal40;
@@ -9378,9 +9381,9 @@ static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev)
u32 rev;
if (rt2x00_rt(rt2x00dev, RT3290))
- rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
+ reg = rt2800_register_read(rt2x00dev, MAC_CSR0_3290);
else
- rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+ reg = rt2800_register_read(rt2x00dev, MAC_CSR0);
rt = rt2x00_get_field32(reg, MAC_CSR0_CHIPSET);
rev = rt2x00_get_field32(reg, MAC_CSR0_REVISION);
@@ -9440,7 +9443,7 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
- rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+ reg = rt2800_register_read(rt2x00dev, GPIO_CTRL);
rt2x00_set_field32(&reg, GPIO_CTRL_DIR2, 1);
rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
@@ -9515,31 +9518,31 @@ int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
u32 reg;
bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD);
- rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, TX_RTS_CFG);
rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES, value);
rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg);
- rt2800_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, CCK_PROT_CFG);
rt2x00_set_field32(&reg, CCK_PROT_CFG_RTS_TH_EN, enabled);
rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);
- rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, OFDM_PROT_CFG);
rt2x00_set_field32(&reg, OFDM_PROT_CFG_RTS_TH_EN, enabled);
rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
- rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, MM20_PROT_CFG);
rt2x00_set_field32(&reg, MM20_PROT_CFG_RTS_TH_EN, enabled);
rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
- rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, MM40_PROT_CFG);
rt2x00_set_field32(&reg, MM40_PROT_CFG_RTS_TH_EN, enabled);
rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
- rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, GF20_PROT_CFG);
rt2x00_set_field32(&reg, GF20_PROT_CFG_RTS_TH_EN, enabled);
rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
- rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, GF40_PROT_CFG);
rt2x00_set_field32(&reg, GF40_PROT_CFG_RTS_TH_EN, enabled);
rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
@@ -9582,7 +9585,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw,
field.bit_offset = (queue_idx & 1) * 16;
field.bit_mask = 0xffff << field.bit_offset;
- rt2800_register_read(rt2x00dev, offset, &reg);
+ reg = rt2800_register_read(rt2x00dev, offset);
rt2x00_set_field32(&reg, field, queue->txop);
rt2800_register_write(rt2x00dev, offset, reg);
@@ -9590,22 +9593,22 @@ int rt2800_conf_tx(struct ieee80211_hw *hw,
field.bit_offset = queue_idx * 4;
field.bit_mask = 0xf << field.bit_offset;
- rt2800_register_read(rt2x00dev, WMM_AIFSN_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, WMM_AIFSN_CFG);
rt2x00_set_field32(&reg, field, queue->aifs);
rt2800_register_write(rt2x00dev, WMM_AIFSN_CFG, reg);
- rt2800_register_read(rt2x00dev, WMM_CWMIN_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, WMM_CWMIN_CFG);
rt2x00_set_field32(&reg, field, queue->cw_min);
rt2800_register_write(rt2x00dev, WMM_CWMIN_CFG, reg);
- rt2800_register_read(rt2x00dev, WMM_CWMAX_CFG, &reg);
+ reg = rt2800_register_read(rt2x00dev, WMM_CWMAX_CFG);
rt2x00_set_field32(&reg, field, queue->cw_max);
rt2800_register_write(rt2x00dev, WMM_CWMAX_CFG, reg);
/* Update EDCA registers */
offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx);
- rt2800_register_read(rt2x00dev, offset, &reg);
+ reg = rt2800_register_read(rt2x00dev, offset);
rt2x00_set_field32(&reg, EDCA_AC0_CFG_TX_OP, queue->txop);
rt2x00_set_field32(&reg, EDCA_AC0_CFG_AIFSN, queue->aifs);
rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMIN, queue->cw_min);
@@ -9622,9 +9625,9 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
u64 tsf;
u32 reg;
- rt2800_register_read(rt2x00dev, TSF_TIMER_DW1, &reg);
+ reg = rt2800_register_read(rt2x00dev, TSF_TIMER_DW1);
tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32;
- rt2800_register_read(rt2x00dev, TSF_TIMER_DW0, &reg);
+ reg = rt2800_register_read(rt2x00dev, TSF_TIMER_DW0);
tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD);
return tsf;
@@ -9691,9 +9694,9 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
survey->channel = conf->chandef.chan;
- rt2800_register_read(rt2x00dev, CH_IDLE_STA, &idle);
- rt2800_register_read(rt2x00dev, CH_BUSY_STA, &busy);
- rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &busy_ext);
+ idle = rt2800_register_read(rt2x00dev, CH_IDLE_STA);
+ busy = rt2800_register_read(rt2x00dev, CH_BUSY_STA);
+ busy_ext = rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC);
if (idle || busy) {
survey->filled = SURVEY_INFO_TIME |
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
index f357531..275e396 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
@@ -49,10 +49,10 @@ struct rt2800_drv_data {
};
struct rt2800_ops {
- void (*register_read)(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset, u32 *value);
- void (*register_read_lock)(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset, u32 *value);
+ u32 (*register_read)(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset);
+ u32 (*register_read_lock)(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset);
void (*register_write)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset, u32 value);
void (*register_write_lock)(struct rt2x00_dev *rt2x00dev,
@@ -78,22 +78,20 @@ struct rt2800_ops {
__le32 *(*drv_get_txwi)(struct queue_entry *entry);
};
-static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- u32 *value)
+static inline u32 rt2800_register_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset)
{
const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
- rt2800ops->register_read(rt2x00dev, offset, value);
+ return rt2800ops->register_read(rt2x00dev, offset);
}
-static inline void rt2800_register_read_lock(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- u32 *value)
+static inline u32 rt2800_register_read_lock(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset)
{
const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
- rt2800ops->register_read_lock(rt2x00dev, offset, value);
+ return rt2800ops->register_read_lock(rt2x00dev, offset);
}
static inline void rt2800_register_write(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
index 3ab3b53..ee5276e 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
@@ -109,7 +109,7 @@ void rt2800mmio_fill_rxdone(struct queue_entry *entry,
__le32 *rxd = entry_priv->desc;
u32 word;
- rt2x00_desc_read(rxd, 3, &word);
+ word = rt2x00_desc_read(rxd, 3);
if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
@@ -175,7 +175,7 @@ static bool rt2800mmio_txdone_entry_check(struct queue_entry *entry, u32 status)
wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID);
txwi = rt2800_drv_get_txwi(entry);
- rt2x00_desc_read(txwi, 1, &word);
+ word = rt2x00_desc_read(txwi, 1);
tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
return (tx_wcid == wcid);
@@ -331,7 +331,7 @@ static inline void rt2800mmio_enable_interrupt(struct rt2x00_dev *rt2x00dev,
* access needs locking.
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR);
rt2x00_set_field32(&reg, irq_field, 1);
rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
@@ -376,12 +376,12 @@ void rt2800mmio_tbtt_tasklet(unsigned long data)
* interval every 64 beacons by 64us to mitigate this effect.
*/
if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) {
- rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
(rt2x00dev->beacon_int * 16) - 1);
rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
} else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) {
- rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
(rt2x00dev->beacon_int * 16));
rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
@@ -439,7 +439,7 @@ static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
* need to lock the kfifo.
*/
for (i = 0; i < rt2x00dev->tx->limit; i++) {
- rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status);
+ status = rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO);
if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
break;
@@ -460,7 +460,7 @@ irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
u32 reg, mask;
/* Read status and ACK all interrupts */
- rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR);
rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
if (!reg)
@@ -501,7 +501,7 @@ irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
* the tasklet will reenable the appropriate interrupts.
*/
spin_lock(&rt2x00dev->irqmask_lock);
- rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR);
reg &= mask;
rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock(&rt2x00dev->irqmask_lock);
@@ -521,7 +521,7 @@ void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev,
* should clear the register to assure a clean state.
*/
if (state == STATE_RADIO_IRQ_ON) {
- rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR);
rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
}
@@ -560,18 +560,18 @@ void rt2800mmio_start_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
- rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG);
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);
rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
- rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN);
rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 1);
rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg);
break;
@@ -613,18 +613,18 @@ void rt2800mmio_stop_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
- rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG);
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);
rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
- rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN);
rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 0);
rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg);
@@ -696,11 +696,11 @@ bool rt2800mmio_get_entry_state(struct queue_entry *entry)
u32 word;
if (entry->queue->qid == QID_RX) {
- rt2x00_desc_read(entry_priv->desc, 1, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 1);
return (!rt2x00_get_field32(word, RXD_W1_DMA_DONE));
} else {
- rt2x00_desc_read(entry_priv->desc, 1, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 1);
return (!rt2x00_get_field32(word, TXD_W1_DMA_DONE));
}
@@ -715,11 +715,11 @@ void rt2800mmio_clear_entry(struct queue_entry *entry)
u32 word;
if (entry->queue->qid == QID_RX) {
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
rt2x00_set_field32(&word, RXD_W0_SDP0, skbdesc->skb_dma);
rt2x00_desc_write(entry_priv->desc, 0, word);
- rt2x00_desc_read(entry_priv->desc, 1, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 1);
rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0);
rt2x00_desc_write(entry_priv->desc, 1, word);
@@ -730,7 +730,7 @@ void rt2800mmio_clear_entry(struct queue_entry *entry)
rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX,
entry->entry_idx);
} else {
- rt2x00_desc_read(entry_priv->desc, 1, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 1);
rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1);
rt2x00_desc_write(entry_priv->desc, 1, word);
}
@@ -810,7 +810,7 @@ int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev)
/*
* Reset DMA indexes
*/
- rt2x00mmio_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, WPDMA_RST_IDX);
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);
@@ -831,7 +831,7 @@ int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392) ||
rt2x00_rt(rt2x00dev, RT5592))) {
- rt2x00mmio_register_read(rt2x00dev, AUX_CTRL, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, AUX_CTRL);
rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
rt2x00mmio_register_write(rt2x00dev, AUX_CTRL, reg);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
index 0af2257..5cf655f 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
@@ -69,7 +69,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
return;
for (i = 0; i < 200; i++) {
- rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID);
if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
(rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
@@ -92,7 +92,7 @@ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR);
eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
@@ -122,7 +122,7 @@ static int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
struct eeprom_93cx6 eeprom;
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR);
eeprom.data = rt2x00dev;
eeprom.register_read = rt2800pci_eepromregister_read;
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
index f11e3f5..685b8e0 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
@@ -61,12 +61,12 @@ static void rt2800usb_start_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
- rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG);
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);
@@ -84,12 +84,12 @@ static void rt2800usb_stop_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
- rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG);
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);
@@ -333,7 +333,7 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
if (rt2800_wait_csr_ready(rt2x00dev))
return -EBUSY;
- rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL);
rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
reg = 0;
@@ -456,7 +456,7 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry,
/*
* Initialize TXINFO descriptor
*/
- rt2x00_desc_read(txi, 0, &word);
+ word = rt2x00_desc_read(txi, 0);
/*
* The size of TXINFO_W0_USB_DMA_TX_PKT_LEN is
@@ -527,7 +527,7 @@ static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
*/
txwi = rt2800usb_get_txwi(entry);
- rt2x00_desc_read(txwi, 1, &word);
+ word = rt2x00_desc_read(txwi, 1);
tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
@@ -652,7 +652,7 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
* | RXINFO | RXWI | header | L2 pad | payload | pad | RXD | USB pad |
* |<------------ rx_pkt_len -------------->|
*/
- rt2x00_desc_read(rxi, 0, &word);
+ word = rt2x00_desc_read(rxi, 0);
rx_pkt_len = rt2x00_get_field32(word, RXINFO_W0_USB_DMA_RX_PKT_LEN);
/*
@@ -676,7 +676,7 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
/*
* It is now safe to read the descriptor on all architectures.
*/
- rt2x00_desc_read(rxd, 0, &word);
+ word = rt2x00_desc_read(rxd, 0);
if (rt2x00_get_field32(word, RXD_W0_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
@@ -1156,6 +1156,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x2001, 0x3c17) },
/* Panasonic */
{ USB_DEVICE(0x083a, 0xb511) },
+ /* Accton/Arcadyan/Epson */
+ { USB_DEVICE(0x083a, 0xb512) },
/* Philips */
{ USB_DEVICE(0x0471, 0x20dd) },
/* Ralink */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index 1bc353e..1f38c33 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -1049,11 +1049,11 @@ struct rt2x00_bar_list_entry {
* Generic RF access.
* The RF is being accessed by word index.
*/
-static inline void rt2x00_rf_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u32 *data)
+static inline u32 rt2x00_rf_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word)
{
BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32));
- *data = rt2x00dev->rf[word - 1];
+ return rt2x00dev->rf[word - 1];
}
static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -1072,10 +1072,10 @@ static inline void *rt2x00_eeprom_addr(struct rt2x00_dev *rt2x00dev,
return (void *)&rt2x00dev->eeprom[word];
}
-static inline void rt2x00_eeprom_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u16 *data)
+static inline u16 rt2x00_eeprom_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word)
{
- *data = le16_to_cpu(rt2x00dev->eeprom[word]);
+ return le16_to_cpu(rt2x00dev->eeprom[word]);
}
static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
index 964aefd..51520a0 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
@@ -188,7 +188,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
return;
}
- dump_hdr = (struct rt2x00dump_hdr *)skb_put(skbcopy, sizeof(*dump_hdr));
+ dump_hdr = skb_put(skbcopy, sizeof(*dump_hdr));
dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION);
dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr));
dump_hdr->desc_length = cpu_to_le32(skbdesc->desc_len);
@@ -203,9 +203,8 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
if (!(skbdesc->flags & SKBDESC_DESC_IN_SKB))
- memcpy(skb_put(skbcopy, skbdesc->desc_len), skbdesc->desc,
- skbdesc->desc_len);
- memcpy(skb_put(skbcopy, skb->len), skb->data, skb->len);
+ skb_put_data(skbcopy, skbdesc->desc, skbdesc->desc_len);
+ skb_put_data(skbcopy, skb->data, skb->len);
skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy);
wake_up_interruptible(&intf->frame_dump_waitqueue);
@@ -460,7 +459,7 @@ static ssize_t rt2x00debug_read_##__name(struct file *file, \
if (debug->__name.flags & RT2X00DEBUGFS_OFFSET) \
index *= debug->__name.word_size; \
\
- debug->__name.read(intf->rt2x00dev, index, &value); \
+ value = debug->__name.read(intf->rt2x00dev, index); \
\
size = sprintf(line, __format, value); \
\
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.h b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.h
index e65712c..a357a07 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.h
@@ -38,8 +38,8 @@ enum rt2x00debugfs_entry_flags {
#define RT2X00DEBUGFS_REGISTER_ENTRY(__name, __type) \
struct reg##__name { \
- void (*read)(struct rt2x00_dev *rt2x00dev, \
- const unsigned int word, __type *data); \
+ __type (*read)(struct rt2x00_dev *rt2x00dev, \
+ const unsigned int word); \
void (*write)(struct rt2x00_dev *rt2x00dev, \
const unsigned int word, __type data); \
\
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c
index da38d25..528cb04 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c
@@ -43,7 +43,7 @@ int rt2x00mmio_regbusy_read(struct rt2x00_dev *rt2x00dev,
return 0;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00mmio_register_read(rt2x00dev, offset, reg);
+ *reg = rt2x00mmio_register_read(rt2x00dev, offset);
if (!rt2x00_get_field32(*reg, field))
return 1;
udelay(REGISTER_BUSY_DELAY);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h
index 701c312..184a414 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h
@@ -29,11 +29,10 @@
/*
* Register access.
*/
-static inline void rt2x00mmio_register_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- u32 *value)
+static inline u32 rt2x00mmio_register_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset)
{
- *value = readl(rt2x00dev->csr.base + offset);
+ return readl(rt2x00dev->csr.base + offset);
}
static inline void rt2x00mmio_register_multiread(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
index 6055f36..a15bae2 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
@@ -642,11 +642,10 @@ static inline int rt2x00queue_dma_timeout(struct queue_entry *entry)
* _rt2x00_desc_read - Read a word from the hardware descriptor.
* @desc: Base descriptor address
* @word: Word index from where the descriptor should be read.
- * @value: Address where the descriptor value should be written into.
*/
-static inline void _rt2x00_desc_read(__le32 *desc, const u8 word, __le32 *value)
+static inline __le32 _rt2x00_desc_read(__le32 *desc, const u8 word)
{
- *value = desc[word];
+ return desc[word];
}
/**
@@ -654,13 +653,10 @@ static inline void _rt2x00_desc_read(__le32 *desc, const u8 word, __le32 *value)
* function will take care of the byte ordering.
* @desc: Base descriptor address
* @word: Word index from where the descriptor should be read.
- * @value: Address where the descriptor value should be written into.
*/
-static inline void rt2x00_desc_read(__le32 *desc, const u8 word, u32 *value)
+static inline u32 rt2x00_desc_read(__le32 *desc, const u8 word)
{
- __le32 tmp;
- _rt2x00_desc_read(desc, word, &tmp);
- *value = le32_to_cpu(tmp);
+ return le32_to_cpu(_rt2x00_desc_read(desc, word));
}
/**
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
index c696f0a..e2f4f57 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
@@ -145,7 +145,7 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
return -ENODEV;
for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
- rt2x00usb_register_read_lock(rt2x00dev, offset, reg);
+ *reg = rt2x00usb_register_read_lock(rt2x00dev, offset);
if (!rt2x00_get_field32(*reg, field))
return 1;
udelay(REGISTER_BUSY_DELAY);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.h b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.h
index 569363d..ff94c69 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.h
@@ -190,40 +190,36 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
* rt2x00usb_register_read - Read 32bit register word
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
* @offset: Register offset
- * @value: Pointer to where register contents should be stored
*
* This function is a simple wrapper for 32bit register access
* through rt2x00usb_vendor_request_buff().
*/
-static inline void rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- u32 *value)
+static inline u32 rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset)
{
__le32 reg = 0;
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
&reg, sizeof(reg));
- *value = le32_to_cpu(reg);
+ return le32_to_cpu(reg);
}
/**
* rt2x00usb_register_read_lock - Read 32bit register word
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
* @offset: Register offset
- * @value: Pointer to where register contents should be stored
*
* This function is a simple wrapper for 32bit register access
* through rt2x00usb_vendor_req_buff_lock().
*/
-static inline void rt2x00usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- u32 *value)
+static inline u32 rt2x00usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset)
{
__le32 reg = 0;
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
&reg, sizeof(reg), REGISTER_TIMEOUT);
- *value = le32_to_cpu(reg);
+ return le32_to_cpu(reg);
}
/**
diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.c b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
index 973d418..2343102 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
@@ -86,10 +86,11 @@ static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,
mutex_unlock(&rt2x00dev->csr_mutex);
}
-static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u8 *value)
+static u8 rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word)
{
u32 reg;
+ u8 value;
mutex_lock(&rt2x00dev->csr_mutex);
@@ -112,9 +113,11 @@ static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
WAIT_FOR_BBP(rt2x00dev, &reg);
}
- *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
+ value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
mutex_unlock(&rt2x00dev->csr_mutex);
+
+ return value;
}
static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -161,7 +164,7 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg);
- rt2x00mmio_register_read(rt2x00dev, HOST_CMD_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, HOST_CMD_CSR);
rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
rt2x00_set_field32(&reg, HOST_CMD_CSR_INTERRUPT_MCU, 1);
rt2x00mmio_register_write(rt2x00dev, HOST_CMD_CSR, reg);
@@ -176,7 +179,7 @@ static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR);
eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
@@ -240,7 +243,7 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR13);
return rt2x00_get_field32(reg, MAC_CSR13_VAL5);
}
@@ -291,7 +294,7 @@ static int rt61pci_blink_set(struct led_classdev *led_cdev,
container_of(led_cdev, struct rt2x00_led, led_dev);
u32 reg;
- rt2x00mmio_register_read(led->rt2x00dev, MAC_CSR14, &reg);
+ reg = rt2x00mmio_register_read(led->rt2x00dev, MAC_CSR14);
rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
rt2x00mmio_register_write(led->rt2x00dev, MAC_CSR14, reg);
@@ -336,7 +339,7 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
*/
mask = (0xf << crypto->bssidx);
- rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR0);
reg &= mask;
if (reg && reg == mask)
@@ -369,14 +372,14 @@ 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;
- rt2x00mmio_register_read(rt2x00dev, SEC_CSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR1);
rt2x00_set_field32(&reg, field, crypto->cipher);
rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, reg);
} else {
field.bit_offset = (3 * (key->hw_key_idx - 8));
field.bit_mask = 0x7 << field.bit_offset;
- rt2x00mmio_register_read(rt2x00dev, SEC_CSR5, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR5);
rt2x00_set_field32(&reg, field, crypto->cipher);
rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, reg);
}
@@ -401,7 +404,7 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
*/
mask = 1 << key->hw_key_idx;
- rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR0);
if (crypto->cmd == SET_KEY)
reg |= mask;
else if (crypto->cmd == DISABLE_KEY)
@@ -430,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.
*/
- rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR2);
if (reg && reg == ~0) {
key->hw_key_idx = 32;
- rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR3);
if (reg && reg == ~0)
return -ENOSPC;
}
@@ -467,7 +470,7 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
* Without this, received frames will not be decrypted
* by the hardware.
*/
- rt2x00mmio_register_read(rt2x00dev, SEC_CSR4, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR4);
reg |= (1 << crypto->bssidx);
rt2x00mmio_register_write(rt2x00dev, SEC_CSR4, reg);
@@ -492,7 +495,7 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
if (key->hw_key_idx < 32) {
mask = 1 << key->hw_key_idx;
- rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR2);
if (crypto->cmd == SET_KEY)
reg |= mask;
else if (crypto->cmd == DISABLE_KEY)
@@ -501,7 +504,7 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
} else {
mask = 1 << (key->hw_key_idx - 32);
- rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR3);
if (crypto->cmd == SET_KEY)
reg |= mask;
else if (crypto->cmd == DISABLE_KEY)
@@ -523,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.
*/
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0);
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
@@ -555,7 +558,7 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
/*
* Enable synchronisation.
*/
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
}
@@ -586,13 +589,13 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0);
rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32);
rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4);
rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
!!erp->short_preamble);
@@ -604,18 +607,18 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
erp->basic_rates);
if (changed & BSS_CHANGED_BEACON_INT) {
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
erp->beacon_int * 16);
rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
}
if (changed & BSS_CHANGED_ERP_SLOT) {
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR9);
rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg);
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR8, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR8);
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);
@@ -630,9 +633,9 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
u8 r4;
u8 r77;
- rt61pci_bbp_read(rt2x00dev, 3, &r3);
- rt61pci_bbp_read(rt2x00dev, 4, &r4);
- rt61pci_bbp_read(rt2x00dev, 77, &r77);
+ r3 = rt61pci_bbp_read(rt2x00dev, 3);
+ r4 = rt61pci_bbp_read(rt2x00dev, 4);
+ r77 = rt61pci_bbp_read(rt2x00dev, 77);
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF5325));
@@ -676,9 +679,9 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
u8 r4;
u8 r77;
- rt61pci_bbp_read(rt2x00dev, 3, &r3);
- rt61pci_bbp_read(rt2x00dev, 4, &r4);
- rt61pci_bbp_read(rt2x00dev, 77, &r77);
+ r3 = rt61pci_bbp_read(rt2x00dev, 3);
+ r4 = rt61pci_bbp_read(rt2x00dev, 4);
+ r77 = rt61pci_bbp_read(rt2x00dev, 77);
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529));
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
@@ -712,7 +715,7 @@ static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR13);
rt2x00_set_field32(&reg, MAC_CSR13_DIR4, 0);
rt2x00_set_field32(&reg, MAC_CSR13_VAL4, p1);
@@ -730,9 +733,9 @@ static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev,
u8 r4;
u8 r77;
- rt61pci_bbp_read(rt2x00dev, 3, &r3);
- rt61pci_bbp_read(rt2x00dev, 4, &r4);
- rt61pci_bbp_read(rt2x00dev, 77, &r77);
+ r3 = rt61pci_bbp_read(rt2x00dev, 3);
+ r4 = rt61pci_bbp_read(rt2x00dev, 4);
+ r77 = rt61pci_bbp_read(rt2x00dev, 77);
/*
* Configure the RX antenna.
@@ -819,7 +822,7 @@ 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]);
- rt2x00mmio_register_read(rt2x00dev, PHY_CSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, PHY_CSR0);
rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
rt2x00dev->curr_band == NL80211_BAND_2GHZ);
@@ -850,13 +853,13 @@ static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
if (rt2x00_has_cap_external_lna_bg(rt2x00dev))
lna_gain += 14;
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG);
lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
} else {
if (rt2x00_has_cap_external_lna_a(rt2x00dev))
lna_gain += 14;
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A);
lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
}
@@ -875,7 +878,7 @@ static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev,
smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
- rt61pci_bbp_read(rt2x00dev, 3, &r3);
+ r3 = rt61pci_bbp_read(rt2x00dev, 3);
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
rt61pci_bbp_write(rt2x00dev, 3, r3);
@@ -913,10 +916,10 @@ static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev,
{
struct rf_channel rf;
- rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
- rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
- rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
- rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
+ rf.rf1 = rt2x00_rf_read(rt2x00dev, 1);
+ rf.rf2 = rt2x00_rf_read(rt2x00dev, 2);
+ rf.rf3 = rt2x00_rf_read(rt2x00dev, 3);
+ rf.rf4 = rt2x00_rf_read(rt2x00dev, 4);
rt61pci_config_channel(rt2x00dev, &rf, txpower);
}
@@ -926,7 +929,7 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4);
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);
@@ -946,7 +949,7 @@ static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
u32 reg;
if (state == STATE_SLEEP) {
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR11);
rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
rt2x00dev->beacon_int - 10);
rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
@@ -967,7 +970,7 @@ static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
rt61pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0);
} else {
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR11);
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);
@@ -1013,13 +1016,13 @@ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,
/*
* Update FCS error count from register.
*/
- rt2x00mmio_register_read(rt2x00dev, STA_CSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, STA_CSR0);
qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
- rt2x00mmio_register_read(rt2x00dev, STA_CSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, STA_CSR1);
qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
}
@@ -1138,12 +1141,12 @@ static void rt61pci_start_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
break;
case QID_BEACON:
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9);
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);
@@ -1161,22 +1164,22 @@ static void rt61pci_kick_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_AC_VO:
- rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, 1);
rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_VI:
- rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, 1);
rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BE:
- rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, 1);
rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BK:
- rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, 1);
rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
@@ -1192,32 +1195,32 @@ static void rt61pci_stop_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_AC_VO:
- rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC0, 1);
rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_VI:
- rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, 1);
rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BE:
- rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, 1);
rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BK:
- rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, 1);
rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_RX:
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 1);
rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
break;
case QID_BEACON:
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9);
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);
@@ -1299,7 +1302,7 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
* Wait for stable hardware.
*/
for (i = 0; i < 100; i++) {
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR0);
if (reg)
break;
msleep(1);
@@ -1338,7 +1341,7 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
for (i = 0; i < 100; i++) {
- rt2x00mmio_register_read(rt2x00dev, MCU_CNTL_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MCU_CNTL_CSR);
if (rt2x00_get_field32(reg, MCU_CNTL_CSR_READY))
break;
msleep(1);
@@ -1362,12 +1365,12 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR1);
rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR1);
rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
@@ -1383,11 +1386,11 @@ static bool rt61pci_get_entry_state(struct queue_entry *entry)
u32 word;
if (entry->queue->qid == QID_RX) {
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
} else {
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
rt2x00_get_field32(word, TXD_W0_VALID));
@@ -1401,16 +1404,16 @@ static void rt61pci_clear_entry(struct queue_entry *entry)
u32 word;
if (entry->queue->qid == QID_RX) {
- rt2x00_desc_read(entry_priv->desc, 5, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 5);
rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
skbdesc->skb_dma);
rt2x00_desc_write(entry_priv->desc, 5, word);
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
rt2x00_desc_write(entry_priv->desc, 0, word);
} else {
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
rt2x00_set_field32(&word, TXD_W0_VALID, 0);
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
rt2x00_desc_write(entry_priv->desc, 0, word);
@@ -1425,7 +1428,7 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
/*
* Initialize registers.
*/
- rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR0);
rt2x00_set_field32(&reg, TX_RING_CSR0_AC0_RING_SIZE,
rt2x00dev->tx[0].limit);
rt2x00_set_field32(&reg, TX_RING_CSR0_AC1_RING_SIZE,
@@ -1436,36 +1439,36 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
rt2x00dev->tx[3].limit);
rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR0, reg);
- rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR1);
rt2x00_set_field32(&reg, TX_RING_CSR1_TXD_SIZE,
rt2x00dev->tx[0].desc_size / 4);
rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR1, reg);
entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
- rt2x00mmio_register_read(rt2x00dev, AC0_BASE_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, AC0_BASE_CSR);
rt2x00_set_field32(&reg, AC0_BASE_CSR_RING_REGISTER,
entry_priv->desc_dma);
rt2x00mmio_register_write(rt2x00dev, AC0_BASE_CSR, reg);
entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
- rt2x00mmio_register_read(rt2x00dev, AC1_BASE_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, AC1_BASE_CSR);
rt2x00_set_field32(&reg, AC1_BASE_CSR_RING_REGISTER,
entry_priv->desc_dma);
rt2x00mmio_register_write(rt2x00dev, AC1_BASE_CSR, reg);
entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
- rt2x00mmio_register_read(rt2x00dev, AC2_BASE_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, AC2_BASE_CSR);
rt2x00_set_field32(&reg, AC2_BASE_CSR_RING_REGISTER,
entry_priv->desc_dma);
rt2x00mmio_register_write(rt2x00dev, AC2_BASE_CSR, reg);
entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
- rt2x00mmio_register_read(rt2x00dev, AC3_BASE_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, AC3_BASE_CSR);
rt2x00_set_field32(&reg, AC3_BASE_CSR_RING_REGISTER,
entry_priv->desc_dma);
rt2x00mmio_register_write(rt2x00dev, AC3_BASE_CSR, reg);
- rt2x00mmio_register_read(rt2x00dev, RX_RING_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RX_RING_CSR);
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);
@@ -1473,26 +1476,26 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
rt2x00mmio_register_write(rt2x00dev, RX_RING_CSR, reg);
entry_priv = rt2x00dev->rx->entries[0].priv_data;
- rt2x00mmio_register_read(rt2x00dev, RX_BASE_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RX_BASE_CSR);
rt2x00_set_field32(&reg, RX_BASE_CSR_RING_REGISTER,
entry_priv->desc_dma);
rt2x00mmio_register_write(rt2x00dev, RX_BASE_CSR, reg);
- rt2x00mmio_register_read(rt2x00dev, TX_DMA_DST_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TX_DMA_DST_CSR);
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);
rt2x00mmio_register_write(rt2x00dev, TX_DMA_DST_CSR, reg);
- rt2x00mmio_register_read(rt2x00dev, LOAD_TX_RING_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, LOAD_TX_RING_CSR);
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);
rt2x00mmio_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg);
- rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR);
rt2x00_set_field32(&reg, RX_CNTL_CSR_LOAD_RXD, 1);
rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg);
@@ -1503,13 +1506,13 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0);
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);
rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR1);
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 */
@@ -1523,7 +1526,7 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
/*
* CCK TXD BBP registers
*/
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR2, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR2);
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);
@@ -1537,7 +1540,7 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
/*
* OFDM TXD BBP registers
*/
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR3, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR3);
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);
@@ -1546,21 +1549,21 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2_VALID, 1);
rt2x00mmio_register_write(rt2x00dev, TXRX_CSR3, reg);
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR7, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR7);
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);
rt2x00mmio_register_write(rt2x00dev, TXRX_CSR7, reg);
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR8, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR8);
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);
rt2x00mmio_register_write(rt2x00dev, TXRX_CSR8, reg);
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9);
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);
@@ -1573,7 +1576,7 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00mmio_register_write(rt2x00dev, MAC_CSR6, 0x00000fff);
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR9);
rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg);
@@ -1619,24 +1622,24 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
*/
- rt2x00mmio_register_read(rt2x00dev, STA_CSR0, &reg);
- rt2x00mmio_register_read(rt2x00dev, STA_CSR1, &reg);
- rt2x00mmio_register_read(rt2x00dev, STA_CSR2, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, STA_CSR0);
+ reg = rt2x00mmio_register_read(rt2x00dev, STA_CSR1);
+ reg = rt2x00mmio_register_read(rt2x00dev, STA_CSR2);
/*
* Reset MAC and BBP registers.
*/
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR1);
rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR1);
rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR1);
rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
@@ -1649,7 +1652,7 @@ static int rt61pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
u8 value;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt61pci_bbp_read(rt2x00dev, 0, &value);
+ value = rt61pci_bbp_read(rt2x00dev, 0);
if ((value != 0xff) && (value != 0x00))
return 0;
udelay(REGISTER_BUSY_DELAY);
@@ -1695,7 +1698,7 @@ static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev)
rt61pci_bbp_write(rt2x00dev, 107, 0x04);
for (i = 0; i < EEPROM_BBP_SIZE; i++) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i);
if (eeprom != 0xffff && eeprom != 0x0000) {
reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
@@ -1722,10 +1725,10 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
* should clear the register to assure a clean state.
*/
if (state == STATE_RADIO_IRQ_ON) {
- rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR);
rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
- rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR);
rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
}
@@ -1735,7 +1738,7 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
- rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR);
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);
@@ -1743,7 +1746,7 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
- rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR);
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);
@@ -1783,7 +1786,7 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Enable RX.
*/
- rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR);
rt2x00_set_field32(&reg, RX_CNTL_CSR_ENABLE_RX_DMA, 1);
rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg);
@@ -1806,7 +1809,7 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
put_to_sleep = (state != STATE_AWAKE);
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR12, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR12);
rt2x00_set_field32(&reg, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep);
rt2x00_set_field32(&reg, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep);
rt2x00mmio_register_write(rt2x00dev, MAC_CSR12, reg);
@@ -1817,7 +1820,7 @@ 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++) {
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR12, &reg2);
+ reg2 = rt2x00mmio_register_read(rt2x00dev, MAC_CSR12);
state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);
if (state == !put_to_sleep)
return 0;
@@ -1876,7 +1879,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
/*
* Start writing the descriptor words.
*/
- rt2x00_desc_read(txd, 1, &word);
+ word = rt2x00_desc_read(txd, 1);
rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid);
rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs);
rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
@@ -1887,7 +1890,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
rt2x00_desc_write(txd, 1, word);
- rt2x00_desc_read(txd, 2, &word);
+ word = rt2x00_desc_read(txd, 2);
rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
@@ -1901,7 +1904,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
_rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
}
- rt2x00_desc_read(txd, 5, &word);
+ word = rt2x00_desc_read(txd, 5);
rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid);
rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx);
rt2x00_set_field32(&word, TXD_W5_TX_POWER,
@@ -1910,12 +1913,12 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
rt2x00_desc_write(txd, 5, word);
if (entry->queue->qid != QID_BEACON) {
- rt2x00_desc_read(txd, 6, &word);
+ word = rt2x00_desc_read(txd, 6);
rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
skbdesc->skb_dma);
rt2x00_desc_write(txd, 6, word);
- rt2x00_desc_read(txd, 11, &word);
+ word = rt2x00_desc_read(txd, 11);
rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0,
txdesc->length);
rt2x00_desc_write(txd, 11, word);
@@ -1926,7 +1929,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
* the device, whereby the device may take hold of the TXD before we
* finished updating it.
*/
- rt2x00_desc_read(txd, 0, &word);
+ word = rt2x00_desc_read(txd, 0);
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
rt2x00_set_field32(&word, TXD_W0_VALID, 1);
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
@@ -1975,7 +1978,7 @@ 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.
*/
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9);
orig_reg = reg;
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
@@ -2036,7 +2039,7 @@ 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.
*/
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &orig_reg);
+ orig_reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9);
reg = orig_reg;
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
@@ -2092,8 +2095,8 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
u32 word0;
u32 word1;
- rt2x00_desc_read(entry_priv->desc, 0, &word0);
- rt2x00_desc_read(entry_priv->desc, 1, &word1);
+ word0 = rt2x00_desc_read(entry_priv->desc, 0);
+ word1 = rt2x00_desc_read(entry_priv->desc, 1);
if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
@@ -2102,11 +2105,11 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
rxdesc->cipher_status = rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
if (rxdesc->cipher != CIPHER_NONE) {
- _rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv[0]);
- _rt2x00_desc_read(entry_priv->desc, 3, &rxdesc->iv[1]);
+ rxdesc->iv[0] = _rt2x00_desc_read(entry_priv->desc, 2);
+ rxdesc->iv[1] = _rt2x00_desc_read(entry_priv->desc, 3);
rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
- _rt2x00_desc_read(entry_priv->desc, 4, &rxdesc->icv);
+ rxdesc->icv = _rt2x00_desc_read(entry_priv->desc, 4);
rxdesc->dev_flags |= RXDONE_CRYPTO_ICV;
/*
@@ -2172,7 +2175,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
* tx ring size for now.
*/
for (i = 0; i < rt2x00dev->tx->limit; i++) {
- rt2x00mmio_register_read(rt2x00dev, STA_CSR4, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, STA_CSR4);
if (!rt2x00_get_field32(reg, STA_CSR4_VALID))
break;
@@ -2195,7 +2198,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
entry = &queue->entries[index];
entry_priv = entry->priv_data;
- rt2x00_desc_read(entry_priv->desc, 0, &word);
+ word = rt2x00_desc_read(entry_priv->desc, 0);
if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
!rt2x00_get_field32(word, TXD_W0_VALID))
@@ -2258,7 +2261,7 @@ static inline void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR);
rt2x00_set_field32(&reg, irq_field, 0);
rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
@@ -2276,7 +2279,7 @@ static void rt61pci_enable_mcu_interrupt(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR);
rt2x00_set_field32(&reg, irq_field, 0);
rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
@@ -2328,10 +2331,10 @@ 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.
*/
- rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg_mcu);
+ reg_mcu = rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR);
rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu);
- rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR);
rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
if (!reg && !reg_mcu)
@@ -2369,11 +2372,11 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
*/
spin_lock(&rt2x00dev->irqmask_lock);
- rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR);
reg |= mask;
rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
- rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR);
reg |= mask_mcu;
rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
@@ -2393,7 +2396,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
u8 *mac;
s8 value;
- rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR);
eeprom.data = rt2x00dev;
eeprom.register_read = rt61pci_eepromregister_read;
@@ -2414,7 +2417,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
rt2x00lib_set_mac_address(rt2x00dev, mac);
- rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
@@ -2429,7 +2432,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_NIC_ENABLE_DIVERSITY, 0);
rt2x00_set_field16(&word, EEPROM_NIC_TX_DIVERSITY, 0);
@@ -2442,7 +2445,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_LED);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_LED_LED_MODE,
LED_MODE_DEFAULT);
@@ -2450,7 +2453,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_dbg(rt2x00dev, "Led: 0x%04x\n", word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0);
@@ -2458,7 +2461,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
@@ -2474,7 +2477,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
@@ -2502,13 +2505,13 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Read EEPROM word for configuration.
*/
- rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
/*
* Identify RF chipset.
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR0);
rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
@@ -2549,7 +2552,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Read frequency offset and RF programming sequence.
*/
- rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ);
if (rt2x00_get_field16(eeprom, EEPROM_FREQ_SEQ))
__set_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags);
@@ -2558,7 +2561,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Read external LNA informations.
*/
- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
@@ -2589,7 +2592,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* switch to default led mode.
*/
#ifdef CONFIG_RT2X00_LIB_LEDS
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_LED);
value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
rt61pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
@@ -2850,7 +2853,7 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
- rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR13);
rt2x00_set_field32(&reg, MAC_CSR13_DIR5, 1);
rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, reg);
@@ -2922,7 +2925,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw,
field.bit_offset = (queue_idx & 1) * 16;
field.bit_mask = 0xffff << field.bit_offset;
- rt2x00mmio_register_read(rt2x00dev, offset, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, offset);
rt2x00_set_field32(&reg, field, queue->txop);
rt2x00mmio_register_write(rt2x00dev, offset, reg);
@@ -2930,15 +2933,15 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw,
field.bit_offset = queue_idx * 4;
field.bit_mask = 0xf << field.bit_offset;
- rt2x00mmio_register_read(rt2x00dev, AIFSN_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, AIFSN_CSR);
rt2x00_set_field32(&reg, field, queue->aifs);
rt2x00mmio_register_write(rt2x00dev, AIFSN_CSR, reg);
- rt2x00mmio_register_read(rt2x00dev, CWMIN_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CWMIN_CSR);
rt2x00_set_field32(&reg, field, queue->cw_min);
rt2x00mmio_register_write(rt2x00dev, CWMIN_CSR, reg);
- rt2x00mmio_register_read(rt2x00dev, CWMAX_CSR, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, CWMAX_CSR);
rt2x00_set_field32(&reg, field, queue->cw_max);
rt2x00mmio_register_write(rt2x00dev, CWMAX_CSR, reg);
@@ -2951,9 +2954,9 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
u64 tsf;
u32 reg;
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR13, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR13);
tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32;
- rt2x00mmio_register_read(rt2x00dev, TXRX_CSR12, &reg);
+ reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR12);
tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER);
return tsf;
diff --git a/drivers/net/wireless/ralink/rt2x00/rt73usb.c b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
index bb8d307..fd91322 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
@@ -84,10 +84,11 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
mutex_unlock(&rt2x00dev->csr_mutex);
}
-static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u8 *value)
+static u8 rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word)
{
u32 reg;
+ u8 value;
mutex_lock(&rt2x00dev->csr_mutex);
@@ -110,9 +111,11 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
WAIT_FOR_BBP(rt2x00dev, &reg);
}
- *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
+ value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
mutex_unlock(&rt2x00dev->csr_mutex);
+
+ return value;
}
static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -185,7 +188,7 @@ static int rt73usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR13);
return rt2x00_get_field32(reg, MAC_CSR13_VAL7);
}
@@ -238,7 +241,7 @@ static int rt73usb_blink_set(struct led_classdev *led_cdev,
container_of(led_cdev, struct rt2x00_led, led_dev);
u32 reg;
- rt2x00usb_register_read(led->rt2x00dev, MAC_CSR14, &reg);
+ reg = rt2x00usb_register_read(led->rt2x00dev, MAC_CSR14);
rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
rt2x00usb_register_write(led->rt2x00dev, MAC_CSR14, reg);
@@ -283,7 +286,7 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
*/
mask = (0xf << crypto->bssidx);
- rt2x00usb_register_read(rt2x00dev, SEC_CSR0, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR0);
reg &= mask;
if (reg && reg == mask)
@@ -316,14 +319,14 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
field.bit_offset = (3 * key->hw_key_idx);
field.bit_mask = 0x7 << field.bit_offset;
- rt2x00usb_register_read(rt2x00dev, SEC_CSR1, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR1);
rt2x00_set_field32(&reg, field, crypto->cipher);
rt2x00usb_register_write(rt2x00dev, SEC_CSR1, reg);
} else {
field.bit_offset = (3 * (key->hw_key_idx - 8));
field.bit_mask = 0x7 << field.bit_offset;
- rt2x00usb_register_read(rt2x00dev, SEC_CSR5, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR5);
rt2x00_set_field32(&reg, field, crypto->cipher);
rt2x00usb_register_write(rt2x00dev, SEC_CSR5, reg);
}
@@ -348,7 +351,7 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
*/
mask = 1 << key->hw_key_idx;
- rt2x00usb_register_read(rt2x00dev, SEC_CSR0, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR0);
if (crypto->cmd == SET_KEY)
reg |= mask;
else if (crypto->cmd == DISABLE_KEY)
@@ -377,10 +380,10 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
* When both registers are full, we drop the key,
* otherwise we use the first invalid entry.
*/
- rt2x00usb_register_read(rt2x00dev, SEC_CSR2, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR2);
if (reg && reg == ~0) {
key->hw_key_idx = 32;
- rt2x00usb_register_read(rt2x00dev, SEC_CSR3, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR3);
if (reg && reg == ~0)
return -ENOSPC;
}
@@ -417,7 +420,7 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
* without this received frames will not be decrypted
* by the hardware.
*/
- rt2x00usb_register_read(rt2x00dev, SEC_CSR4, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR4);
reg |= (1 << crypto->bssidx);
rt2x00usb_register_write(rt2x00dev, SEC_CSR4, reg);
@@ -442,7 +445,7 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
if (key->hw_key_idx < 32) {
mask = 1 << key->hw_key_idx;
- rt2x00usb_register_read(rt2x00dev, SEC_CSR2, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR2);
if (crypto->cmd == SET_KEY)
reg |= mask;
else if (crypto->cmd == DISABLE_KEY)
@@ -451,7 +454,7 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
} else {
mask = 1 << (key->hw_key_idx - 32);
- rt2x00usb_register_read(rt2x00dev, SEC_CSR3, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR3);
if (crypto->cmd == SET_KEY)
reg |= mask;
else if (crypto->cmd == DISABLE_KEY)
@@ -473,7 +476,7 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
* and broadcast frames will always be accepted since
* there is no filter for it at this time.
*/
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR0);
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
@@ -505,7 +508,7 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
/*
* Enable synchronisation.
*/
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
}
@@ -535,13 +538,13 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR0);
rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32);
rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR4);
rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
!!erp->short_preamble);
@@ -553,18 +556,18 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
erp->basic_rates);
if (changed & BSS_CHANGED_BEACON_INT) {
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
erp->beacon_int * 16);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
}
if (changed & BSS_CHANGED_ERP_SLOT) {
- rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR9);
rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
- rt2x00usb_register_read(rt2x00dev, MAC_CSR8, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR8);
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);
@@ -580,9 +583,9 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
u8 r77;
u8 temp;
- rt73usb_bbp_read(rt2x00dev, 3, &r3);
- rt73usb_bbp_read(rt2x00dev, 4, &r4);
- rt73usb_bbp_read(rt2x00dev, 77, &r77);
+ r3 = rt73usb_bbp_read(rt2x00dev, 3);
+ r4 = rt73usb_bbp_read(rt2x00dev, 4);
+ r77 = rt73usb_bbp_read(rt2x00dev, 77);
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
@@ -627,9 +630,9 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
u8 r4;
u8 r77;
- rt73usb_bbp_read(rt2x00dev, 3, &r3);
- rt73usb_bbp_read(rt2x00dev, 4, &r4);
- rt73usb_bbp_read(rt2x00dev, 77, &r77);
+ r3 = rt73usb_bbp_read(rt2x00dev, 3);
+ r4 = rt73usb_bbp_read(rt2x00dev, 4);
+ r77 = rt73usb_bbp_read(rt2x00dev, 77);
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
@@ -715,7 +718,7 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,
for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
- rt2x00usb_register_read(rt2x00dev, PHY_CSR0, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, PHY_CSR0);
rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
(rt2x00dev->curr_band == NL80211_BAND_2GHZ));
@@ -740,10 +743,10 @@ static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
if (rt2x00_has_cap_external_lna_bg(rt2x00dev))
lna_gain += 14;
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG);
lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
} else {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A);
lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
}
@@ -762,7 +765,7 @@ static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev,
smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
- rt73usb_bbp_read(rt2x00dev, 3, &r3);
+ r3 = rt73usb_bbp_read(rt2x00dev, 3);
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
rt73usb_bbp_write(rt2x00dev, 3, r3);
@@ -796,10 +799,10 @@ static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev,
{
struct rf_channel rf;
- rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
- rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
- rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
- rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
+ rf.rf1 = rt2x00_rf_read(rt2x00dev, 1);
+ rf.rf2 = rt2x00_rf_read(rt2x00dev, 2);
+ rf.rf3 = rt2x00_rf_read(rt2x00dev, 3);
+ rf.rf4 = rt2x00_rf_read(rt2x00dev, 4);
rt73usb_config_channel(rt2x00dev, &rf, txpower);
}
@@ -809,7 +812,7 @@ static void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR4);
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);
@@ -829,7 +832,7 @@ static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev,
u32 reg;
if (state == STATE_SLEEP) {
- rt2x00usb_register_read(rt2x00dev, MAC_CSR11, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR11);
rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
rt2x00dev->beacon_int - 10);
rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
@@ -846,7 +849,7 @@ static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev,
rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
USB_MODE_SLEEP, REGISTER_TIMEOUT);
} else {
- rt2x00usb_register_read(rt2x00dev, MAC_CSR11, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR11);
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);
@@ -888,13 +891,13 @@ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
/*
* Update FCS error count from register.
*/
- rt2x00usb_register_read(rt2x00dev, STA_CSR0, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, STA_CSR0);
qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
- rt2x00usb_register_read(rt2x00dev, STA_CSR1, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, STA_CSR1);
qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
}
@@ -1025,12 +1028,12 @@ static void rt73usb_start_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR0);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
break;
case QID_BEACON:
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
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);
@@ -1048,12 +1051,12 @@ static void rt73usb_stop_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR0);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 1);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
break;
case QID_BEACON:
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
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);
@@ -1112,7 +1115,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev,
* Wait for stable hardware.
*/
for (i = 0; i < 100; i++) {
- rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR0);
if (reg)
break;
msleep(1);
@@ -1150,13 +1153,13 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR0);
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);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR1);
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 */
@@ -1170,7 +1173,7 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
/*
* CCK TXD BBP registers
*/
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR2);
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);
@@ -1184,7 +1187,7 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
/*
* OFDM TXD BBP registers
*/
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR3, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR3);
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);
@@ -1193,21 +1196,21 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2_VALID, 1);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR3, reg);
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR7, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR7);
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);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR7, reg);
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR8, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR8);
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);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR8, reg);
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
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);
@@ -1218,7 +1221,7 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
- rt2x00usb_register_read(rt2x00dev, MAC_CSR6, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR6);
rt2x00_set_field32(&reg, MAC_CSR6_MAX_FRAME_UNIT, 0xfff);
rt2x00usb_register_write(rt2x00dev, MAC_CSR6, reg);
@@ -1246,7 +1249,7 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
rt2x00usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408);
- rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR9);
rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
@@ -1266,24 +1269,24 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
*/
- rt2x00usb_register_read(rt2x00dev, STA_CSR0, &reg);
- rt2x00usb_register_read(rt2x00dev, STA_CSR1, &reg);
- rt2x00usb_register_read(rt2x00dev, STA_CSR2, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, STA_CSR0);
+ reg = rt2x00usb_register_read(rt2x00dev, STA_CSR1);
+ reg = rt2x00usb_register_read(rt2x00dev, STA_CSR2);
/*
* Reset MAC and BBP registers.
*/
- rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR1);
rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR1);
rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR1);
rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
@@ -1296,7 +1299,7 @@ static int rt73usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
u8 value;
for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
- rt73usb_bbp_read(rt2x00dev, 0, &value);
+ value = rt73usb_bbp_read(rt2x00dev, 0);
if ((value != 0xff) && (value != 0x00))
return 0;
udelay(REGISTER_BUSY_DELAY);
@@ -1343,7 +1346,7 @@ static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev)
rt73usb_bbp_write(rt2x00dev, 107, 0x04);
for (i = 0; i < EEPROM_BBP_SIZE; i++) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i);
if (eeprom != 0xffff && eeprom != 0x0000) {
reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
@@ -1390,7 +1393,7 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
put_to_sleep = (state != STATE_AWAKE);
- rt2x00usb_register_read(rt2x00dev, MAC_CSR12, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR12);
rt2x00_set_field32(&reg, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep);
rt2x00_set_field32(&reg, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep);
rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg);
@@ -1401,7 +1404,7 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
* device has entered the correct state.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00usb_register_read(rt2x00dev, MAC_CSR12, &reg2);
+ reg2 = rt2x00usb_register_read(rt2x00dev, MAC_CSR12);
state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);
if (state == !put_to_sleep)
return 0;
@@ -1459,7 +1462,7 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry,
/*
* Start writing the descriptor words.
*/
- rt2x00_desc_read(txd, 0, &word);
+ word = rt2x00_desc_read(txd, 0);
rt2x00_set_field32(&word, TXD_W0_BURST,
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_VALID, 1);
@@ -1485,7 +1488,7 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry,
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
rt2x00_desc_write(txd, 0, word);
- rt2x00_desc_read(txd, 1, &word);
+ word = rt2x00_desc_read(txd, 1);
rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid);
rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs);
rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
@@ -1495,7 +1498,7 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry,
test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
rt2x00_desc_write(txd, 1, word);
- rt2x00_desc_read(txd, 2, &word);
+ word = rt2x00_desc_read(txd, 2);
rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
@@ -1509,7 +1512,7 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry,
_rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
}
- rt2x00_desc_read(txd, 5, &word);
+ word = rt2x00_desc_read(txd, 5);
rt2x00_set_field32(&word, TXD_W5_TX_POWER,
TXPOWER_TO_DEV(entry->queue->rt2x00dev->tx_power));
rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
@@ -1538,7 +1541,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
orig_reg = reg;
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
@@ -1603,7 +1606,7 @@ static void rt73usb_clear_beacon(struct queue_entry *entry)
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &orig_reg);
+ orig_reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
reg = orig_reg;
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
@@ -1691,8 +1694,8 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,
/*
* It is now safe to read the descriptor on all architectures.
*/
- rt2x00_desc_read(rxd, 0, &word0);
- rt2x00_desc_read(rxd, 1, &word1);
+ word0 = rt2x00_desc_read(rxd, 0);
+ word1 = rt2x00_desc_read(rxd, 1);
if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
@@ -1701,11 +1704,11 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,
rxdesc->cipher_status = rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
if (rxdesc->cipher != CIPHER_NONE) {
- _rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]);
- _rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]);
+ rxdesc->iv[0] = _rt2x00_desc_read(rxd, 2);
+ rxdesc->iv[1] = _rt2x00_desc_read(rxd, 3);
rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
- _rt2x00_desc_read(rxd, 4, &rxdesc->icv);
+ rxdesc->icv = _rt2x00_desc_read(rxd, 4);
rxdesc->dev_flags |= RXDONE_CRYPTO_ICV;
/*
@@ -1768,7 +1771,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
rt2x00lib_set_mac_address(rt2x00dev, mac);
- rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
@@ -1783,14 +1786,14 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_LED);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_LED_POLARITY_RDY_G, 0);
rt2x00_set_field16(&word, EEPROM_LED_POLARITY_RDY_A, 0);
@@ -1806,7 +1809,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_dbg(rt2x00dev, "Led: 0x%04x\n", word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0);
@@ -1814,7 +1817,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
@@ -1830,7 +1833,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
}
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &word);
+ word = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
@@ -1858,13 +1861,13 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Read EEPROM word for configuration.
*/
- rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
/*
* Identify RF chipset.
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
- rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR0);
rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
@@ -1904,13 +1907,13 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Read frequency offset.
*/
- rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ);
rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
/*
* Read external LNA informations.
*/
- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA)) {
__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
@@ -1921,7 +1924,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Store led settings, for correct led behaviour.
*/
#ifdef CONFIG_RT2X00_LIB_LEDS
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
+ eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_LED);
rt73usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
rt73usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
@@ -2188,7 +2191,7 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
- rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR13);
rt2x00_set_field32(&reg, MAC_CSR13_DIR7, 0);
rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg);
@@ -2260,7 +2263,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw,
field.bit_offset = (queue_idx & 1) * 16;
field.bit_mask = 0xffff << field.bit_offset;
- rt2x00usb_register_read(rt2x00dev, offset, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, offset);
rt2x00_set_field32(&reg, field, queue->txop);
rt2x00usb_register_write(rt2x00dev, offset, reg);
@@ -2268,15 +2271,15 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw,
field.bit_offset = queue_idx * 4;
field.bit_mask = 0xf << field.bit_offset;
- rt2x00usb_register_read(rt2x00dev, AIFSN_CSR, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, AIFSN_CSR);
rt2x00_set_field32(&reg, field, queue->aifs);
rt2x00usb_register_write(rt2x00dev, AIFSN_CSR, reg);
- rt2x00usb_register_read(rt2x00dev, CWMIN_CSR, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, CWMIN_CSR);
rt2x00_set_field32(&reg, field, queue->cw_min);
rt2x00usb_register_write(rt2x00dev, CWMIN_CSR, reg);
- rt2x00usb_register_read(rt2x00dev, CWMAX_CSR, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, CWMAX_CSR);
rt2x00_set_field32(&reg, field, queue->cw_max);
rt2x00usb_register_write(rt2x00dev, CWMAX_CSR, reg);
@@ -2289,9 +2292,9 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
u64 tsf;
u32 reg;
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR13, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR13);
tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32;
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR12, &reg);
+ reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR12);
tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER);
return tsf;
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index b944794..170cd50 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -247,7 +247,10 @@ static const UCHAR b4_default_startup_parms[] = {
0x04, 0x08, /* Noise gain, limit offset */
0x28, 0x28, /* det rssi, med busy offsets */
7, /* det sync thresh */
- 0, 2, 2 /* test mode, min, max */
+ 0, 2, 2, /* test mode, min, max */
+ 0, /* rx/tx delay */
+ 0, 0, 0, 0, 0, 0, /* current BSS id */
+ 0 /* hop set */
};
/*===========================================================================*/
@@ -597,7 +600,7 @@ static void init_startup_params(ray_dev_t *local)
* a_beacon_period = hops a_beacon_period = KuS
*//* 64ms = 010000 */
if (local->fw_ver == 0x55) {
- memcpy((UCHAR *) &local->sparm.b4, b4_default_startup_parms,
+ memcpy(&local->sparm.b4, b4_default_startup_parms,
sizeof(struct b4_startup_params));
/* Translate sane kus input values to old build 4/5 format */
/* i = hop time in uS truncated to 3 bytes */
diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
index 35fe991..55198ac2 100644
--- a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
@@ -278,8 +278,7 @@ static void rtl8187_tx(struct ieee80211_hw *dev,
}
if (!priv->is_rtl8187b) {
- struct rtl8187_tx_hdr *hdr =
- (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
+ struct rtl8187_tx_hdr *hdr = skb_push(skb, sizeof(*hdr));
hdr->flags = cpu_to_le32(flags);
hdr->len = 0;
hdr->rts_duration = rts_dur;
@@ -292,8 +291,7 @@ static void rtl8187_tx(struct ieee80211_hw *dev,
unsigned int epmap[4] = { 6, 7, 5, 4 };
u16 fc = le16_to_cpu(tx_hdr->frame_control);
- struct rtl8187b_tx_hdr *hdr =
- (struct rtl8187b_tx_hdr *)skb_push(skb, sizeof(*hdr));
+ struct rtl8187b_tx_hdr *hdr = skb_push(skb, sizeof(*hdr));
struct ieee80211_rate *txrate =
ieee80211_get_tx_rate(dev, info);
memset(hdr, 0, sizeof(*hdr));
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index 39d5631..21e5ef0 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -4952,7 +4952,7 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
if (control && control->sta)
sta = control->sta;
- tx_desc = (struct rtl8xxxu_txdesc32 *)skb_push(skb, tx_desc_size);
+ tx_desc = skb_push(skb, tx_desc_size);
memset(tx_desc, 0, tx_desc_size);
tx_desc->pkt_size = cpu_to_le16(pktlen);
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index bdc3791..e36ee59 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -405,6 +405,10 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
ieee80211_hw_set(hw, SUPPORTS_PS);
ieee80211_hw_set(hw, PS_NULLFUNC_STACK);
}
+ if (rtlpriv->psc.fwctrl_lps) {
+ ieee80211_hw_set(hw, SUPPORTS_PS);
+ ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
+ }
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_STATION) |
@@ -560,6 +564,7 @@ int rtl_init_core(struct ieee80211_hw *hw)
spin_lock_init(&rtlpriv->locks.waitq_lock);
spin_lock_init(&rtlpriv->locks.entry_list_lock);
spin_lock_init(&rtlpriv->locks.c2hcmd_lock);
+ spin_lock_init(&rtlpriv->locks.scan_list_lock);
spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock);
spin_lock_init(&rtlpriv->locks.check_sendpkt_lock);
spin_lock_init(&rtlpriv->locks.fw_ps_lock);
@@ -568,6 +573,7 @@ int rtl_init_core(struct ieee80211_hw *hw)
/* <5> init list */
INIT_LIST_HEAD(&rtlpriv->entry_list);
INIT_LIST_HEAD(&rtlpriv->c2hcmd_list);
+ INIT_LIST_HEAD(&rtlpriv->scan_list.list);
rtlmac->link_state = MAC80211_NOLINK;
@@ -578,9 +584,12 @@ int rtl_init_core(struct ieee80211_hw *hw)
}
EXPORT_SYMBOL_GPL(rtl_init_core);
+static void rtl_free_entries_from_scan_list(struct ieee80211_hw *hw);
+
void rtl_deinit_core(struct ieee80211_hw *hw)
{
rtl_c2hcmd_launcher(hw, 0);
+ rtl_free_entries_from_scan_list(hw);
}
EXPORT_SYMBOL_GPL(rtl_deinit_core);
@@ -1110,6 +1119,9 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
if (txrate)
tcb_desc->hw_rate = txrate->hw_value;
+ if (rtl_is_tx_report_skb(hw, skb))
+ tcb_desc->use_spe_rpt = 1;
+
if (ieee80211_is_data(fc)) {
/*
*we set data rate INX 0
@@ -1306,33 +1318,26 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
}
EXPORT_SYMBOL_GPL(rtl_action_proc);
-static void setup_arp_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc)
+static void setup_special_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc,
+ int type)
{
struct ieee80211_hw *hw = rtlpriv->hw;
rtlpriv->ra.is_special_data = true;
if (rtlpriv->cfg->ops->get_btc_status())
rtlpriv->btcoexist.btc_ops->btc_special_packet_notify(
- rtlpriv, 1);
+ rtlpriv, type);
rtl_lps_leave(hw);
ppsc->last_delaylps_stamp_jiffies = jiffies;
}
-/*should call before software enc*/
-u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
- bool is_enc)
+static const u8 *rtl_skb_ether_type_ptr(struct ieee80211_hw *hw,
+ struct sk_buff *skb, bool is_enc)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- __le16 fc = rtl_get_fc(skb);
- u16 ether_type;
u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb);
u8 encrypt_header_len = 0;
u8 offset;
- const struct iphdr *ip;
-
- if (!ieee80211_is_data(fc))
- goto end;
switch (rtlpriv->sec.pairwise_enc_algorithm) {
case WEP40_ENCRYPTION:
@@ -1352,10 +1357,29 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
offset = mac_hdr_len + SNAP_SIZE;
if (is_enc)
offset += encrypt_header_len;
- ether_type = be16_to_cpup((__be16 *)(skb->data + offset));
+
+ return skb->data + offset;
+}
+
+/*should call before software enc*/
+u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
+ bool is_enc)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ __le16 fc = rtl_get_fc(skb);
+ u16 ether_type;
+ const u8 *ether_type_ptr;
+ const struct iphdr *ip;
+
+ if (!ieee80211_is_data(fc))
+ goto end;
+
+ ether_type_ptr = rtl_skb_ether_type_ptr(hw, skb, is_enc);
+ ether_type = be16_to_cpup((__be16 *)ether_type_ptr);
if (ETH_P_IP == ether_type) {
- ip = (struct iphdr *)((u8 *)skb->data + offset +
+ ip = (struct iphdr *)((u8 *)ether_type_ptr +
PROTOC_TYPE_SIZE);
if (IPPROTO_UDP == ip->protocol) {
struct udphdr *udp = (struct udphdr *)((u8 *)ip +
@@ -1372,13 +1396,15 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
(is_tx) ? "Tx" : "Rx");
if (is_tx)
- setup_arp_tx(rtlpriv, ppsc);
+ setup_special_tx(rtlpriv, ppsc,
+ PACKET_DHCP);
+
return true;
}
}
} else if (ETH_P_ARP == ether_type) {
if (is_tx)
- setup_arp_tx(rtlpriv, ppsc);
+ setup_special_tx(rtlpriv, ppsc, PACKET_ARP);
return true;
} else if (ETH_P_PAE == ether_type) {
@@ -1389,6 +1415,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
rtlpriv->ra.is_special_data = true;
rtl_lps_leave(hw);
ppsc->last_delaylps_stamp_jiffies = jiffies;
+
+ setup_special_tx(rtlpriv, ppsc, PACKET_EAPOL);
}
return true;
@@ -1405,6 +1433,96 @@ end:
}
EXPORT_SYMBOL_GPL(rtl_is_special_data);
+bool rtl_is_tx_report_skb(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+ u16 ether_type;
+ const u8 *ether_type_ptr;
+
+ ether_type_ptr = rtl_skb_ether_type_ptr(hw, skb, true);
+ ether_type = be16_to_cpup((__be16 *)ether_type_ptr);
+
+ /* EAPOL */
+ if (ether_type == ETH_P_PAE)
+ return true;
+
+ return false;
+}
+
+static u16 rtl_get_tx_report_sn(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_tx_report *tx_report = &rtlpriv->tx_report;
+ u16 sn;
+
+ sn = atomic_inc_return(&tx_report->sn) & 0x0FFF;
+
+ tx_report->last_sent_sn = sn;
+ tx_report->last_sent_time = jiffies;
+
+ RT_TRACE(rtlpriv, COMP_TX_REPORT, DBG_DMESG,
+ "Send TX-Report sn=0x%X\n", sn);
+
+ return sn;
+}
+
+void rtl_get_tx_report(struct rtl_tcb_desc *ptcb_desc, u8 *pdesc,
+ struct ieee80211_hw *hw)
+{
+ if (ptcb_desc->use_spe_rpt) {
+ u16 sn = rtl_get_tx_report_sn(hw);
+
+ SET_TX_DESC_SPE_RPT(pdesc, 1);
+ SET_TX_DESC_SW_DEFINE(pdesc, sn);
+ }
+}
+EXPORT_SYMBOL_GPL(rtl_get_tx_report);
+
+void rtl_tx_report_handler(struct ieee80211_hw *hw, u8 *tmp_buf, u8 c2h_cmd_len)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_tx_report *tx_report = &rtlpriv->tx_report;
+ u16 sn;
+
+ sn = ((tmp_buf[7] & 0x0F) << 8) | tmp_buf[6];
+
+ tx_report->last_recv_sn = sn;
+
+ RT_TRACE(rtlpriv, COMP_TX_REPORT, DBG_DMESG,
+ "Recv TX-Report st=0x%02X sn=0x%X retry=0x%X\n",
+ tmp_buf[0], sn, tmp_buf[2]);
+}
+EXPORT_SYMBOL_GPL(rtl_tx_report_handler);
+
+bool rtl_check_tx_report_acked(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_tx_report *tx_report = &rtlpriv->tx_report;
+
+ if (tx_report->last_sent_sn == tx_report->last_recv_sn)
+ return true;
+
+ if (time_before(tx_report->last_sent_time + 3 * HZ, jiffies)) {
+ RT_TRACE(rtlpriv, COMP_TX_REPORT, DBG_WARNING,
+ "Check TX-Report timeout!!\n");
+ return true; /* 3 sec. (timeout) seen as acked */
+ }
+
+ return false;
+}
+
+void rtl_wait_tx_report_acked(struct ieee80211_hw *hw, u32 wait_ms)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ int i;
+
+ for (i = 0; i < wait_ms; i++) {
+ if (rtl_check_tx_report_acked(hw))
+ break;
+ usleep_range(1000, 2000);
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+ "Wait 1ms (%d/%d) to disable key.\n", i, wait_ms);
+ }
+}
/*********************************************************
*
* functions called by core.c
@@ -1469,6 +1587,7 @@ int rtl_rx_agg_start(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_tid_data *tid_data;
struct rtl_sta_info *sta_entry = NULL;
+ u8 reject_agg;
if (sta == NULL)
return -EINVAL;
@@ -1476,6 +1595,14 @@ int rtl_rx_agg_start(struct ieee80211_hw *hw,
if (unlikely(tid >= MAX_TID_COUNT))
return -EINVAL;
+ if (rtlpriv->cfg->ops->get_btc_status()) {
+ rtlpriv->btcoexist.btc_ops->btc_get_ampdu_cfg(rtlpriv,
+ &reject_agg,
+ NULL, NULL);
+ if (reject_agg)
+ return -EINVAL;
+ }
+
sta_entry = (struct rtl_sta_info *)sta->drv_priv;
if (!sta_entry)
return -ENXIO;
@@ -1530,6 +1657,24 @@ int rtl_tx_agg_oper(struct ieee80211_hw *hw,
return 0;
}
+void rtl_rx_ampdu_apply(struct rtl_priv *rtlpriv)
+{
+ struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
+ u8 reject_agg, ctrl_agg_size = 0, agg_size;
+
+ if (rtlpriv->cfg->ops->get_btc_status())
+ btc_ops->btc_get_ampdu_cfg(rtlpriv, &reject_agg,
+ &ctrl_agg_size, &agg_size);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "Set RX AMPDU: coex - reject=%d, ctrl_agg_size=%d, size=%d",
+ reject_agg, ctrl_agg_size, agg_size);
+
+ rtlpriv->hw->max_rx_aggregation_subframes =
+ (ctrl_agg_size ? agg_size : IEEE80211_MAX_AMPDU_BUF);
+}
+EXPORT_SYMBOL(rtl_rx_ampdu_apply);
+
/*********************************************************
*
* wq & timer callback functions
@@ -1564,6 +1709,100 @@ void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb)
}
EXPORT_SYMBOL_GPL(rtl_beacon_statistic);
+static void rtl_free_entries_from_scan_list(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_bssid_entry *entry, *next;
+
+ list_for_each_entry_safe(entry, next, &rtlpriv->scan_list.list, list) {
+ list_del(&entry->list);
+ kfree(entry);
+ rtlpriv->scan_list.num--;
+ }
+}
+
+void rtl_scan_list_expire(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_bssid_entry *entry, *next;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtlpriv->locks.scan_list_lock, flags);
+
+ list_for_each_entry_safe(entry, next, &rtlpriv->scan_list.list, list) {
+ /* 180 seconds */
+ if (jiffies_to_msecs(jiffies - entry->age) < 180000)
+ continue;
+
+ list_del(&entry->list);
+ kfree(entry);
+ rtlpriv->scan_list.num--;
+
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
+ "BSSID=%pM is expire in scan list (total=%d)\n",
+ entry->bssid, rtlpriv->scan_list.num);
+ }
+
+ spin_unlock_irqrestore(&rtlpriv->locks.scan_list_lock, flags);
+
+ rtlpriv->btcoexist.btc_info.ap_num = rtlpriv->scan_list.num;
+}
+
+void rtl_collect_scan_list(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+ unsigned long flags;
+
+ struct rtl_bssid_entry *entry;
+ bool entry_found = false;
+
+ /* check if it is scanning */
+ if (!mac->act_scanning)
+ return;
+
+ /* check if this really is a beacon */
+ if (!ieee80211_is_beacon(hdr->frame_control) &&
+ !ieee80211_is_probe_resp(hdr->frame_control))
+ return;
+
+ spin_lock_irqsave(&rtlpriv->locks.scan_list_lock, flags);
+
+ list_for_each_entry(entry, &rtlpriv->scan_list.list, list) {
+ if (memcmp(entry->bssid, hdr->addr3, ETH_ALEN) == 0) {
+ list_del_init(&entry->list);
+ entry_found = true;
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
+ "Update BSSID=%pM to scan list (total=%d)\n",
+ hdr->addr3, rtlpriv->scan_list.num);
+ break;
+ }
+ }
+
+ if (!entry_found) {
+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+
+ if (!entry)
+ goto label_err;
+
+ memcpy(entry->bssid, hdr->addr3, ETH_ALEN);
+ rtlpriv->scan_list.num++;
+
+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
+ "Add BSSID=%pM to scan list (total=%d)\n",
+ hdr->addr3, rtlpriv->scan_list.num);
+ }
+
+ entry->age = jiffies;
+
+ list_add_tail(&entry->list, &rtlpriv->scan_list.list);
+
+label_err:
+ spin_unlock_irqrestore(&rtlpriv->locks.scan_list_lock, flags);
+}
+EXPORT_SYMBOL(rtl_collect_scan_list);
+
void rtl_watchdog_wq_callback(void *data)
{
struct rtl_works *rtlworks = container_of_dwork_rtl(data,
@@ -1662,12 +1901,20 @@ void rtl_watchdog_wq_callback(void *data)
false;
}
+ /* PS is controlled by coex. */
+ if (rtlpriv->cfg->ops->get_btc_status() &&
+ rtlpriv->btcoexist.btc_ops->btc_is_bt_ctrl_lps(rtlpriv))
+ goto label_lps_done;
+
if (((rtlpriv->link_info.num_rx_inperiod +
rtlpriv->link_info.num_tx_inperiod) > 8) ||
(rtlpriv->link_info.num_rx_inperiod > 2))
rtl_lps_leave(hw);
else
rtl_lps_enter(hw);
+
+label_lps_done:
+ ;
}
rtlpriv->link_info.num_rx_inperiod = 0;
@@ -1713,6 +1960,9 @@ void rtl_watchdog_wq_callback(void *data)
rtlpriv->btcoexist.btc_ops->btc_periodical(rtlpriv);
rtlpriv->link_info.bcn_rx_inperiod = 0;
+
+ /* <6> scan list */
+ rtl_scan_list_expire(hw);
}
void rtl_watch_dog_timer_callback(unsigned long data)
@@ -1875,8 +2125,7 @@ static struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw,
return NULL;
skb_reserve(skb, hw->extra_tx_headroom);
- action_frame = (void *)skb_put(skb, 27);
- memset(action_frame, 0, 27);
+ action_frame = skb_put_zero(skb, 27);
memcpy(action_frame->da, da, ETH_ALEN);
memcpy(action_frame->sa, rtlefuse->dev_addr, ETH_ALEN);
memcpy(action_frame->bssid, bssid, ETH_ALEN);
@@ -2005,8 +2254,7 @@ struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw,
return NULL;
skb_reserve(skb, hw->extra_tx_headroom);
- action_frame = (void *)skb_put(skb, 34);
- memset(action_frame, 0, 34);
+ action_frame = skb_put_zero(skb, 34);
memcpy(action_frame->sa, sa, ETH_ALEN);
memcpy(action_frame->da, rtlefuse->dev_addr, ETH_ALEN);
memcpy(action_frame->bssid, bssid, ETH_ALEN);
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h
index 02ff0c5..ab7d819 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.h
+++ b/drivers/net/wireless/realtek/rtlwifi/base.h
@@ -107,6 +107,11 @@ enum ap_peer {
SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, \
(GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) & (~(__val))))
+#define SET_TX_DESC_SPE_RPT(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 8, 19, 1, __val)
+#define SET_TX_DESC_SW_DEFINE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 0, 12, __val)
+
int rtl_init_core(struct ieee80211_hw *hw);
void rtl_deinit_core(struct ieee80211_hw *hw);
void rtl_init_rx_config(struct ieee80211_hw *hw);
@@ -123,7 +128,17 @@ bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb);
u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
bool is_enc);
+bool rtl_is_tx_report_skb(struct ieee80211_hw *hw, struct sk_buff *skb);
+void rtl_get_tx_report(struct rtl_tcb_desc *ptcb_desc, u8 *pdesc,
+ struct ieee80211_hw *hw);
+void rtl_tx_report_handler(struct ieee80211_hw *hw, u8 *tmp_buf,
+ u8 c2h_cmd_len);
+bool rtl_check_tx_report_acked(struct ieee80211_hw *hw);
+void rtl_wait_tx_report_acked(struct ieee80211_hw *hw, u32 wait_ms);
+
void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb);
+void rtl_collect_scan_list(struct ieee80211_hw *hw, struct sk_buff *skb);
+void rtl_scan_list_expire(struct ieee80211_hw *hw);
int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid, u16 *ssn);
int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
@@ -134,6 +149,7 @@ int rtl_rx_agg_start(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u16 tid);
int rtl_rx_agg_stop(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u16 tid);
+void rtl_rx_ampdu_apply(struct rtl_priv *rtlpriv);
void rtl_watchdog_wq_callback(void *data);
void rtl_fwevt_wq_callback(void *data);
void rtl_c2hcmd_wq_callback(void *data);
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h
index 39b9a33..2ac989a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h
@@ -37,6 +37,28 @@
#include "halbtcoutsrc.h"
+/* Interface type */
+#define RT_PCI_INTERFACE 1
+#define RT_USB_INTERFACE 2
+#define RT_SDIO_INTERFACE 3
+#define DEV_BUS_TYPE RT_PCI_INTERFACE
+
+/* IC type */
+#define RTL_HW_TYPE(adapter) (rtl_hal((struct rtl_priv *)adapter)->hw_type)
+
+#define IS_NEW_GENERATION_IC(adapter) \
+ (RTL_HW_TYPE(adapter) >= HARDWARE_TYPE_RTL8192EE)
+#define IS_HARDWARE_TYPE_8812(adapter) \
+ (RTL_HW_TYPE(adapter) == HARDWARE_TYPE_RTL8812AE)
+#define IS_HARDWARE_TYPE_8821(adapter) \
+ (RTL_HW_TYPE(adapter) == HARDWARE_TYPE_RTL8821AE)
+#define IS_HARDWARE_TYPE_8723A(adapter) \
+ (RTL_HW_TYPE(adapter) == HARDWARE_TYPE_RTL8723AE)
+#define IS_HARDWARE_TYPE_8723B(adapter) \
+ (RTL_HW_TYPE(adapter) == HARDWARE_TYPE_RTL8723BE)
+#define IS_HARDWARE_TYPE_8192E(adapter) \
+ (RTL_HW_TYPE(adapter) == HARDWARE_TYPE_RTL8192EE)
+
#include "halbtc8192e2ant.h"
#include "halbtc8723b1ant.h"
#include "halbtc8723b2ant.h"
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c
index 57e633d..44c2572 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c
@@ -456,6 +456,39 @@ static void btc8192e2ant_query_bt_info(struct btc_coexist *btcoexist)
btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter);
}
+static
+bool btc8192e2ant_is_wifi_status_changed(struct btc_coexist *btcoexist)
+{
+ static bool pre_wifi_busy = false, pre_under_4way = false,
+ pre_bt_hs_on = false;
+ bool wifi_busy = false, under_4way = false, bt_hs_on = false;
+ bool wifi_connected = false;
+
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
+ &wifi_connected);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS,
+ &under_4way);
+
+ if (wifi_connected) {
+ if (wifi_busy != pre_wifi_busy) {
+ pre_wifi_busy = wifi_busy;
+ return true;
+ }
+ if (under_4way != pre_under_4way) {
+ pre_under_4way = under_4way;
+ return true;
+ }
+ if (bt_hs_on != pre_bt_hs_on) {
+ pre_bt_hs_on = bt_hs_on;
+ return true;
+ }
+ }
+
+ return false;
+}
+
static void btc8192e2ant_update_bt_link_info(struct btc_coexist *btcoexist)
{
struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
@@ -2886,9 +2919,8 @@ void ex_btc8192e2ant_display_coex_info(struct btc_coexist *btcoexist)
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d",
"0x774(lp rx[31:16]/tx[15:0])",
coex_sta->low_priority_rx, coex_sta->low_priority_tx);
-#if (BT_AUTO_REPORT_ONLY_8192E_2ANT == 1)
- btc8192e2ant_monitor_bt_ctr(btcoexist);
-#endif
+ if (btcoexist->auto_report_2ant)
+ btc8192e2ant_monitor_bt_ctr(btcoexist);
btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_COEX_STATISTICS);
}
@@ -3078,14 +3110,12 @@ void ex_btc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist,
*/
}
-#if (BT_AUTO_REPORT_ONLY_8192E_2ANT == 0)
- if ((coex_sta->bt_info_ext & BIT4)) {
- /* BT auto report already enabled, do nothing */
- } else {
- btc8192e2ant_bt_auto_report(btcoexist, FORCE_EXEC,
- true);
+ if (!btcoexist->auto_report_2ant) {
+ if (!(coex_sta->bt_info_ext & BIT4))
+ btc8192e2ant_bt_auto_report(btcoexist,
+ FORCE_EXEC,
+ true);
}
-#endif
}
/* check BIT2 first ==> check if bt is under inquiry or page scan */
@@ -3164,7 +3194,7 @@ void ex_btc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist,
btc8192e2ant_run_coexist_mechanism(btcoexist);
}
-void ex_halbtc8192e2ant_halt_notify(struct btc_coexist *btcoexist)
+void ex_btc8192e2ant_halt_notify(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -3207,13 +3237,13 @@ void ex_btc8192e2ant_periodical(struct btc_coexist *btcoexist)
"************************************************\n");
}
-#if (BT_AUTO_REPORT_ONLY_8192E_2ANT == 0)
- btc8192e2ant_query_bt_info(btcoexist);
- btc8192e2ant_monitor_bt_ctr(btcoexist);
- btc8192e2ant_monitor_bt_enable_disable(btcoexist);
-#else
- if (btc8192e2ant_is_wifi_status_changed(btcoexist) ||
- coex_dm->auto_tdma_adjust)
- btc8192e2ant_run_coexist_mechanism(btcoexist);
-#endif
+ if (!btcoexist->auto_report_2ant) {
+ btc8192e2ant_query_bt_info(btcoexist);
+ btc8192e2ant_monitor_bt_ctr(btcoexist);
+ btc8192e2ant_monitor_bt_enable_disable(btcoexist);
+ } else {
+ if (btc8192e2ant_is_wifi_status_changed(btcoexist) ||
+ coex_dm->auto_tdma_adjust)
+ btc8192e2ant_run_coexist_mechanism(btcoexist);
+ }
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h
index fc0fa87..65502ac 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h
@@ -25,8 +25,6 @@
/*****************************************************************
* The following is for 8192E 2Ant BT Co-exist definition
*****************************************************************/
-#define BT_AUTO_REPORT_ONLY_8192E_2ANT 0
-
#define BT_INFO_8192E_2ANT_B_FTP BIT7
#define BT_INFO_8192E_2ANT_B_A2DP BIT6
#define BT_INFO_8192E_2ANT_B_HID BIT5
@@ -166,20 +164,20 @@ struct coex_sta_8192e_2ant {
/****************************************************************
* The following is interface which will notify coex module.
****************************************************************/
-void ex_halbtc8192e2ant_init_hwconfig(struct btc_coexist *btcoexist);
-void ex_halbtc8192e2ant_init_coex_dm(struct btc_coexist *btcoexist);
-void ex_halbtc8192e2ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8192e2ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8192e2ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8192e2ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8192e2ant_media_status_notify(struct btc_coexist *btcoexist,
+void ex_btc8192e2ant_init_hwconfig(struct btc_coexist *btcoexist);
+void ex_btc8192e2ant_init_coex_dm(struct btc_coexist *btcoexist);
+void ex_btc8192e2ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8192e2ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8192e2ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8192e2ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8192e2ant_media_status_notify(struct btc_coexist *btcoexist,
+ u8 type);
+void ex_btc8192e2ant_special_packet_notify(struct btc_coexist *btcoexist,
+ u8 type);
+void ex_btc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist,
+ u8 *tmpbuf, u8 length);
+void ex_btc8192e2ant_stack_operation_notify(struct btc_coexist *btcoexist,
u8 type);
-void ex_halbtc8192e2ant_special_packet_notify(struct btc_coexist *btcoexist,
- u8 type);
-void ex_halbtc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist,
- u8 *tmpbuf, u8 length);
-void ex_halbtc8192e2ant_stack_operation_notify(struct btc_coexist *btcoexist,
- u8 type);
-void ex_halbtc8192e2ant_halt_notify(struct btc_coexist *btcoexist);
-void ex_halbtc8192e2ant_periodical(struct btc_coexist *btcoexist);
-void ex_halbtc8192e2ant_display_coex_info(struct btc_coexist *btcoexist);
+void ex_btc8192e2ant_halt_notify(struct btc_coexist *btcoexist);
+void ex_btc8192e2ant_periodical(struct btc_coexist *btcoexist);
+void ex_btc8192e2ant_display_coex_info(struct btc_coexist *btcoexist);
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
index 2003c8c..03998d2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
@@ -210,11 +210,24 @@ static void halbtc8723b1ant_limited_rx(struct btc_coexist *btcoexist,
btcoexist->btc_set(btcoexist, BTC_SET_ACT_AGGREGATE_CTRL, NULL);
}
+static void halbtc8723b1ant_query_bt_info(struct btc_coexist *btcoexist)
+{
+ u8 h2c_parameter[1] = {0};
+
+ coex_sta->c2h_bt_info_req_sent = true;
+
+ /* trigger */
+ h2c_parameter[0] |= BIT(0);
+
+ btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter);
+}
+
static void halbtc8723b1ant_monitor_bt_ctr(struct btc_coexist *btcoexist)
{
u32 reg_hp_txrx, reg_lp_txrx, u32tmp;
u32 reg_hp_tx = 0, reg_hp_rx = 0;
u32 reg_lp_tx = 0, reg_lp_rx = 0;
+ static u32 num_of_bt_counter_chk;
reg_hp_txrx = 0x770;
reg_lp_txrx = 0x774;
@@ -232,25 +245,122 @@ static void halbtc8723b1ant_monitor_bt_ctr(struct btc_coexist *btcoexist)
coex_sta->low_priority_tx = reg_lp_tx;
coex_sta->low_priority_rx = reg_lp_rx;
+ if ((coex_sta->low_priority_tx > 1050) &&
+ (!coex_sta->c2h_bt_inquiry_page))
+ coex_sta->pop_event_cnt++;
+
/* reset counter */
btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc);
+
+ /* This part is for wifi FW and driver to update BT's status as
+ * disabled.
+ *
+ * The flow is as the following
+ * 1. disable BT
+ * 2. if all BT Tx/Rx counter = 0, after 6 sec we query bt info
+ * 3. Because BT will not rsp from mailbox, so wifi fw will know BT is
+ * disabled
+ *
+ * 4. FW will rsp c2h for BT that driver will know BT is disabled.
+ */
+ if ((reg_hp_tx == 0) && (reg_hp_rx == 0) && (reg_lp_tx == 0) &&
+ (reg_lp_rx == 0)) {
+ num_of_bt_counter_chk++;
+ if (num_of_bt_counter_chk == 3)
+ halbtc8723b1ant_query_bt_info(btcoexist);
+ } else {
+ num_of_bt_counter_chk = 0;
+ }
}
-static void halbtc8723b1ant_query_bt_info(struct btc_coexist *btcoexist)
+static void halbtc8723b1ant_monitor_wifi_ctr(struct btc_coexist *btcoexist)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- u8 h2c_parameter[1] = {0};
+ s32 wifi_rssi = 0;
+ bool wifi_busy = false, wifi_under_b_mode = false;
+ static u8 cck_lock_counter;
+ u32 total_cnt;
- coex_sta->c2h_bt_info_req_sent = true;
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
+ btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_B_MODE,
+ &wifi_under_b_mode);
- /* trigger */
- h2c_parameter[0] |= BIT0;
+ if (coex_sta->under_ips) {
+ coex_sta->crc_ok_cck = 0;
+ coex_sta->crc_ok_11g = 0;
+ coex_sta->crc_ok_11n = 0;
+ coex_sta->crc_ok_11n_agg = 0;
+
+ coex_sta->crc_err_cck = 0;
+ coex_sta->crc_err_11g = 0;
+ coex_sta->crc_err_11n = 0;
+ coex_sta->crc_err_11n_agg = 0;
+ } else {
+ coex_sta->crc_ok_cck =
+ btcoexist->btc_read_4byte(btcoexist, 0xf88);
+ coex_sta->crc_ok_11g =
+ btcoexist->btc_read_2byte(btcoexist, 0xf94);
+ coex_sta->crc_ok_11n =
+ btcoexist->btc_read_2byte(btcoexist, 0xf90);
+ coex_sta->crc_ok_11n_agg =
+ btcoexist->btc_read_2byte(btcoexist, 0xfb8);
+
+ coex_sta->crc_err_cck =
+ btcoexist->btc_read_4byte(btcoexist, 0xf84);
+ coex_sta->crc_err_11g =
+ btcoexist->btc_read_2byte(btcoexist, 0xf96);
+ coex_sta->crc_err_11n =
+ btcoexist->btc_read_2byte(btcoexist, 0xf92);
+ coex_sta->crc_err_11n_agg =
+ btcoexist->btc_read_2byte(btcoexist, 0xfba);
+ }
- RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n",
- h2c_parameter[0]);
+ /* reset counter */
+ btcoexist->btc_write_1byte_bitmask(btcoexist, 0xf16, 0x1, 0x1);
+ btcoexist->btc_write_1byte_bitmask(btcoexist, 0xf16, 0x1, 0x0);
+
+ if ((wifi_busy) && (wifi_rssi >= 30) && (!wifi_under_b_mode)) {
+ total_cnt = coex_sta->crc_ok_cck + coex_sta->crc_ok_11g +
+ coex_sta->crc_ok_11n + coex_sta->crc_ok_11n_agg;
+
+ if ((coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) ||
+ (coex_dm->bt_status ==
+ BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) ||
+ (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_SCO_BUSY)) {
+ if (coex_sta->crc_ok_cck >
+ (total_cnt - coex_sta->crc_ok_cck)) {
+ if (cck_lock_counter < 3)
+ cck_lock_counter++;
+ } else {
+ if (cck_lock_counter > 0)
+ cck_lock_counter--;
+ }
- btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter);
+ } else {
+ if (cck_lock_counter > 0)
+ cck_lock_counter--;
+ }
+ } else {
+ if (cck_lock_counter > 0)
+ cck_lock_counter--;
+ }
+
+ if (!coex_sta->pre_ccklock) {
+ if (cck_lock_counter >= 3)
+ coex_sta->cck_lock = true;
+ else
+ coex_sta->cck_lock = false;
+ } else {
+ if (cck_lock_counter == 0)
+ coex_sta->cck_lock = false;
+ else
+ coex_sta->cck_lock = true;
+ }
+
+ if (coex_sta->cck_lock)
+ coex_sta->cck_ever_lock = true;
+
+ coex_sta->pre_ccklock = coex_sta->cck_lock;
}
static bool btc8723b1ant_is_wifi_status_changed(struct btc_coexist *btcoexist)
@@ -297,6 +407,7 @@ static void halbtc8723b1ant_update_bt_link_info(struct btc_coexist *btcoexist)
bt_link_info->a2dp_exist = coex_sta->a2dp_exist;
bt_link_info->pan_exist = coex_sta->pan_exist;
bt_link_info->hid_exist = coex_sta->hid_exist;
+ bt_link_info->bt_hi_pri_link_exist = coex_sta->bt_hi_pri_link_exist;
/* work around for HS mode. */
if (bt_hs_on) {
@@ -333,6 +444,35 @@ static void halbtc8723b1ant_update_bt_link_info(struct btc_coexist *btcoexist)
bt_link_info->hid_only = false;
}
+static void halbtc8723b1ant_set_bt_auto_report(struct btc_coexist *btcoexist,
+ bool enable_auto_report)
+{
+ u8 h2c_parameter[1] = {0};
+
+ h2c_parameter[0] = 0;
+
+ if (enable_auto_report)
+ h2c_parameter[0] |= BIT(0);
+
+ btcoexist->btc_fill_h2c(btcoexist, 0x68, 1, h2c_parameter);
+}
+
+static void halbtc8723b1ant_bt_auto_report(struct btc_coexist *btcoexist,
+ bool force_exec,
+ bool enable_auto_report)
+{
+ coex_dm->cur_bt_auto_report = enable_auto_report;
+
+ if (!force_exec) {
+ if (coex_dm->pre_bt_auto_report == coex_dm->cur_bt_auto_report)
+ return;
+ }
+ halbtc8723b1ant_set_bt_auto_report(btcoexist,
+ coex_dm->cur_bt_auto_report);
+
+ coex_dm->pre_bt_auto_report = coex_dm->cur_bt_auto_report;
+}
+
static void btc8723b1ant_set_sw_pen_tx_rate_adapt(struct btc_coexist *btcoexist,
bool low_penalty_ra)
{
@@ -430,6 +570,8 @@ static void halbtc8723b1ant_coex_table(struct btc_coexist *btcoexist,
static void halbtc8723b1ant_coex_table_with_type(struct btc_coexist *btcoexist,
bool force_exec, u8 type)
{
+ coex_sta->coex_table_type = type;
+
switch (type) {
case 0:
halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555,
@@ -445,24 +587,68 @@ static void halbtc8723b1ant_coex_table_with_type(struct btc_coexist *btcoexist,
break;
case 3:
halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555,
- 0xaaaaaaaa, 0xffffff, 0x3);
+ 0x5a5a5a5a, 0xffffff, 0x3);
break;
case 4:
- halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555,
- 0x5aaa5aaa, 0xffffff, 0x3);
+ if ((coex_sta->cck_ever_lock) && (coex_sta->scan_ap_num <= 5))
+ halbtc8723b1ant_coex_table(btcoexist, force_exec,
+ 0x55555555, 0xaaaa5a5a,
+ 0xffffff, 0x3);
+ else
+ halbtc8723b1ant_coex_table(btcoexist, force_exec,
+ 0x55555555, 0x5a5a5a5a,
+ 0xffffff, 0x3);
break;
case 5:
- halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x5a5a5a5a,
- 0xaaaa5a5a, 0xffffff, 0x3);
+ if ((coex_sta->cck_ever_lock) && (coex_sta->scan_ap_num <= 5))
+ halbtc8723b1ant_coex_table(btcoexist, force_exec,
+ 0x5a5a5a5a, 0x5aaa5a5a,
+ 0xffffff, 0x3);
+ else
+ halbtc8723b1ant_coex_table(btcoexist, force_exec,
+ 0x5a5a5a5a, 0x5aaa5a5a,
+ 0xffffff, 0x3);
break;
case 6:
halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555,
- 0xaaaa5a5a, 0xffffff, 0x3);
+ 0xaaaaaaaa, 0xffffff, 0x3);
break;
case 7:
halbtc8723b1ant_coex_table(btcoexist, force_exec, 0xaaaaaaaa,
0xaaaaaaaa, 0xffffff, 0x3);
break;
+ case 8:
+ halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55dd55dd,
+ 0x5ada5ada, 0xffffff, 0x3);
+ break;
+ case 9:
+ halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55dd55dd,
+ 0x5ada5ada, 0xffffff, 0x3);
+ break;
+ case 10:
+ halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55dd55dd,
+ 0x5ada5ada, 0xffffff, 0x3);
+ break;
+ case 11:
+ halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55dd55dd,
+ 0x5ada5ada, 0xffffff, 0x3);
+ break;
+ case 12:
+ halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55dd55dd,
+ 0x5ada5ada, 0xffffff, 0x3);
+ break;
+ case 13:
+ halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x5fff5fff,
+ 0xaaaaaaaa, 0xffffff, 0x3);
+ break;
+ case 14:
+ halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x5fff5fff,
+ 0x5ada5ada, 0xffffff, 0x3);
+ break;
+ case 15:
+ halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55dd55dd,
+ 0xaaaaaaaa, 0xffffff, 0x3);
+ break;
default:
break;
}
@@ -611,14 +797,18 @@ static void halbtc8723b1ant_sw_mechanism(struct btc_coexist *btcoexist,
}
static void halbtc8723b1ant_set_ant_path(struct btc_coexist *btcoexist,
- u8 ant_pos_type, bool init_hw_cfg,
- bool wifi_off)
+ u8 ant_pos_type, bool force_exec,
+ bool init_hw_cfg, bool wifi_off)
{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
struct btc_board_info *board_info = &btcoexist->board_info;
- u32 fw_ver = 0, u32tmp = 0;
+ u32 fw_ver = 0, u32tmp = 0, cnt_bt_cal_chk = 0;
bool pg_ext_switch = false;
bool use_ext_switch = false;
- u8 h2c_parameter[2] = {0};
+ bool is_in_mp_mode = false;
+ u8 h2c_parameter[2] = {0}, u8tmp = 0;
+
+ coex_dm->cur_ant_pos_type = ant_pos_type;
btcoexist->btc_get(btcoexist, BTC_GET_BL_EXT_SWITCH, &pg_ext_switch);
/* [31:16] = fw ver, [15:0] = fw sub ver */
@@ -628,24 +818,103 @@ static void halbtc8723b1ant_set_ant_path(struct btc_coexist *btcoexist,
use_ext_switch = true;
if (init_hw_cfg) {
- /*BT select s0/s1 is controlled by WiFi */
- btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67, 0x20, 0x1);
+ /* WiFi TRx Mask on */
+ btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff,
+ 0x780);
+ /* remove due to interrupt is disabled that polling c2h will
+ * fail and delay 100ms.
+ */
- /*Force GNT_BT to Normal */
- btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x0);
- } else if (wifi_off) {
- /*Force GNT_BT to High */
- btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x3);
- /*BT select s0/s1 is controlled by BT */
+ if (fw_ver >= 0x180000) {
+ /* Use H2C to set GNT_BT to HIGH */
+ h2c_parameter[0] = 1;
+ btcoexist->btc_fill_h2c(btcoexist, 0x6E, 1,
+ h2c_parameter);
+ } else {
+ /* set grant_bt to high */
+ btcoexist->btc_write_1byte(btcoexist, 0x765, 0x18);
+ }
+ /* set wlan_act control by PTA */
+ btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4);
+
+ /* BT select s0/s1 is controlled by BT */
btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67, 0x20, 0x0);
+ btcoexist->btc_write_1byte_bitmask(btcoexist, 0x39, 0x8, 0x1);
+ btcoexist->btc_write_1byte(btcoexist, 0x974, 0xff);
+ btcoexist->btc_write_1byte_bitmask(btcoexist, 0x944, 0x3, 0x3);
+ btcoexist->btc_write_1byte(btcoexist, 0x930, 0x77);
+ } else if (wifi_off) {
+ if (fw_ver >= 0x180000) {
+ /* Use H2C to set GNT_BT to HIGH */
+ h2c_parameter[0] = 1;
+ btcoexist->btc_fill_h2c(btcoexist, 0x6E, 1,
+ h2c_parameter);
+ } else {
+ /* set grant_bt to high */
+ btcoexist->btc_write_1byte(btcoexist, 0x765, 0x18);
+ }
+ /* set wlan_act to always low */
+ btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_IS_IN_MP_MODE,
+ &is_in_mp_mode);
+ if (!is_in_mp_mode)
+ /* BT select s0/s1 is controlled by BT */
+ btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67,
+ 0x20, 0x0);
+ else
+ /* BT select s0/s1 is controlled by WiFi */
+ btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67,
+ 0x20, 0x1);
- /* 0x4c[24:23] = 00, Set Antenna control by BT_RFE_CTRL
- * BT Vendor 0xac = 0xf002
+ /* 0x4c[24:23]=00, Set Antenna control by BT_RFE_CTRL
+ * BT Vendor 0xac=0xf002
*/
u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c);
u32tmp &= ~BIT23;
u32tmp &= ~BIT24;
btcoexist->btc_write_4byte(btcoexist, 0x4c, u32tmp);
+ } else {
+ /* Use H2C to set GNT_BT to LOW */
+ if (fw_ver >= 0x180000) {
+ if (btcoexist->btc_read_1byte(btcoexist, 0x765) != 0) {
+ h2c_parameter[0] = 0;
+ btcoexist->btc_fill_h2c(btcoexist, 0x6E, 1,
+ h2c_parameter);
+ }
+ } else {
+ /* BT calibration check */
+ while (cnt_bt_cal_chk <= 20) {
+ u8tmp = btcoexist->btc_read_1byte(btcoexist,
+ 0x49d);
+ cnt_bt_cal_chk++;
+ if (u8tmp & BIT(0)) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST,
+ DBG_LOUD,
+ "[BTCoex], ########### BT is calibrating (wait cnt=%d) ###########\n",
+ cnt_bt_cal_chk);
+ mdelay(50);
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST,
+ DBG_LOUD,
+ "[BTCoex], ********** BT is NOT calibrating (wait cnt=%d)**********\n",
+ cnt_bt_cal_chk);
+ break;
+ }
+ }
+
+ /* set grant_bt to PTA */
+ btcoexist->btc_write_1byte(btcoexist, 0x765, 0x0);
+ }
+
+ if (btcoexist->btc_read_1byte(btcoexist, 0x76e) != 0xc) {
+ /* set wlan_act control by PTA */
+ btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc);
+ }
+
+ btcoexist->btc_write_1byte_bitmask(
+ btcoexist, 0x67, 0x20,
+ 0x1); /* BT select s0/s1 is controlled by WiFi */
}
if (use_ext_switch) {
@@ -658,216 +927,278 @@ static void halbtc8723b1ant_set_ant_path(struct btc_coexist *btcoexist,
u32tmp |= BIT24;
btcoexist->btc_write_4byte(btcoexist, 0x4c, u32tmp);
+ /* fixed internal switch S1->WiFi, S0->BT */
+ btcoexist->btc_write_4byte(btcoexist, 0x948, 0x0);
+
if (board_info->btdm_ant_pos ==
BTC_ANTENNA_AT_MAIN_PORT) {
- /* Main Ant to BT for IPS case 0x4c[23] = 1 */
- btcoexist->btc_write_1byte_bitmask(btcoexist,
- 0x64, 0x1,
- 0x1);
-
/* tell firmware "no antenna inverse" */
h2c_parameter[0] = 0;
- h2c_parameter[1] = 1; /*ext switch type*/
+ /* ext switch type */
+ h2c_parameter[1] = 1;
btcoexist->btc_fill_h2c(btcoexist, 0x65, 2,
h2c_parameter);
} else {
- /* Aux Ant to BT for IPS case 0x4c[23] = 1 */
- btcoexist->btc_write_1byte_bitmask(btcoexist,
- 0x64, 0x1,
- 0x0);
-
/* tell firmware "antenna inverse" */
h2c_parameter[0] = 1;
- h2c_parameter[1] = 1; /* ext switch type */
+ /* ext switch type */
+ h2c_parameter[1] = 1;
btcoexist->btc_fill_h2c(btcoexist, 0x65, 2,
h2c_parameter);
}
}
- /* fixed internal switch first
- * fixed internal switch S1->WiFi, S0->BT
- */
- if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT)
- btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0);
- else /* fixed internal switch S0->WiFi, S1->BT */
- btcoexist->btc_write_2byte(btcoexist, 0x948, 0x280);
-
- /* ext switch setting */
- switch (ant_pos_type) {
- case BTC_ANT_PATH_WIFI:
- if (board_info->btdm_ant_pos ==
- BTC_ANTENNA_AT_MAIN_PORT)
- btcoexist->btc_write_1byte_bitmask(btcoexist,
- 0x92c, 0x3,
- 0x1);
- else
- btcoexist->btc_write_1byte_bitmask(btcoexist,
- 0x92c, 0x3,
- 0x2);
- break;
- case BTC_ANT_PATH_BT:
- if (board_info->btdm_ant_pos ==
- BTC_ANTENNA_AT_MAIN_PORT)
- btcoexist->btc_write_1byte_bitmask(btcoexist,
- 0x92c, 0x3,
- 0x2);
- else
- btcoexist->btc_write_1byte_bitmask(btcoexist,
- 0x92c, 0x3,
- 0x1);
- break;
- default:
- case BTC_ANT_PATH_PTA:
- if (board_info->btdm_ant_pos ==
- BTC_ANTENNA_AT_MAIN_PORT)
- btcoexist->btc_write_1byte_bitmask(btcoexist,
- 0x92c, 0x3,
- 0x1);
- else
- btcoexist->btc_write_1byte_bitmask(btcoexist,
- 0x92c, 0x3,
- 0x2);
- break;
+ if (force_exec ||
+ (coex_dm->cur_ant_pos_type != coex_dm->pre_ant_pos_type)) {
+ /* ext switch setting */
+ switch (ant_pos_type) {
+ case BTC_ANT_PATH_WIFI:
+ if (board_info->btdm_ant_pos ==
+ BTC_ANTENNA_AT_MAIN_PORT)
+ btcoexist->btc_write_1byte_bitmask(
+ btcoexist, 0x92c, 0x3, 0x1);
+ else
+ btcoexist->btc_write_1byte_bitmask(
+ btcoexist, 0x92c, 0x3, 0x2);
+ break;
+ case BTC_ANT_PATH_BT:
+ if (board_info->btdm_ant_pos ==
+ BTC_ANTENNA_AT_MAIN_PORT)
+ btcoexist->btc_write_1byte_bitmask(
+ btcoexist, 0x92c, 0x3, 0x2);
+ else
+ btcoexist->btc_write_1byte_bitmask(
+ btcoexist, 0x92c, 0x3, 0x1);
+ break;
+ default:
+ case BTC_ANT_PATH_PTA:
+ if (board_info->btdm_ant_pos ==
+ BTC_ANTENNA_AT_MAIN_PORT)
+ btcoexist->btc_write_1byte_bitmask(
+ btcoexist, 0x92c, 0x3, 0x1);
+ else
+ btcoexist->btc_write_1byte_bitmask(
+ btcoexist, 0x92c, 0x3, 0x2);
+ break;
+ }
}
-
} else {
if (init_hw_cfg) {
- /* 0x4c[23] = 1, 0x4c[24] = 0 Antenna control by 0x64 */
+ /* 0x4c[23] = 1, 0x4c[24] = 0,
+ * Antenna control by 0x64
+ */
u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c);
u32tmp |= BIT23;
u32tmp &= ~BIT24;
btcoexist->btc_write_4byte(btcoexist, 0x4c, u32tmp);
+ /* Fix Ext switch Main->S1, Aux->S0 */
+ btcoexist->btc_write_1byte_bitmask(btcoexist, 0x64, 0x1,
+ 0x0);
+
if (board_info->btdm_ant_pos ==
BTC_ANTENNA_AT_MAIN_PORT) {
- /* Main Ant to WiFi for IPS case 0x4c[23] = 1 */
- btcoexist->btc_write_1byte_bitmask(btcoexist,
- 0x64, 0x1,
- 0x0);
-
/* tell firmware "no antenna inverse" */
h2c_parameter[0] = 0;
- h2c_parameter[1] = 0; /* internal switch type */
+ /* internal switch type */
+ h2c_parameter[1] = 0;
btcoexist->btc_fill_h2c(btcoexist, 0x65, 2,
h2c_parameter);
} else {
- /* Aux Ant to BT for IPS case 0x4c[23] = 1 */
- btcoexist->btc_write_1byte_bitmask(btcoexist,
- 0x64, 0x1,
- 0x1);
-
/* tell firmware "antenna inverse" */
h2c_parameter[0] = 1;
- h2c_parameter[1] = 0; /* internal switch type */
+ /* internal switch type */
+ h2c_parameter[1] = 0;
btcoexist->btc_fill_h2c(btcoexist, 0x65, 2,
h2c_parameter);
}
}
- /* fixed external switch first
- * Main->WiFi, Aux->BT
- */
- if (board_info->btdm_ant_pos ==
- BTC_ANTENNA_AT_MAIN_PORT)
- btcoexist->btc_write_1byte_bitmask(btcoexist, 0x92c,
- 0x3, 0x1);
- else /* Main->BT, Aux->WiFi */
- btcoexist->btc_write_1byte_bitmask(btcoexist, 0x92c,
- 0x3, 0x2);
-
- /* internal switch setting */
- switch (ant_pos_type) {
- case BTC_ANT_PATH_WIFI:
- if (board_info->btdm_ant_pos ==
- BTC_ANTENNA_AT_MAIN_PORT)
- btcoexist->btc_write_2byte(btcoexist, 0x948,
- 0x0);
- else
- btcoexist->btc_write_2byte(btcoexist, 0x948,
- 0x280);
- break;
- case BTC_ANT_PATH_BT:
- if (board_info->btdm_ant_pos ==
- BTC_ANTENNA_AT_MAIN_PORT)
- btcoexist->btc_write_2byte(btcoexist, 0x948,
- 0x280);
- else
- btcoexist->btc_write_2byte(btcoexist, 0x948,
- 0x0);
- break;
- default:
- case BTC_ANT_PATH_PTA:
- if (board_info->btdm_ant_pos ==
- BTC_ANTENNA_AT_MAIN_PORT)
- btcoexist->btc_write_2byte(btcoexist, 0x948,
- 0x200);
- else
- btcoexist->btc_write_2byte(btcoexist, 0x948,
- 0x80);
- break;
+ if (force_exec ||
+ (coex_dm->cur_ant_pos_type != coex_dm->pre_ant_pos_type)) {
+ /* internal switch setting */
+ switch (ant_pos_type) {
+ case BTC_ANT_PATH_WIFI:
+ if (board_info->btdm_ant_pos ==
+ BTC_ANTENNA_AT_MAIN_PORT)
+ btcoexist->btc_write_4byte(btcoexist,
+ 0x948, 0x0);
+ else
+ btcoexist->btc_write_4byte(btcoexist,
+ 0x948, 0x280);
+ break;
+ case BTC_ANT_PATH_BT:
+ if (board_info->btdm_ant_pos ==
+ BTC_ANTENNA_AT_MAIN_PORT)
+ btcoexist->btc_write_4byte(btcoexist,
+ 0x948, 0x280);
+ else
+ btcoexist->btc_write_4byte(btcoexist,
+ 0x948, 0x0);
+ break;
+ default:
+ case BTC_ANT_PATH_PTA:
+ if (board_info->btdm_ant_pos ==
+ BTC_ANTENNA_AT_MAIN_PORT)
+ btcoexist->btc_write_4byte(btcoexist,
+ 0x948, 0x200);
+ else
+ btcoexist->btc_write_4byte(btcoexist,
+ 0x948, 0x80);
+ break;
+ }
}
}
+
+ coex_dm->pre_ant_pos_type = coex_dm->cur_ant_pos_type;
}
static void halbtc8723b1ant_ps_tdma(struct btc_coexist *btcoexist,
bool force_exec, bool turn_on, u8 type)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
bool wifi_busy = false;
u8 rssi_adjust_val = 0;
+ u8 ps_tdma_byte0_val = 0x51;
+ u8 ps_tdma_byte3_val = 0x10;
+ u8 ps_tdma_byte4_val = 0x50;
+ s8 wifi_duration_adjust = 0x0;
+ static bool pre_wifi_busy;
coex_dm->cur_ps_tdma_on = turn_on;
coex_dm->cur_ps_tdma = type;
btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
- if (!force_exec) {
- if (coex_dm->cur_ps_tdma_on)
- RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], ******** TDMA(on, %d) *********\n",
- coex_dm->cur_ps_tdma);
- else
- RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], ******** TDMA(off, %d) ********\n",
- coex_dm->cur_ps_tdma);
+ if (wifi_busy != pre_wifi_busy) {
+ force_exec = true;
+ pre_wifi_busy = wifi_busy;
+ }
+ if (!force_exec) {
if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) &&
(coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma))
return;
}
+
+ if (coex_sta->scan_ap_num <= 5) {
+ wifi_duration_adjust = 5;
+
+ if (coex_sta->a2dp_bit_pool >= 35)
+ wifi_duration_adjust = -10;
+ else if (coex_sta->a2dp_bit_pool >= 45)
+ wifi_duration_adjust = -15;
+ } else if (coex_sta->scan_ap_num >= 40) {
+ wifi_duration_adjust = -15;
+
+ if (coex_sta->a2dp_bit_pool < 35)
+ wifi_duration_adjust = -5;
+ else if (coex_sta->a2dp_bit_pool < 45)
+ wifi_duration_adjust = -10;
+ } else if (coex_sta->scan_ap_num >= 20) {
+ wifi_duration_adjust = -10;
+
+ if (coex_sta->a2dp_bit_pool >= 45)
+ wifi_duration_adjust = -15;
+ } else {
+ wifi_duration_adjust = 0;
+
+ if (coex_sta->a2dp_bit_pool >= 35)
+ wifi_duration_adjust = -10;
+ else if (coex_sta->a2dp_bit_pool >= 45)
+ wifi_duration_adjust = -15;
+ }
+
+ if ((type == 1) || (type == 2) || (type == 9) || (type == 11) ||
+ (type == 101) || (type == 102) || (type == 109) || (type == 101)) {
+ if (!coex_sta->force_lps_on) {
+ /* Native power save TDMA, only for A2DP-only case
+ * 1/2/9/11 while wifi noisy threshold > 30
+ */
+
+ /* no null-pkt */
+ ps_tdma_byte0_val = 0x61;
+ /* no tx-pause at BT-slot */
+ ps_tdma_byte3_val = 0x11;
+ /* 0x778 = d/1 toggle, no dynamic slot */
+ ps_tdma_byte4_val = 0x10;
+ } else {
+ /* null-pkt */
+ ps_tdma_byte0_val = 0x51;
+ /* tx-pause at BT-slot */
+ ps_tdma_byte3_val = 0x10;
+ /* 0x778 = d/1 toggle, dynamic slot */
+ ps_tdma_byte4_val = 0x50;
+ }
+ } else if ((type == 3) || (type == 13) || (type == 14) ||
+ (type == 103) || (type == 113) || (type == 114)) {
+ /* null-pkt */
+ ps_tdma_byte0_val = 0x51;
+ /* tx-pause at BT-slot */
+ ps_tdma_byte3_val = 0x10;
+ /* 0x778 = d/1 toggle, no dynamic slot */
+ ps_tdma_byte4_val = 0x10;
+ } else { /* native power save case */
+ /* no null-pkt */
+ ps_tdma_byte0_val = 0x61;
+ /* no tx-pause at BT-slot */
+ ps_tdma_byte3_val = 0x11;
+ /* 0x778 = d/1 toggle, no dynamic slot */
+ ps_tdma_byte4_val = 0x11;
+ /* psTdmaByte4Va is not define for 0x778 = d/1, 1/1 case */
+ }
+
+ /* if (bt_link_info->slave_role) */
+ if ((bt_link_info->slave_role) && (bt_link_info->a2dp_exist))
+ /* 0x778 = 0x1 at wifi slot (no blocking BT Low-Pri pkts) */
+ ps_tdma_byte4_val = ps_tdma_byte4_val | 0x1;
+
+ if (type > 100) {
+ /* set antenna control by SW */
+ ps_tdma_byte0_val = ps_tdma_byte0_val | 0x82;
+ /* set antenna no toggle, control by antenna diversity */
+ ps_tdma_byte3_val = ps_tdma_byte3_val | 0x60;
+ }
+
if (turn_on) {
switch (type) {
default:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x1a,
- 0x1a, 0x0, 0x50);
+ 0x1a, 0x0,
+ ps_tdma_byte4_val);
break;
case 1:
- halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x3a,
- 0x03, 0x10, 0x50);
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val,
+ 0x3a + wifi_duration_adjust, 0x03,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
rssi_adjust_val = 11;
break;
case 2:
- halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x2b,
- 0x03, 0x10, 0x50);
- rssi_adjust_val = 14;
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val,
+ 0x2d + wifi_duration_adjust, 0x03,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
break;
case 3:
- halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x1d,
- 0x1d, 0x0, 0x52);
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x30, 0x03,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
break;
case 4:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x15,
- 0x3, 0x14, 0x0);
- rssi_adjust_val = 17;
+ 0x3, 0x14, 0x0);
break;
case 5:
- halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x15,
- 0x3, 0x11, 0x10);
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x1f, 0x3,
+ ps_tdma_byte3_val, 0x11);
break;
case 6:
- halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x20,
- 0x3, 0x11, 0x13);
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x20, 0x3,
+ ps_tdma_byte3_val, 0x11);
break;
case 7:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xc,
@@ -875,33 +1206,44 @@ static void halbtc8723b1ant_ps_tdma(struct btc_coexist *btcoexist,
break;
case 8:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x25,
- 0x3, 0x10, 0x0);
+ 0x3, 0x10, 0x0);
break;
case 9:
- halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x21,
- 0x3, 0x10, 0x50);
- rssi_adjust_val = 18;
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x21, 0x3,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
break;
case 10:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xa,
0xa, 0x0, 0x40);
break;
case 11:
- halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x15,
- 0x03, 0x10, 0x50);
- rssi_adjust_val = 20;
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x21, 0x03,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
break;
case 12:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x0a,
- 0x0a, 0x0, 0x50);
+ 0x0a, 0x0, 0x50);
break;
case 13:
- halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x15,
- 0x15, 0x0, 0x50);
+ if (coex_sta->scan_ap_num <= 3)
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x40, 0x3,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
+ else
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x21, 0x3,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
break;
case 14:
- halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x21,
- 0x3, 0x10, 0x52);
+ if (coex_sta->scan_ap_num <= 3)
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, 0x51, 0x30, 0x3, 0x10, 0x50);
+ else
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x21, 0x3,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
break;
case 15:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xa,
@@ -909,103 +1251,173 @@ static void halbtc8723b1ant_ps_tdma(struct btc_coexist *btcoexist,
break;
case 16:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x15,
- 0x3, 0x10, 0x0);
- rssi_adjust_val = 18;
+ 0x3, 0x10, 0x0);
break;
case 18:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x25,
- 0x3, 0x10, 0x0);
- rssi_adjust_val = 14;
+ 0x3, 0x10, 0x0);
break;
case 20:
- halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x35,
- 0x03, 0x11, 0x10);
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x3f, 0x03,
+ ps_tdma_byte3_val, 0x10);
break;
case 21:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x25,
- 0x03, 0x11, 0x11);
+ 0x03, 0x11, 0x11);
break;
case 22:
- halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x25,
- 0x03, 0x11, 0x10);
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x25, 0x03,
+ ps_tdma_byte3_val, 0x10);
break;
case 23:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x25,
- 0x3, 0x31, 0x18);
- rssi_adjust_val = 22;
+ 0x3, 0x31, 0x18);
break;
case 24:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x15,
- 0x3, 0x31, 0x18);
- rssi_adjust_val = 22;
+ 0x3, 0x31, 0x18);
break;
case 25:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0xa,
0x3, 0x31, 0x18);
- rssi_adjust_val = 22;
break;
case 26:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0xa,
0x3, 0x31, 0x18);
- rssi_adjust_val = 22;
break;
case 27:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x25,
- 0x3, 0x31, 0x98);
- rssi_adjust_val = 22;
+ 0x3, 0x31, 0x98);
break;
case 28:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x69, 0x25,
- 0x3, 0x31, 0x0);
+ 0x3, 0x31, 0x0);
break;
case 29:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xab, 0x1a,
- 0x1a, 0x1, 0x10);
+ 0x1a, 0x1, 0x10);
break;
case 30:
- halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x14,
- 0x3, 0x10, 0x50);
+ halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x30,
+ 0x3, 0x10, 0x10);
break;
case 31:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xd3, 0x1a,
- 0x1a, 0, 0x58);
+ 0x1a, 0, 0x58);
break;
case 32:
- halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0xa,
- 0x3, 0x10, 0x0);
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x35, 0x3,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
break;
case 33:
- halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xa3, 0x25,
- 0x3, 0x30, 0x90);
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x35, 0x3,
+ ps_tdma_byte3_val, 0x10);
break;
case 34:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x53, 0x1a,
- 0x1a, 0x0, 0x10);
+ 0x1a, 0x0, 0x10);
break;
case 35:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x63, 0x1a,
- 0x1a, 0x0, 0x10);
+ 0x1a, 0x0, 0x10);
break;
case 36:
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xd3, 0x12,
- 0x3, 0x14, 0x50);
+ 0x3, 0x14, 0x50);
break;
- /* SoftAP only with no sta associated, BT disable,
- * TDMA mode for power saving
- * here softap mode screen off will cost 70-80mA for phone
- */
case 40:
+ /* SoftAP only with no sta associated,BT disable ,TDMA
+ * mode for power saving
+ *
+ * here softap mode screen off will cost 70-80mA for
+ * phone
+ */
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x23, 0x18,
- 0x00, 0x10, 0x24);
+ 0x00, 0x10, 0x24);
+ break;
+
+ case 101:
+ /* for 1-Ant translate to 2-Ant */
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val,
+ 0x3a + wifi_duration_adjust, 0x03,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
+ break;
+ case 102:
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val,
+ 0x2d + wifi_duration_adjust, 0x03,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
+ break;
+ case 103:
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x3a, 0x03,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
+ break;
+ case 105:
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x15, 0x3,
+ ps_tdma_byte3_val, 0x11);
+ break;
+ case 106:
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x20, 0x3,
+ ps_tdma_byte3_val, 0x11);
+ break;
+ case 109:
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x21, 0x3,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
+ break;
+ case 111:
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x21, 0x03,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
+ break;
+ case 113:
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x21, 0x3,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
+ break;
+ case 114:
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x21, 0x3,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
+ break;
+ case 120:
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x3f, 0x03,
+ ps_tdma_byte3_val, 0x10);
+ break;
+ case 122:
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x25, 0x03,
+ ps_tdma_byte3_val, 0x10);
+ break;
+ case 132:
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x25, 0x03,
+ ps_tdma_byte3_val, ps_tdma_byte4_val);
+ break;
+ case 133:
+ halbtc8723b1ant_set_fw_ps_tdma(
+ btcoexist, ps_tdma_byte0_val, 0x25, 0x03,
+ ps_tdma_byte3_val, 0x11);
break;
}
} else {
+ /* disable PS tdma */
switch (type) {
case 8: /* PTA Control */
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x8, 0x0,
0x0, 0x0, 0x0);
halbtc8723b1ant_set_ant_path(btcoexist,
BTC_ANT_PATH_PTA,
+ FORCE_EXEC,
false, false);
break;
case 0:
@@ -1013,17 +1425,10 @@ static void halbtc8723b1ant_ps_tdma(struct btc_coexist *btcoexist,
/* Software control, Antenna at BT side */
halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0,
0x0, 0x0, 0x0);
- halbtc8723b1ant_set_ant_path(btcoexist,
- BTC_ANT_PATH_BT,
- false, false);
break;
- case 9:
- /* Software control, Antenna at WiFi side */
- halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0,
- 0x0, 0x0, 0x0);
- halbtc8723b1ant_set_ant_path(btcoexist,
- BTC_ANT_PATH_WIFI,
- false, false);
+ case 1: /* 2-Ant, 0x778=3, antenna control by ant diversity */
+ halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0, 0x0,
+ 0x48, 0x0);
break;
}
}
@@ -1037,8 +1442,191 @@ static void halbtc8723b1ant_ps_tdma(struct btc_coexist *btcoexist,
coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma;
}
+void btc8723b1ant_tdma_dur_adj_for_acl(struct btc_coexist *btcoexist,
+ u8 wifi_status)
+{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ static s32 up, dn, m, n, wait_count;
+ /* 0: no change, +1: increase WiFi duration,
+ * -1: decrease WiFi duration
+ */
+ s32 result;
+ u8 retry_count = 0, bt_info_ext;
+ bool wifi_busy = false;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], TdmaDurationAdjustForAcl()\n");
+
+ if (wifi_status == BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY)
+ wifi_busy = true;
+ else
+ wifi_busy = false;
+
+ if ((wifi_status ==
+ BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN) ||
+ (wifi_status == BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN) ||
+ (wifi_status == BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT)) {
+ if (coex_dm->cur_ps_tdma != 1 && coex_dm->cur_ps_tdma != 2 &&
+ coex_dm->cur_ps_tdma != 3 && coex_dm->cur_ps_tdma != 9) {
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 9);
+ coex_dm->ps_tdma_du_adj_type = 9;
+
+ up = 0;
+ dn = 0;
+ m = 1;
+ n = 3;
+ result = 0;
+ wait_count = 0;
+ }
+ return;
+ }
+
+ if (!coex_dm->auto_tdma_adjust) {
+ coex_dm->auto_tdma_adjust = true;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], first run TdmaDurationAdjust()!!\n");
+
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2);
+ coex_dm->ps_tdma_du_adj_type = 2;
+
+ up = 0;
+ dn = 0;
+ m = 1;
+ n = 3;
+ result = 0;
+ wait_count = 0;
+ } else {
+ /* acquire the BT TRx retry count from BT_Info byte2 */
+ retry_count = coex_sta->bt_retry_cnt;
+ bt_info_ext = coex_sta->bt_info_ext;
+
+ if ((coex_sta->low_priority_tx) > 1050 ||
+ (coex_sta->low_priority_rx) > 1250)
+ retry_count++;
+
+ result = 0;
+ wait_count++;
+ /* no retry in the last 2-second duration */
+ if (retry_count == 0) {
+ up++;
+ dn--;
+
+ if (dn <= 0)
+ dn = 0;
+
+ if (up >= n) {
+ /* if retry count during continuous n*2 seconds
+ * is 0, enlarge WiFi duration
+ */
+ wait_count = 0;
+ n = 3;
+ up = 0;
+ dn = 0;
+ result = 1;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], Increase wifi duration!!\n");
+ }
+ } else if (retry_count <= 3) {
+ /* <=3 retry in the last 2-second duration */
+ up--;
+ dn++;
+
+ if (up <= 0)
+ up = 0;
+
+ if (dn == 2) {
+ /* if continuous 2 retry count(every 2 seconds)
+ * >0 and < 3, reduce WiFi duration
+ */
+ if (wait_count <= 2)
+ /* avoid loop between the two levels */
+ m++;
+ else
+ m = 1;
+
+ if (m >= 20)
+ /* maximum of m = 20 ' will recheck if
+ * need to adjust wifi duration in
+ * maximum time interval 120 seconds
+ */
+ m = 20;
+
+ n = 3 * m;
+ up = 0;
+ dn = 0;
+ wait_count = 0;
+ result = -1;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], Decrease wifi duration for retryCounter<3!!\n");
+ }
+ } else {
+ /* retry count > 3, once retry count > 3, to reduce
+ * WiFi duration
+ */
+ if (wait_count == 1)
+ /* to avoid loop between the two levels */
+ m++;
+ else
+ m = 1;
+
+ if (m >= 20)
+ /* maximum of m = 20 ' will recheck if need to
+ * adjust wifi duration in maximum time interval
+ * 120 seconds
+ */
+ m = 20;
+
+ n = 3 * m;
+ up = 0;
+ dn = 0;
+ wait_count = 0;
+ result = -1;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], Decrease wifi duration for retryCounter>3!!\n");
+ }
+
+ if (result == -1) {
+ if (coex_dm->cur_ps_tdma == 1) {
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 2);
+ coex_dm->ps_tdma_du_adj_type = 2;
+ } else if (coex_dm->cur_ps_tdma == 2) {
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 9);
+ coex_dm->ps_tdma_du_adj_type = 9;
+ } else if (coex_dm->cur_ps_tdma == 9) {
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 11);
+ coex_dm->ps_tdma_du_adj_type = 11;
+ }
+ } else if (result == 1) {
+ if (coex_dm->cur_ps_tdma == 11) {
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 9);
+ coex_dm->ps_tdma_du_adj_type = 9;
+ } else if (coex_dm->cur_ps_tdma == 9) {
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 2);
+ coex_dm->ps_tdma_du_adj_type = 2;
+ } else if (coex_dm->cur_ps_tdma == 2) {
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+ true, 1);
+ coex_dm->ps_tdma_du_adj_type = 1;
+ }
+ }
+
+ if (coex_dm->cur_ps_tdma != 1 && coex_dm->cur_ps_tdma != 2 &&
+ coex_dm->cur_ps_tdma != 9 && coex_dm->cur_ps_tdma != 11) {
+ /* recover to previous adjust type */
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true,
+ coex_dm->ps_tdma_du_adj_type);
+ }
+ }
+}
+
static void halbtc8723b1ant_ps_tdma_chk_pwr_save(struct btc_coexist *btcoexist,
- bool new_ps_state)
+ bool new_ps_state)
{
u8 lps_mode = 0x0;
@@ -1078,6 +1666,7 @@ static void halbtc8723b1ant_power_save_state(struct btc_coexist *btcoexist,
btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER,
&low_pwr_disable);
btcoexist->btc_set(btcoexist, BTC_SET_ACT_NORMAL_LPS, NULL);
+ coex_sta->force_lps_on = false;
break;
case BTC_PS_LPS_ON:
halbtc8723b1ant_ps_tdma_chk_pwr_save(btcoexist, true);
@@ -1089,27 +1678,95 @@ static void halbtc8723b1ant_power_save_state(struct btc_coexist *btcoexist,
&low_pwr_disable);
/* power save must executed before psTdma */
btcoexist->btc_set(btcoexist, BTC_SET_ACT_ENTER_LPS, NULL);
+ coex_sta->force_lps_on = true;
break;
case BTC_PS_LPS_OFF:
halbtc8723b1ant_ps_tdma_chk_pwr_save(btcoexist, false);
btcoexist->btc_set(btcoexist, BTC_SET_ACT_LEAVE_LPS, NULL);
+ coex_sta->force_lps_on = false;
break;
default:
break;
}
}
+static void halbtc8723b1ant_action_wifi_only(struct btc_coexist *btcoexist)
+{
+ halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0);
+ halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+ FORCE_EXEC, false, false);
+}
+
+/* check if BT is disabled */
+static void halbtc8723b1ant_monitor_bt_enable_disable(struct btc_coexist
+ *btcoexist)
+{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ static u32 bt_disable_cnt;
+ bool bt_active = true, bt_disabled = false;
+
+ if (coex_sta->high_priority_tx == 0 &&
+ coex_sta->high_priority_rx == 0 && coex_sta->low_priority_tx == 0 &&
+ coex_sta->low_priority_rx == 0)
+ bt_active = false;
+ if (coex_sta->high_priority_tx == 0xffff &&
+ coex_sta->high_priority_rx == 0xffff &&
+ coex_sta->low_priority_tx == 0xffff &&
+ coex_sta->low_priority_rx == 0xffff)
+ bt_active = false;
+ if (bt_active) {
+ bt_disable_cnt = 0;
+ bt_disabled = false;
+ } else {
+ bt_disable_cnt++;
+ if (bt_disable_cnt >= 2)
+ bt_disabled = true;
+ }
+ if (coex_sta->bt_disabled != bt_disabled) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], BT is from %s to %s!!\n",
+ (coex_sta->bt_disabled ? "disabled" : "enabled"),
+ (bt_disabled ? "disabled" : "enabled"));
+
+ coex_sta->bt_disabled = bt_disabled;
+ btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE,
+ &bt_disabled);
+ if (bt_disabled) {
+ halbtc8723b1ant_action_wifi_only(btcoexist);
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_LEAVE_LPS,
+ NULL);
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_NORMAL_LPS,
+ NULL);
+ }
+ }
+}
+
/*****************************************************
*
* Non-Software Coex Mechanism start
*
*****************************************************/
+
+static void halbtc8723b1ant_action_bt_whck_test(struct btc_coexist *btcoexist)
+{
+ halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, 0x0,
+ 0x0);
+
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA, NORMAL_EXEC,
+ false, false);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+}
+
static void halbtc8723b1ant_action_wifi_multiport(struct btc_coexist *btcoexist)
{
halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
0x0, 0x0);
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA, NORMAL_EXEC,
+ false, false);
halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
}
@@ -1123,35 +1780,56 @@ static void halbtc8723b1ant_action_bt_inquiry(struct btc_coexist *btcoexist)
{
struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
bool wifi_connected = false, ap_enable = false;
+ bool wifi_busy = false, bt_busy = false;
btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE,
&ap_enable);
btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
&wifi_connected);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
+ btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy);
- if (!wifi_connected) {
- halbtc8723b1ant_power_save_state(btcoexist,
- BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+ if (coex_sta->bt_abnormal_scan) {
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 33);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 7);
+ } else if (!wifi_connected && !coex_sta->wifi_is_high_pri_task) {
+ halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ 0x0, 0x0);
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
- halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
- } else if (bt_link_info->sco_exist || bt_link_info->hid_only) {
- /* SCO/HID-only busy */
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+ NORMAL_EXEC, false, false);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+ } else if (bt_link_info->sco_exist || bt_link_info->hid_exist ||
+ bt_link_info->a2dp_exist) {
+ /* SCO/HID/A2DP busy */
halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
0x0, 0x0);
- halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32);
- halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
- } else {
- if (ap_enable)
- halbtc8723b1ant_power_save_state(btcoexist,
- BTC_PS_WIFI_NATIVE,
- 0x0, 0x0);
+ if (coex_sta->c2h_bt_remote_name_req)
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true,
+ 33);
else
- halbtc8723b1ant_power_save_state(btcoexist,
- BTC_PS_LPS_ON,
- 0x50, 0x4);
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true,
+ 32);
+
+ halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+ } else if (bt_link_info->pan_exist || wifi_busy) {
+ halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ 0x0, 0x0);
+ if (coex_sta->c2h_bt_remote_name_req)
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true,
+ 33);
+ else
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true,
+ 32);
- halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 30);
- halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+ } else {
+ halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ 0x0, 0x0);
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+ NORMAL_EXEC, false, false);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 7);
}
}
@@ -1167,7 +1845,7 @@ static void btc8723b1ant_act_bt_sco_hid_only_busy(struct btc_coexist *btcoexist,
/* tdma and coex table */
if (bt_link_info->sco_exist) {
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5);
- halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 5);
} else {
/* HID */
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 6);
@@ -1181,6 +1859,10 @@ static void halbtc8723b1ant_action_wifi_connected_bt_acl_busy(
{
struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
+ if ((coex_sta->low_priority_rx >= 950) && (!coex_sta->under_ips))
+ bt_link_info->slave_role = true;
+ else
+ bt_link_info->slave_role = false;
if (bt_link_info->hid_only) { /* HID */
btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist, wifi_status);
@@ -1189,39 +1871,40 @@ static void halbtc8723b1ant_action_wifi_connected_bt_acl_busy(
} else if (bt_link_info->a2dp_only) { /* A2DP */
if (wifi_status == BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE) {
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
- false, 8);
+ true, 32);
halbtc8723b1ant_coex_table_with_type(btcoexist,
- NORMAL_EXEC, 2);
+ NORMAL_EXEC, 4);
coex_dm->auto_tdma_adjust = false;
- } else { /* for low BT RSSI */
- halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
- true, 11);
+ } else {
+ btc8723b1ant_tdma_dur_adj_for_acl(btcoexist,
+ wifi_status);
halbtc8723b1ant_coex_table_with_type(btcoexist,
NORMAL_EXEC, 1);
- coex_dm->auto_tdma_adjust = false;
+ coex_dm->auto_tdma_adjust = true;
}
- } else if (bt_link_info->hid_exist &&
- bt_link_info->a2dp_exist) { /* HID + A2DP */
+ } else if (((bt_link_info->a2dp_exist) && (bt_link_info->pan_exist)) ||
+ (bt_link_info->hid_exist && bt_link_info->a2dp_exist &&
+ bt_link_info->pan_exist)) {
+ /* A2DP + PAN(OPP,FTP), HID + A2DP + PAN(OPP,FTP) */
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+ coex_dm->auto_tdma_adjust = false;
+ } else if (bt_link_info->hid_exist && bt_link_info->a2dp_exist) {
+ /* HID + A2DP */
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14);
coex_dm->auto_tdma_adjust = false;
- halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 6);
- /* PAN(OPP,FTP), HID + PAN(OPP,FTP) */
+ halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
} else if (bt_link_info->pan_only ||
- (bt_link_info->hid_exist && bt_link_info->pan_exist)) {
+ (bt_link_info->hid_exist && bt_link_info->pan_exist)) {
+ /* PAN(OPP,FTP), HID + PAN(OPP,FTP) */
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3);
- halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 6);
- coex_dm->auto_tdma_adjust = false;
- /* A2DP + PAN(OPP,FTP), HID + A2DP + PAN(OPP,FTP) */
- } else if ((bt_link_info->a2dp_exist && bt_link_info->pan_exist) ||
- (bt_link_info->hid_exist && bt_link_info->a2dp_exist &&
- bt_link_info->pan_exist)) {
- halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13);
- halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
coex_dm->auto_tdma_adjust = false;
} else {
- halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11);
- halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+ /* BT no-profile busy (0x9) */
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 33);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
coex_dm->auto_tdma_adjust = false;
}
}
@@ -1233,7 +1916,9 @@ static void btc8723b1ant_action_wifi_not_conn(struct btc_coexist *btcoexist)
0x0, 0x0);
/* tdma and coex table */
- halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+ halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA, NORMAL_EXEC,
+ false, false);
halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
}
@@ -1246,30 +1931,31 @@ btc8723b1ant_action_wifi_not_conn_scan(struct btc_coexist *btcoexist)
0x0, 0x0);
/* tdma and coex table */
- if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) {
- if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) {
+ if (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) {
+ if (bt_link_info->a2dp_exist) {
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
- true, 22);
+ true, 32);
halbtc8723b1ant_coex_table_with_type(btcoexist,
- NORMAL_EXEC, 1);
- } else if (bt_link_info->pan_only) {
+ NORMAL_EXEC, 4);
+ } else if (bt_link_info->a2dp_exist) {
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
- true, 20);
+ true, 22);
halbtc8723b1ant_coex_table_with_type(btcoexist,
- NORMAL_EXEC, 2);
+ NORMAL_EXEC, 4);
} else {
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
true, 20);
halbtc8723b1ant_coex_table_with_type(btcoexist,
NORMAL_EXEC, 1);
}
- } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) ||
- (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY ==
- coex_dm->bt_status)){
+ } else if (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_SCO_BUSY ||
+ coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY){
btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist,
BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN);
} else {
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+ NORMAL_EXEC, false, false);
halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
}
}
@@ -1282,14 +1968,19 @@ btc8723b1ant_act_wifi_not_conn_asso_auth(struct btc_coexist *btcoexist)
halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
0x0, 0x0);
- if ((BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == coex_dm->bt_status) ||
- (bt_link_info->sco_exist) || (bt_link_info->hid_only) ||
- (bt_link_info->a2dp_only) || (bt_link_info->pan_only)) {
- halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
- halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 7);
- } else {
+ /* tdma and coex table */
+ if ((bt_link_info->sco_exist) || (bt_link_info->hid_exist) ||
+ (bt_link_info->a2dp_exist)) {
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 4);
+ } else if (bt_link_info->pan_exist) {
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20);
- halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 4);
+ } else {
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+ NORMAL_EXEC, false, false);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 2);
}
}
@@ -1301,30 +1992,32 @@ static void btc8723b1ant_action_wifi_conn_scan(struct btc_coexist *btcoexist)
0x0, 0x0);
/* tdma and coex table */
- if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) {
- if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) {
+ if (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) {
+ if (bt_link_info->a2dp_exist) {
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
- true, 22);
+ true, 32);
halbtc8723b1ant_coex_table_with_type(btcoexist,
- NORMAL_EXEC, 1);
- } else if (bt_link_info->pan_only) {
+ NORMAL_EXEC, 4);
+ } else if (bt_link_info->a2dp_exist &&
+ bt_link_info->pan_exist) {
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
- true, 20);
+ true, 22);
halbtc8723b1ant_coex_table_with_type(btcoexist,
- NORMAL_EXEC, 2);
+ NORMAL_EXEC, 4);
} else {
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
true, 20);
halbtc8723b1ant_coex_table_with_type(btcoexist,
- NORMAL_EXEC, 1);
+ NORMAL_EXEC, 4);
}
- } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) ||
- (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY ==
- coex_dm->bt_status)) {
+ } else if (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_SCO_BUSY ||
+ coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) {
btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist,
BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN);
} else {
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+ NORMAL_EXEC, false, false);
halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
}
}
@@ -1332,23 +2025,34 @@ static void btc8723b1ant_action_wifi_conn_scan(struct btc_coexist *btcoexist)
static void halbtc8723b1ant_action_wifi_connected_special_packet(
struct btc_coexist *btcoexist)
{
- bool hs_connecting = false;
struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
+ bool wifi_busy = false;
- btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_CONNECTING, &hs_connecting);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
+
+ /* no special packet process for both WiFi and BT very busy */
+ if ((wifi_busy) &&
+ ((bt_link_info->pan_exist) || (coex_sta->num_of_profile >= 2)))
+ return;
halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
0x0, 0x0);
/* tdma and coex table */
- if ((BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == coex_dm->bt_status) ||
- (bt_link_info->sco_exist) || (bt_link_info->hid_only) ||
- (bt_link_info->a2dp_only) || (bt_link_info->pan_only)) {
- halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
- halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 7);
- } else {
+ if ((bt_link_info->sco_exist) || (bt_link_info->hid_exist)) {
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 5);
+ } else if (bt_link_info->a2dp_exist) {
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+ } else if (bt_link_info->pan_exist) {
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20);
- halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+ } else {
+ halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+ NORMAL_EXEC, false, false);
+ halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
}
}
@@ -1391,12 +2095,31 @@ static void halbtc8723b1ant_action_wifi_connected(struct btc_coexist *btcoexist)
btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
/* power save state */
if (!ap_enable &&
- BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status &&
+ coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_BUSY &&
!btcoexist->bt_link_info.hid_only) {
- if (!wifi_busy && btcoexist->bt_link_info.a2dp_only)
- halbtc8723b1ant_power_save_state(btcoexist,
+ if (btcoexist->bt_link_info.a2dp_only) {
+ if (!wifi_busy) {
+ halbtc8723b1ant_power_save_state(btcoexist,
BTC_PS_WIFI_NATIVE,
0x0, 0x0);
+ } else { /* busy */
+ if (coex_sta->scan_ap_num >=
+ BT_8723B_1ANT_WIFI_NOISY_THRESH)
+ /* no force LPS, no PS-TDMA,
+ * use pure TDMA
+ */
+ halbtc8723b1ant_power_save_state(
+ btcoexist, BTC_PS_WIFI_NATIVE,
+ 0x0, 0x0);
+ else
+ halbtc8723b1ant_power_save_state(
+ btcoexist, BTC_PS_LPS_ON, 0x50,
+ 0x4);
+ }
+ } else if ((!coex_sta->pan_exist) && (!coex_sta->a2dp_exist) &&
+ (!coex_sta->hid_exist))
+ halbtc8723b1ant_power_save_state(
+ btcoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
else
halbtc8723b1ant_power_save_state(btcoexist,
BTC_PS_LPS_ON,
@@ -1407,36 +2130,44 @@ static void halbtc8723b1ant_action_wifi_connected(struct btc_coexist *btcoexist)
}
/* tdma and coex table */
if (!wifi_busy) {
- if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) {
- halbtc8723b1ant_action_wifi_connected_bt_acl_busy(btcoexist,
- BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE);
- } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY ==
- coex_dm->bt_status) ||
- (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY ==
- coex_dm->bt_status)) {
+ if (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) {
+ halbtc8723b1ant_action_wifi_connected_bt_acl_busy(
+ btcoexist,
+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE);
+ } else if (coex_dm->bt_status ==
+ BT_8723B_1ANT_BT_STATUS_SCO_BUSY ||
+ coex_dm->bt_status ==
+ BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) {
btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist,
BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE);
} else {
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
false, 8);
+ halbtc8723b1ant_set_ant_path(btcoexist,
+ BTC_ANT_PATH_PTA,
+ NORMAL_EXEC, false, false);
halbtc8723b1ant_coex_table_with_type(btcoexist,
NORMAL_EXEC, 2);
}
} else {
- if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) {
- halbtc8723b1ant_action_wifi_connected_bt_acl_busy(btcoexist,
- BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY);
- } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY ==
- coex_dm->bt_status) ||
- (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY ==
- coex_dm->bt_status)) {
+ if (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) {
+ halbtc8723b1ant_action_wifi_connected_bt_acl_busy(
+ btcoexist,
+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY);
+ } else if (coex_dm->bt_status ==
+ BT_8723B_1ANT_BT_STATUS_SCO_BUSY ||
+ coex_dm->bt_status ==
+ BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) {
btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist,
BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY);
} else {
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
- false, 8);
+ true, 32);
+ halbtc8723b1ant_set_ant_path(btcoexist,
+ BTC_ANT_PATH_PTA,
+ NORMAL_EXEC, false, false);
halbtc8723b1ant_coex_table_with_type(btcoexist,
- NORMAL_EXEC, 2);
+ NORMAL_EXEC, 4);
}
}
}
@@ -1445,12 +2176,15 @@ static void halbtc8723b1ant_run_coexist_mechanism(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
- bool wifi_connected = false, bt_hs_on = false;
+ bool wifi_connected = false, bt_hs_on = false, wifi_busy = false;
bool increase_scan_dev_num = false;
bool bt_ctrl_agg_buf_size = false;
+ bool miracast_plus_bt = false;
u8 agg_buf_size = 5;
+ u8 iot_peer = BTC_IOT_PEER_UNKNOWN;
u32 wifi_link_status = 0;
u32 num_of_wifi_link = 0;
+ u32 wifi_bw;
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], RunCoexistMechanism()===>\n");
@@ -1473,54 +2207,99 @@ static void halbtc8723b1ant_run_coexist_mechanism(struct btc_coexist *btcoexist)
return;
}
- if ((BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) ||
- (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) ||
- (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) {
- increase_scan_dev_num = true;
+ if (coex_sta->bt_whck_test) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], wifi is under IPS !!!\n");
+ halbtc8723b1ant_action_bt_whck_test(btcoexist);
+ return;
}
+ if (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_BUSY ||
+ coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_SCO_BUSY ||
+ coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY)
+ increase_scan_dev_num = true;
+
btcoexist->btc_set(btcoexist, BTC_SET_BL_INC_SCAN_DEV_NUM,
&increase_scan_dev_num);
-
btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
&wifi_connected);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS,
&wifi_link_status);
num_of_wifi_link = wifi_link_status >> 16;
- if (num_of_wifi_link >= 2) {
- halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0);
+
+ if (num_of_wifi_link >= 2 ||
+ wifi_link_status & WIFI_P2P_GO_CONNECTED) {
+ if (bt_link_info->bt_link_exist) {
+ halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 1, 1,
+ 0, 1);
+ miracast_plus_bt = true;
+ } else {
+ halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0,
+ 0, 0);
+ miracast_plus_bt = false;
+ }
+ btcoexist->btc_set(btcoexist, BTC_SET_BL_MIRACAST_PLUS_BT,
+ &miracast_plus_bt);
halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false,
- bt_ctrl_agg_buf_size,
- agg_buf_size);
- halbtc8723b1ant_action_wifi_multiport(btcoexist);
+ bt_ctrl_agg_buf_size, agg_buf_size);
+
+ if ((bt_link_info->a2dp_exist || wifi_busy) &&
+ (coex_sta->c2h_bt_inquiry_page))
+ halbtc8723b1ant_action_bt_inquiry(btcoexist);
+ else
+ halbtc8723b1ant_action_wifi_multiport(btcoexist);
+
return;
}
- if (!bt_link_info->sco_exist && !bt_link_info->hid_exist) {
- halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0);
+ miracast_plus_bt = false;
+ btcoexist->btc_set(btcoexist, BTC_SET_BL_MIRACAST_PLUS_BT,
+ &miracast_plus_bt);
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+
+ if (bt_link_info->bt_link_exist && wifi_connected) {
+ halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 1, 1, 0, 1);
+
+ btcoexist->btc_get(btcoexist, BTC_GET_U1_IOT_PEER, &iot_peer);
+
+ if (iot_peer != BTC_IOT_PEER_CISCO &&
+ iot_peer != BTC_IOT_PEER_BROADCOM) {
+ if (bt_link_info->sco_exist)
+ halbtc8723b1ant_limited_rx(btcoexist,
+ NORMAL_EXEC, false,
+ false, 0x5);
+ else
+ halbtc8723b1ant_limited_rx(btcoexist,
+ NORMAL_EXEC, false,
+ false, 0x5);
+ } else {
+ if (bt_link_info->sco_exist) {
+ halbtc8723b1ant_limited_rx(btcoexist,
+ NORMAL_EXEC, true,
+ false, 0x5);
+ } else {
+ if (wifi_bw == BTC_WIFI_BW_HT40)
+ halbtc8723b1ant_limited_rx(
+ btcoexist, NORMAL_EXEC, false,
+ true, 0x10);
+ else
+ halbtc8723b1ant_limited_rx(
+ btcoexist, NORMAL_EXEC, false,
+ true, 0x8);
+ }
+ }
+
+ halbtc8723b1ant_sw_mechanism(btcoexist, true);
} else {
- if (wifi_connected)
- halbtc8723b1ant_limited_tx(btcoexist,
- NORMAL_EXEC, 1, 1, 1, 1);
- else
- halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC,
- 0, 0, 0, 0);
- }
+ halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0);
- if (bt_link_info->sco_exist) {
- bt_ctrl_agg_buf_size = true;
- agg_buf_size = 0x3;
- } else if (bt_link_info->hid_exist) {
- bt_ctrl_agg_buf_size = true;
- agg_buf_size = 0x5;
- } else if (bt_link_info->a2dp_exist || bt_link_info->pan_exist) {
- bt_ctrl_agg_buf_size = true;
- agg_buf_size = 0x8;
- }
- halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false,
- bt_ctrl_agg_buf_size, agg_buf_size);
+ halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false, false,
+ 0x5);
+ halbtc8723b1ant_sw_mechanism(btcoexist, false);
+ }
btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on);
if (coex_sta->c2h_bt_inquiry_page) {
@@ -1556,91 +2335,141 @@ static void halbtc8723b1ant_run_coexist_mechanism(struct btc_coexist *btcoexist)
}
}
+/* force coex mechanism to reset */
static void halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist)
{
/* sw all off */
halbtc8723b1ant_sw_mechanism(btcoexist, false);
- halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
- halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0);
+ coex_sta->pop_event_cnt = 0;
}
static void halbtc8723b1ant_init_hw_config(struct btc_coexist *btcoexist,
- bool backup)
+ bool backup, bool wifi_only)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
u32 u32tmp = 0;
- u8 u8tmp = 0;
- u32 cnt_bt_cal_chk = 0;
+ u8 u8tmpa = 0, u8tmpb = 0;
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], 1Ant Init HW Config!!\n");
- if (backup) {/* backup rf 0x1e value */
- coex_dm->backup_arfr_cnt1 =
- btcoexist->btc_read_4byte(btcoexist, 0x430);
- coex_dm->backup_arfr_cnt2 =
- btcoexist->btc_read_4byte(btcoexist, 0x434);
- coex_dm->backup_retry_limit =
- btcoexist->btc_read_2byte(btcoexist, 0x42a);
- coex_dm->backup_ampdu_max_time =
- btcoexist->btc_read_1byte(btcoexist, 0x456);
- }
-
- /* WiFi goto standby while GNT_BT 0-->1 */
- btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x780);
- /* BT goto standby while GNT_BT 1-->0 */
- btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x2, 0xfffff, 0x500);
-
- btcoexist->btc_write_1byte(btcoexist, 0x974, 0xff);
- btcoexist->btc_write_1byte_bitmask(btcoexist, 0x944, 0x3, 0x3);
- btcoexist->btc_write_1byte(btcoexist, 0x930, 0x77);
-
- /* BT calibration check */
- while (cnt_bt_cal_chk <= 20) {
- u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x49d);
- cnt_bt_cal_chk++;
- if (u32tmp & BIT0) {
- RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], ########### BT calibration(cnt=%d) ###########\n",
- cnt_bt_cal_chk);
- mdelay(50);
- } else {
- RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], ********** BT NOT calibration (cnt=%d)**********\n",
- cnt_bt_cal_chk);
- break;
- }
- }
+ /* 0xf0[15:12] --> Chip Cut information */
+ coex_sta->cut_version =
+ (btcoexist->btc_read_1byte(btcoexist, 0xf1) & 0xf0) >> 4;
+ /* enable TBTT interrupt */
+ btcoexist->btc_write_1byte_bitmask(btcoexist, 0x550, 0x8, 0x1);
/* 0x790[5:0] = 0x5 */
- u8tmp = btcoexist->btc_read_1byte(btcoexist, 0x790);
- u8tmp &= 0xc0;
- u8tmp |= 0x5;
- btcoexist->btc_write_1byte(btcoexist, 0x790, u8tmp);
+ btcoexist->btc_write_1byte(btcoexist, 0x790, 0x5);
/* Enable counter statistics */
- /*0x76e[3] = 1, WLAN_Act control by PTA */
- btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc);
btcoexist->btc_write_1byte(btcoexist, 0x778, 0x1);
btcoexist->btc_write_1byte_bitmask(btcoexist, 0x40, 0x20, 0x1);
+ halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
+
/* Antenna config */
- halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA, true, false);
+ if (wifi_only)
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_WIFI,
+ FORCE_EXEC, true, false);
+ else
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT,
+ FORCE_EXEC, true, false);
+
/* PTA parameter */
halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0);
+
+ u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x948);
+ u8tmpa = btcoexist->btc_read_1byte(btcoexist, 0x765);
+ u8tmpb = btcoexist->btc_read_1byte(btcoexist, 0x67);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "############# [BTCoex], 0x948=0x%x, 0x765=0x%x, 0x67=0x%x\n",
+ u32tmp, u8tmpa, u8tmpb);
}
/**************************************************************
- * extern function start with ex_halbtc8723b1ant_
+ * extern function start with ex_btc8723b1ant_
**************************************************************/
+void ex_btc8723b1ant_power_on_setting(struct btc_coexist *btcoexist)
+{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct btc_board_info *board_info = &btcoexist->board_info;
+ u8 u8tmp = 0x0;
+ u16 u16tmp = 0x0;
+ u32 value;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "xxxxxxxxxxxxxxxx Execute 8723b 1-Ant PowerOn Setting xxxxxxxxxxxxxxxx!!\n");
+
+ btcoexist->stop_coex_dm = true;
+
+ btcoexist->btc_write_1byte(btcoexist, 0x67, 0x20);
+
+ /* enable BB, REG_SYS_FUNC_EN such that we can write 0x948 correctly. */
+ u16tmp = btcoexist->btc_read_2byte(btcoexist, 0x2);
+ btcoexist->btc_write_2byte(btcoexist, 0x2, u16tmp | BIT0 | BIT1);
+
+ /* set GRAN_BT = 1 */
+ btcoexist->btc_write_1byte(btcoexist, 0x765, 0x18);
+ /* set WLAN_ACT = 0 */
+ btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4);
+
+ /* S0 or S1 setting and Local register setting(By the setting fw can get
+ * ant number, S0/S1, ... info)
+ *
+ * Local setting bit define
+ * BIT0: "0" for no antenna inverse; "1" for antenna inverse
+ * BIT1: "0" for internal switch; "1" for external switch
+ * BIT2: "0" for one antenna; "1" for two antenna
+ * NOTE: here default all internal switch and 1-antenna ==> BIT1=0 and
+ * BIT2 = 0
+ */
+ if (btcoexist->chip_interface == BTC_INTF_USB) {
+ /* fixed at S0 for USB interface */
+ btcoexist->btc_write_4byte(btcoexist, 0x948, 0x0);
-void ex_halbtc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist)
+ u8tmp |= 0x1; /* antenna inverse */
+ btcoexist->btc_write_local_reg_1byte(btcoexist, 0xfe08, u8tmp);
+
+ board_info->btdm_ant_pos = BTC_ANTENNA_AT_AUX_PORT;
+ } else {
+ /* for PCIE and SDIO interface, we check efuse 0xc3[6] */
+ if (board_info->single_ant_path == 0) {
+ /* set to S1 */
+ btcoexist->btc_write_4byte(btcoexist, 0x948, 0x280);
+ board_info->btdm_ant_pos = BTC_ANTENNA_AT_MAIN_PORT;
+ value = 1;
+ } else if (board_info->single_ant_path == 1) {
+ /* set to S0 */
+ btcoexist->btc_write_4byte(btcoexist, 0x948, 0x0);
+ u8tmp |= 0x1; /* antenna inverse */
+ board_info->btdm_ant_pos = BTC_ANTENNA_AT_AUX_PORT;
+ value = 0;
+ }
+
+ btcoexist->btc_set(btcoexist, BTC_SET_ACT_ANTPOSREGRISTRY_CTRL,
+ &value);
+
+ if (btcoexist->chip_interface == BTC_INTF_PCI)
+ btcoexist->btc_write_local_reg_1byte(btcoexist, 0x384,
+ u8tmp);
+ else if (btcoexist->chip_interface == BTC_INTF_SDIO)
+ btcoexist->btc_write_local_reg_1byte(btcoexist, 0x60,
+ u8tmp);
+ }
+}
+
+
+void ex_btc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist,
+ bool wifi_only)
{
- halbtc8723b1ant_init_hw_config(btcoexist, true);
+ halbtc8723b1ant_init_hw_config(btcoexist, true, wifi_only);
+ btcoexist->stop_coex_dm = false;
}
-void ex_halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist)
+void ex_btc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -1654,7 +2483,7 @@ void ex_halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist)
halbtc8723b1ant_query_bt_info(btcoexist);
}
-void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
+void ex_btc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
{
struct btc_board_info *board_info = &btcoexist->board_info;
struct btc_stack_info *stack_info = &btcoexist->stack_info;
@@ -1687,11 +2516,6 @@ void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
"\r\n ==========================================");
}
- if (!board_info->bt_exist) {
- RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n BT not exists !!!");
- return;
- }
-
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d",
"Ant PG Num/ Ant Mech/ Ant Pos:",
board_info->pg_ant_num, board_info->btdm_ant_num,
@@ -1760,7 +2584,7 @@ void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = [%s/ %d/ %d] ",
"BT [status/ rssi/ retryCnt]",
- ((btcoexist->bt_info.bt_disabled) ? ("disabled") :
+ ((coex_sta->bt_disabled) ? ("disabled") :
((coex_sta->c2h_bt_inquiry_page) ? ("inquiry/page scan") :
((BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE ==
coex_dm->bt_status) ?
@@ -1835,6 +2659,9 @@ void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
coex_dm->error_condition);
}
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d",
+ "Coex Table Type", coex_sta->coex_table_type);
+
/* Hw setting */
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s",
"============[Hw setting]============");
@@ -1926,13 +2753,12 @@ void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d",
"0x774(low-pri rx/tx)", coex_sta->low_priority_rx,
coex_sta->low_priority_tx);
-#if (BT_AUTO_REPORT_ONLY_8723B_1ANT == 1)
- halbtc8723b1ant_monitor_bt_ctr(btcoexist);
-#endif
+ if (btcoexist->auto_report_1ant)
+ halbtc8723b1ant_monitor_bt_ctr(btcoexist);
btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_COEX_STATISTICS);
}
-void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
+void ex_btc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -1945,7 +2771,7 @@ void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
coex_sta->under_ips = true;
halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT,
- false, true);
+ FORCE_EXEC, false, true);
/* set PTA control */
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 0);
halbtc8723b1ant_coex_table_with_type(btcoexist,
@@ -1955,13 +2781,13 @@ void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
"[BTCoex], IPS LEAVE notify\n");
coex_sta->under_ips = false;
- halbtc8723b1ant_init_hw_config(btcoexist, false);
+ halbtc8723b1ant_init_hw_config(btcoexist, false, false);
halbtc8723b1ant_init_coex_dm(btcoexist);
halbtc8723b1ant_query_bt_info(btcoexist);
}
}
-void ex_halbtc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type)
+void ex_btc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -1979,17 +2805,45 @@ void ex_halbtc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type)
}
}
-void ex_halbtc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type)
+void ex_btc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
bool wifi_connected = false, bt_hs_on = false;
+ u8 u8tmpa, u8tmpb;
+ u32 u32tmp;
u32 wifi_link_status = 0;
u32 num_of_wifi_link = 0;
bool bt_ctrl_agg_buf_size = false;
u8 agg_buf_size = 5;
- if (btcoexist->manual_control || btcoexist->stop_coex_dm ||
- btcoexist->bt_info.bt_disabled)
+ if (btcoexist->manual_control || btcoexist->stop_coex_dm)
+ return;
+
+ if (type == BTC_SCAN_START) {
+ coex_sta->wifi_is_high_pri_task = true;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], SCAN START notify\n");
+ /* Force antenna setup for no scan result issue */
+ halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+ FORCE_EXEC, false, false);
+ u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x948);
+ u8tmpa = btcoexist->btc_read_1byte(btcoexist, 0x765);
+ u8tmpb = btcoexist->btc_read_1byte(btcoexist, 0x67);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], 0x948=0x%x, 0x765=0x%x, 0x67=0x%x\n",
+ u32tmp, u8tmpa, u8tmpb);
+ } else {
+ coex_sta->wifi_is_high_pri_task = false;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], SCAN FINISH notify\n");
+
+ btcoexist->btc_get(btcoexist, BTC_GET_U1_AP_NUM,
+ &coex_sta->scan_ap_num);
+ }
+
+ if (coex_sta->bt_disabled)
return;
btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on);
@@ -2037,19 +2891,38 @@ void ex_halbtc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type)
}
}
-void ex_halbtc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type)
+void ex_btc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
bool wifi_connected = false, bt_hs_on = false;
u32 wifi_link_status = 0;
u32 num_of_wifi_link = 0;
- bool bt_ctrl_agg_buf_size = false;
+ bool bt_ctrl_agg_buf_size = false, under_4way = false;
u8 agg_buf_size = 5;
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS,
+ &under_4way);
+
if (btcoexist->manual_control || btcoexist->stop_coex_dm ||
- btcoexist->bt_info.bt_disabled)
+ coex_sta->bt_disabled)
return;
+ if (type == BTC_ASSOCIATE_START) {
+ coex_sta->wifi_is_high_pri_task = true;
+
+ /* Force antenna setup for no scan result issue */
+ halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+ FORCE_EXEC, false, false);
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], CONNECT START notify\n");
+ coex_dm->arp_cnt = 0;
+ } else {
+ coex_sta->wifi_is_high_pri_task = false;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], CONNECT FINISH notify\n");
+ }
+
btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS,
&wifi_link_status);
num_of_wifi_link = wifi_link_status>>16;
@@ -2088,33 +2961,68 @@ void ex_halbtc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type)
}
}
-void ex_halbtc8723b1ant_media_status_notify(struct btc_coexist *btcoexist,
- u8 type)
+void ex_btc8723b1ant_media_status_notify(struct btc_coexist *btcoexist,
+ u8 type)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
u8 h2c_parameter[3] = {0};
u32 wifi_bw;
- u8 wifiCentralChnl;
+ u8 wifi_central_chnl;
+ bool wifi_under_b_mode = false;
if (btcoexist->manual_control || btcoexist->stop_coex_dm ||
- btcoexist->bt_info.bt_disabled)
+ coex_sta->bt_disabled)
return;
- if (BTC_MEDIA_CONNECT == type)
+ if (type == BTC_MEDIA_CONNECT) {
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], MEDIA connect notify\n");
- else
+ /* Force antenna setup for no scan result issue */
+ halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+ FORCE_EXEC, false, false);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_B_MODE,
+ &wifi_under_b_mode);
+
+ /* Set CCK Tx/Rx high Pri except 11b mode */
+ if (wifi_under_b_mode) {
+ btcoexist->btc_write_1byte(btcoexist, 0x6cd,
+ 0x00); /* CCK Tx */
+ btcoexist->btc_write_1byte(btcoexist, 0x6cf,
+ 0x00); /* CCK Rx */
+ } else {
+ btcoexist->btc_write_1byte(btcoexist, 0x6cd,
+ 0x00); /* CCK Tx */
+ btcoexist->btc_write_1byte(btcoexist, 0x6cf,
+ 0x10); /* CCK Rx */
+ }
+
+ coex_dm->backup_arfr_cnt1 =
+ btcoexist->btc_read_4byte(btcoexist, 0x430);
+ coex_dm->backup_arfr_cnt2 =
+ btcoexist->btc_read_4byte(btcoexist, 0x434);
+ coex_dm->backup_retry_limit =
+ btcoexist->btc_read_2byte(btcoexist, 0x42a);
+ coex_dm->backup_ampdu_max_time =
+ btcoexist->btc_read_1byte(btcoexist, 0x456);
+ } else {
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], MEDIA disconnect notify\n");
+ coex_dm->arp_cnt = 0;
+
+ btcoexist->btc_write_1byte(btcoexist, 0x6cd, 0x0); /* CCK Tx */
+ btcoexist->btc_write_1byte(btcoexist, 0x6cf, 0x0); /* CCK Rx */
+
+ coex_sta->cck_ever_lock = false;
+ }
/* only 2.4G we need to inform bt the chnl mask */
btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL,
- &wifiCentralChnl);
+ &wifi_central_chnl);
- if ((BTC_MEDIA_CONNECT == type) &&
- (wifiCentralChnl <= 14)) {
+ if (type == BTC_MEDIA_CONNECT && wifi_central_chnl <= 14) {
h2c_parameter[0] = 0x0;
- h2c_parameter[1] = wifiCentralChnl;
+ h2c_parameter[1] = wifi_central_chnl;
btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
if (BTC_WIFI_BW_HT40 == wifi_bw)
h2c_parameter[2] = 0x30;
@@ -2134,20 +3042,53 @@ void ex_halbtc8723b1ant_media_status_notify(struct btc_coexist *btcoexist,
btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter);
}
-void ex_halbtc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist,
- u8 type)
+void ex_btc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist,
+ u8 type)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
bool bt_hs_on = false;
u32 wifi_link_status = 0;
u32 num_of_wifi_link = 0;
- bool bt_ctrl_agg_buf_size = false;
+ bool bt_ctrl_agg_buf_size = false, under_4way = false;
u8 agg_buf_size = 5;
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS,
+ &under_4way);
+
if (btcoexist->manual_control || btcoexist->stop_coex_dm ||
- btcoexist->bt_info.bt_disabled)
+ coex_sta->bt_disabled)
return;
+ if (type == BTC_PACKET_DHCP || type == BTC_PACKET_EAPOL ||
+ type == BTC_PACKET_ARP) {
+ if (type == BTC_PACKET_ARP) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], special Packet ARP notify\n");
+
+ coex_dm->arp_cnt++;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], ARP Packet Count = %d\n",
+ coex_dm->arp_cnt);
+
+ if ((coex_dm->arp_cnt >= 10) && (!under_4way))
+ /* if APR PKT > 10 after connect, do not go to
+ * ActionWifiConnectedSpecificPacket(btcoexist)
+ */
+ coex_sta->wifi_is_high_pri_task = false;
+ else
+ coex_sta->wifi_is_high_pri_task = true;
+ } else {
+ coex_sta->wifi_is_high_pri_task = true;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], special Packet DHCP or EAPOL notify\n");
+ }
+ } else {
+ coex_sta->wifi_is_high_pri_task = false;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], special Packet [Type = %d] notify\n",
+ type);
+ }
+
btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS,
&wifi_link_status);
num_of_wifi_link = wifi_link_status >> 16;
@@ -2178,8 +3119,8 @@ void ex_halbtc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist,
}
}
-void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
- u8 *tmp_buf, u8 length)
+void ex_btc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
+ u8 *tmp_buf, u8 length)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
u8 bt_info = 0;
@@ -2209,16 +3150,58 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
"0x%02x, ", tmp_buf[i]);
}
- if (BT_INFO_SRC_8723B_1ANT_WIFI_FW != rsp_source) {
- coex_sta->bt_retry_cnt = /* [3:0] */
+ /* if 0xff, it means BT is under WHCK test */
+ if (bt_info == 0xff)
+ coex_sta->bt_whck_test = true;
+ else
+ coex_sta->bt_whck_test = false;
+
+ if (rsp_source != BT_INFO_SRC_8723B_1ANT_WIFI_FW) {
+ coex_sta->bt_retry_cnt = /* [3:0] */
coex_sta->bt_info_c2h[rsp_source][2] & 0xf;
+ if (coex_sta->bt_retry_cnt >= 1)
+ coex_sta->pop_event_cnt++;
+
+ if (coex_sta->bt_info_c2h[rsp_source][2] & 0x20)
+ coex_sta->c2h_bt_remote_name_req = true;
+ else
+ coex_sta->c2h_bt_remote_name_req = false;
+
coex_sta->bt_rssi =
- coex_sta->bt_info_c2h[rsp_source][3] * 2 + 10;
+ coex_sta->bt_info_c2h[rsp_source][3] * 2 - 90;
coex_sta->bt_info_ext =
coex_sta->bt_info_c2h[rsp_source][4];
+ if (coex_sta->bt_info_c2h[rsp_source][1] == 0x49) {
+ coex_sta->a2dp_bit_pool =
+ coex_sta->bt_info_c2h[rsp_source][6];
+ } else {
+ coex_sta->a2dp_bit_pool = 0;
+ }
+
+ coex_sta->bt_tx_rx_mask =
+ (coex_sta->bt_info_c2h[rsp_source][2] & 0x40);
+ btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TX_RX_MASK,
+ &coex_sta->bt_tx_rx_mask);
+
+ if (!coex_sta->bt_tx_rx_mask) {
+ /* BT into is responded by BT FW and BT RF REG
+ * 0x3C != 0x15 => Need to switch BT TRx Mask
+ */
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], Switch BT TRx Mask since BT RF REG 0x3C != 0x15\n");
+ btcoexist->btc_set_bt_reg(btcoexist, BTC_BT_REG_RF,
+ 0x3c, 0x15);
+
+ /* BT TRx Mask lock 0x2c[0], 0x30[0] = 0 */
+ btcoexist->btc_set_bt_reg(btcoexist, BTC_BT_REG_RF,
+ 0x2c, 0x7c44);
+ btcoexist->btc_set_bt_reg(btcoexist, BTC_BT_REG_RF,
+ 0x30, 0x7c44);
+ }
+
/* Here we need to resend some wifi info to BT
* because bt is reset and loss of the info.
*/
@@ -2228,11 +3211,11 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
&wifi_connected);
if (wifi_connected)
- ex_halbtc8723b1ant_media_status_notify(btcoexist,
- BTC_MEDIA_CONNECT);
+ ex_btc8723b1ant_media_status_notify(btcoexist,
+ BTC_MEDIA_CONNECT);
else
- ex_halbtc8723b1ant_media_status_notify(btcoexist,
- BTC_MEDIA_DISCONNECT);
+ ex_btc8723b1ant_media_status_notify(btcoexist,
+ BTC_MEDIA_DISCONNECT);
}
if (coex_sta->bt_info_ext & BIT3) {
@@ -2247,14 +3230,15 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
} else {
/* BT already NOT ignore Wlan active, do nothing here.*/
}
-#if (BT_AUTO_REPORT_ONLY_8723B_1ANT == 0)
- if (coex_sta->bt_info_ext & BIT4) {
- /* BT auto report already enabled, do nothing */
- } else {
- halbtc8723b1ant_bt_auto_report(btcoexist, FORCE_EXEC,
- true);
+ if (!btcoexist->auto_report_1ant) {
+ if (coex_sta->bt_info_ext & BIT4) {
+ /* BT auto report already enabled, do nothing */
+ } else {
+ halbtc8723b1ant_bt_auto_report(btcoexist,
+ FORCE_EXEC,
+ true);
+ }
}
-#endif
}
/* check BIT2 first ==> check if bt is under inquiry or page scan */
@@ -2263,6 +3247,8 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
else
coex_sta->c2h_bt_inquiry_page = false;
+ coex_sta->num_of_profile = 0;
+
/* set link exist status */
if (!(bt_info & BT_INFO_8723B_1ANT_B_CONNECTION)) {
coex_sta->bt_link_exist = false;
@@ -2270,30 +3256,77 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
coex_sta->a2dp_exist = false;
coex_sta->hid_exist = false;
coex_sta->sco_exist = false;
+
+ coex_sta->bt_hi_pri_link_exist = false;
} else {
/* connection exists */
coex_sta->bt_link_exist = true;
- if (bt_info & BT_INFO_8723B_1ANT_B_FTP)
+ if (bt_info & BT_INFO_8723B_1ANT_B_FTP) {
coex_sta->pan_exist = true;
- else
+ coex_sta->num_of_profile++;
+ } else {
coex_sta->pan_exist = false;
- if (bt_info & BT_INFO_8723B_1ANT_B_A2DP)
+ }
+ if (bt_info & BT_INFO_8723B_1ANT_B_A2DP) {
coex_sta->a2dp_exist = true;
- else
+ coex_sta->num_of_profile++;
+ } else {
coex_sta->a2dp_exist = false;
- if (bt_info & BT_INFO_8723B_1ANT_B_HID)
+ }
+ if (bt_info & BT_INFO_8723B_1ANT_B_HID) {
coex_sta->hid_exist = true;
- else
+ coex_sta->num_of_profile++;
+ } else {
coex_sta->hid_exist = false;
- if (bt_info & BT_INFO_8723B_1ANT_B_SCO_ESCO)
+ }
+ if (bt_info & BT_INFO_8723B_1ANT_B_SCO_ESCO) {
coex_sta->sco_exist = true;
- else
+ coex_sta->num_of_profile++;
+ } else {
coex_sta->sco_exist = false;
+ }
+
+ if ((!coex_sta->hid_exist) &&
+ (!coex_sta->c2h_bt_inquiry_page) &&
+ (!coex_sta->sco_exist)) {
+ if (coex_sta->high_priority_tx +
+ coex_sta->high_priority_rx >=
+ 160) {
+ coex_sta->hid_exist = true;
+ coex_sta->wrong_profile_notification++;
+ coex_sta->num_of_profile++;
+ bt_info = bt_info | 0x28;
+ }
+ }
+
+ /* Add Hi-Pri Tx/Rx counter to avoid false detection */
+ if (((coex_sta->hid_exist) || (coex_sta->sco_exist)) &&
+ (coex_sta->high_priority_tx + coex_sta->high_priority_rx >=
+ 160) &&
+ (!coex_sta->c2h_bt_inquiry_page))
+ coex_sta->bt_hi_pri_link_exist = true;
+
+ if ((bt_info & BT_INFO_8723B_1ANT_B_ACL_BUSY) &&
+ (coex_sta->num_of_profile == 0)) {
+ if (coex_sta->low_priority_tx +
+ coex_sta->low_priority_rx >=
+ 160) {
+ coex_sta->pan_exist = true;
+ coex_sta->num_of_profile++;
+ coex_sta->wrong_profile_notification++;
+ bt_info = bt_info | 0x88;
+ }
+ }
}
halbtc8723b1ant_update_bt_link_info(btcoexist);
- if (!(bt_info&BT_INFO_8723B_1ANT_B_CONNECTION)) {
+ /* mask profile bit for connect-ilde identification
+ * ( for CSR case: A2DP idle --> 0x41)
+ */
+ bt_info = bt_info & 0x1f;
+
+ if (!(bt_info & BT_INFO_8723B_1ANT_B_CONNECTION)) {
coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE;
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], BtInfoNotify(), BT Non-Connected idle!\n");
@@ -2315,8 +3348,7 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], BtInfoNotify(), BT ACL busy!!!\n");
} else {
- coex_dm->bt_status =
- BT_8723B_1ANT_BT_STATUS_MAX;
+ coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_MAX;
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], BtInfoNotify(), BT Non-Defined state!!\n");
}
@@ -2332,7 +3364,44 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
halbtc8723b1ant_run_coexist_mechanism(btcoexist);
}
-void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist)
+void ex_btc8723b1ant_rf_status_notify(struct btc_coexist *btcoexist, u8 type)
+{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ u32 u32tmp;
+ u8 u8tmpa, u8tmpb, u8tmpc;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], RF Status notify\n");
+
+ if (type == BTC_RF_ON) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], RF is turned ON!!\n");
+ btcoexist->stop_coex_dm = false;
+ } else if (type == BTC_RF_OFF) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], RF is turned OFF!!\n");
+
+ halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ 0x0, 0x0);
+ halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 0);
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT,
+ FORCE_EXEC, false, true);
+
+ halbtc8723b1ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true);
+ btcoexist->stop_coex_dm = true;
+
+ u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x948);
+ u8tmpa = btcoexist->btc_read_1byte(btcoexist, 0x765);
+ u8tmpb = btcoexist->btc_read_1byte(btcoexist, 0x67);
+ u8tmpc = btcoexist->btc_read_1byte(btcoexist, 0x76e);
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "############# [BTCoex], 0x948=0x%x, 0x765=0x%x, 0x67=0x%x, 0x76e=0x%x\n",
+ u32tmp, u8tmpa, u8tmpb, u8tmpc);
+ }
+}
+
+void ex_btc8723b1ant_halt_notify(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -2340,7 +3409,8 @@ void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist)
btcoexist->stop_coex_dm = true;
- halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT, false, true);
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT, FORCE_EXEC,
+ false, true);
halbtc8723b1ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true);
@@ -2348,10 +3418,12 @@ void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist)
0x0, 0x0);
halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 0);
- ex_halbtc8723b1ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT);
+ ex_btc8723b1ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT);
+
+ btcoexist->stop_coex_dm = true;
}
-void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
+void ex_btc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -2360,81 +3432,66 @@ void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
if (BTC_WIFI_PNP_SLEEP == pnp_state) {
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], Pnp notify to SLEEP\n");
- btcoexist->stop_coex_dm = true;
- halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT, false,
- true);
+ halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT,
+ FORCE_EXEC, false, true);
halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
0x0, 0x0);
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 0);
halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
+
+ /* Driver do not leave IPS/LPS when driver is going to sleep, so
+ * BTCoexistence think wifi is still under IPS/LPS
+ *
+ * BT should clear UnderIPS/UnderLPS state to avoid mismatch
+ * state after wakeup.
+ */
+ coex_sta->under_ips = false;
+ coex_sta->under_lps = false;
+ btcoexist->stop_coex_dm = true;
} else if (BTC_WIFI_PNP_WAKE_UP == pnp_state) {
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], Pnp notify to WAKE UP\n");
btcoexist->stop_coex_dm = false;
- halbtc8723b1ant_init_hw_config(btcoexist, false);
+ halbtc8723b1ant_init_hw_config(btcoexist, false, false);
halbtc8723b1ant_init_coex_dm(btcoexist);
halbtc8723b1ant_query_bt_info(btcoexist);
}
}
-void ex_halbtc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist)
+void ex_btc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], *****************Coex DM Reset****************\n");
- halbtc8723b1ant_init_hw_config(btcoexist, false);
- btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
- btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x2, 0xfffff, 0x0);
+ halbtc8723b1ant_init_hw_config(btcoexist, false, false);
halbtc8723b1ant_init_coex_dm(btcoexist);
}
-void ex_halbtc8723b1ant_periodical(struct btc_coexist *btcoexist)
+void ex_btc8723b1ant_periodical(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct btc_board_info *board_info = &btcoexist->board_info;
- struct btc_stack_info *stack_info = &btcoexist->stack_info;
- static u8 dis_ver_info_cnt;
- u32 fw_ver = 0, bt_patch_ver = 0;
+ struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], ==========================Periodical===========================\n");
- if (dis_ver_info_cnt <= 5) {
- dis_ver_info_cnt += 1;
- RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], ****************************************************************\n");
- RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n",
- board_info->pg_ant_num, board_info->btdm_ant_num,
- board_info->btdm_ant_pos);
- RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], BT stack/ hci ext ver = %s / %d\n",
- stack_info->profile_notified ? "Yes" : "No",
- stack_info->hci_version);
- btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER,
- &bt_patch_ver);
- btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver);
- RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n",
- glcoex_ver_date_8723b_1ant,
- glcoex_ver_8723b_1ant, fw_ver,
- bt_patch_ver, bt_patch_ver);
- RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], ****************************************************************\n");
- }
+ if (!btcoexist->auto_report_1ant) {
+ halbtc8723b1ant_query_bt_info(btcoexist);
+ halbtc8723b1ant_monitor_bt_enable_disable(btcoexist);
+ } else {
+ halbtc8723b1ant_monitor_bt_ctr(btcoexist);
+ halbtc8723b1ant_monitor_wifi_ctr(btcoexist);
-#if (BT_AUTO_REPORT_ONLY_8723B_1ANT == 0)
- halbtc8723b1ant_query_bt_info(btcoexist);
- halbtc8723b1ant_monitor_bt_ctr(btcoexist);
- halbtc8723b1ant_monitor_bt_enable_disable(btcoexist);
-#else
- if (btc8723b1ant_is_wifi_status_changed(btcoexist) ||
- coex_dm->auto_tdma_adjust) {
- halbtc8723b1ant_run_coexist_mechanism(btcoexist);
- }
+ if ((coex_sta->high_priority_tx + coex_sta->high_priority_rx < 50) &&
+ bt_link_info->hid_exist)
+ bt_link_info->hid_exist = false;
- coex_sta->special_pkt_period_cnt++;
-#endif
+ if (btc8723b1ant_is_wifi_status_changed(btcoexist) ||
+ coex_dm->auto_tdma_adjust) {
+ halbtc8723b1ant_run_coexist_mechanism(btcoexist);
+ }
+ coex_sta->special_pkt_period_cnt++;
+ }
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h
index 75f8094..8d4fde2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h
@@ -25,8 +25,6 @@
/**********************************************************************
* The following is for 8723B 1ANT BT Co-exist definition
**********************************************************************/
-#define BT_AUTO_REPORT_ONLY_8723B_1ANT 1
-
#define BT_INFO_8723B_1ANT_B_FTP BIT7
#define BT_INFO_8723B_1ANT_B_A2DP BIT6
#define BT_INFO_8723B_1ANT_B_HID BIT5
@@ -41,6 +39,8 @@
#define BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT 2
+#define BT_8723B_1ANT_WIFI_NOISY_THRESH 50
+
enum _BT_INFO_SRC_8723B_1ANT {
BT_INFO_SRC_8723B_1ANT_WIFI_FW = 0x0,
BT_INFO_SRC_8723B_1ANT_BT_RSP = 0x1,
@@ -84,13 +84,16 @@ enum _BT_8723B_1ANT_COEX_ALGO {
};
struct coex_dm_8723b_1ant {
+ /* hw setting */
+ u8 pre_ant_pos_type;
+ u8 cur_ant_pos_type;
/* fw mechanism */
bool cur_ignore_wlan_act;
bool pre_ignore_wlan_act;
u8 pre_ps_tdma;
u8 cur_ps_tdma;
u8 ps_tdma_para[5];
- u8 tdma_adj_type;
+ u8 ps_tdma_du_adj_type;
bool auto_tdma_adjust;
bool pre_ps_tdma_on;
bool cur_ps_tdma_on;
@@ -133,16 +136,21 @@ struct coex_dm_8723b_1ant {
u8 cur_retry_limit_type;
u8 pre_ampdu_time_type;
u8 cur_ampdu_time_type;
+ u32 arp_cnt;
u8 error_condition;
};
struct coex_sta_8723b_1ant {
+ bool bt_disabled;
bool bt_link_exist;
bool sco_exist;
bool a2dp_exist;
bool hid_exist;
bool pan_exist;
+ bool bt_hi_pri_link_exist;
+ u8 num_of_profile;
+ bool bt_abnormal_scan;
bool under_lps;
bool under_ips;
@@ -154,31 +162,63 @@ struct coex_sta_8723b_1ant {
u8 bt_rssi;
u8 pre_bt_rssi_state;
u8 pre_wifi_rssi_state[4];
+ bool bt_tx_rx_mask;
bool c2h_bt_info_req_sent;
u8 bt_info_c2h[BT_INFO_SRC_8723B_1ANT_MAX][10];
u32 bt_info_c2h_cnt[BT_INFO_SRC_8723B_1ANT_MAX];
+ bool bt_whck_test;
bool c2h_bt_inquiry_page;
+ bool c2h_bt_remote_name_req;
+ bool wifi_is_high_pri_task;
u8 bt_retry_cnt;
u8 bt_info_ext;
+ u8 scan_ap_num;
+ bool cck_ever_lock;
+ u8 coex_table_type;
+ bool force_lps_on;
+ u32 pop_event_cnt;
+
+ u32 crc_ok_cck;
+ u32 crc_ok_11g;
+ u32 crc_ok_11n;
+ u32 crc_ok_11n_agg;
+
+ u32 crc_err_cck;
+ u32 crc_err_11g;
+ u32 crc_err_11n;
+ u32 crc_err_11n_agg;
+
+ bool cck_lock;
+ bool pre_ccklock;
+
+ u32 wrong_profile_notification;
+
+ u8 a2dp_bit_pool;
+ u8 cut_version;
};
/*************************************************************************
* The following is interface which will notify coex module.
*************************************************************************/
-void ex_halbtc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist);
-void ex_halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist);
-void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8723b1ant_media_status_notify(struct btc_coexist *btcoexist,
- u8 type);
-void ex_halbtc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist,
- u8 type);
-void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
- u8 *tmpbuf, u8 length);
-void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist);
-void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnpstate);
-void ex_halbtc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist);
-void ex_halbtc8723b1ant_periodical(struct btc_coexist *btcoexist);
-void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist);
+void ex_btc8723b1ant_power_on_setting(struct btc_coexist *btcoexist);
+void ex_btc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist,
+ bool wifi_only);
+void ex_btc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist);
+void ex_btc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8723b1ant_media_status_notify(struct btc_coexist *btcoexist,
+ u8 type);
+void ex_btc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist,
+ u8 type);
+void ex_btc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
+ u8 *tmpbuf, u8 length);
+void ex_btc8723b1ant_rf_status_notify(struct btc_coexist *btcoexist,
+ u8 type);
+void ex_btc8723b1ant_halt_notify(struct btc_coexist *btcoexist);
+void ex_btc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnpstate);
+void ex_btc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist);
+void ex_btc8723b1ant_periodical(struct btc_coexist *btcoexist);
+void ex_btc8723b1ant_display_coex_info(struct btc_coexist *btcoexist);
+void ex_btc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state);
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
index 2f3946b..31965f0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
@@ -707,6 +707,36 @@ static void btc8723b2ant_dec_bt_pwr(struct btc_coexist *btcoexist,
coex_dm->pre_dec_bt_pwr_lvl = coex_dm->cur_dec_bt_pwr_lvl;
}
+static
+void halbtc8723b2ant_set_bt_auto_report(struct btc_coexist *btcoexist,
+ bool enable_auto_report)
+{
+ u8 h2c_parameter[1] = {0};
+
+ h2c_parameter[0] = 0;
+
+ if (enable_auto_report)
+ h2c_parameter[0] |= BIT(0);
+
+ btcoexist->btc_fill_h2c(btcoexist, 0x68, 1, h2c_parameter);
+}
+
+static
+void btc8723b2ant_bt_auto_report(struct btc_coexist *btcoexist,
+ bool force_exec, bool enable_auto_report)
+{
+ coex_dm->cur_bt_auto_report = enable_auto_report;
+
+ if (!force_exec) {
+ if (coex_dm->pre_bt_auto_report == coex_dm->cur_bt_auto_report)
+ return;
+ }
+ halbtc8723b2ant_set_bt_auto_report(btcoexist,
+ coex_dm->cur_bt_auto_report);
+
+ coex_dm->pre_bt_auto_report = coex_dm->cur_bt_auto_report;
+}
+
static void btc8723b2ant_fw_dac_swing_lvl(struct btc_coexist *btcoexist,
bool force_exec, u8 fw_dac_swing_lvl)
{
@@ -3666,6 +3696,7 @@ void ex_btc8723b2ant_init_hwconfig(struct btc_coexist *btcoexist)
btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4);
btcoexist->btc_write_1byte(btcoexist, 0x778, 0x3);
btcoexist->btc_write_1byte_bitmask(btcoexist, 0x40, 0x20, 0x1);
+ btcoexist->auto_report_2ant = true;
}
void ex_btc8723b2ant_power_on_setting(struct btc_coexist *btcoexist)
@@ -3966,9 +3997,8 @@ void ex_btc8723b2ant_display_coex_info(struct btc_coexist *btcoexist)
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d",
"0x774(low-pri rx/tx)", coex_sta->low_priority_rx,
coex_sta->low_priority_tx);
-#if (BT_AUTO_REPORT_ONLY_8723B_2ANT == 1)
- btc8723b2ant_monitor_bt_ctr(btcoexist);
-#endif
+ if (btcoexist->auto_report_2ant)
+ btc8723b2ant_monitor_bt_ctr(btcoexist);
btcoexist->btc_disp_dbg_msg(btcoexist,
BTC_DBG_DISP_COEX_STATISTICS);
}
@@ -4190,14 +4220,11 @@ void ex_btc8723b2ant_bt_info_notify(struct btc_coexist *btcoexist,
} else {
/* BT already NOT ignore Wlan active, do nothing here.*/
}
-#if (BT_AUTO_REPORT_ONLY_8723B_2ANT == 0)
- if ((coex_sta->bt_info_ext & BIT4)) {
- /* BT auto report already enabled, do nothing*/
- } else {
- btc8723b2ant_bt_auto_report(btcoexist, FORCE_EXEC,
- true);
+ if (!btcoexist->auto_report_2ant) {
+ if (!(coex_sta->bt_info_ext & BIT4))
+ btc8723b2ant_bt_auto_report(btcoexist,
+ FORCE_EXEC, true);
}
-#endif
}
/* check BIT2 first ==> check if bt is under inquiry or page scan */
@@ -4347,21 +4374,22 @@ void ex_btc8723b2ant_periodical(struct btc_coexist *btcoexist)
}
}
-#if (BT_AUTO_REPORT_ONLY_8723B_2ANT == 0)
- btc8723b2ant_query_bt_info(btcoexist);
-#else
- btc8723b2ant_monitor_bt_ctr(btcoexist);
- btc8723b2ant_monitor_wifi_ctr(btcoexist);
+ if (!btcoexist->auto_report_2ant) {
+ btc8723b2ant_query_bt_info(btcoexist);
+ } else {
+ btc8723b2ant_monitor_bt_ctr(btcoexist);
+ btc8723b2ant_monitor_wifi_ctr(btcoexist);
- /* for some BT speakers that High-Priority pkts appear before
- * playing, this will cause HID exist
- */
- if ((coex_sta->high_priority_tx + coex_sta->high_priority_rx < 50) &&
- (bt_link_info->hid_exist))
- bt_link_info->hid_exist = false;
-
- if (btc8723b2ant_is_wifi_status_changed(btcoexist) ||
- coex_dm->auto_tdma_adjust)
- btc8723b2ant_run_coexist_mechanism(btcoexist);
-#endif
+ /* for some BT speakers that High-Priority pkts appear before
+ * playing, this will cause HID exist
+ */
+ if ((coex_sta->high_priority_tx +
+ coex_sta->high_priority_rx < 50) &&
+ (bt_link_info->hid_exist))
+ bt_link_info->hid_exist = false;
+
+ if (btc8723b2ant_is_wifi_status_changed(btcoexist) ||
+ coex_dm->auto_tdma_adjust)
+ btc8723b2ant_run_coexist_mechanism(btcoexist);
+ }
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h
index 18a35c7..bc1e304 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h
@@ -28,8 +28,6 @@
/************************************************************************
* The following is for 8723B 2Ant BT Co-exist definition
************************************************************************/
-#define BT_AUTO_REPORT_ONLY_8723B_2ANT 1
-
#define BT_INFO_8723B_2ANT_B_FTP BIT7
#define BT_INFO_8723B_2ANT_B_A2DP BIT6
#define BT_INFO_8723B_2ANT_B_HID BIT5
@@ -198,5 +196,8 @@ void ex_btc8723b2ant_bt_info_notify(struct btc_coexist *btcoexist,
void ex_btc8723b2ant_halt_notify(struct btc_coexist *btcoexist);
void ex_btc8723b2ant_periodical(struct btc_coexist *btcoexist);
void ex_btc8723b2ant_display_coex_info(struct btc_coexist *btcoexist);
+void ex_btc8723b2ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state);
+void ex_btc8723b2ant_pre_load_firmware(struct btc_coexist *btcoexist);
+void ex_btc8723b2ant_power_on_setting(struct btc_coexist *btcoexist);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c
index 5e9f3b0..4efac5f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c
@@ -1107,8 +1107,8 @@ static void btc8821a1ant_ps_tdma(struct btc_coexist *btcoexist,
0x3, 0x11, 0x10);
break;
case 6:
- btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xa,
- 0x3, 0x0, 0x0);
+ btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x20,
+ 0x3, 0x11, 0x13);
break;
case 7:
btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xc,
@@ -1128,8 +1128,8 @@ static void btc8821a1ant_ps_tdma(struct btc_coexist *btcoexist,
0xa, 0x0, 0x40);
break;
case 11:
- btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x14,
- 0x03, 0x10, 0x10);
+ btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x15,
+ 0x03, 0x10, 0x50);
rssi_adjust_val = 20;
break;
case 12:
@@ -1137,8 +1137,8 @@ static void btc8821a1ant_ps_tdma(struct btc_coexist *btcoexist,
0x0a, 0x0, 0x50);
break;
case 13:
- btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x18,
- 0x18, 0x0, 0x10);
+ btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x12,
+ 0x12, 0x0, 0x50);
break;
case 14:
btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x1e,
@@ -1163,8 +1163,8 @@ static void btc8821a1ant_ps_tdma(struct btc_coexist *btcoexist,
0x03, 0x11, 0x10);
break;
case 21:
- btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x15,
- 0x03, 0x11, 0x10);
+ btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x25,
+ 0x03, 0x11, 0x11);
break;
case 22:
btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x25,
@@ -1204,16 +1204,16 @@ static void btc8821a1ant_ps_tdma(struct btc_coexist *btcoexist,
0x1a, 0x1, 0x10);
break;
case 30:
- btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x14,
- 0x3, 0x10, 0x50);
+ btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x30,
+ 0x3, 0x10, 0x10);
break;
case 31:
btc8821a1ant_set_fw_ps_tdma(btcoexist, 0xd3, 0x1a,
0x1a, 0, 0x58);
break;
case 32:
- btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x61, 0xa,
- 0x3, 0x10, 0x0);
+ btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x35,
+ 0x3, 0x11, 0x11);
break;
case 33:
btc8821a1ant_set_fw_ps_tdma(btcoexist, 0xa3, 0x25,
@@ -1231,6 +1231,28 @@ static void btc8821a1ant_ps_tdma(struct btc_coexist *btcoexist,
btc8821a1ant_set_fw_ps_tdma(btcoexist, 0xd3, 0x12,
0x3, 0x14, 0x50);
break;
+ case 40:
+ /* SoftAP only with no sta associated, BT disable, TDMA
+ * mode for power saving
+ *
+ * here softap mode screen off will cost 70-80mA for
+ * phone
+ */
+ btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x23, 0x18,
+ 0x00, 0x10, 0x24);
+ break;
+ case 41:
+ btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x15,
+ 0x3, 0x11, 0x11);
+ break;
+ case 42:
+ btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x20,
+ 0x3, 0x11, 0x11);
+ break;
+ case 43:
+ btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x30,
+ 0x3, 0x10, 0x11);
+ break;
}
} else {
/* disable PS tdma */
@@ -1619,15 +1641,23 @@ static void btc8821a1ant_act_wifi_con_bt_acl_busy(struct btc_coexist *btcoexist,
return;
} else if (bt_link_info->a2dp_only) {
/* A2DP */
- if ((bt_rssi_state != BTC_RSSI_STATE_HIGH) &&
- (bt_rssi_state != BTC_RSSI_STATE_STAY_HIGH)) {
+ if (wifi_status == BT_8821A_1ANT_WIFI_STATUS_CONNECTED_IDLE) {
+ btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32);
+ btc8821a1ant_coex_table_with_type(btcoexist,
+ NORMAL_EXEC, 1);
+ coex_dm->auto_tdma_adjust = false;
+ } else if ((bt_rssi_state != BTC_RSSI_STATE_HIGH) &&
+ (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
+ btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14);
+ btc8821a1ant_coex_table_with_type(btcoexist,
+ NORMAL_EXEC, 1);
+ } else {
/* for low BT RSSI */
- btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
- true, 11);
+ btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14);
+ btc8821a1ant_coex_table_with_type(btcoexist,
+ NORMAL_EXEC, 1);
coex_dm->auto_tdma_adjust = false;
}
-
- btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
} else if (bt_link_info->hid_exist && bt_link_info->a2dp_exist) {
/* HID+A2DP */
if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
@@ -1638,7 +1668,7 @@ static void btc8821a1ant_act_wifi_con_bt_acl_busy(struct btc_coexist *btcoexist,
} else {
/*for low BT RSSI*/
btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
- true, 11);
+ true, 14);
coex_dm->auto_tdma_adjust = false;
}
@@ -1647,13 +1677,13 @@ static void btc8821a1ant_act_wifi_con_bt_acl_busy(struct btc_coexist *btcoexist,
(bt_link_info->hid_exist && bt_link_info->pan_exist)) {
/* PAN(OPP, FTP), HID+PAN(OPP, FTP) */
btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3);
- btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+ btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 6);
coex_dm->auto_tdma_adjust = false;
} else if (((bt_link_info->a2dp_exist) && (bt_link_info->pan_exist)) ||
(bt_link_info->hid_exist && bt_link_info->a2dp_exist &&
bt_link_info->pan_exist)) {
/* A2DP+PAN(OPP, FTP), HID+A2DP+PAN(OPP, FTP) */
- btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13);
+ btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 43);
btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
coex_dm->auto_tdma_adjust = false;
} else {
@@ -1718,52 +1748,49 @@ void btc8821a1ant_action_wifi_connected_scan(struct btc_coexist *btcoexist)
/* tdma and coex table */
if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) {
- if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) {
- btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 22);
+ if (bt_link_info->a2dp_exist) {
+ btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14);
btc8821a1ant_coex_table_with_type(btcoexist,
NORMAL_EXEC, 1);
} else {
- btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20);
- btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
- }
- } else if ((BT_8821A_1ANT_BT_STATUS_SCO_BUSY ==
- coex_dm->bt_status) ||
- (BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY ==
- coex_dm->bt_status)) {
+ btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20);
+ btc8821a1ant_coex_table_with_type(btcoexist,
+ NORMAL_EXEC, 4);
+ }
+ } else if ((coex_dm->bt_status == BT_8821A_1ANT_BT_STATUS_SCO_BUSY) ||
+ (coex_dm->bt_status ==
+ BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY)) {
btc8821a1ant_act_bt_sco_hid_only_busy(btcoexist,
BT_8821A_1ANT_WIFI_STATUS_CONNECTED_SCAN);
} else {
- btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20);
- btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+ btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+ btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
}
}
static void btc8821a1ant_act_wifi_conn_sp_pkt(struct btc_coexist *btcoexist)
{
struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
- bool hs_connecting = false;
-
- btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_CONNECTING, &hs_connecting);
btc8821a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
0x0, 0x0);
/* tdma and coex table */
- if (coex_dm->bt_status == BT_8821A_1ANT_BT_STATUS_ACL_BUSY) {
- if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) {
- btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
- true, 22);
- btc8821a1ant_coex_table_with_type(btcoexist,
- NORMAL_EXEC, 1);
- } else {
- btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
- true, 20);
- btc8821a1ant_coex_table_with_type(btcoexist,
- NORMAL_EXEC, 1);
- }
- } else {
- btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20);
+ if ((bt_link_info->sco_exist) || (bt_link_info->hid_exist) ||
+ (bt_link_info->a2dp_exist)) {
+ btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32);
+ btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+ }
+
+ if ((bt_link_info->hid_exist) && (bt_link_info->a2dp_exist)) {
+ btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14);
btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+ } else if (bt_link_info->pan_exist) {
+ btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20);
+ btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+ } else {
+ btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+ btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
}
}
@@ -1773,6 +1800,7 @@ static void btc8821a1ant_action_wifi_connected(struct btc_coexist *btcoexist)
bool wifi_busy = false;
bool scan = false, link = false, roam = false;
bool under_4way = false;
+ bool ap_enable = false;
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], CoexForWifiConnect()===>\n");
@@ -1790,24 +1818,37 @@ static void btc8821a1ant_action_wifi_connected(struct btc_coexist *btcoexist)
btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link);
btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam);
if (scan || link || roam) {
- btc8821a1ant_action_wifi_connected_scan(btcoexist);
+ if (scan)
+ btc8821a1ant_action_wifi_connected_scan(btcoexist);
+ else
+ btc8821a1ant_act_wifi_conn_sp_pkt(btcoexist);
+
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], CoexForWifiConnect(), return for wifi is under scan<===\n");
return;
}
/* power save state*/
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE,
+ &ap_enable);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY ==
- coex_dm->bt_status && !btcoexist->bt_link_info.hid_only)
- btc8821a1ant_power_save_state(btcoexist,
- BTC_PS_LPS_ON, 0x50, 0x4);
- else
+ coex_dm->bt_status && !ap_enable &&
+ !btcoexist->bt_link_info.hid_only) {
+ if (!wifi_busy && btcoexist->bt_link_info.a2dp_only)
+ /* A2DP */
+ btc8821a1ant_power_save_state(btcoexist,
+ BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+ else
+ btc8821a1ant_power_save_state(btcoexist, BTC_PS_LPS_ON,
+ 0x50, 0x4);
+ } else {
btc8821a1ant_power_save_state(btcoexist,
BTC_PS_WIFI_NATIVE,
0x0, 0x0);
+ }
/* tdma and coex table */
- btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
if (!wifi_busy) {
if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) {
btc8821a1ant_act_wifi_con_bt_acl_busy(btcoexist,
@@ -1819,8 +1860,7 @@ static void btc8821a1ant_action_wifi_connected(struct btc_coexist *btcoexist)
btc8821a1ant_act_bt_sco_hid_only_busy(btcoexist,
BT_8821A_1ANT_WIFI_STATUS_CONNECTED_IDLE);
} else {
- btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
- true, 5);
+ btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
btc8821a1ant_coex_table_with_type(btcoexist,
NORMAL_EXEC, 2);
}
@@ -1835,7 +1875,7 @@ static void btc8821a1ant_action_wifi_connected(struct btc_coexist *btcoexist)
btc8821a1ant_act_bt_sco_hid_only_busy(btcoexist,
BT_8821A_1ANT_WIFI_STATUS_CONNECTED_BUSY);
} else {
- btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5);
+ btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
btc8821a1ant_coex_table_with_type(btcoexist,
NORMAL_EXEC, 2);
}
@@ -1988,11 +2028,11 @@ static void btc8821a1ant_run_coexist_mechanism(struct btc_coexist *btcoexist)
(wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
btc8821a1ant_limited_tx(btcoexist,
NORMAL_EXEC, 1, 1,
- 1, 1);
+ 0, 1);
} else {
btc8821a1ant_limited_tx(btcoexist,
NORMAL_EXEC, 1, 1,
- 1, 1);
+ 0, 1);
}
} else {
btc8821a1ant_limited_tx(btcoexist, NORMAL_EXEC,
@@ -2056,7 +2096,6 @@ static void btc8821a1ant_init_coex_dm(struct btc_coexist *btcoexist)
*/
btc8821a1ant_sw_mechanism(btcoexist, false);
- btc8821a1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
btc8821a1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0);
}
@@ -2116,6 +2155,7 @@ static void btc8821a1ant_init_hw_config(struct btc_coexist *btcoexist,
void ex_btc8821a1ant_init_hwconfig(struct btc_coexist *btcoexist, bool wifionly)
{
btc8821a1ant_init_hw_config(btcoexist, true, wifionly);
+ btcoexist->auto_report_1ant = true;
}
void ex_btc8821a1ant_init_coex_dm(struct btc_coexist *btcoexist)
@@ -2406,9 +2446,8 @@ void ex_btc8821a1ant_display_coex_info(struct btc_coexist *btcoexist)
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
"\r\n %-35s = %d/ %d", "0x774(low-pri rx/tx)",
coex_sta->low_priority_rx, coex_sta->low_priority_tx);
-#if (BT_AUTO_REPORT_ONLY_8821A_1ANT == 1)
- btc8821a1ant_monitor_bt_ctr(btcoexist);
-#endif
+ if (btcoexist->auto_report_1ant)
+ btc8821a1ant_monitor_bt_ctr(btcoexist);
btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_COEX_STATISTICS);
}
@@ -2434,7 +2473,7 @@ void ex_btc8821a1ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
btc8821a1ant_set_ant_path(btcoexist,
BTC_ANT_PATH_BT, false, true);
/* set PTA control */
- btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+ btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 0);
btc8821a1ant_coex_table_with_type(btcoexist,
NORMAL_EXEC, 0);
} else if (BTC_IPS_LEAVE == type) {
@@ -2442,7 +2481,9 @@ void ex_btc8821a1ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
"[BTCoex], IPS LEAVE notify\n");
coex_sta->under_ips = false;
- btc8821a1ant_run_coexist_mechanism(btcoexist);
+ btc8821a1ant_init_hw_config(btcoexist, false, false);
+ btc8821a1ant_init_coex_dm(btcoexist);
+ btc8821a1ant_query_bt_info(btcoexist);
}
}
@@ -2484,6 +2525,19 @@ void ex_btc8821a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type)
return;
}
+ if (type == BTC_SCAN_START) {
+ coex_sta->wifi_is_high_pri_task = true;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], SCAN START notify\n");
+
+ /* Force antenna setup for no scan result issue */
+ btc8821a1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
+ } else {
+ coex_sta->wifi_is_high_pri_task = false;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], SCAN FINISH notify\n");
+ }
+
if (coex_sta->bt_disabled)
return;
@@ -2538,7 +2592,7 @@ void ex_btc8821a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type)
void ex_btc8821a1ant_connect_notify(struct btc_coexist *btcoexist, u8 type)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
- bool wifi_connected = false, bt_hs_on = false;
+ bool wifi_connected = false, bt_hs_on = false;
u32 wifi_link_status = 0;
u32 num_of_wifi_link = 0;
bool bt_ctrl_agg_buf_size = false;
@@ -2556,6 +2610,18 @@ void ex_btc8821a1ant_connect_notify(struct btc_coexist *btcoexist, u8 type)
return;
}
+ if (type == BTC_ASSOCIATE_START) {
+ coex_sta->wifi_is_high_pri_task = true;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], CONNECT START notify\n");
+ coex_dm->arp_cnt = 0;
+ } else {
+ coex_sta->wifi_is_high_pri_task = false;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], CONNECT FINISH notify\n");
+ coex_dm->arp_cnt = 0;
+ }
+
btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS,
&wifi_link_status);
num_of_wifi_link = wifi_link_status >> 16;
@@ -2621,6 +2687,7 @@ void ex_btc8821a1ant_media_status_notify(struct btc_coexist *btcoexist,
} else {
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], MEDIA disconnect notify\n");
+ coex_dm->arp_cnt = 0;
}
/* only 2.4G we need to inform bt the chnl mask */
@@ -2674,6 +2741,24 @@ void ex_btc8821a1ant_special_packet_notify(struct btc_coexist *btcoexist,
return;
}
+ if (type == BTC_PACKET_DHCP || type == BTC_PACKET_EAPOL ||
+ type == BTC_PACKET_ARP) {
+ coex_sta->wifi_is_high_pri_task = true;
+
+ if (type == BTC_PACKET_ARP) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], specific Packet ARP notify\n");
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], specific Packet DHCP or EAPOL notify\n");
+ }
+ } else {
+ coex_sta->wifi_is_high_pri_task = false;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], specific Packet [Type = %d] notify\n",
+ type);
+ }
+
coex_sta->special_pkt_period_cnt = 0;
btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS,
@@ -2696,8 +2781,20 @@ void ex_btc8821a1ant_special_packet_notify(struct btc_coexist *btcoexist,
return;
}
- if (BTC_PACKET_DHCP == type ||
- BTC_PACKET_EAPOL == type) {
+ if (type == BTC_PACKET_DHCP || type == BTC_PACKET_EAPOL ||
+ type == BTC_PACKET_ARP) {
+ if (type == BTC_PACKET_ARP) {
+ coex_dm->arp_cnt++;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], ARP Packet Count = %d\n",
+ coex_dm->arp_cnt);
+ if (coex_dm->arp_cnt >= 10)
+ /* if APR PKT > 10 after connect, do not go to
+ * btc8821a1ant_act_wifi_conn_sp_pkt
+ */
+ return;
+ }
+
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], special Packet(%d) notify\n", type);
btc8821a1ant_act_wifi_conn_sp_pkt(btcoexist);
@@ -2742,14 +2839,28 @@ void ex_btc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist,
}
if (BT_INFO_SRC_8821A_1ANT_WIFI_FW != rsp_source) {
- coex_sta->bt_retry_cnt = /* [3:0]*/
- coex_sta->bt_info_c2h[rsp_source][2]&0xf;
+ /* [3:0] */
+ coex_sta->bt_retry_cnt =
+ coex_sta->bt_info_c2h[rsp_source][2] & 0xf;
coex_sta->bt_rssi =
- coex_sta->bt_info_c2h[rsp_source][3]*2+10;
+ coex_sta->bt_info_c2h[rsp_source][3] * 2 + 10;
- coex_sta->bt_info_ext =
- coex_sta->bt_info_c2h[rsp_source][4];
+ coex_sta->bt_info_ext = coex_sta->bt_info_c2h[rsp_source][4];
+
+ coex_sta->bt_tx_rx_mask =
+ (coex_sta->bt_info_c2h[rsp_source][2] & 0x40);
+ btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TX_RX_MASK,
+ &coex_sta->bt_tx_rx_mask);
+ if (!coex_sta->bt_tx_rx_mask) {
+ /* BT into is responded by BT FW and BT RF REG 0x3C !=
+ * 0x15 => Need to switch BT TRx Mask
+ */
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], Switch BT TRx Mask since BT RF REG 0x3C != 0x15\n");
+ btcoexist->btc_set_bt_reg(btcoexist, BTC_BT_REG_RF,
+ 0x3c, 0x15);
+ }
/* Here we need to resend some wifi info to BT
* because bt is reset and lost the info
@@ -2831,11 +2942,11 @@ void ex_btc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist,
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n");
} else if ((bt_info&BT_INFO_8821A_1ANT_B_SCO_ESCO) ||
- (bt_info&BT_INFO_8821A_1ANT_B_SCO_BUSY)) {
+ (bt_info & BT_INFO_8821A_1ANT_B_SCO_BUSY)) {
coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_SCO_BUSY;
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], BtInfoNotify(), BT SCO busy!!!\n");
- } else if (bt_info&BT_INFO_8821A_1ANT_B_ACL_BUSY) {
+ } else if (bt_info & BT_INFO_8821A_1ANT_B_ACL_BUSY) {
if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY != coex_dm->bt_status)
coex_dm->auto_tdma_adjust = false;
coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_ACL_BUSY;
@@ -2964,10 +3075,10 @@ void ex_btc8821a1ant_periodical(struct btc_coexist *btcoexist)
"[BTCoex], ****************************************************************\n");
}
-#if (BT_AUTO_REPORT_ONLY_8821A_1ANT == 0)
- btc8821a1ant_query_bt_info(btcoexist);
- btc8821a1ant_monitor_bt_ctr(btcoexist);
-#else
- coex_sta->special_pkt_period_cnt++;
-#endif
+ if (!btcoexist->auto_report_1ant) {
+ btc8821a1ant_query_bt_info(btcoexist);
+ btc8821a1ant_monitor_bt_ctr(btcoexist);
+ } else {
+ coex_sta->special_pkt_period_cnt++;
+ }
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h
index 1bd1ebe..b0a6626 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h
@@ -27,8 +27,6 @@
* The following is for 8821A 1ANT BT Co-exist definition
*===========================================
*/
-#define BT_AUTO_REPORT_ONLY_8821A_1ANT 0
-
#define BT_INFO_8821A_1ANT_B_FTP BIT7
#define BT_INFO_8821A_1ANT_B_A2DP BIT6
#define BT_INFO_8821A_1ANT_B_HID BIT5
@@ -135,6 +133,7 @@ struct coex_dm_8821a_1ant {
u8 cur_retry_limit_type;
u8 pre_ampdu_time_type;
u8 cur_ampdu_time_type;
+ u32 arp_cnt;
u8 error_condition;
};
@@ -155,6 +154,7 @@ struct coex_sta_8821a_1ant {
u32 low_priority_tx;
u32 low_priority_rx;
u8 bt_rssi;
+ bool bt_tx_rx_mask;
u8 pre_bt_rssi_state;
u8 pre_wifi_rssi_state[4];
bool c2h_bt_info_req_sent;
@@ -170,21 +170,23 @@ struct coex_sta_8821a_1ant {
* The following is interface which will notify coex module.
*===========================================
*/
-void ex_halbtc8821a1ant_init_hwconfig(struct btc_coexist *btcoexist);
-void ex_halbtc8821a1ant_init_coex_dm(struct btc_coexist *btcoexist);
-void ex_halbtc8821a1ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8821a1ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8821a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8821a1ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
-void ex_halbtc8821a1ant_media_status_notify(struct btc_coexist *btcoexist,
- u8 type);
-void ex_halbtc8821a1ant_special_packet_notify(struct btc_coexist *btcoexist,
- u8 type);
-void ex_halbtc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist,
- u8 *tmpbuf, u8 length);
-void ex_halbtc8821a1ant_halt_notify(struct btc_coexist *btcoexist);
-void ex_halbtc8821a1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnpstate);
-void ex_halbtc8821a1ant_periodical(struct btc_coexist *btcoexist);
-void ex_halbtc8821a1ant_display_coex_info(struct btc_coexist *btcoexist);
-void ex_halbtc8821a1ant_dbg_control(struct btc_coexist *btcoexist, u8 op_code,
- u8 op_len, u8 *data);
+void ex_btc8821a1ant_init_hwconfig(struct btc_coexist *btcoexist,
+ bool wifi_only);
+void ex_btc8821a1ant_init_coex_dm(struct btc_coexist *btcoexist);
+void ex_btc8821a1ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8821a1ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8821a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8821a1ant_connect_notify(struct btc_coexist *btcoexist, u8 type);
+void ex_btc8821a1ant_media_status_notify(struct btc_coexist *btcoexist,
+ u8 type);
+void ex_btc8821a1ant_special_packet_notify(struct btc_coexist *btcoexist,
+ u8 type);
+void ex_btc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist,
+ u8 *tmpbuf, u8 length);
+void ex_btc8821a1ant_halt_notify(struct btc_coexist *btcoexist);
+void ex_btc8821a1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnpstate);
+void ex_btc8821a1ant_periodical(struct btc_coexist *btcoexist);
+void ex_btc8821a1ant_display_coex_info(struct btc_coexist *btcoexist);
+void ex_btc8821a1ant_dbg_control(struct btc_coexist *btcoexist, u8 op_code,
+ u8 op_len, u8 *data);
+void ex_btc8821a1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state);
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c
index 841b4a8..41943c3 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c
@@ -3220,12 +3220,16 @@ static void btc8821a2ant_action_pan_edr_hid(struct btc_coexist *btcoexist)
/* HID+A2DP+PAN(EDR) */
static void btc8821a2ant_act_hid_a2dp_pan_edr(struct btc_coexist *btcoexist)
{
- u8 wifi_rssi_state, bt_rssi_state, bt_info_ext;
+ u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
u32 wifi_bw;
- bt_info_ext = coex_sta->bt_info_ext;
wifi_rssi_state = btc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
- bt_rssi_state = btc8821a2ant_bt_rssi_state(btcoexist, 2, 35, 0);
+ wifi_rssi_state1 = btc8821a2ant_wifi_rssi_state(btcoexist, 1, 2,
+ BT_8821A_2ANT_WIFI_RSSI_COEXSWITCH_THRES, 0);
+ bt_rssi_state = btc8821a2ant_bt_rssi_state(btcoexist,
+ 2, BT_8821A_2ANT_BT_RSSI_COEXSWITCH_THRES, 0);
+
+ btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
btc8821a2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8);
btc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
@@ -3235,44 +3239,32 @@ static void btc8821a2ant_act_hid_a2dp_pan_edr(struct btc_coexist *btcoexist)
else
btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ if (BTC_RSSI_HIGH(wifi_rssi_state1) && BTC_RSSI_HIGH(bt_rssi_state)) {
+ btc8821a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 7);
+ btc8821a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+ 0x0, 0x0);
+ } else {
+ btc8821a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 14);
+ btc8821a2ant_power_save_state(btcoexist, BTC_PS_LPS_ON, 0x50,
+ 0x4);
+ }
+
btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
- if (wifi_bw == BTC_WIFI_BW_LEGACY) {
- /* for HID at 11b/g mode */
- btc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff,
- 0x5a5a5a5a, 0xffff, 0x3);
+ if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
+ (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
+ if (wifi_bw == BTC_WIFI_BW_HT40)
+ btc8821a2ant_tdma_duration_adjust(btcoexist, true,
+ true, 3);
+ else
+ btc8821a2ant_tdma_duration_adjust(btcoexist, true,
+ false, 3);
} else {
- /* for HID quality & wifi performance balance at 11n mode */
- btc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff,
- 0x5a5a5a5a, 0xffff, 0x3);
+ btc8821a2ant_tdma_duration_adjust(btcoexist, true, true, 3);
}
- if (BTC_WIFI_BW_HT40 == wifi_bw) {
- /* fw mechanism */
- if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
- (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
- if (bt_info_ext&BIT0) {
- /* a2dp basic rate */
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, true, 3);
- } else {
- /* a2dp edr rate */
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, true, 3);
- }
- } else {
- if (bt_info_ext&BIT0) {
- /* a2dp basic rate */
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, true, 3);
- } else {
- /* a2dp edr rate */
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, true, 3);
- }
- }
-
- /* sw mechanism */
+ /* sw mechanism */
+ if (wifi_bw == BTC_WIFI_BW_HT40) {
if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) ||
(wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
btc8821a2ant_sw_mechanism1(btcoexist, true, true,
@@ -3286,33 +3278,6 @@ static void btc8821a2ant_act_hid_a2dp_pan_edr(struct btc_coexist *btcoexist)
false, 0x18);
}
} else {
- /* fw mechanism */
- if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
- (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
- if (bt_info_ext&BIT0) {
- /* a2dp basic rate */
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, false, 3);
- } else {
- /* a2dp edr rate */
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, false, 3);
- }
- } else {
- if (bt_info_ext&BIT0) {
- /* a2dp basic rate */
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, true,
- 3);
- } else {
- /* a2dp edr rate */
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, true,
- 3);
- }
- }
-
- /* sw mechanism */
if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) ||
(wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
btc8821a2ant_sw_mechanism1(btcoexist, false, true,
@@ -3330,19 +3295,46 @@ static void btc8821a2ant_act_hid_a2dp_pan_edr(struct btc_coexist *btcoexist)
static void btc8821a2ant_action_hid_a2dp(struct btc_coexist *btcoexist)
{
- u8 wifi_rssi_state, bt_rssi_state, bt_info_ext;
u32 wifi_bw;
+ u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
+ u8 ap_num = 0;
- bt_info_ext = coex_sta->bt_info_ext;
wifi_rssi_state = btc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
- bt_rssi_state = btc8821a2ant_bt_rssi_state(btcoexist, 2, 35, 0);
+ wifi_rssi_state1 = btc8821a2ant_wifi_rssi_state(btcoexist, 1, 2,
+ BT_8821A_2ANT_WIFI_RSSI_COEXSWITCH_THRES, 0);
+ bt_rssi_state = btc8821a2ant_bt_rssi_state(btcoexist,
+ 3, BT_8821A_2ANT_BT_RSSI_COEXSWITCH_THRES, 37);
- if (BTC_RSSI_HIGH(bt_rssi_state))
- btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true);
- else
- btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false);
+ btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+
+ btc8821a2ant_limited_rx(btcoexist, NORMAL_EXEC, false, true, 0x5);
+ btc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+ if (wifi_bw == BTC_WIFI_BW_LEGACY) {
+ if (BTC_RSSI_HIGH(bt_rssi_state))
+ btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+ else if (BTC_RSSI_MEDIUM(bt_rssi_state))
+ btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+ else
+ btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ } else {
+ /* only 802.11N mode we have to dec bt power to 4 degree */
+ if (BTC_RSSI_HIGH(bt_rssi_state)) {
+ btcoexist->btc_get(btcoexist, BTC_GET_U1_AP_NUM,
+ &ap_num);
+ if (ap_num < 10)
+ btc8821a2ant_dec_bt_pwr(btcoexist,
+ NORMAL_EXEC, 4);
+ else
+ btc8821a2ant_dec_bt_pwr(btcoexist,
+ NORMAL_EXEC, 2);
+ } else if (BTC_RSSI_MEDIUM(bt_rssi_state)) {
+ btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+ } else {
+ btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+ }
+ }
if (wifi_bw == BTC_WIFI_BW_LEGACY) {
btc8821a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 7);
@@ -3354,36 +3346,15 @@ static void btc8821a2ant_action_hid_a2dp(struct btc_coexist *btcoexist)
0x4);
}
- if (BTC_WIFI_BW_HT40 == wifi_bw) {
- /* fw mechanism */
- if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
- (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
- if (bt_info_ext & BIT0) {
- /* a2dp basic rate */
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, true,
- 2);
- } else {
- /* a2dp edr rate */
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, true,
- 2);
- }
- } else {
- if (bt_info_ext & BIT0) {
- /* a2dp basic rate */
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, true,
- 2);
- } else {
- /* a2dp edr rate */
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, true,
- 2);
- }
- }
+ if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
+ (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
+ btc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 23);
+ } else {
+ btc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 23);
+ }
- /* sw mechanism */
+ /* sw mechanism */
+ if (wifi_bw == BTC_WIFI_BW_HT40) {
if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) ||
(wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
btc8821a2ant_sw_mechanism1(btcoexist, true, true,
@@ -3397,36 +3368,6 @@ static void btc8821a2ant_action_hid_a2dp(struct btc_coexist *btcoexist)
false, 0x18);
}
} else {
- /* fw mechanism */
- if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
- (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
- if (bt_info_ext & BIT0) {
- /* a2dp basic rate */
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, true,
- 2);
-
- } else {
- /* a2dp edr rate */
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, true,
- 2);
- }
- } else {
- if (bt_info_ext & BIT0) {
- /*a2dp basic rate*/
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, true,
- 2);
- } else {
- /*a2dp edr rate*/
- btc8821a2ant_tdma_duration_adjust(btcoexist,
- true, true,
- 2);
- }
- }
-
- /* sw mechanism */
if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) ||
(wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
btc8821a2ant_sw_mechanism1(btcoexist, false, true,
@@ -3544,14 +3485,14 @@ static void btc8821a2ant_run_coexist_mechanism(struct btc_coexist *btcoexist)
if (btc8821a2ant_is_common_action(btcoexist)) {
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], Action 2-Ant common\n");
- coex_dm->reset_tdma_adjust = true;
+ coex_dm->auto_tdma_adjust = true;
} else {
if (coex_dm->cur_algorithm != coex_dm->pre_algorithm) {
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], pre_algorithm = %d, cur_algorithm = %d\n",
coex_dm->pre_algorithm,
coex_dm->cur_algorithm);
- coex_dm->reset_tdma_adjust = true;
+ coex_dm->auto_tdma_adjust = false;
}
switch (coex_dm->cur_algorithm) {
case BT_8821A_2ANT_COEX_ALGO_SCO:
@@ -3614,6 +3555,26 @@ static void btc8821a2ant_run_coexist_mechanism(struct btc_coexist *btcoexist)
}
}
+static void btc8821a2ant_wifi_off_hw_cfg(struct btc_coexist *btcoexist)
+{
+ u8 h2c_parameter[2] = {0};
+ u32 fw_ver = 0;
+
+ /* set wlan_act to low */
+ btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4);
+
+ /* WiFi goto standby while GNT_BT 0-->1 */
+ btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x780);
+ btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver);
+ if (fw_ver >= 0x180000) {
+ /* Use H2C to set GNT_BT to HIGH */
+ h2c_parameter[0] = 1;
+ btcoexist->btc_fill_h2c(btcoexist, 0x6E, 1, h2c_parameter);
+ } else {
+ btcoexist->btc_write_1byte(btcoexist, 0x765, 0x18);
+ }
+}
+
/**************************************************************
* extern function start with ex_btc8821a2ant_
**************************************************************/
@@ -3637,6 +3598,7 @@ void ex_btc8821a2ant_init_hwconfig(struct btc_coexist *btcoexist)
/* Antenna config */
btc8821a2ant_set_ant_path(btcoexist, BTC_ANT_WIFI_AT_MAIN, true, false);
+ coex_sta->dis_ver_info_cnt = 0;
/* PTA parameter */
btc8821a2ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0);
@@ -3648,6 +3610,43 @@ void ex_btc8821a2ant_init_hwconfig(struct btc_coexist *btcoexist)
btcoexist->btc_write_1byte_bitmask(btcoexist, 0x40, 0x20, 0x1);
}
+void ex_btc8821a2ant_pre_load_firmware(struct btc_coexist *btcoexist)
+{
+ struct btc_board_info *board_info = &btcoexist->board_info;
+ u8 u8tmp = 0x4; /* Set BIT2 by default since it's 2ant case */
+
+ /**
+ * S0 or S1 setting and Local register setting(By the setting fw can get
+ * ant number, S0/S1, ... info)
+ *
+ * Local setting bit define
+ * BIT0: "0" for no antenna inverse; "1" for antenna inverse
+ * BIT1: "0" for internal switch; "1" for external switch
+ * BIT2: "0" for one antenna; "1" for two antenna
+ * NOTE: here default all internal switch and 1-antenna ==> BIT1=0 and
+ * BIT2=0
+ */
+ if (btcoexist->chip_interface == BTC_INTF_USB) {
+ /* fixed at S0 for USB interface */
+ u8tmp |= 0x1; /* antenna inverse */
+ btcoexist->btc_write_local_reg_1byte(btcoexist, 0xfe08, u8tmp);
+ } else {
+ /* for PCIE and SDIO interface, we check efuse 0xc3[6] */
+ if (board_info->single_ant_path == 0) {
+ } else if (board_info->single_ant_path == 1) {
+ /* set to S0 */
+ u8tmp |= 0x1; /* antenna inverse */
+ }
+
+ if (btcoexist->chip_interface == BTC_INTF_PCI)
+ btcoexist->btc_write_local_reg_1byte(btcoexist, 0x384,
+ u8tmp);
+ else if (btcoexist->chip_interface == BTC_INTF_SDIO)
+ btcoexist->btc_write_local_reg_1byte(btcoexist, 0x60,
+ u8tmp);
+ }
+}
+
void ex_btc8821a2ant_init_coex_dm(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -3748,14 +3747,6 @@ void ex_btc8821a2ant_display_coex_info(struct btc_coexist *btcoexist)
((BTC_WIFI_TRAFFIC_TX == wifi_traffic_dir) ?
"uplink" : "downlink")));
- RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "\r\n %-35s = [%s/ %d/ %d] ", "BT [status/ rssi/ retryCnt]",
- ((coex_sta->c2h_bt_inquiry_page) ? ("inquiry/page scan") :
- ((BT_8821A_2ANT_BT_STATUS_IDLE == coex_dm->bt_status)
- ? "idle" : ((BT_8821A_2ANT_BT_STATUS_CON_IDLE ==
- coex_dm->bt_status) ? "connected-idle" : "busy"))),
- coex_sta->bt_rssi, coex_sta->bt_retry_cnt);
-
if (stack_info->profile_notified) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
"\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP",
@@ -3791,11 +3782,6 @@ void ex_btc8821a2ant_display_coex_info(struct btc_coexist *btcoexist)
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s",
"============[Sw mechanism]============");
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "\r\n %-35s = %d/ %d/ %d/ %d ",
- "SM1[ShRf/ LpRA/ LimDig/ btLna]",
- coex_dm->cur_rf_rx_lpf_shrink, coex_dm->cur_low_penalty_ra,
- coex_dm->limited_dig, coex_dm->cur_bt_lna_constrain);
- RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
"\r\n %-35s = %d/ %d/ %d(0x%x) ",
"SM2[AgcT/ AdcB/ SwDacSwing(lvl)]",
coex_dm->cur_agc_table_en, coex_dm->cur_adc_back_off,
@@ -3900,11 +3886,16 @@ void ex_btc8821a2ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], IPS ENTER notify\n");
coex_sta->under_ips = true;
+ btc8821a2ant_wifi_off_hw_cfg(btcoexist);
+ btc8821a2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true);
btc8821a2ant_coex_all_off(btcoexist);
} else if (BTC_IPS_LEAVE == type) {
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], IPS LEAVE notify\n");
coex_sta->under_ips = false;
+ ex_btc8821a2ant_init_hwconfig(btcoexist);
+ btc8821a2ant_init_coex_dm(btcoexist);
+ btc8821a2ant_query_bt_info(btcoexist);
}
}
@@ -4016,9 +4007,12 @@ void ex_btc8821a2ant_bt_info_notify(struct btc_coexist *btcoexist,
u8 bt_info = 0;
u8 i, rsp_source = 0;
bool bt_busy = false, limited_dig = false;
- bool wifi_connected = false, bt_hs_on = false;
+ bool wifi_connected = false, wifi_under_5g = false;
coex_sta->c2h_bt_info_req_sent = false;
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g);
+ btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
+ &wifi_connected);
rsp_source = tmp_buf[0] & 0xf;
if (rsp_source >= BT_INFO_SRC_8821A_2ANT_MAX)
@@ -4041,16 +4035,35 @@ void ex_btc8821a2ant_bt_info_notify(struct btc_coexist *btcoexist,
}
}
+ if (btcoexist->manual_control) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], BtInfoNotify(), return for Manual CTRL<===\n");
+ return;
+ }
+
if (BT_INFO_SRC_8821A_2ANT_WIFI_FW != rsp_source) {
/* [3:0] */
coex_sta->bt_retry_cnt =
coex_sta->bt_info_c2h[rsp_source][2]&0xf;
coex_sta->bt_rssi =
- coex_sta->bt_info_c2h[rsp_source][3]*2+10;
+ coex_sta->bt_info_c2h[rsp_source][3] * 2 + 10;
- coex_sta->bt_info_ext =
- coex_sta->bt_info_c2h[rsp_source][4];
+ coex_sta->bt_info_ext = coex_sta->bt_info_c2h[rsp_source][4];
+
+ coex_sta->bt_tx_rx_mask =
+ (coex_sta->bt_info_c2h[rsp_source][2] & 0x40);
+ btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TX_RX_MASK,
+ &coex_sta->bt_tx_rx_mask);
+ if (coex_sta->bt_tx_rx_mask) {
+ /* BT into is responded by BT FW and BT RF REG 0x3C !=
+ * 0x01 => Need to switch BT TRx Mask
+ */
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], Switch BT TRx Mask since BT RF REG 0x3C != 0x01\n");
+ btcoexist->btc_set_bt_reg(btcoexist, BTC_BT_REG_RF,
+ 0x3c, 0x01);
+ }
/* Here we need to resend some wifi info to BT
* because bt is reset and loss of the info
@@ -4068,70 +4081,121 @@ void ex_btc8821a2ant_bt_info_notify(struct btc_coexist *btcoexist,
}
- if ((coex_sta->bt_info_ext & BIT3)) {
- btc8821a2ant_ignore_wlan_act(btcoexist,
- FORCE_EXEC, false);
- } else {
- /* BT already NOT ignore Wlan active, do nothing here.*/
+ if (!btcoexist->manual_control && !wifi_under_5g) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], BT ext info = 0x%x!!\n",
+ coex_sta->bt_info_ext);
+ if ((coex_sta->bt_info_ext & BIT(3))) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], BT ext info bit3=1, wifi_connected=%d\n",
+ wifi_connected);
+ if (wifi_connected) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST,
+ DBG_LOUD,
+ "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n");
+ btc8821a2ant_ignore_wlan_act(btcoexist,
+ FORCE_EXEC,
+ false);
+ }
+ } else {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], BT ext info bit3=0, wifi_connected=%d\n",
+ wifi_connected);
+ /* BT already NOT ignore Wlan active, do nothing
+ * here.
+ */
+ if (!wifi_connected) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST,
+ DBG_LOUD,
+ "[BTCoex], BT ext info bit3 check, set BT to ignore Wlan active!!\n");
+ btc8821a2ant_ignore_wlan_act(
+ btcoexist, FORCE_EXEC, true);
+ }
+ }
}
}
- btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on);
/* check BIT2 first ==> check if bt is under inquiry or page scan*/
if (bt_info & BT_INFO_8821A_2ANT_B_INQ_PAGE) {
coex_sta->c2h_bt_inquiry_page = true;
- coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_NON_IDLE;
} else {
coex_sta->c2h_bt_inquiry_page = false;
- if (bt_info == 0x1) {
- /* connection exists but not busy*/
- coex_sta->bt_link_exist = true;
- coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_CON_IDLE;
- } else if (bt_info & BT_INFO_8821A_2ANT_B_CONNECTION) {
- /* connection exists and some link is busy*/
- coex_sta->bt_link_exist = true;
- if (bt_info & BT_INFO_8821A_2ANT_B_FTP)
- coex_sta->pan_exist = true;
- else
- coex_sta->pan_exist = false;
- if (bt_info & BT_INFO_8821A_2ANT_B_A2DP)
- coex_sta->a2dp_exist = true;
- else
- coex_sta->a2dp_exist = false;
- if (bt_info & BT_INFO_8821A_2ANT_B_HID)
- coex_sta->hid_exist = true;
- else
- coex_sta->hid_exist = false;
- if (bt_info & BT_INFO_8821A_2ANT_B_SCO_ESCO)
- coex_sta->sco_exist = true;
- else
- coex_sta->sco_exist = false;
- coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_NON_IDLE;
- } else {
- coex_sta->bt_link_exist = false;
+ }
+ /* set link exist status */
+ if (!(bt_info & BT_INFO_8821A_2ANT_B_CONNECTION)) {
+ coex_sta->bt_link_exist = false;
+ coex_sta->pan_exist = false;
+ coex_sta->a2dp_exist = false;
+ coex_sta->hid_exist = false;
+ coex_sta->sco_exist = false;
+ } else { /* connection exists */
+ coex_sta->bt_link_exist = true;
+ if (bt_info & BT_INFO_8821A_2ANT_B_FTP)
+ coex_sta->pan_exist = true;
+ else
coex_sta->pan_exist = false;
+ if (bt_info & BT_INFO_8821A_2ANT_B_A2DP)
+ coex_sta->a2dp_exist = true;
+ else
coex_sta->a2dp_exist = false;
+ if (bt_info & BT_INFO_8821A_2ANT_B_HID)
+ coex_sta->hid_exist = true;
+ else
coex_sta->hid_exist = false;
+ if (bt_info & BT_INFO_8821A_2ANT_B_SCO_ESCO)
+ coex_sta->sco_exist = true;
+ else
coex_sta->sco_exist = false;
- coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_IDLE;
+
+ if ((!coex_sta->hid_exist) &&
+ (!coex_sta->c2h_bt_inquiry_page) &&
+ (!coex_sta->sco_exist)) {
+ if (coex_sta->high_priority_tx +
+ coex_sta->high_priority_rx >= 160)
+ coex_sta->hid_exist = true;
}
+ }
- btc8821a2ant_update_bt_link_info(btcoexist);
+ btc8821a2ant_update_bt_link_info(btcoexist);
+
+ if (!(bt_info & BT_INFO_8821A_2ANT_B_CONNECTION)) {
+ coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_IDLE;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], BtInfoNotify(), BT Non-Connected idle!!!\n");
+ } else if (bt_info == BT_INFO_8821A_2ANT_B_CONNECTION) {
+ /* connection exists but no busy */
+ coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_CON_IDLE;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n");
+ } else if ((bt_info & BT_INFO_8821A_2ANT_B_SCO_ESCO) ||
+ (bt_info & BT_INFO_8821A_2ANT_B_SCO_BUSY)) {
+ coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_SCO_BUSY;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n");
+ } else if (bt_info & BT_INFO_8821A_2ANT_B_ACL_BUSY) {
+ coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_ACL_BUSY;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n");
+ } else {
+ coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_MAX;
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], BtInfoNotify(), BT Non-Defined state!!!\n");
}
- if (BT_8821A_2ANT_BT_STATUS_NON_IDLE == coex_dm->bt_status)
+ if ((coex_dm->bt_status == BT_8821A_2ANT_BT_STATUS_ACL_BUSY) ||
+ (coex_dm->bt_status == BT_8821A_2ANT_BT_STATUS_SCO_BUSY) ||
+ (coex_dm->bt_status == BT_8821A_2ANT_BT_STATUS_ACL_SCO_BUSY)) {
bt_busy = true;
- else
+ limited_dig = true;
+ } else {
bt_busy = false;
+ limited_dig = false;
+ }
+
btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy);
- if (BT_8821A_2ANT_BT_STATUS_IDLE != coex_dm->bt_status)
- limited_dig = true;
- else
- limited_dig = false;
coex_dm->limited_dig = limited_dig;
- btcoexist->btc_set(btcoexist,
- BTC_SET_BL_BT_LIMITED_DIG, &limited_dig);
+ btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_LIMITED_DIG, &limited_dig);
btc8821a2ant_run_coexist_mechanism(btcoexist);
}
@@ -4143,46 +4207,57 @@ void ex_btc8821a2ant_halt_notify(struct btc_coexist *btcoexist)
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], Halt notify\n");
+ btc8821a2ant_wifi_off_hw_cfg(btcoexist);
btc8821a2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true);
ex_btc8821a2ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT);
}
+void ex_btc8821a2ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
+{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD, "[BTCoex], Pnp notify\n");
+
+ if (pnp_state == BTC_WIFI_PNP_SLEEP) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], Pnp notify to SLEEP\n");
+ } else if (pnp_state == BTC_WIFI_PNP_WAKE_UP) {
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], Pnp notify to WAKE UP\n");
+ ex_btc8821a2ant_init_hwconfig(btcoexist);
+ btc8821a2ant_init_coex_dm(btcoexist);
+ btc8821a2ant_query_bt_info(btcoexist);
+ }
+}
+
void ex_btc8821a2ant_periodical(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
- static u8 dis_ver_info_cnt;
- struct btc_board_info *board_info = &btcoexist->board_info;
- struct btc_stack_info *stack_info = &btcoexist->stack_info;
- u32 fw_ver = 0, bt_patch_ver = 0;
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"[BTCoex], ==========================Periodical===========================\n");
- if (dis_ver_info_cnt <= 5) {
- dis_ver_info_cnt += 1;
- RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], ****************************************************************\n");
- RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n",
- board_info->pg_ant_num,
- board_info->btdm_ant_num,
- board_info->btdm_ant_pos);
- RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], BT stack/ hci ext ver = %s / %d\n",
- stack_info->profile_notified ? "Yes" : "No",
- stack_info->hci_version);
- btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER,
- &bt_patch_ver);
- btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver);
- RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n",
- glcoex_ver_date_8821a_2ant, glcoex_ver_8821a_2ant,
- fw_ver, bt_patch_ver, bt_patch_ver);
- RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], ****************************************************************\n");
+ if (coex_sta->dis_ver_info_cnt <= 5) {
+ coex_sta->dis_ver_info_cnt += 1;
+ if (coex_sta->dis_ver_info_cnt == 3) {
+ /* Antenna config to set 0x765 = 0x0 (GNT_BT control by
+ * PTA) after initial
+ */
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], Set GNT_BT control by PTA\n");
+ btc8821a2ant_set_ant_path(btcoexist,
+ BTC_ANT_WIFI_AT_MAIN, false, false);
+ }
}
- btc8821a2ant_query_bt_info(btcoexist);
- btc8821a2ant_monitor_bt_ctr(btcoexist);
- btc8821a2ant_monitor_wifi_ctr(btcoexist);
+ if (btcoexist->auto_report_2ant) {
+ btc8821a2ant_query_bt_info(btcoexist);
+ } else {
+ btc8821a2ant_monitor_bt_ctr(btcoexist);
+ btc8821a2ant_monitor_wifi_ctr(btcoexist);
+
+ if (btc8821a2ant_is_wifi_status_changed(btcoexist) ||
+ coex_dm->auto_tdma_adjust)
+ btc8821a2ant_run_coexist_mechanism(btcoexist);
+ }
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h
index 535ca10..a839d55 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h
@@ -54,6 +54,9 @@ enum _BT_8821A_2ANT_BT_STATUS {
BT_8821A_2ANT_BT_STATUS_IDLE = 0x0,
BT_8821A_2ANT_BT_STATUS_CON_IDLE = 0x1,
BT_8821A_2ANT_BT_STATUS_NON_IDLE = 0x2,
+ BT_8821A_2ANT_BT_STATUS_ACL_BUSY = 0x3,
+ BT_8821A_2ANT_BT_STATUS_SCO_BUSY = 0x4,
+ BT_8821A_2ANT_BT_STATUS_ACL_SCO_BUSY = 0x5,
BT_8821A_2ANT_BT_STATUS_MAX
};
@@ -76,10 +79,6 @@ struct coex_dm_8821a_2ant {
/* fw mechanism */
bool pre_dec_bt_pwr_lvl;
bool cur_dec_bt_pwr_lvl;
- bool pre_bt_lna_constrain;
- bool cur_bt_lna_constrain;
- u8 pre_bt_psd_mode;
- u8 cur_bt_psd_mode;
u8 pre_fw_dac_swing_lvl;
u8 cur_fw_dac_swing_lvl;
bool cur_ignore_wlan_act;
@@ -143,6 +142,7 @@ struct coex_sta_8821a_2ant {
u32 low_priority_tx;
u32 low_priority_rx;
u8 bt_rssi;
+ bool bt_tx_rx_mask;
u8 pre_bt_rssi_state;
u8 pre_wifi_rssi_state[4];
bool c2h_bt_info_req_sent;
@@ -164,6 +164,8 @@ struct coex_sta_8821a_2ant {
u8 coex_table_type;
bool force_lps_on;
+
+ u8 dis_ver_info_cnt;
};
/*===========================================
@@ -171,58 +173,60 @@ struct coex_sta_8821a_2ant {
*===========================================
*/
void
-ex_halbtc8821a2ant_init_hwconfig(
+ex_btc8821a2ant_init_hwconfig(
struct btc_coexist *btcoexist
);
void
-ex_halbtc8821a2ant_init_coex_dm(
+ex_btc8821a2ant_init_coex_dm(
struct btc_coexist *btcoexist
);
void
-ex_halbtc8821a2ant_ips_notify(
+ex_btc8821a2ant_ips_notify(
struct btc_coexist *btcoexist,
u8 type
);
void
-ex_halbtc8821a2ant_lps_notify(
+ex_btc8821a2ant_lps_notify(
struct btc_coexist *btcoexist,
u8 type
);
void
-ex_halbtc8821a2ant_scan_notify(
+ex_btc8821a2ant_scan_notify(
struct btc_coexist *btcoexist,
u8 type
);
void
-ex_halbtc8821a2ant_connect_notify(
+ex_btc8821a2ant_connect_notify(
struct btc_coexist *btcoexist,
u8 type
);
void
-ex_halbtc8821a2ant_media_status_notify(
+ex_btc8821a2ant_media_status_notify(
struct btc_coexist *btcoexist,
u8 type
);
void
-ex_halbtc8821a2ant_special_packet_notify(
+ex_btc8821a2ant_special_packet_notify(
struct btc_coexist *btcoexist,
u8 type
);
void
-ex_halbtc8821a2ant_bt_info_notify(
+ex_btc8821a2ant_bt_info_notify(
struct btc_coexist *btcoexist,
u8 *tmp_buf,
u8 length
);
void
-ex_halbtc8821a2ant_halt_notify(
+ex_btc8821a2ant_halt_notify(
struct btc_coexist *btcoexist
);
void
-ex_halbtc8821a2ant_periodical(
+ex_btc8821a2ant_periodical(
struct btc_coexist *btcoexist
);
void
-ex_halbtc8821a2ant_display_coex_info(
+ex_btc8821a2ant_display_coex_info(
struct btc_coexist *btcoexist
);
+void ex_btc8821a2ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state);
+void ex_btc8821a2ant_pre_load_firmware(struct btc_coexist *btcoexist);
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
index f130006..e6024b0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
@@ -36,6 +36,20 @@ u32 btc_dbg_type[BTC_MSG_MAX];
/***************************************************
* Debug related function
***************************************************/
+
+const char *const gl_btc_wifi_bw_string[] = {
+ "11bg",
+ "HT20",
+ "HT40",
+ "HT80",
+ "HT160"
+};
+
+const char *const gl_btc_wifi_freq_string[] = {
+ "2.4G",
+ "5G"
+};
+
static bool halbtc_is_bt_coexist_available(struct btc_coexist *btcoexist)
{
if (!btcoexist->binded || NULL == btcoexist->adapter)
@@ -54,28 +68,39 @@ static bool halbtc_is_wifi_busy(struct rtl_priv *rtlpriv)
static void halbtc_dbg_init(void)
{
- u8 i;
-
- for (i = 0; i < BTC_MSG_MAX; i++)
- btc_dbg_type[i] = 0;
-
- btc_dbg_type[BTC_MSG_INTERFACE] =
-/* INTF_INIT | */
-/* INTF_NOTIFY | */
- 0;
+}
- btc_dbg_type[BTC_MSG_ALGORITHM] =
-/* ALGO_BT_RSSI_STATE | */
-/* ALGO_WIFI_RSSI_STATE | */
-/* ALGO_BT_MONITOR | */
-/* ALGO_TRACE | */
-/* ALGO_TRACE_FW | */
-/* ALGO_TRACE_FW_DETAIL | */
-/* ALGO_TRACE_FW_EXEC | */
-/* ALGO_TRACE_SW | */
-/* ALGO_TRACE_SW_DETAIL | */
-/* ALGO_TRACE_SW_EXEC | */
- 0;
+/***************************************************
+ * helper function
+ ***************************************************/
+static bool is_any_client_connect_to_ap(struct btc_coexist *btcoexist)
+{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct rtl_mac *mac = rtl_mac(rtlpriv);
+ struct rtl_sta_info *drv_priv;
+ u8 cnt = 0;
+
+ if (mac->opmode == NL80211_IFTYPE_ADHOC ||
+ mac->opmode == NL80211_IFTYPE_MESH_POINT ||
+ mac->opmode == NL80211_IFTYPE_AP) {
+ if (in_interrupt() > 0) {
+ list_for_each_entry(drv_priv, &rtlpriv->entry_list,
+ list) {
+ cnt++;
+ }
+ } else {
+ spin_lock_bh(&rtlpriv->locks.entry_list_lock);
+ list_for_each_entry(drv_priv, &rtlpriv->entry_list,
+ list) {
+ cnt++;
+ }
+ spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
+ }
+ }
+ if (cnt > 0)
+ return true;
+ else
+ return false;
}
static bool halbtc_is_bt40(struct rtl_priv *adapter)
@@ -188,12 +213,14 @@ static void halbtc_leave_lps(struct btc_coexist *btcoexist)
&ap_enable);
if (ap_enable) {
- pr_info("halbtc_leave_lps()<--dont leave lps under AP mode\n");
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "%s()<--dont leave lps under AP mode\n", __func__);
return;
}
btcoexist->bt_info.bt_ctrl_lps = true;
btcoexist->bt_info.bt_lps_on = false;
+ rtl_lps_leave(rtlpriv->mac80211.hw);
}
static void halbtc_enter_lps(struct btc_coexist *btcoexist)
@@ -209,36 +236,93 @@ static void halbtc_enter_lps(struct btc_coexist *btcoexist)
&ap_enable);
if (ap_enable) {
- pr_info("halbtc_enter_lps()<--dont enter lps under AP mode\n");
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+ "%s()<--dont enter lps under AP mode\n", __func__);
return;
}
btcoexist->bt_info.bt_ctrl_lps = true;
- btcoexist->bt_info.bt_lps_on = false;
+ btcoexist->bt_info.bt_lps_on = true;
+ rtl_lps_enter(rtlpriv->mac80211.hw);
}
static void halbtc_normal_lps(struct btc_coexist *btcoexist)
{
+ struct rtl_priv *rtlpriv;
+
+ rtlpriv = btcoexist->adapter;
+
if (btcoexist->bt_info.bt_ctrl_lps) {
btcoexist->bt_info.bt_lps_on = false;
+ rtl_lps_leave(rtlpriv->mac80211.hw);
btcoexist->bt_info.bt_ctrl_lps = false;
}
}
-static void halbtc_leave_low_power(void)
+static void halbtc_leave_low_power(struct btc_coexist *btcoexist)
{
}
-static void halbtc_nomal_low_power(void)
+static void halbtc_normal_low_power(struct btc_coexist *btcoexist)
{
}
-static void halbtc_disable_low_power(void)
+static void halbtc_disable_low_power(struct btc_coexist *btcoexist,
+ bool low_pwr_disable)
{
+ /* TODO: original/leave 32k low power */
+ btcoexist->bt_info.bt_disable_low_pwr = low_pwr_disable;
}
-static void halbtc_aggregation_check(void)
+static void halbtc_aggregation_check(struct btc_coexist *btcoexist)
{
+ bool need_to_act = false;
+ static unsigned long pre_time;
+ unsigned long cur_time = 0;
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+
+ /* To void continuous deleteBA=>addBA=>deleteBA=>addBA
+ * This function is not allowed to continuous called
+ * It can only be called after 8 seconds
+ */
+
+ cur_time = jiffies;
+ if (jiffies_to_msecs(cur_time - pre_time) <= 8000) {
+ /* over 8 seconds you can execute this function again. */
+ return;
+ }
+ pre_time = cur_time;
+
+ if (btcoexist->bt_info.reject_agg_pkt) {
+ need_to_act = true;
+ btcoexist->bt_info.pre_reject_agg_pkt =
+ btcoexist->bt_info.reject_agg_pkt;
+ } else {
+ if (btcoexist->bt_info.pre_reject_agg_pkt) {
+ need_to_act = true;
+ btcoexist->bt_info.pre_reject_agg_pkt =
+ btcoexist->bt_info.reject_agg_pkt;
+ }
+
+ if (btcoexist->bt_info.pre_bt_ctrl_agg_buf_size !=
+ btcoexist->bt_info.bt_ctrl_agg_buf_size) {
+ need_to_act = true;
+ btcoexist->bt_info.pre_bt_ctrl_agg_buf_size =
+ btcoexist->bt_info.bt_ctrl_agg_buf_size;
+ }
+
+ if (btcoexist->bt_info.bt_ctrl_agg_buf_size) {
+ if (btcoexist->bt_info.pre_agg_buf_size !=
+ btcoexist->bt_info.agg_buf_size) {
+ need_to_act = true;
+ }
+ btcoexist->bt_info.pre_agg_buf_size =
+ btcoexist->bt_info.agg_buf_size;
+ }
+
+ if (need_to_act)
+ rtl_rx_ampdu_apply(rtlpriv);
+ }
}
static u32 halbtc_get_bt_patch_version(struct btc_coexist *btcoexist)
@@ -246,10 +330,37 @@ static u32 halbtc_get_bt_patch_version(struct btc_coexist *btcoexist)
return 0;
}
-static s32 halbtc_get_wifi_rssi(struct rtl_priv *adapter)
+u32 halbtc_get_wifi_link_status(struct btc_coexist *btcoexist)
{
- struct rtl_priv *rtlpriv = adapter;
- s32 undec_sm_pwdb = 0;
+ /* return value:
+ * [31:16] => connected port number
+ * [15:0] => port connected bit define
+ */
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct rtl_mac *mac = rtl_mac(rtlpriv);
+ u32 ret_val = 0;
+ u32 port_connected_status = 0, num_of_connected_port = 0;
+
+ if (mac->opmode == NL80211_IFTYPE_STATION &&
+ mac->link_state >= MAC80211_LINKED) {
+ port_connected_status |= WIFI_STA_CONNECTED;
+ num_of_connected_port++;
+ }
+ /* AP & ADHOC & MESH */
+ if (is_any_client_connect_to_ap(btcoexist)) {
+ port_connected_status |= WIFI_AP_CONNECTED;
+ num_of_connected_port++;
+ }
+ /* TODO: P2P Connected Status */
+
+ ret_val = (num_of_connected_port << 16) | port_connected_status;
+
+ return ret_val;
+}
+
+static s32 halbtc_get_wifi_rssi(struct rtl_priv *rtlpriv)
+{
+ int undec_sm_pwdb = 0;
if (rtlpriv->mac80211.link_state >= MAC80211_LINKED)
undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
@@ -270,6 +381,7 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
u32 *u32_tmp = (u32 *)out_buf;
u8 *u8_tmp = (u8 *)out_buf;
bool tmp = false;
+ bool ret = true;
if (!halbtc_is_bt_coexist_available(btcoexist))
return false;
@@ -277,12 +389,17 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
switch (get_type) {
case BTC_GET_BL_HS_OPERATION:
*bool_tmp = false;
+ ret = false;
break;
case BTC_GET_BL_HS_CONNECTING:
*bool_tmp = false;
+ ret = false;
break;
case BTC_GET_BL_WIFI_CONNECTED:
- if (rtlpriv->mac80211.link_state >= MAC80211_LINKED)
+ if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
+ rtlpriv->mac80211.link_state >= MAC80211_LINKED)
+ tmp = true;
+ if (is_any_client_connect_to_ap(btcoexist))
tmp = true;
*bool_tmp = tmp;
break;
@@ -304,32 +421,26 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
else
*bool_tmp = false;
break;
- case BTC_GET_BL_WIFI_ROAM: /*TODO*/
+ case BTC_GET_BL_WIFI_ROAM:
if (mac->link_state == MAC80211_LINKING)
*bool_tmp = true;
else
*bool_tmp = false;
break;
- case BTC_GET_BL_WIFI_4_WAY_PROGRESS: /*TODO*/
- *bool_tmp = false;
-
+ case BTC_GET_BL_WIFI_4_WAY_PROGRESS:
+ *bool_tmp = rtlpriv->btcoexist.btc_info.in_4way;
break;
case BTC_GET_BL_WIFI_UNDER_5G:
- *bool_tmp = false; /*TODO*/
-
- case BTC_GET_BL_WIFI_DHCP: /*TODO*/
- break;
- case BTC_GET_BL_WIFI_SOFTAP_IDLE:
- *bool_tmp = true;
- break;
- case BTC_GET_BL_WIFI_SOFTAP_LINKING:
- *bool_tmp = false;
- break;
- case BTC_GET_BL_WIFI_IN_EARLY_SUSPEND:
- *bool_tmp = false;
+ if (rtlhal->current_bandtype == BAND_ON_5G)
+ *bool_tmp = true;
+ else
+ *bool_tmp = false;
break;
case BTC_GET_BL_WIFI_AP_MODE_ENABLE:
- *bool_tmp = false;
+ if (mac->opmode == NL80211_IFTYPE_AP)
+ *bool_tmp = true;
+ else
+ *bool_tmp = false;
break;
case BTC_GET_BL_WIFI_ENABLE_ENCRYPTION:
if (NO_ENCRYPTION == rtlpriv->sec.pairwise_enc_algorithm)
@@ -338,16 +449,26 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
*bool_tmp = true;
break;
case BTC_GET_BL_WIFI_UNDER_B_MODE:
- *bool_tmp = false; /*TODO*/
+ if (rtlpriv->mac80211.mode == WIRELESS_MODE_B)
+ *bool_tmp = true;
+ else
+ *bool_tmp = false;
break;
case BTC_GET_BL_EXT_SWITCH:
*bool_tmp = false;
break;
+ case BTC_GET_BL_WIFI_IS_IN_MP_MODE:
+ *bool_tmp = false;
+ break;
+ case BTC_GET_BL_IS_ASUS_8723B:
+ *bool_tmp = false;
+ break;
case BTC_GET_S4_WIFI_RSSI:
*s32_tmp = halbtc_get_wifi_rssi(rtlpriv);
break;
- case BTC_GET_S4_HS_RSSI: /*TODO*/
- *s32_tmp = halbtc_get_wifi_rssi(rtlpriv);
+ case BTC_GET_S4_HS_RSSI:
+ *s32_tmp = 0;
+ ret = false;
break;
case BTC_GET_U4_WIFI_BW:
*u32_tmp = halbtc_get_wifi_bw(btcoexist);
@@ -359,7 +480,10 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
*u32_tmp = BTC_WIFI_TRAFFIC_RX;
break;
case BTC_GET_U4_WIFI_FW_VER:
- *u32_tmp = rtlhal->fw_version;
+ *u32_tmp = (rtlhal->fw_version << 16) | rtlhal->fw_subversion;
+ break;
+ case BTC_GET_U4_WIFI_LINK_STATUS:
+ *u32_tmp = halbtc_get_wifi_link_status(btcoexist);
break;
case BTC_GET_U4_BT_PATCH_VER:
*u32_tmp = halbtc_get_bt_patch_version(btcoexist);
@@ -374,10 +498,17 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
*u8_tmp = halbtc_get_wifi_central_chnl(btcoexist);
break;
case BTC_GET_U1_WIFI_HS_CHNL:
- *u8_tmp = 1;/*BT_OperateChnl(rtlpriv);*/
+ *u8_tmp = 0;
+ ret = false;
break;
- case BTC_GET_U1_MAC_PHY_MODE:
- *u8_tmp = BTC_MP_UNKNOWN;
+ case BTC_GET_U1_AP_NUM:
+ *u8_tmp = rtlpriv->btcoexist.btc_info.ap_num;
+ break;
+ case BTC_GET_U1_ANT_TYPE:
+ *u8_tmp = (u8)BTC_ANT_TYPE_0;
+ break;
+ case BTC_GET_U1_IOT_PEER:
+ *u8_tmp = 0;
break;
/************* 1Ant **************/
@@ -386,10 +517,11 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
break;
default:
+ ret = false;
break;
}
- return true;
+ return ret;
}
static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf)
@@ -398,6 +530,7 @@ static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf)
bool *bool_tmp = (bool *)in_buf;
u8 *u8_tmp = (u8 *)in_buf;
u32 *u32_tmp = (u32 *)in_buf;
+ bool ret = true;
if (!halbtc_is_bt_coexist_available(btcoexist))
return false;
@@ -420,11 +553,17 @@ static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf)
btcoexist->bt_info.reject_agg_pkt = *bool_tmp;
break;
case BTC_SET_BL_BT_CTRL_AGG_SIZE:
- btcoexist->bt_info.bt_ctrl_buf_size = *bool_tmp;
+ btcoexist->bt_info.bt_ctrl_agg_buf_size = *bool_tmp;
break;
case BTC_SET_BL_INC_SCAN_DEV_NUM:
btcoexist->bt_info.increase_scan_dev_num = *bool_tmp;
break;
+ case BTC_SET_BL_BT_TX_RX_MASK:
+ btcoexist->bt_info.bt_tx_rx_mask = *bool_tmp;
+ break;
+ case BTC_SET_BL_MIRACAST_PLUS_BT:
+ btcoexist->bt_info.miracast_plus_bt = *bool_tmp;
+ break;
/* set some u1Byte type variables. */
case BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON:
btcoexist->bt_info.rssi_adjust_for_agc_table_on = *u8_tmp;
@@ -432,25 +571,25 @@ static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf)
case BTC_SET_U1_AGG_BUF_SIZE:
btcoexist->bt_info.agg_buf_size = *u8_tmp;
break;
- /* the following are some action which will be triggered */
+
+ /* the following are some action which will be triggered */
case BTC_SET_ACT_GET_BT_RSSI:
- /*BTHCI_SendGetBtRssiEvent(rtlpriv);*/
+ ret = false;
break;
case BTC_SET_ACT_AGGREGATE_CTRL:
- halbtc_aggregation_check();
+ halbtc_aggregation_check(btcoexist);
break;
- /* 1Ant */
+ /* 1Ant */
case BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE:
btcoexist->bt_info.rssi_adjust_for_1ant_coex_type = *u8_tmp;
break;
case BTC_SET_UI_SCAN_SIG_COMPENSATION:
- /* rtlpriv->mlmepriv.scan_compensation = *u8_tmp; */
break;
- case BTC_SET_U1_1ANT_LPS:
+ case BTC_SET_U1_LPS_VAL:
btcoexist->bt_info.lps_val = *u8_tmp;
break;
- case BTC_SET_U1_1ANT_RPWM:
+ case BTC_SET_U1_RPWM_VAL:
btcoexist->bt_info.rpwm_val = *u8_tmp;
break;
/* the following are some action which will be triggered */
@@ -464,41 +603,24 @@ static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf)
halbtc_normal_lps(btcoexist);
break;
case BTC_SET_ACT_DISABLE_LOW_POWER:
- halbtc_disable_low_power();
+ halbtc_disable_low_power(btcoexist, *bool_tmp);
break;
case BTC_SET_ACT_UPDATE_RAMASK:
btcoexist->bt_info.ra_mask = *u32_tmp;
break;
case BTC_SET_ACT_SEND_MIMO_PS:
break;
- case BTC_SET_ACT_INC_FORCE_EXEC_PWR_CMD_CNT:
- btcoexist->bt_info.force_exec_pwr_cmd_cnt++;
- break;
case BTC_SET_ACT_CTRL_BT_INFO: /*wait for 8812/8821*/
break;
case BTC_SET_ACT_CTRL_BT_COEX:
break;
+ case BTC_SET_ACT_CTRL_8723B_ANT:
+ break;
default:
break;
}
- return true;
-}
-
-static void halbtc_display_coex_statistics(struct btc_coexist *btcoexist)
-{
-}
-
-static void halbtc_display_bt_link_info(struct btc_coexist *btcoexist)
-{
-}
-
-static void halbtc_display_bt_fw_info(struct btc_coexist *btcoexist)
-{
-}
-
-static void halbtc_display_fw_pwr_mode_cmd(struct btc_coexist *btcoexist)
-{
+ return ret;
}
/************************************************************
@@ -574,6 +696,35 @@ static void halbtc_write_4byte(void *bt_context, u32 reg_addr, u32 data)
rtl_write_dword(rtlpriv, reg_addr, data);
}
+void halbtc_write_local_reg_1byte(void *btc_context, u32 reg_addr, u8 data)
+{
+ struct btc_coexist *btcoexist = (struct btc_coexist *)btc_context;
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+
+ if (btcoexist->chip_interface == BTC_INTF_SDIO)
+ ;
+ else if (btcoexist->chip_interface == BTC_INTF_PCI)
+ rtl_write_byte(rtlpriv, reg_addr, data);
+ else if (btcoexist->chip_interface == BTC_INTF_USB)
+ rtl_write_byte(rtlpriv, reg_addr, data);
+}
+
+void halbtc_set_macreg(void *btc_context, u32 reg_addr, u32 bit_mask, u32 data)
+{
+ struct btc_coexist *btcoexist = (struct btc_coexist *)btc_context;
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+
+ rtl_set_bbreg(rtlpriv->mac80211.hw, reg_addr, bit_mask, data);
+}
+
+u32 halbtc_get_macreg(void *btc_context, u32 reg_addr, u32 bit_mask)
+{
+ struct btc_coexist *btcoexist = (struct btc_coexist *)btc_context;
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+
+ return rtl_get_bbreg(rtlpriv->mac80211.hw, reg_addr, bit_mask);
+}
+
static void halbtc_set_bbreg(void *bt_context, u32 reg_addr, u32 bit_mask,
u32 data)
{
@@ -619,50 +770,64 @@ static void halbtc_fill_h2c_cmd(void *bt_context, u8 element_id,
cmd_len, cmd_buf);
}
-static void halbtc_display_dbg_msg(void *bt_context, u8 disp_type)
+void halbtc_set_bt_reg(void *btc_context, u8 reg_type, u32 offset, u32 set_val)
{
- struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context;
- switch (disp_type) {
- case BTC_DBG_DISP_COEX_STATISTICS:
- halbtc_display_coex_statistics(btcoexist);
- break;
- case BTC_DBG_DISP_BT_LINK_INFO:
- halbtc_display_bt_link_info(btcoexist);
- break;
- case BTC_DBG_DISP_BT_FW_VER:
- halbtc_display_bt_fw_info(btcoexist);
- break;
- case BTC_DBG_DISP_FW_PWR_MODE_CMD:
- halbtc_display_fw_pwr_mode_cmd(btcoexist);
- break;
- default:
- break;
+ struct btc_coexist *btcoexist = (struct btc_coexist *)btc_context;
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ u8 cmd_buffer1[4] = {0};
+ u8 cmd_buffer2[4] = {0};
+ u8 *addr_to_set = (u8 *)&offset;
+ u8 *value_to_set = (u8 *)&set_val;
+ u8 oper_ver = 0;
+ u8 req_num = 0;
+
+ if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ cmd_buffer1[0] |= (oper_ver & 0x0f); /* Set OperVer */
+ cmd_buffer1[0] |= ((req_num << 4) & 0xf0); /* Set ReqNum */
+ cmd_buffer1[1] = 0x0d; /* OpCode: BT_LO_OP_WRITE_REG_VALUE */
+ cmd_buffer1[2] = value_to_set[0]; /* Set WriteRegValue */
+ rtlpriv->cfg->ops->fill_h2c_cmd(rtlpriv->mac80211.hw, 0x67, 4,
+ &cmd_buffer1[0]);
+
+ msleep(200);
+ req_num++;
+
+ cmd_buffer2[0] |= (oper_ver & 0x0f); /* Set OperVer */
+ cmd_buffer2[0] |= ((req_num << 4) & 0xf0); /* Set ReqNum */
+ cmd_buffer2[1] = 0x0c; /* OpCode: BT_LO_OP_WRITE_REG_ADDR */
+ cmd_buffer2[3] = addr_to_set[0]; /* Set WriteRegAddr */
+ rtlpriv->cfg->ops->fill_h2c_cmd(rtlpriv->mac80211.hw, 0x67, 4,
+ &cmd_buffer2[0]);
}
}
+bool halbtc_under_ips(struct btc_coexist *btcoexist)
+{
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
+ enum rf_pwrstate rtstate;
+
+ if (ppsc->inactiveps) {
+ rtstate = ppsc->rfpwr_state;
+
+ if (rtstate != ERFON &&
+ ppsc->rfoff_reason == RF_CHANGE_BY_IPS) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
/*****************************************************************
* Extern functions called by other module
*****************************************************************/
-bool exhalbtc_initlize_variables(struct rtl_priv *adapter)
+bool exhalbtc_initlize_variables(void)
{
struct btc_coexist *btcoexist = &gl_bt_coexist;
- btcoexist->statistics.cnt_bind++;
-
halbtc_dbg_init();
- if (btcoexist->binded)
- return false;
- else
- btcoexist->binded = true;
-
- btcoexist->chip_interface = BTC_INTF_UNKNOWN;
-
- if (NULL == btcoexist->adapter)
- btcoexist->adapter = adapter;
-
- btcoexist->stack_info.profile_notified = false;
-
btcoexist->btc_read_1byte = halbtc_read_1byte;
btcoexist->btc_write_1byte = halbtc_write_1byte;
btcoexist->btc_write_1byte_bitmask = halbtc_bitmask_write_1byte;
@@ -670,6 +835,7 @@ bool exhalbtc_initlize_variables(struct rtl_priv *adapter)
btcoexist->btc_write_2byte = halbtc_write_2byte;
btcoexist->btc_read_4byte = halbtc_read_4byte;
btcoexist->btc_write_4byte = halbtc_write_4byte;
+ btcoexist->btc_write_local_reg_1byte = halbtc_write_local_reg_1byte;
btcoexist->btc_set_bb_reg = halbtc_set_bbreg;
btcoexist->btc_get_bb_reg = halbtc_get_bbreg;
@@ -678,10 +844,11 @@ bool exhalbtc_initlize_variables(struct rtl_priv *adapter)
btcoexist->btc_get_rf_reg = halbtc_get_rfreg;
btcoexist->btc_fill_h2c = halbtc_fill_h2c_cmd;
- btcoexist->btc_disp_dbg_msg = halbtc_display_dbg_msg;
btcoexist->btc_get = halbtc_get;
btcoexist->btc_set = halbtc_set;
+ btcoexist->btc_set_bt_reg = halbtc_set_bt_reg;
+
btcoexist->bt_info.bt_ctrl_buf_size = false;
btcoexist->bt_info.agg_buf_size = 5;
@@ -690,40 +857,148 @@ bool exhalbtc_initlize_variables(struct rtl_priv *adapter)
return true;
}
-void exhalbtc_init_hw_config(struct btc_coexist *btcoexist)
+bool exhalbtc_bind_bt_coex_withadapter(void *adapter)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ struct btc_coexist *btcoexist = &gl_bt_coexist;
+ struct rtl_priv *rtlpriv = adapter;
+ u8 ant_num = 2, chip_type, single_ant_path = 0;
+
+ if (btcoexist->binded)
+ return false;
+
+ switch (rtlpriv->rtlhal.interface) {
+ case INTF_PCI:
+ btcoexist->chip_interface = BTC_INTF_PCI;
+ break;
+ case INTF_USB:
+ btcoexist->chip_interface = BTC_INTF_USB;
+ break;
+ default:
+ btcoexist->chip_interface = BTC_INTF_UNKNOWN;
+ break;
+ }
+
+ btcoexist->binded = true;
+ btcoexist->statistics.cnt_bind++;
+
+ btcoexist->adapter = adapter;
+
+ btcoexist->stack_info.profile_notified = false;
+
+ btcoexist->bt_info.bt_ctrl_agg_buf_size = false;
+ btcoexist->bt_info.agg_buf_size = 5;
+
+ btcoexist->bt_info.increase_scan_dev_num = false;
+ btcoexist->bt_info.miracast_plus_bt = false;
+
+ chip_type = rtl_get_hwpg_bt_type(rtlpriv);
+ exhalbtc_set_chip_type(chip_type);
+ ant_num = rtl_get_hwpg_ant_num(rtlpriv);
+ exhalbtc_set_ant_num(rtlpriv, BT_COEX_ANT_TYPE_PG, ant_num);
+ /* set default antenna position to main port */
+ btcoexist->board_info.btdm_ant_pos = BTC_ANTENNA_AT_MAIN_PORT;
+
+ single_ant_path = rtl_get_hwpg_single_ant_path(rtlpriv);
+ exhalbtc_set_single_ant_path(single_ant_path);
+
+ if (rtl_get_hwpg_package_type(rtlpriv) == 0)
+ btcoexist->board_info.tfbga_package = false;
+ else if (rtl_get_hwpg_package_type(rtlpriv) == 1)
+ btcoexist->board_info.tfbga_package = false;
+ else
+ btcoexist->board_info.tfbga_package = true;
+
+ if (btcoexist->board_info.tfbga_package)
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], Package Type = TFBGA\n");
+ else
+ RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+ "[BTCoex], Package Type = Non-TFBGA\n");
+
+ return true;
+}
+
+void exhalbtc_power_on_setting(struct btc_coexist *btcoexist)
+{
+ if (!halbtc_is_bt_coexist_available(btcoexist))
+ return;
+
+ btcoexist->statistics.cnt_power_on++;
+
+ if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_power_on_setting(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_power_on_setting(btcoexist);
+ }
+}
+
+void exhalbtc_pre_load_firmware(struct btc_coexist *btcoexist)
+{
+ if (!halbtc_is_bt_coexist_available(btcoexist))
+ return;
+
+ btcoexist->statistics.cnt_pre_load_firmware++;
+
+ if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_pre_load_firmware(btcoexist);
+ }
+}
+
+void exhalbtc_init_hw_config(struct btc_coexist *btcoexist, bool wifi_only)
+{
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
btcoexist->statistics.cnt_init_hw_config++;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_init_hwconfig(btcoexist);
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_init_hwconfig(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_init_hwconfig(btcoexist, wifi_only);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_init_hwconfig(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_init_hwconfig(btcoexist, wifi_only);
+ } else if (IS_HARDWARE_TYPE_8723A(btcoexist->adapter)) {
+ /* 8723A has no this function */
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_init_hwconfig(btcoexist);
+ }
}
void exhalbtc_init_coex_dm(struct btc_coexist *btcoexist)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
-
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
btcoexist->statistics.cnt_init_coex_dm++;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_init_coex_dm(btcoexist);
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_init_coex_dm(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_init_coex_dm(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_init_coex_dm(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_init_coex_dm(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_init_coex_dm(btcoexist);
+ }
btcoexist->initilized = true;
}
void exhalbtc_ips_notify(struct btc_coexist *btcoexist, u8 type)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 ips_type;
if (!halbtc_is_bt_coexist_available(btcoexist))
@@ -737,18 +1012,28 @@ void exhalbtc_ips_notify(struct btc_coexist *btcoexist, u8 type)
else
ips_type = BTC_IPS_LEAVE;
- halbtc_leave_low_power();
-
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_ips_notify(btcoexist, ips_type);
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_ips_notify(btcoexist, ips_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_ips_notify(btcoexist, ips_type);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_ips_notify(btcoexist, ips_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_ips_notify(btcoexist, ips_type);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_ips_notify(btcoexist, ips_type);
+ }
- halbtc_nomal_low_power();
+ halbtc_normal_low_power(btcoexist);
}
void exhalbtc_lps_notify(struct btc_coexist *btcoexist, u8 type)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 lps_type;
if (!halbtc_is_bt_coexist_available(btcoexist))
@@ -762,14 +1047,24 @@ void exhalbtc_lps_notify(struct btc_coexist *btcoexist, u8 type)
else
lps_type = BTC_LPS_ENABLE;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_lps_notify(btcoexist, lps_type);
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_lps_notify(btcoexist, lps_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_lps_notify(btcoexist, lps_type);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_lps_notify(btcoexist, lps_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_lps_notify(btcoexist, lps_type);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_lps_notify(btcoexist, lps_type);
+ }
}
void exhalbtc_scan_notify(struct btc_coexist *btcoexist, u8 type)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 scan_type;
if (!halbtc_is_bt_coexist_available(btcoexist))
@@ -783,18 +1078,28 @@ void exhalbtc_scan_notify(struct btc_coexist *btcoexist, u8 type)
else
scan_type = BTC_SCAN_FINISH;
- halbtc_leave_low_power();
-
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_scan_notify(btcoexist, scan_type);
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_scan_notify(btcoexist, scan_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_scan_notify(btcoexist, scan_type);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_scan_notify(btcoexist, scan_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_scan_notify(btcoexist, scan_type);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_scan_notify(btcoexist, scan_type);
+ }
- halbtc_nomal_low_power();
+ halbtc_normal_low_power(btcoexist);
}
void exhalbtc_connect_notify(struct btc_coexist *btcoexist, u8 action)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 asso_type;
if (!halbtc_is_bt_coexist_available(btcoexist))
@@ -808,10 +1113,24 @@ void exhalbtc_connect_notify(struct btc_coexist *btcoexist, u8 action)
else
asso_type = BTC_ASSOCIATE_FINISH;
- halbtc_leave_low_power();
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_connect_notify(btcoexist, asso_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_connect_notify(btcoexist, asso_type);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_connect_notify(btcoexist, asso_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_connect_notify(btcoexist, asso_type);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_connect_notify(btcoexist, asso_type);
+ }
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_connect_notify(btcoexist, asso_type);
+ halbtc_normal_low_power(btcoexist);
}
void exhalbtc_mediastatus_notify(struct btc_coexist *btcoexist,
@@ -830,15 +1149,28 @@ void exhalbtc_mediastatus_notify(struct btc_coexist *btcoexist,
else
status = BTC_MEDIA_DISCONNECT;
- halbtc_leave_low_power();
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_media_status_notify(btcoexist, status);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_media_status_notify(btcoexist, status);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_media_status_notify(btcoexist, status);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_media_status_notify(btcoexist, status);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_media_status_notify(btcoexist, status);
+ }
- halbtc_nomal_low_power();
+ halbtc_normal_low_power(btcoexist);
}
void exhalbtc_special_packet_notify(struct btc_coexist *btcoexist, u8 pkt_type)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 packet_type;
if (!halbtc_is_bt_coexist_available(btcoexist))
@@ -847,28 +1179,85 @@ void exhalbtc_special_packet_notify(struct btc_coexist *btcoexist, u8 pkt_type)
if (btcoexist->manual_control)
return;
- packet_type = BTC_PACKET_DHCP;
-
- halbtc_leave_low_power();
+ if (pkt_type == PACKET_DHCP) {
+ packet_type = BTC_PACKET_DHCP;
+ } else if (pkt_type == PACKET_EAPOL) {
+ packet_type = BTC_PACKET_EAPOL;
+ } else if (pkt_type == PACKET_ARP) {
+ packet_type = BTC_PACKET_ARP;
+ } else {
+ packet_type = BTC_PACKET_UNKNOWN;
+ return;
+ }
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_special_packet_notify(btcoexist,
- packet_type);
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_special_packet_notify(btcoexist,
+ packet_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_special_packet_notify(btcoexist,
+ packet_type);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_special_packet_notify(btcoexist,
+ packet_type);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_special_packet_notify(btcoexist,
+ packet_type);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_special_packet_notify(btcoexist,
+ packet_type);
+ }
- halbtc_nomal_low_power();
+ halbtc_normal_low_power(btcoexist);
}
void exhalbtc_bt_info_notify(struct btc_coexist *btcoexist,
u8 *tmp_buf, u8 length)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
btcoexist->statistics.cnt_bt_info_notify++;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_bt_info_notify(btcoexist, tmp_buf, length);
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_bt_info_notify(btcoexist, tmp_buf,
+ length);
+ }
+
+ halbtc_normal_low_power(btcoexist);
+}
+
+void exhalbtc_rf_status_notify(struct btc_coexist *btcoexist, u8 type)
+{
+ if (!halbtc_is_bt_coexist_available(btcoexist))
+ return;
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_rf_status_notify(btcoexist, type);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ }
}
void exhalbtc_stack_operation_notify(struct btc_coexist *btcoexist, u8 type)
@@ -881,44 +1270,117 @@ void exhalbtc_stack_operation_notify(struct btc_coexist *btcoexist, u8 type)
if (btcoexist->manual_control)
return;
- stack_op_type = BTC_STACK_OP_NONE;
-
- halbtc_leave_low_power();
-
- halbtc_nomal_low_power();
+ if ((type == HCI_BT_OP_INQUIRY_START) ||
+ (type == HCI_BT_OP_PAGING_START) ||
+ (type == HCI_BT_OP_PAIRING_START)) {
+ stack_op_type = BTC_STACK_OP_INQ_PAGE_PAIR_START;
+ } else if ((type == HCI_BT_OP_INQUIRY_FINISH) ||
+ (type == HCI_BT_OP_PAGING_SUCCESS) ||
+ (type == HCI_BT_OP_PAGING_UNSUCCESS) ||
+ (type == HCI_BT_OP_PAIRING_FINISH)) {
+ stack_op_type = BTC_STACK_OP_INQ_PAGE_PAIR_FINISH;
+ } else {
+ stack_op_type = BTC_STACK_OP_NONE;
+ }
}
void exhalbtc_halt_notify(struct btc_coexist *btcoexist)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_halt_notify(btcoexist);
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_halt_notify(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_halt_notify(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_halt_notify(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_halt_notify(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_halt_notify(btcoexist);
+ }
+
+ btcoexist->binded = false;
}
void exhalbtc_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
{
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
+
+ /* currently only 1ant we have to do the notification,
+ * once pnp is notified to sleep state, we have to leave LPS that
+ * we can sleep normally.
+ */
+
+ if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_pnp_notify(btcoexist, pnp_state);
+ else if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_pnp_notify(btcoexist, pnp_state);
+ } else if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_pnp_notify(btcoexist, pnp_state);
+ else if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_pnp_notify(btcoexist, pnp_state);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ }
}
-void exhalbtc_periodical(struct btc_coexist *btcoexist)
+void exhalbtc_coex_dm_switch(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
- btcoexist->statistics.cnt_periodical++;
+ btcoexist->statistics.cnt_coex_dm_switch++;
+
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 1) {
+ btcoexist->stop_coex_dm = true;
+ ex_btc8723b1ant_coex_dm_reset(btcoexist);
+ exhalbtc_set_ant_num(rtlpriv,
+ BT_COEX_ANT_TYPE_DETECTED, 2);
+ ex_btc8723b2ant_init_hwconfig(btcoexist);
+ ex_btc8723b2ant_init_coex_dm(btcoexist);
+ btcoexist->stop_coex_dm = false;
+ }
+ }
- halbtc_leave_low_power();
+ halbtc_normal_low_power(btcoexist);
+}
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_periodical(btcoexist);
+void exhalbtc_periodical(struct btc_coexist *btcoexist)
+{
+ if (!halbtc_is_bt_coexist_available(btcoexist))
+ return;
+ btcoexist->statistics.cnt_periodical++;
+
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_periodical(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ if (!halbtc_under_ips(btcoexist))
+ ex_btc8821a1ant_periodical(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_periodical(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_periodical(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_periodical(btcoexist);
+ }
- halbtc_nomal_low_power();
+ halbtc_normal_low_power(btcoexist);
}
void exhalbtc_dbg_control(struct btc_coexist *btcoexist,
@@ -927,6 +1389,17 @@ void exhalbtc_dbg_control(struct btc_coexist *btcoexist,
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
btcoexist->statistics.cnt_dbg_ctrl++;
+
+ halbtc_leave_low_power(btcoexist);
+
+ halbtc_normal_low_power(btcoexist);
+}
+
+void exhalbtc_antenna_detection(struct btc_coexist *btcoexist, u32 cent_freq,
+ u32 offset, u32 span, u32 seconds)
+{
+ if (!halbtc_is_bt_coexist_available(btcoexist))
+ return;
}
void exhalbtc_stack_update_profile_info(void)
@@ -964,11 +1437,6 @@ void exhalbtc_set_bt_patch_version(u16 bt_hci_version, u16 bt_patch_version)
btcoexist->bt_info.bt_hci_ver = bt_hci_version;
}
-void exhalbtc_set_bt_exist(bool bt_exist)
-{
- gl_bt_coexist.board_info.bt_exist = bt_exist;
-}
-
void exhalbtc_set_chip_type(u8 chip_type)
{
switch (chip_type) {
@@ -1002,25 +1470,8 @@ void exhalbtc_set_ant_num(struct rtl_priv *rtlpriv, u8 type, u8 ant_num)
if (BT_COEX_ANT_TYPE_PG == type) {
gl_bt_coexist.board_info.pg_ant_num = ant_num;
gl_bt_coexist.board_info.btdm_ant_num = ant_num;
- /* The antenna position:
- * Main (default) or Aux for pgAntNum=2 && btdmAntNum =1.
- * The antenna position should be determined by
- * auto-detect mechanism.
- * The following is assumed to main,
- * and those must be modified
- * if y auto-detect mechanism is ready
- */
- if ((gl_bt_coexist.board_info.pg_ant_num == 2) &&
- (gl_bt_coexist.board_info.btdm_ant_num == 1))
- gl_bt_coexist.board_info.btdm_ant_pos =
- BTC_ANTENNA_AT_MAIN_PORT;
- else
- gl_bt_coexist.board_info.btdm_ant_pos =
- BTC_ANTENNA_AT_MAIN_PORT;
} else if (BT_COEX_ANT_TYPE_ANTDIV == type) {
gl_bt_coexist.board_info.btdm_ant_num = ant_num;
- gl_bt_coexist.board_info.btdm_ant_pos =
- BTC_ANTENNA_AT_MAIN_PORT;
} else if (type == BT_COEX_ANT_TYPE_DETECTED) {
gl_bt_coexist.board_info.btdm_ant_num = ant_num;
if (rtlpriv->cfg->mod_params->ant_sel == 1)
@@ -1032,13 +1483,33 @@ void exhalbtc_set_ant_num(struct rtl_priv *rtlpriv, u8 type, u8 ant_num)
}
}
+/* Currently used by 8723b only, S0 or S1 */
+void exhalbtc_set_single_ant_path(u8 single_ant_path)
+{
+ gl_bt_coexist.board_info.single_ant_path = single_ant_path;
+}
+
void exhalbtc_display_bt_coex_info(struct btc_coexist *btcoexist)
{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
- struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
if (!halbtc_is_bt_coexist_available(btcoexist))
return;
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE)
- ex_btc8723b2ant_display_coex_info(btcoexist);
+ halbtc_leave_low_power(btcoexist);
+
+ if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8821a2ant_display_coex_info(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8821a1ant_display_coex_info(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8723b2ant_display_coex_info(btcoexist);
+ else if (btcoexist->board_info.btdm_ant_num == 1)
+ ex_btc8723b1ant_display_coex_info(btcoexist);
+ } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
+ if (btcoexist->board_info.btdm_ant_num == 2)
+ ex_btc8192e2ant_display_coex_info(btcoexist);
+ }
+
+ halbtc_normal_low_power(btcoexist);
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
index c827113..f9b87c1 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
@@ -30,6 +30,9 @@
#define NORMAL_EXEC false
#define FORCE_EXEC true
+#define BTC_RF_OFF 0x0
+#define BTC_RF_ON 0x1
+
#define BTC_RF_A RF90_PATH_A
#define BTC_RF_B RF90_PATH_B
#define BTC_RF_C RF90_PATH_C
@@ -150,6 +153,7 @@ struct btc_board_info {
u8 btdm_ant_pos;
u8 single_ant_path; /* current used for 8723b only, 1=>s0, 0=>s1 */
bool bt_exist;
+ bool tfbga_package;
};
enum btc_dbg_opcode {
@@ -196,6 +200,44 @@ enum btc_wifi_pnp {
BTC_WIFI_PNP_MAX
};
+enum btc_iot_peer {
+ BTC_IOT_PEER_UNKNOWN = 0,
+ BTC_IOT_PEER_REALTEK = 1,
+ BTC_IOT_PEER_REALTEK_92SE = 2,
+ BTC_IOT_PEER_BROADCOM = 3,
+ BTC_IOT_PEER_RALINK = 4,
+ BTC_IOT_PEER_ATHEROS = 5,
+ BTC_IOT_PEER_CISCO = 6,
+ BTC_IOT_PEER_MERU = 7,
+ BTC_IOT_PEER_MARVELL = 8,
+ BTC_IOT_PEER_REALTEK_SOFTAP = 9,
+ BTC_IOT_PEER_SELF_SOFTAP = 10, /* Self is SoftAP */
+ BTC_IOT_PEER_AIRGO = 11,
+ BTC_IOT_PEER_REALTEK_JAGUAR_BCUTAP = 12,
+ BTC_IOT_PEER_REALTEK_JAGUAR_CCUTAP = 13,
+ BTC_IOT_PEER_MAX,
+};
+
+/* for 8723b-d cut large current issue */
+enum bt_wifi_coex_state {
+ BTC_WIFI_STAT_INIT,
+ BTC_WIFI_STAT_IQK,
+ BTC_WIFI_STAT_NORMAL_OFF,
+ BTC_WIFI_STAT_MP_OFF,
+ BTC_WIFI_STAT_NORMAL,
+ BTC_WIFI_STAT_ANT_DIV,
+ BTC_WIFI_STAT_MAX
+};
+
+enum bt_ant_type {
+ BTC_ANT_TYPE_0,
+ BTC_ANT_TYPE_1,
+ BTC_ANT_TYPE_2,
+ BTC_ANT_TYPE_3,
+ BTC_ANT_TYPE_4,
+ BTC_ANT_TYPE_MAX
+};
+
enum btc_get_type {
/* type bool */
BTC_GET_BL_HS_OPERATION,
@@ -216,6 +258,9 @@ enum btc_get_type {
BTC_GET_BL_WIFI_UNDER_B_MODE,
BTC_GET_BL_EXT_SWITCH,
BTC_GET_BL_WIFI_IS_IN_MP_MODE,
+ BTC_GET_BL_IS_ASUS_8723B,
+ BTC_GET_BL_FW_READY,
+ BTC_GET_BL_RF4CE_CONNECTED,
/* type s4Byte */
BTC_GET_S4_WIFI_RSSI,
@@ -228,6 +273,11 @@ enum btc_get_type {
BTC_GET_U4_WIFI_LINK_STATUS,
BTC_GET_U4_BT_PATCH_VER,
BTC_GET_U4_VENDOR,
+ BTC_GET_U4_SUPPORTED_VERSION,
+ BTC_GET_U4_SUPPORTED_FEATURE,
+ BTC_GET_U4_WIFI_IQK_TOTAL,
+ BTC_GET_U4_WIFI_IQK_OK,
+ BTC_GET_U4_WIFI_IQK_FAIL,
/* type u1Byte */
BTC_GET_U1_WIFI_DOT11_CHNL,
@@ -235,6 +285,8 @@ enum btc_get_type {
BTC_GET_U1_WIFI_HS_CHNL,
BTC_GET_U1_MAC_PHY_MODE,
BTC_GET_U1_AP_NUM,
+ BTC_GET_U1_ANT_TYPE,
+ BTC_GET_U1_IOT_PEER,
/* for 1Ant */
BTC_GET_U1_LPS_MODE,
@@ -293,6 +345,7 @@ enum btc_set_type {
/* BT Coex related */
BTC_SET_ACT_CTRL_BT_INFO,
BTC_SET_ACT_CTRL_BT_COEX,
+ BTC_SET_ACT_CTRL_8723B_ANT,
/***************************/
BTC_SET_MAX
};
@@ -411,12 +464,18 @@ struct btc_bt_info {
bool bt_disabled;
u8 rssi_adjust_for_agc_table_on;
u8 rssi_adjust_for_1ant_coex_type;
+ bool pre_bt_ctrl_agg_buf_size;
bool bt_busy;
+ u8 pre_agg_buf_size;
u8 agg_buf_size;
bool limited_dig;
+ bool pre_reject_agg_pkt;
bool reject_agg_pkt;
bool bt_ctrl_buf_size;
bool increase_scan_dev_num;
+ bool miracast_plus_bt;
+ bool bt_ctrl_agg_buf_size;
+ bool bt_tx_rx_mask;
u16 bt_hci_ver;
u16 bt_real_fw_ver;
u8 bt_fw_ver;
@@ -464,10 +523,13 @@ struct btc_statistics {
u32 cnt_coex_dm_switch;
u32 cnt_stack_operation_notify;
u32 cnt_dbg_ctrl;
+ u32 cnt_pre_load_firmware;
+ u32 cnt_power_on;
};
struct btc_bt_link_info {
bool bt_link_exist;
+ bool bt_hi_pri_link_exist;
bool sco_exist;
bool sco_only;
bool a2dp_exist;
@@ -496,6 +558,11 @@ struct btc_coexist {
enum btc_chip_interface chip_interface;
struct btc_bt_link_info bt_link_info;
+ /* boolean variables to replace BT_AUTO_REPORT_ONLY_XXXXY_ZANT
+ * configuration parameters
+ */
+ bool auto_report_1ant;
+ bool auto_report_2ant;
bool initilized;
bool stop_coex_dm;
bool manual_control;
@@ -532,8 +599,9 @@ bool halbtc_is_wifi_uplink(struct rtl_priv *adapter);
extern struct btc_coexist gl_bt_coexist;
-bool exhalbtc_initlize_variables(struct rtl_priv *adapter);
-void exhalbtc_init_hw_config(struct btc_coexist *btcoexist);
+bool exhalbtc_initlize_variables(void);
+bool exhalbtc_bind_bt_coex_withadapter(void *adapter);
+void exhalbtc_init_hw_config(struct btc_coexist *btcoexist, bool wifi_only);
void exhalbtc_init_coex_dm(struct btc_coexist *btcoexist);
void exhalbtc_ips_notify(struct btc_coexist *btcoexist, u8 type);
void exhalbtc_lps_notify(struct btc_coexist *btcoexist, u8 type);
@@ -563,5 +631,6 @@ void exhalbtc_signal_compensation(struct btc_coexist *btcoexist,
u8 *rssi_wifi, u8 *rssi_bt);
void exhalbtc_lps_leave(struct btc_coexist *btcoexist);
void exhalbtc_low_wifi_traffic_notify(struct btc_coexist *btcoexist);
+void exhalbtc_set_single_ant_path(u8 single_ant_path);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
index 46e0fa6..4366c98 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
@@ -45,42 +45,79 @@ static struct rtl_btc_ops rtl_btc_operation = {
.btc_is_disable_edca_turbo = rtl_btc_is_disable_edca_turbo,
.btc_is_bt_disabled = rtl_btc_is_bt_disabled,
.btc_special_packet_notify = rtl_btc_special_packet_notify,
+ .btc_record_pwr_mode = rtl_btc_record_pwr_mode,
+ .btc_get_lps_val = rtl_btc_get_lps_val,
+ .btc_get_rpwm_val = rtl_btc_get_rpwm_val,
+ .btc_is_bt_ctrl_lps = rtl_btc_is_bt_ctrl_lps,
+ .btc_is_bt_lps_on = rtl_btc_is_bt_lps_on,
+ .btc_get_ampdu_cfg = rtl_btc_get_ampdu_cfg,
};
-void rtl_btc_init_variables(struct rtl_priv *rtlpriv)
+void rtl_btc_record_pwr_mode(struct rtl_priv *rtlpriv, u8 *buf, u8 len)
{
- exhalbtc_initlize_variables(rtlpriv);
+ u8 safe_len;
+
+ safe_len = sizeof(gl_bt_coexist.pwr_mode_val);
+
+ if (safe_len > len)
+ safe_len = len;
+
+ memcpy(gl_bt_coexist.pwr_mode_val, buf, safe_len);
}
-void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv)
+u8 rtl_btc_get_lps_val(struct rtl_priv *rtlpriv)
{
- u8 ant_num;
- u8 bt_exist;
- u8 bt_type;
+ return gl_bt_coexist.bt_info.lps_val;
+}
- ant_num = rtl_get_hwpg_ant_num(rtlpriv);
- RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "%s, antNum is %d\n", __func__, ant_num);
+u8 rtl_btc_get_rpwm_val(struct rtl_priv *rtlpriv)
+{
+ return gl_bt_coexist.bt_info.rpwm_val;
+}
- bt_exist = rtl_get_hwpg_bt_exist(rtlpriv);
- RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "%s, bt_exist is %d\n", __func__, bt_exist);
- exhalbtc_set_bt_exist(bt_exist);
+bool rtl_btc_is_bt_ctrl_lps(struct rtl_priv *rtlpriv)
+{
+ return gl_bt_coexist.bt_info.bt_ctrl_lps;
+}
+
+bool rtl_btc_is_bt_lps_on(struct rtl_priv *rtlpriv)
+{
+ return gl_bt_coexist.bt_info.bt_lps_on;
+}
- bt_type = rtl_get_hwpg_bt_type(rtlpriv);
- RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%s, bt_type is %d\n",
- __func__, bt_type);
- exhalbtc_set_chip_type(bt_type);
+void rtl_btc_get_ampdu_cfg(struct rtl_priv *rtlpriv, u8 *reject_agg,
+ u8 *ctrl_agg_size, u8 *agg_size)
+{
+ if (reject_agg)
+ *reject_agg = gl_bt_coexist.bt_info.reject_agg_pkt;
+ if (ctrl_agg_size)
+ *ctrl_agg_size = gl_bt_coexist.bt_info.bt_ctrl_agg_buf_size;
+ if (agg_size)
+ *agg_size = gl_bt_coexist.bt_info.agg_buf_size;
+}
- if (rtlpriv->cfg->mod_params->ant_sel == 1)
- exhalbtc_set_ant_num(rtlpriv, BT_COEX_ANT_TYPE_DETECTED, 1);
- else
- exhalbtc_set_ant_num(rtlpriv, BT_COEX_ANT_TYPE_PG, ant_num);
+void rtl_btc_init_variables(struct rtl_priv *rtlpriv)
+{
+ exhalbtc_initlize_variables();
+ exhalbtc_bind_bt_coex_withadapter(rtlpriv);
+}
+
+void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv)
+{
+ /* move ant_num, bt_type and single_ant_path to
+ * exhalbtc_bind_bt_coex_withadapter()
+ */
}
void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv)
{
- exhalbtc_init_hw_config(&gl_bt_coexist);
+ u8 bt_exist;
+
+ bt_exist = rtl_get_hwpg_bt_exist(rtlpriv);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+ "%s, bt_exist is %d\n", __func__, bt_exist);
+
+ exhalbtc_init_hw_config(&gl_bt_coexist, !bt_exist);
exhalbtc_init_coex_dm(&gl_bt_coexist);
}
@@ -118,7 +155,9 @@ void rtl_btc_periodical(struct rtl_priv *rtlpriv)
void rtl_btc_halt_notify(void)
{
- exhalbtc_halt_notify(&gl_bt_coexist);
+ struct btc_coexist *btcoexist = &gl_bt_coexist;
+
+ exhalbtc_halt_notify(btcoexist);
}
void rtl_btc_btinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length)
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h
index fff5117..6fe521c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h
@@ -43,6 +43,13 @@ bool rtl_btc_is_limited_dig(struct rtl_priv *rtlpriv);
bool rtl_btc_is_disable_edca_turbo(struct rtl_priv *rtlpriv);
bool rtl_btc_is_bt_disabled(struct rtl_priv *rtlpriv);
void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type);
+void rtl_btc_record_pwr_mode(struct rtl_priv *rtlpriv, u8 *buf, u8 len);
+u8 rtl_btc_get_lps_val(struct rtl_priv *rtlpriv);
+u8 rtl_btc_get_rpwm_val(struct rtl_priv *rtlpriv);
+bool rtl_btc_is_bt_ctrl_lps(struct rtl_priv *rtlpriv);
+bool rtl_btc_is_bt_lps_on(struct rtl_priv *rtlpriv);
+void rtl_btc_get_ampdu_cfg(struct rtl_priv *rtlpriv, u8 *reject_agg,
+ u8 *ctrl_agg_size, u8 *agg_size);
struct rtl_btc_ops *rtl_btc_get_ops_pointer(void);
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index a4f8e32..b0ad061 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -629,7 +629,8 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
}
/*For LPS */
- if (changed & IEEE80211_CONF_CHANGE_PS) {
+ if ((changed & IEEE80211_CONF_CHANGE_PS) &&
+ rtlpriv->psc.swctrl_lps && !rtlpriv->psc.fwctrl_lps) {
cancel_delayed_work(&rtlpriv->works.ps_work);
cancel_delayed_work(&rtlpriv->works.ps_rfon_wq);
if (conf->flags & IEEE80211_CONF_PS) {
@@ -1463,6 +1464,9 @@ static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw,
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n");
mac->act_scanning = false;
mac->skip_scan = false;
+
+ rtlpriv->btcoexist.btc_info.ap_num = rtlpriv->scan_list.num;
+
if (rtlpriv->link_info.higher_busytraffic)
return;
@@ -1670,6 +1674,8 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
*so don't use rtl_cam_reset_all_entry
*or clear all entry here.
*/
+ rtl_wait_tx_report_acked(hw, 500); /* wait 500ms for TX ack */
+
rtl_cam_delete_one_entry(hw, mac_addr, key_idx);
break;
default:
diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.c b/drivers/net/wireless/realtek/rtlwifi/debug.c
index 7ecac611..38fef6d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/debug.c
+++ b/drivers/net/wireless/realtek/rtlwifi/debug.c
@@ -27,7 +27,7 @@
#include <linux/moduleparam.h>
#ifdef CONFIG_RTLWIFI_DEBUG
-void _rtl_dbg_trace(struct rtl_priv *rtlpriv, int comp, int level,
+void _rtl_dbg_trace(struct rtl_priv *rtlpriv, u64 comp, int level,
const char *fmt, ...)
{
if (unlikely((comp & rtlpriv->cfg->mod_params->debug_mask) &&
diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.h b/drivers/net/wireless/realtek/rtlwifi/debug.h
index bf5339f..9477180 100644
--- a/drivers/net/wireless/realtek/rtlwifi/debug.h
+++ b/drivers/net/wireless/realtek/rtlwifi/debug.h
@@ -105,6 +105,7 @@
#define COMP_EASY_CONCURRENT COMP_USB /* reuse of this bit is OK */
#define COMP_BT_COEXIST BIT(30)
#define COMP_IQK BIT(31)
+#define COMP_TX_REPORT BIT_ULL(32)
/*--------------------------------------------------------------
Define the rt_print components
@@ -169,7 +170,7 @@ enum dbgp_flag_e {
struct rtl_priv;
__printf(4, 5)
-void _rtl_dbg_trace(struct rtl_priv *rtlpriv, int comp, int level,
+void _rtl_dbg_trace(struct rtl_priv *rtlpriv, u64 comp, int level,
const char *fmt, ...);
__printf(4, 5)
@@ -198,7 +199,7 @@ struct rtl_priv;
__printf(4, 5)
static inline void RT_TRACE(struct rtl_priv *rtlpriv,
- int comp, int level,
+ u64 comp, int level,
const char *fmt, ...)
{
}
@@ -211,7 +212,7 @@ static inline void RTPRINT(struct rtl_priv *rtlpriv,
}
static inline void RT_PRINT_DATA(struct rtl_priv *rtlpriv,
- int comp, int level,
+ u64 comp, int level,
const char *titlestring,
const void *hexdata, size_t hexdatalen)
{
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index 2e6b888..032b631 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -729,14 +729,12 @@ static void _rtl_pci_rx_to_mac80211(struct ieee80211_hw *hw,
dev_kfree_skb_any(skb);
} else {
struct sk_buff *uskb = NULL;
- u8 *pdata;
uskb = dev_alloc_skb(skb->len + 128);
if (likely(uskb)) {
memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status,
sizeof(rx_status));
- pdata = (u8 *)skb_put(uskb, skb->len);
- memcpy(pdata, skb->data, skb->len);
+ skb_put_data(uskb, skb->data, skb->len);
dev_kfree_skb_any(skb);
ieee80211_rx_irqsafe(hw, uskb);
} else {
@@ -881,6 +879,9 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
if (unicast)
rtlpriv->link_info.num_rx_inperiod++;
}
+
+ rtl_collect_scan_list(hw, skb);
+
/* static bcn for roaming */
rtl_beacon_statistic(hw, skb);
rtl_p2p_info(hw, (void *)skb->data, skb->len);
@@ -1826,6 +1827,7 @@ static int rtl_pci_start(struct ieee80211_hw *hw)
rtlpci->driver_is_goingto_unload = false;
if (rtlpriv->cfg->ops->get_btc_status &&
rtlpriv->cfg->ops->get_btc_status()) {
+ rtlpriv->btcoexist.btc_info.ap_num = 36;
rtlpriv->btcoexist.btc_ops->btc_init_variables(rtlpriv);
rtlpriv->btcoexist.btc_ops->btc_init_hal_vars(rtlpriv);
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c
index 0d15287..07ee309 100644
--- a/drivers/net/wireless/realtek/rtlwifi/ps.c
+++ b/drivers/net/wireless/realtek/rtlwifi/ps.c
@@ -356,7 +356,7 @@ void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode)
if (mac->link_state != MAC80211_LINKED)
return;
- if (ppsc->dot11_psmode == rt_psmode)
+ if (ppsc->dot11_psmode == rt_psmode && rt_psmode == EACTIVE)
return;
/* Update power save mode configured. */
@@ -438,11 +438,13 @@ static void rtl_lps_enter_core(struct ieee80211_hw *hw)
spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
- if (ppsc->dot11_psmode == EACTIVE) {
- RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
- "Enter 802.11 power save mode...\n");
- rtl_lps_set_psmode(hw, EAUTOPS);
- }
+ /* Don't need to check (ppsc->dot11_psmode == EACTIVE), because
+ * bt_ccoexist may ask to enter lps.
+ * In normal case, this constraint move to rtl_lps_set_psmode().
+ */
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+ "Enter 802.11 power save mode...\n");
+ rtl_lps_set_psmode(hw, EAUTOPS);
spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c
index 21ed9ad..a2eca66 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c
@@ -620,8 +620,7 @@ void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
u1rsvdpageloc, 3);
skb = dev_alloc_skb(totalpacketlen);
- memcpy(skb_put(skb, totalpacketlen),
- &reserved_page_packet, totalpacketlen);
+ skb_put_data(skb, &reserved_page_packet, totalpacketlen);
rtstatus = rtl_cmd_send_packet(hw, skb);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h
index 15400ee..0c0d64a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h
@@ -248,7 +248,6 @@
#define REG_RD_NAV_NXT 0x0544
#define REG_NAV_PROT_LEN 0x0546
#define REG_BCN_CTRL 0x0550
-#define REG_USTIME_TSF 0x0551
#define REG_MBID_NUM 0x0552
#define REG_DUAL_TSF_RST 0x0553
#define REG_BCN_INTERVAL 0x0554
@@ -256,6 +255,7 @@
#define REG_DRVERLYINT 0x0558
#define REG_BCNDMATIM 0x0559
#define REG_ATIMWND 0x055A
+#define REG_USTIME_TSF 0x055C
#define REG_BCN_MAX_ERR 0x055D
#define REG_RXTSF_OFFSET_CCK 0x055E
#define REG_RXTSF_OFFSET_OFDM 0x055F
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
index 7661cfa..774e720 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
@@ -270,7 +270,7 @@ static struct rtl_hal_ops rtl8188ee_hal_ops = {
static struct rtl_mod_params rtl88ee_mod_params = {
.sw_crypto = false,
- .inactiveps = false,
+ .inactiveps = true,
.swctrl_lps = false,
.fwctrl_lps = false,
.msi_support = true,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c
index c7a7746..015476e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c
@@ -647,8 +647,7 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
skb = dev_alloc_skb(totalpacketlen);
- memcpy((u8 *)skb_put(skb, totalpacketlen),
- &reserved_page_packet, totalpacketlen);
+ skb_put_data(skb, &reserved_page_packet, totalpacketlen);
if (cmd_send_packet)
rtstatus = cmd_send_packet(hw, skb);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h
index 1bb7ed3..9e3b58a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h
@@ -227,7 +227,6 @@
#define REG_RD_NAV_NXT 0x0544
#define REG_NAV_PROT_LEN 0x0546
#define REG_BCN_CTRL 0x0550
-#define REG_USTIME_TSF 0x0551
#define REG_MBID_NUM 0x0552
#define REG_DUAL_TSF_RST 0x0553
#define REG_BCN_INTERVAL 0x0554
@@ -235,6 +234,7 @@
#define REG_DRVERLYINT 0x0558
#define REG_BCNDMATIM 0x0559
#define REG_ATIMWND 0x055A
+#define REG_USTIME_TSF 0x055C
#define REG_BCN_MAX_ERR 0x055D
#define REG_RXTSF_OFFSET_CCK 0x055E
#define REG_RXTSF_OFFSET_OFDM 0x055F
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
index 41422e4..de6c342 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
@@ -512,7 +512,7 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc);
- txdesc = (u8 *)skb_push(skb, RTL_TX_HEADER_SIZE);
+ txdesc = skb_push(skb, RTL_TX_HEADER_SIZE);
memset(txdesc, 0, RTL_TX_HEADER_SIZE);
SET_TX_DESC_PKT_SIZE(txdesc, pktlen);
SET_TX_DESC_LINIP(txdesc, 0);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c
index 88faeab..f4129cf 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c
@@ -668,8 +668,7 @@ void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
if (!skb) {
dlok = false;
} else {
- memcpy((u8 *) skb_put(skb, totalpacketlen),
- &reserved_page_packet, totalpacketlen);
+ skb_put_data(skb, &reserved_page_packet, totalpacketlen);
rtstatus = _rtl92d_cmd_send_packet(hw, skb);
if (rtstatus)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h
index b354b95..d4c4e76 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h
@@ -255,7 +255,6 @@
#define REG_RD_NAV_NXT 0x0544
#define REG_NAV_PROT_LEN 0x0546
#define REG_BCN_CTRL 0x0550
-#define REG_USTIME_TSF 0x0551
#define REG_MBID_NUM 0x0552
#define REG_DUAL_TSF_RST 0x0553
#define REG_BCN_INTERVAL 0x0554
@@ -263,6 +262,7 @@
#define REG_DRVERLYINT 0x0558
#define REG_BCNDMATIM 0x0559
#define REG_ATIMWND 0x055A
+#define REG_USTIME_TSF 0x055C
#define REG_BCN_MAX_ERR 0x055D
#define REG_RXTSF_OFFSET_CCK 0x055E
#define REG_RXTSF_OFFSET_OFDM 0x055F
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c
index 1f42ce5..f5d4df9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c
@@ -422,28 +422,86 @@ void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- u8 rlbm , power_state = 0;
+ u8 rlbm, power_state = 0, byte5 = 0;
+ u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
+ struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
+ bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
+ btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
+ bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
+ btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
+
+ if (bt_ctrl_lps)
+ mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
+
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
+ mode, bt_ctrl_lps);
+
+ switch (mode) {
+ case FW_PS_MIN_MODE:
+ rlbm = 0;
+ awake_intvl = 2;
+ break;
+ case FW_PS_MAX_MODE:
+ rlbm = 1;
+ awake_intvl = 2;
+ break;
+ case FW_PS_DTIM_MODE:
+ rlbm = 2;
+ awake_intvl = ppsc->reg_max_lps_awakeintvl;
+ /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
+ * is only used in swlps.
+ */
+ break;
+ default:
+ rlbm = 2;
+ awake_intvl = 4;
+ break;
+ }
- RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , "FW LPS mode = %d\n", mode);
+ if (rtlpriv->mac80211.p2p) {
+ awake_intvl = 2;
+ rlbm = 1;
+ }
+
+ if (mode == FW_PS_ACTIVE_MODE) {
+ byte5 = 0x40;
+ power_state = FW_PWR_STATE_ACTIVE;
+ } else {
+ if (bt_ctrl_lps) {
+ byte5 = btc_ops->btc_get_lps_val(rtlpriv);
+ power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
+
+ if ((rlbm == 2) && (byte5 & BIT(4))) {
+ /* Keep awake interval to 1 to prevent from
+ * decreasing coex performance
+ */
+ awake_intvl = 2;
+ rlbm = 2;
+ }
+ } else {
+ byte5 = 0x40;
+ power_state = FW_PWR_STATE_RF_OFF;
+ }
+ }
SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
- rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
- (rtlpriv->mac80211.p2p) ?
- ppsc->smart_ps : 1);
+ bt_ctrl_lps ? 0 :
+ ((rtlpriv->mac80211.p2p) ?
+ ppsc->smart_ps : 1));
SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
- ppsc->reg_max_lps_awakeintvl);
+ awake_intvl);
SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
- if (mode == FW_PS_ACTIVE_MODE)
- power_state |= FW_PWR_STATE_ACTIVE;
- else
- power_state |= FW_PWR_STATE_RF_OFF;
SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
+ SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
"rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
+ if (rtlpriv->cfg->ops->get_btc_status())
+ btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
+ H2C_92E_PWEMODE_LENGTH);
rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
u1_h2c_set_pwrmode);
}
@@ -708,8 +766,7 @@ void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
u1rsvdpageloc, 3);
skb = dev_alloc_skb(totalpacketlen);
- memcpy((u8 *)skb_put(skb, totalpacketlen),
- &reserved_page_packet, totalpacketlen);
+ skb_put_data(skb, &reserved_page_packet, totalpacketlen);
b_dlok = true;
@@ -843,6 +900,7 @@ void rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
case C2H_8192E_TX_REPORT:
RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE ,
"[C2H], C2H_8723BE_TX_REPORT!\n");
+ rtl_tx_report_handler(hw, tmp_buf, c2h_cmd_len);
break;
case C2H_8192E_BT_INFO:
RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h
index af82719..b770f72 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h
@@ -37,7 +37,7 @@
#define USE_OLD_WOWLAN_DEBUG_FW 0
#define H2C_92E_RSVDPAGE_LOC_LEN 5
-#define H2C_92E_PWEMODE_LENGTH 5
+#define H2C_92E_PWEMODE_LENGTH 7
#define H2C_92E_JOINBSSRPT_LENGTH 1
#define H2C_92E_AP_OFFLOAD_LENGTH 3
#define H2C_92E_WOWLAN_LENGTH 3
@@ -154,6 +154,8 @@ enum rtl8192e_c2h_evt {
SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __val)
#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__cmd, __val) \
SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_BYTE5(__cmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__cmd) + 5, 0, 8, __val)
#define GET_92E_H2CCMD_PWRMODE_PARM_MODE(__cmd) \
LE_BITS_TO_1BYTE(__cmd, 0, 8)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
index 6f5098a..d84ac7a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
@@ -1670,7 +1670,8 @@ void rtl92ee_card_disable(struct ieee80211_hw *hw)
_rtl92ee_poweroff_adapter(hw);
/* after power off we should do iqk again */
- rtlpriv->phy.iqk_initialized = false;
+ if (!rtlpriv->cfg->ops->get_btc_status())
+ rtlpriv->phy.iqk_initialized = false;
}
void rtl92ee_interrupt_recognized(struct ieee80211_hw *hw,
@@ -2506,7 +2507,7 @@ void rtl92ee_set_key(struct ieee80211_hw *hw, u32 key_index,
"add one entry\n");
if (is_pairwise) {
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
- "set Pairwiase key\n");
+ "set Pairwise key\n");
rtl_cam_add_one_entry(hw, macaddr, key_index,
entry_id, enc_algo,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
index 48820bc..eaa503b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
@@ -253,7 +253,7 @@ static struct rtl_hal_ops rtl8192ee_hal_ops = {
static struct rtl_mod_params rtl92ee_mod_params = {
.sw_crypto = false,
- .inactiveps = false,
+ .inactiveps = true,
.swctrl_lps = false,
.fwctrl_lps = true,
.msi_support = true,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c
index b1864bb..55f238a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c
@@ -731,6 +731,9 @@ void rtl92ee_tx_fill_desc(struct ieee80211_hw *hw,
SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
}
+ /* tx report */
+ rtl_get_tx_report(ptcb_desc, pdesc, hw);
+
SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);
if (ieee80211_is_mgmt(fc)) {
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h
index 8053d1b..b0105c5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h
@@ -159,7 +159,7 @@
#define SET_TX_DESC_NULL_0(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 1, __val)
#define SET_TX_DESC_NULL_1(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+8, 15, 1, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 8, 15, 1, __val)
#define SET_TX_DESC_BK(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val)
#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \
@@ -167,7 +167,7 @@
#define SET_TX_DESC_RAW(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val)
#define SET_TX_DESC_SPE_RPT(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 8, 19, 1, __val)
#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val)
#define SET_TX_DESC_BT_NULL(__pdesc, __val) \
@@ -252,15 +252,15 @@
/* Dword 6 */
#define SET_TX_DESC_SW_DEFINE(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 12, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 0, 12, __val)
#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 3, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 16, 3, __val)
#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+24, 19, 3, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 19, 3, __val)
#define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+24, 22, 3, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 22, 3, __val)
#define SET_TX_DESC_ANTSEL_D(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+24, 25, 3, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 25, 3, __val)
/* Dword 7 */
#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c
index 89a0a28..e7b1d7c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c
@@ -188,10 +188,9 @@ static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw,
if (!skb)
return false;
skb_reserve(skb, extra_descoffset);
- seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length -
- extra_descoffset));
- memcpy(seg_ptr, code_virtual_address + frag_offset,
- (u32)(frag_length - extra_descoffset));
+ seg_ptr = skb_put_data(skb,
+ code_virtual_address + frag_offset,
+ (u32)(frag_length - extra_descoffset));
tcb_desc = (struct rtl_tcb_desc *)(skb->cb);
tcb_desc->queue_index = TXCMD_QUEUE;
@@ -463,7 +462,7 @@ static u32 _rtl92s_fill_h2c_cmd(struct sk_buff *skb, u32 h2cbufferlen,
break;
/* Clear content */
- ph2c_buffer = (u8 *)skb_put(skb, (u32)len);
+ ph2c_buffer = skb_put(skb, (u32)len);
memset((ph2c_buffer + totallen + tx_desclen), 0, len);
/* CMD len */
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c
index a954a87b..bf9859f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c
@@ -470,8 +470,7 @@ void rtl8723e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
u1rsvdpageloc, 3);
skb = dev_alloc_skb(totalpacketlen);
- memcpy((u8 *)skb_put(skb, totalpacketlen),
- &reserved_page_packet, totalpacketlen);
+ skb_put_data(skb, &reserved_page_packet, totalpacketlen);
rtstatus = rtl_cmd_send_packet(hw, skb);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
index 859c045..5ac7b81 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
@@ -2264,7 +2264,7 @@ void rtl8723e_set_key(struct ieee80211_hw *hw, u32 key_index,
"add one entry\n");
if (is_pairwise) {
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
- "set Pairwiase key\n");
+ "set Pairwise key\n");
rtl_cam_add_one_entry(hw, macaddr, key_index,
entry_id, enc_algo,
@@ -2313,7 +2313,7 @@ static void rtl8723e_bt_var_init(struct ieee80211_hw *hw)
rtlpriv->btcoexist.eeprom_bt_radio_shared;
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
- "BT Coexistance = 0x%x\n",
+ "BT Coexistence = 0x%x\n",
rtlpriv->btcoexist.bt_coexistence);
if (rtlpriv->btcoexist.bt_coexistence) {
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h
index 306059f..30938cd 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h
@@ -217,7 +217,6 @@
#define REG_RD_NAV_NXT 0x0544
#define REG_NAV_PROT_LEN 0x0546
#define REG_BCN_CTRL 0x0550
-#define REG_USTIME_TSF 0x0551
#define REG_MBID_NUM 0x0552
#define REG_DUAL_TSF_RST 0x0553
#define REG_BCN_INTERVAL 0x0554
@@ -225,6 +224,7 @@
#define REG_DRVERLYINT 0x0558
#define REG_BCNDMATIM 0x0559
#define REG_ATIMWND 0x055A
+#define REG_USTIME_TSF 0x055C
#define REG_BCN_MAX_ERR 0x055D
#define REG_RXTSF_OFFSET_CCK 0x055E
#define REG_RXTSF_OFFSET_OFDM 0x055F
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c
index 4fc839b..dd6f95c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c
@@ -240,27 +240,84 @@ void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 u1_h2c_set_pwrmode[H2C_PWEMODE_LENGTH] = { 0 };
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- u8 rlbm, power_state = 0;
- RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
+ u8 rlbm, power_state = 0, byte5 = 0;
+ u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
+ struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
+ bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
+ btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
+ bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
+ btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
+
+ if (bt_ctrl_lps)
+ mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
+
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
+ mode, bt_ctrl_lps);
+
+ switch (mode) {
+ case FW_PS_MIN_MODE:
+ rlbm = 0;
+ awake_intvl = 2;
+ break;
+ case FW_PS_MAX_MODE:
+ rlbm = 1;
+ awake_intvl = 2;
+ break;
+ case FW_PS_DTIM_MODE:
+ rlbm = 2;
+ awake_intvl = ppsc->reg_max_lps_awakeintvl;
+ /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
+ * is only used in swlps.
+ */
+ break;
+ default:
+ rlbm = 2;
+ awake_intvl = 4;
+ break;
+ }
+
+ if (rtlpriv->mac80211.p2p) {
+ awake_intvl = 2;
+ rlbm = 1;
+ }
+
+ if (mode == FW_PS_ACTIVE_MODE) {
+ byte5 = 0x40;
+ power_state = FW_PWR_STATE_ACTIVE;
+ } else {
+ if (bt_ctrl_lps) {
+ byte5 = btc_ops->btc_get_lps_val(rtlpriv);
+ power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
+
+ if ((rlbm == 2) && (byte5 & BIT(4))) {
+ /* Keep awake interval to 1 to prevent from
+ * decreasing coex performance
+ */
+ awake_intvl = 2;
+ rlbm = 2;
+ }
+ } else {
+ byte5 = 0x40;
+ power_state = FW_PWR_STATE_RF_OFF;
+ }
+ }
SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
- rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
- (rtlpriv->mac80211.p2p) ?
- ppsc->smart_ps : 1);
+ bt_ctrl_lps ? 0 : ppsc->smart_ps);
SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
- ppsc->reg_max_lps_awakeintvl);
+ awake_intvl);
SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
- if (mode == FW_PS_ACTIVE_MODE)
- power_state |= FW_PWR_STATE_ACTIVE;
- else
- power_state |= FW_PWR_STATE_RF_OFF;
SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
+ SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
"rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
u1_h2c_set_pwrmode, H2C_PWEMODE_LENGTH);
+ if (rtlpriv->cfg->ops->get_btc_status())
+ btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
+ H2C_PWEMODE_LENGTH);
rtl8723be_fill_h2c_cmd(hw, H2C_8723B_SETPWRMODE, H2C_PWEMODE_LENGTH,
u1_h2c_set_pwrmode);
}
@@ -527,8 +584,7 @@ void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
u1rsvdpageloc, sizeof(u1rsvdpageloc));
skb = dev_alloc_skb(totalpacketlen);
- memcpy((u8 *)skb_put(skb, totalpacketlen),
- &reserved_page_packet, totalpacketlen);
+ skb_put_data(skb, &reserved_page_packet, totalpacketlen);
rtstatus = rtl_cmd_send_packet(hw, skb);
@@ -662,6 +718,7 @@ void rtl8723be_c2h_content_parsing(struct ieee80211_hw *hw,
case C2H_8723B_TX_REPORT:
RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
"[C2H], C2H_8723BE_TX_REPORT!\n");
+ rtl_tx_report_handler(hw, tmp_buf, c2h_cmd_len);
break;
case C2H_8723B_BT_INFO:
RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h
index 2482b3b..2de4edb 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h
@@ -33,7 +33,7 @@
#define USE_OLD_WOWLAN_DEBUG_FW 0
-#define H2C_PWEMODE_LENGTH 5
+#define H2C_PWEMODE_LENGTH 7
/* Fw PS state for RPWM.
*BIT[2:0] = HW state
@@ -125,6 +125,8 @@ enum rtl8723b_c2h_evt {
SET_BITS_TO_LE_1BYTE((__ph2ccmd)+3, 0, 8, __val)
#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__ph2ccmd, __val) \
SET_BITS_TO_LE_1BYTE((__ph2ccmd)+4, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_BYTE5(__ph2ccmd, __val) \
+ SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 5, 0, 8, __val)
#define GET_88E_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd) \
LE_BITS_TO_1BYTE(__ph2ccmd, 0, 8)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
index 1acbfb8..2a7ad5f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
@@ -846,6 +846,9 @@ static bool _rtl8723be_init_mac(struct ieee80211_hw *hw)
return false;
}
+ if (rtlpriv->cfg->ops->get_btc_status())
+ rtlpriv->btcoexist.btc_ops->btc_power_on_setting(rtlpriv);
+
bytetmp = rtl_read_byte(rtlpriv, REG_MULTI_FUNC_CTRL);
rtl_write_byte(rtlpriv, REG_MULTI_FUNC_CTRL, bytetmp | BIT(3));
@@ -1440,7 +1443,9 @@ int rtl8723be_hw_init(struct ieee80211_hw *hw)
*/
if (rtlpriv->btcoexist.btc_info.ant_num == ANT_X2 ||
!rtlpriv->cfg->ops->get_btc_status()) {
- rtl8723be_phy_iq_calibrate(hw, false);
+ rtl8723be_phy_iq_calibrate(hw,
+ (rtlphy->iqk_initialized ?
+ true : false));
rtlphy->iqk_initialized = true;
}
rtl8723be_dm_check_txpower_tracking(hw);
@@ -1674,7 +1679,8 @@ void rtl8723be_card_disable(struct ieee80211_hw *hw)
_rtl8723be_poweroff_adapter(hw);
/* after power off we should do iqk again */
- rtlpriv->phy.iqk_initialized = false;
+ if (!rtlpriv->cfg->ops->get_btc_status())
+ rtlpriv->phy.iqk_initialized = false;
}
void rtl8723be_interrupt_recognized(struct ieee80211_hw *hw,
@@ -2637,7 +2643,7 @@ void rtl8723be_set_key(struct ieee80211_hw *hw, u32 key_index,
"add one entry\n");
if (is_pairwise) {
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
- "set Pairwiase key\n");
+ "set Pairwise key\n");
rtl_cam_add_one_entry(hw, macaddr, key_index,
entry_id, enc_algo,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
index ab0f39e..9752175 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
@@ -2352,7 +2352,7 @@ void rtl8723be_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery)
if (b_recovery) {
rtl8723_phy_reload_adda_registers(hw, iqk_bb_reg,
rtlphy->iqk_bb_backup, 9);
- return;
+ goto label_done;
}
/* Save RF Path */
path_sel_bb = rtl_get_bbreg(hw, 0x948, MASKDWORD);
@@ -2460,6 +2460,7 @@ void rtl8723be_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery)
rtl_set_bbreg(hw, 0x948, MASKDWORD, path_sel_bb);
/* rtl_set_rfreg(hw, RF90_PATH_A, 0xb0, 0xfffff, path_sel_rf); */
+label_done:
spin_lock(&rtlpriv->locks.iqk_lock);
rtlphy->lck_inprogress = false;
spin_unlock(&rtlpriv->locks.iqk_lock);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h
index 03581d2..95c4f8e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h
@@ -261,7 +261,6 @@
#define REG_RD_NAV_NXT 0x0544
#define REG_NAV_PROT_LEN 0x0546
#define REG_BCN_CTRL 0x0550
-#define REG_USTIME_TSF 0x0551
#define REG_MBID_NUM 0x0552
#define REG_DUAL_TSF_RST 0x0553
#define REG_BCN_INTERVAL 0x0554
@@ -269,6 +268,7 @@
#define REG_DRVERLYINT 0x0558
#define REG_BCNDMATIM 0x0559
#define REG_ATIMWND 0x055A
+#define REG_USTIME_TSF 0x055C
#define REG_BCN_MAX_ERR 0x055D
#define REG_RXTSF_OFFSET_CCK 0x055E
#define REG_RXTSF_OFFSET_OFDM 0x055F
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
index 8c0ac96..f9d10f1 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
@@ -155,8 +155,8 @@ int rtl8723be_init_sw_vars(struct ieee80211_hw *hw)
rtlpriv->cfg->mod_params->disable_watchdog;
if (rtlpriv->cfg->mod_params->disable_watchdog)
pr_info("watchdog disabled\n");
- rtlpriv->psc.reg_fwctrl_lps = 3;
- rtlpriv->psc.reg_max_lps_awakeintvl = 5;
+ rtlpriv->psc.reg_fwctrl_lps = 2;
+ rtlpriv->psc.reg_max_lps_awakeintvl = 2;
/* for ASPM, you can close aspm through
* set const_support_pciaspm = 0
*/
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c
index 3c6ce99..0e89441 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c
@@ -488,6 +488,9 @@ void rtl8723be_tx_fill_desc(struct ieee80211_hw *hw,
SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
}
+ /* tx report */
+ rtl_get_tx_report(ptcb_desc, pdesc, hw);
+
/* ptcb_desc->use_driver_rate = true; */
SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);
if (ptcb_desc->hw_rate > DESC92C_RATEMCS0)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h
index 8a9fe41..0274659 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h
@@ -107,7 +107,7 @@
#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val)
#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 8, 14, 2, __val)
#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val)
#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \
@@ -115,7 +115,7 @@
#define SET_TX_DESC_RAW(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val)
#define SET_TX_DESC_SPE_RPT(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 8, 19, 1, __val)
#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val)
#define SET_TX_DESC_BT_INT(__pdesc, __val) \
@@ -187,6 +187,18 @@
#define SET_TX_DESC_RTS_SC(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val)
+#define SET_TX_DESC_SW_DEFINE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 0, 12, __val)
+#define SET_TX_DESC_MBSSID(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 12, 4, __val)
+#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 16, 3, __val)
+#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 19, 3, __val)
+#define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 22, 3, __val)
+#define SET_TX_DESC_ANTSEL_D(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 25, 3, __val)
#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c
index 7335010..03259aa 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c
@@ -489,29 +489,86 @@ void rtl8821ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 u1_h2c_set_pwrmode[H2C_8821AE_PWEMODE_LENGTH] = { 0 };
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- u8 rlbm, power_state = 0;
+ u8 rlbm, power_state = 0, byte5 = 0;
+ u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
+ struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
+ bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
+ btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
+ bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
+ btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
+
+ if (bt_ctrl_lps)
+ mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
+
+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
+ mode, bt_ctrl_lps);
+
+ switch (mode) {
+ case FW_PS_MIN_MODE:
+ rlbm = 0;
+ awake_intvl = 2;
+ break;
+ case FW_PS_MAX_MODE:
+ rlbm = 1;
+ awake_intvl = 2;
+ break;
+ case FW_PS_DTIM_MODE:
+ rlbm = 2;
+ awake_intvl = ppsc->reg_max_lps_awakeintvl;
+ /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
+ * is only used in swlps.
+ */
+ break;
+ default:
+ rlbm = 2;
+ awake_intvl = 4;
+ break;
+ }
- RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
+ if (rtlpriv->mac80211.p2p) {
+ awake_intvl = 2;
+ rlbm = 1;
+ }
+
+ if (mode == FW_PS_ACTIVE_MODE) {
+ byte5 = 0x40;
+ power_state = FW_PWR_STATE_ACTIVE;
+ } else {
+ if (bt_ctrl_lps) {
+ byte5 = btc_ops->btc_get_lps_val(rtlpriv);
+ power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
+
+ if ((rlbm == 2) && (byte5 & BIT(4))) {
+ /* Keep awake interval to 1 to prevent from
+ * decreasing coex performance
+ */
+ awake_intvl = 2;
+ rlbm = 2;
+ }
+ } else {
+ byte5 = 0x40;
+ power_state = FW_PWR_STATE_RF_OFF;
+ }
+ }
SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
- rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
- (rtlpriv->mac80211.p2p) ?
- ppsc->smart_ps : 1);
+ bt_ctrl_lps ? 0 :
+ ((rtlpriv->mac80211.p2p) ?
+ ppsc->smart_ps : 1));
SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
- ppsc->reg_max_lps_awakeintvl);
+ awake_intvl);
SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
- if (mode == FW_PS_ACTIVE_MODE)
- power_state |= FW_PWR_STATE_ACTIVE;
- else
- power_state |= FW_PWR_STATE_RF_OFF;
-
SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
+ SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
"rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
u1_h2c_set_pwrmode, H2C_8821AE_PWEMODE_LENGTH);
+ if (rtlpriv->cfg->ops->get_btc_status())
+ btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
+ H2C_8821AE_PWEMODE_LENGTH);
rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_SETPWRMODE,
H2C_8821AE_PWEMODE_LENGTH,
u1_h2c_set_pwrmode);
@@ -1588,8 +1645,7 @@ out:
&reserved_page_packet_8812[0], totalpacketlen);
skb = dev_alloc_skb(totalpacketlen);
- memcpy((u8 *)skb_put(skb, totalpacketlen),
- &reserved_page_packet_8812, totalpacketlen);
+ skb_put_data(skb, &reserved_page_packet_8812, totalpacketlen);
rtstatus = rtl_cmd_send_packet(hw, skb);
@@ -1725,8 +1781,7 @@ out:
&reserved_page_packet_8821[0], totalpacketlen);
skb = dev_alloc_skb(totalpacketlen);
- memcpy((u8 *)skb_put(skb, totalpacketlen),
- &reserved_page_packet_8821, totalpacketlen);
+ skb_put_data(skb, &reserved_page_packet_8821, totalpacketlen);
rtstatus = rtl_cmd_send_packet(hw, skb);
@@ -1873,6 +1928,9 @@ void rtl8821ae_c2h_content_parsing(struct ieee80211_hw *hw,
case C2H_8812_DBG:
RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "[C2H], C2H_8812_DBG!!\n");
break;
+ case C2H_8812_TX_REPORT:
+ rtl_tx_report_handler(hw, tmp_buf, c2h_cmd_len);
+ break;
case C2H_8812_RA_RPT:
rtl8821ae_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len);
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h
index 98d871a..32d46d7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h
@@ -42,7 +42,7 @@
#define USE_OLD_WOWLAN_DEBUG_FW 0
#define H2C_8821AE_RSVDPAGE_LOC_LEN 5
-#define H2C_8821AE_PWEMODE_LENGTH 5
+#define H2C_8821AE_PWEMODE_LENGTH 7
#define H2C_8821AE_JOINBSSRPT_LENGTH 1
#define H2C_8821AE_AP_OFFLOAD_LENGTH 3
#define H2C_8821AE_WOWLAN_LENGTH 3
@@ -218,6 +218,8 @@ enum rtl8821a_h2c_cmd {
SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value)
#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value)
+#define SET_H2CCMD_PWRMODE_PARM_BYTE5(__cmd, __value) \
+ SET_BITS_TO_LE_1BYTE((__cmd) + 5, 0, 8, __value)
#define GET_8821AE_H2CCMD_PWRMODE_PARM_MODE(__cmd) \
LE_BITS_TO_1BYTE(__cmd, 0, 8)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h
index ed69dbe..db8bc8a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h
@@ -267,7 +267,6 @@
#define REG_RD_NAV_NXT 0x0544
#define REG_NAV_PROT_LEN 0x0546
#define REG_BCN_CTRL 0x0550
-#define REG_USTIME_TSF 0x0551
#define REG_MBID_NUM 0x0552
#define REG_DUAL_TSF_RST 0x0553
#define REG_BCN_INTERVAL 0x0554
@@ -275,6 +274,7 @@
#define REG_DRVERLYINT 0x0558
#define REG_BCNDMATIM 0x0559
#define REG_ATIMWND 0x055A
+#define REG_USTIME_TSF 0x055C
#define REG_BCN_MAX_ERR 0x055D
#define REG_RXTSF_OFFSET_CCK 0x055E
#define REG_RXTSF_OFFSET_OFDM 0x055F
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
index abaf34c..d71d277 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
@@ -172,8 +172,8 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
rtlpriv->cfg->mod_params->disable_watchdog;
if (rtlpriv->cfg->mod_params->disable_watchdog)
pr_info("watchdog disabled\n");
- rtlpriv->psc.reg_fwctrl_lps = 3;
- rtlpriv->psc.reg_max_lps_awakeintvl = 5;
+ rtlpriv->psc.reg_fwctrl_lps = 2;
+ rtlpriv->psc.reg_max_lps_awakeintvl = 2;
/* for ASPM, you can close aspm through
* set const_support_pciaspm = 0
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c
index 03665e8..7498189 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c
@@ -740,6 +740,9 @@ void rtl8821ae_tx_fill_desc(struct ieee80211_hw *hw,
SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
}
+ /* tx report */
+ rtl_get_tx_report(ptcb_desc, pdesc, hw);
+
/* ptcb_desc->use_driver_rate = true; */
SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);
if (ptcb_desc->hw_rate > DESC_RATEMCS0)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h
index b6f3c56..9843a61 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h
@@ -114,7 +114,7 @@
#define SET_TX_DESC_RAW(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val)
#define SET_TX_DESC_SPE_RPT(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 8, 19, 1, __val)
#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val)
#define SET_TX_DESC_BT_INT(__pdesc, __val) \
@@ -185,8 +185,21 @@
#define SET_TX_DESC_RTS_SC(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val)
+#define SET_TX_DESC_SW_DEFINE(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 0, 12, __val)
+#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 16, 3, __val)
+#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 19, 3, __val)
+#define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 22, 3, __val)
+#define SET_TX_DESC_ANTSEL_D(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 24, 25, 3, __val)
+#define SET_TX_DESC_MBSSID(__pdesc, __val) \
+ SET_BITS_TO_LE_4BYTE(i(__pdesc) + 24, 12, 4, __val)
+
#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \
- SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val)
+ SET_BITS_TO_LE_4BYTE((__pdesc) + 28, 0, 16, __val)
#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+28, 0, 16)
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
index 4d989b8..5590d07 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -653,7 +653,7 @@ static void _rtl_rx_completed(struct urb *_urb)
/* reserve some space for mac80211's radiotap */
skb_reserve(skb, __RADIO_TAP_SIZE_RSV);
- memcpy(skb_put(skb, size), _urb->transfer_buffer, size);
+ skb_put_data(skb, _urb->transfer_buffer, size);
skb_queue_tail(&rtlusb->rx_queue, skb);
tasklet_schedule(&rtlusb->rx_work_tasklet);
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
index c0d2601..fb1ebb0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -1886,6 +1886,13 @@ struct rtl_efuse {
u8 channel_plan;
};
+struct rtl_tx_report {
+ atomic_t sn;
+ u16 last_sent_sn;
+ unsigned long last_sent_time;
+ u16 last_recv_sn;
+};
+
struct rtl_ps_ctl {
bool pwrdomain_protect;
bool in_powersavemode;
@@ -2075,6 +2082,8 @@ struct rtl_tcb_desc {
u8 use_driver_rate:1;
u8 disable_ratefallback:1;
+ u8 use_spe_rpt:1;
+
u8 ratr_index;
u8 mac_id;
u8 hw_rate;
@@ -2324,6 +2333,7 @@ struct rtl_locks {
spinlock_t entry_list_lock;
spinlock_t usb_lock;
spinlock_t c2hcmd_lock;
+ spinlock_t scan_list_lock; /* lock for the scan list */
/*FW clock change */
spinlock_t fw_ps_lock;
@@ -2472,6 +2482,9 @@ struct rtl_btc_info {
u8 btcoexist;
u8 ant_num;
u8 single_ant_path;
+
+ u8 ap_num;
+ bool in_4way;
};
struct bt_coexist_info {
@@ -2534,6 +2547,7 @@ struct bt_coexist_info {
struct rtl_btc_ops {
void (*btc_init_variables) (struct rtl_priv *rtlpriv);
void (*btc_init_hal_vars) (struct rtl_priv *rtlpriv);
+ void (*btc_power_on_setting)(struct rtl_priv *rtlpriv);
void (*btc_init_hw_config) (struct rtl_priv *rtlpriv);
void (*btc_ips_notify) (struct rtl_priv *rtlpriv, u8 type);
void (*btc_lps_notify)(struct rtl_priv *rtlpriv, u8 type);
@@ -2550,6 +2564,13 @@ struct rtl_btc_ops {
bool (*btc_is_bt_disabled) (struct rtl_priv *rtlpriv);
void (*btc_special_packet_notify)(struct rtl_priv *rtlpriv,
u8 pkt_type);
+ void (*btc_record_pwr_mode)(struct rtl_priv *rtlpriv, u8 *buf, u8 len);
+ u8 (*btc_get_lps_val)(struct rtl_priv *rtlpriv);
+ u8 (*btc_get_rpwm_val)(struct rtl_priv *rtlpriv);
+ bool (*btc_is_bt_ctrl_lps)(struct rtl_priv *rtlpriv);
+ void (*btc_get_ampdu_cfg)(struct rtl_priv *rtlpriv, u8 *reject_agg,
+ u8 *ctrl_agg_size, u8 *agg_size);
+ bool (*btc_is_bt_lps_on)(struct rtl_priv *rtlpriv);
};
struct proxim {
@@ -2568,6 +2589,17 @@ struct rtl_c2hcmd {
u8 *val;
};
+struct rtl_bssid_entry {
+ struct list_head list;
+ u8 bssid[ETH_ALEN];
+ u32 age;
+};
+
+struct rtl_scan_list {
+ int num;
+ struct list_head list; /* sort by age */
+};
+
struct rtl_priv {
struct ieee80211_hw *hw;
struct completion firmware_loading_complete;
@@ -2588,6 +2620,8 @@ struct rtl_priv {
struct rtl_security sec;
struct rtl_efuse efuse;
struct rtl_led_ctl ledctl;
+ struct rtl_tx_report tx_report;
+ struct rtl_scan_list scan_list;
struct rtl_ps_ctl psc;
struct rate_adaptive ra;
diff --git a/drivers/net/wireless/rsi/Makefile b/drivers/net/wireless/rsi/Makefile
index 25828b6..a475c81 100644
--- a/drivers/net/wireless/rsi/Makefile
+++ b/drivers/net/wireless/rsi/Makefile
@@ -2,7 +2,7 @@ rsi_91x-y += rsi_91x_main.o
rsi_91x-y += rsi_91x_core.o
rsi_91x-y += rsi_91x_mac80211.o
rsi_91x-y += rsi_91x_mgmt.o
-rsi_91x-y += rsi_91x_pkt.o
+rsi_91x-y += rsi_91x_hal.o
rsi_91x-$(CONFIG_RSI_DEBUGFS) += rsi_91x_debugfs.o
rsi_usb-y += rsi_91x_usb.o rsi_91x_usb_ops.o
diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c
index f3d3995..68f04a7 100644
--- a/drivers/net/wireless/rsi/rsi_91x_core.c
+++ b/drivers/net/wireless/rsi/rsi_91x_core.c
@@ -306,7 +306,7 @@ void rsi_core_qos_processor(struct rsi_common *common)
tstamp_2 = jiffies;
mutex_unlock(&common->tx_rxlock);
- if (tstamp_2 > tstamp_1 + (300 * HZ / 1000))
+ if (time_after(tstamp_2, tstamp_1 + (300 * HZ) / 1000))
schedule();
}
}
diff --git a/drivers/net/wireless/rsi/rsi_91x_debugfs.c b/drivers/net/wireless/rsi/rsi_91x_debugfs.c
index 828a042..4c0a493 100644
--- a/drivers/net/wireless/rsi/rsi_91x_debugfs.c
+++ b/drivers/net/wireless/rsi/rsi_91x_debugfs.c
@@ -125,7 +125,9 @@ static int rsi_stats_read(struct seq_file *seq, void *data)
struct rsi_common *common = seq->private;
unsigned char fsm_state[][32] = {
+ "FSM_FW_NOT_LOADED",
"FSM_CARD_NOT_READY",
+ "FSM_COMMON_DEV_PARAMS_SENT",
"FSM_BOOT_PARAMS_SENT",
"FSM_EEPROM_READ_MAC_ADDR",
"FSM_RESET_MAC_SENT",
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
new file mode 100644
index 0000000..c230359
--- /dev/null
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -0,0 +1,742 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/firmware.h>
+#include "rsi_mgmt.h"
+#include "rsi_hal.h"
+#include "rsi_sdio.h"
+
+/* FLASH Firmware */
+static struct ta_metadata metadata_flash_content[] = {
+ {"flash_content", 0x00010000},
+ {"rsi/rs9113_wlan_qspi.rps", 0x00010000},
+};
+
+/**
+ * rsi_send_data_pkt() - This function sends the recieved data packet from
+ * driver to device.
+ * @common: Pointer to the driver private structure.
+ * @skb: Pointer to the socket buffer structure.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct ieee80211_hdr *tmp_hdr;
+ struct ieee80211_tx_info *info;
+ struct skb_info *tx_params;
+ struct ieee80211_bss_conf *bss;
+ int status;
+ u8 ieee80211_size = MIN_802_11_HDR_LEN;
+ u8 extnd_size;
+ __le16 *frame_desc;
+ u16 seq_num;
+
+ info = IEEE80211_SKB_CB(skb);
+ bss = &info->control.vif->bss_conf;
+ tx_params = (struct skb_info *)info->driver_data;
+
+ if (!bss->assoc) {
+ status = -EINVAL;
+ goto err;
+ }
+
+ tmp_hdr = (struct ieee80211_hdr *)&skb->data[0];
+ seq_num = (le16_to_cpu(tmp_hdr->seq_ctrl) >> 4);
+
+ extnd_size = ((uintptr_t)skb->data & 0x3);
+
+ if ((FRAME_DESC_SZ + extnd_size) > skb_headroom(skb)) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__);
+ status = -ENOSPC;
+ goto err;
+ }
+
+ skb_push(skb, (FRAME_DESC_SZ + extnd_size));
+ frame_desc = (__le16 *)&skb->data[0];
+ memset((u8 *)frame_desc, 0, FRAME_DESC_SZ);
+
+ if (ieee80211_is_data_qos(tmp_hdr->frame_control)) {
+ ieee80211_size += 2;
+ frame_desc[6] |= cpu_to_le16(BIT(12));
+ }
+
+ if ((!(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) &&
+ (common->secinfo.security_enable)) {
+ if (rsi_is_cipher_wep(common))
+ ieee80211_size += 4;
+ else
+ ieee80211_size += 8;
+ frame_desc[6] |= cpu_to_le16(BIT(15));
+ }
+
+ frame_desc[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) |
+ (RSI_WIFI_DATA_Q << 12));
+ frame_desc[2] = cpu_to_le16((extnd_size) | (ieee80211_size) << 8);
+
+ if (common->min_rate != 0xffff) {
+ /* Send fixed rate */
+ frame_desc[3] = cpu_to_le16(RATE_INFO_ENABLE);
+ frame_desc[4] = cpu_to_le16(common->min_rate);
+
+ if (conf_is_ht40(&common->priv->hw->conf))
+ frame_desc[5] = cpu_to_le16(FULL40M_ENABLE);
+
+ if (common->vif_info[0].sgi) {
+ if (common->min_rate & 0x100) /* Only MCS rates */
+ frame_desc[4] |=
+ cpu_to_le16(ENABLE_SHORTGI_RATE);
+ }
+
+ }
+
+ frame_desc[6] |= cpu_to_le16(seq_num & 0xfff);
+ frame_desc[7] = cpu_to_le16(((tx_params->tid & 0xf) << 4) |
+ (skb->priority & 0xf) |
+ (tx_params->sta_id << 8));
+
+ status = adapter->host_intf_ops->write_pkt(common->priv, skb->data,
+ skb->len);
+ if (status)
+ rsi_dbg(ERR_ZONE, "%s: Failed to write pkt\n",
+ __func__);
+
+err:
+ ++common->tx_stats.total_tx_pkt_freed[skb->priority];
+ rsi_indicate_tx_status(common->priv, skb, status);
+ return status;
+}
+
+/**
+ * rsi_send_mgmt_pkt() - This functions sends the received management packet
+ * from driver to device.
+ * @common: Pointer to the driver private structure.
+ * @skb: Pointer to the socket buffer structure.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+int rsi_send_mgmt_pkt(struct rsi_common *common,
+ struct sk_buff *skb)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct ieee80211_hdr *wh;
+ struct ieee80211_tx_info *info;
+ struct ieee80211_bss_conf *bss;
+ struct ieee80211_hw *hw = adapter->hw;
+ struct ieee80211_conf *conf = &hw->conf;
+ struct skb_info *tx_params;
+ int status = -E2BIG;
+ __le16 *msg;
+ u8 extnd_size;
+ u8 vap_id = 0;
+
+ info = IEEE80211_SKB_CB(skb);
+ tx_params = (struct skb_info *)info->driver_data;
+ extnd_size = ((uintptr_t)skb->data & 0x3);
+
+ if (tx_params->flags & INTERNAL_MGMT_PKT) {
+ if ((extnd_size) > skb_headroom(skb)) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__);
+ dev_kfree_skb(skb);
+ return -ENOSPC;
+ }
+ skb_push(skb, extnd_size);
+ skb->data[extnd_size + 4] = extnd_size;
+ status = adapter->host_intf_ops->write_pkt(common->priv,
+ (u8 *)skb->data,
+ skb->len);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to write the packet\n", __func__);
+ }
+ dev_kfree_skb(skb);
+ return status;
+ }
+
+ bss = &info->control.vif->bss_conf;
+ wh = (struct ieee80211_hdr *)&skb->data[0];
+
+ if (FRAME_DESC_SZ > skb_headroom(skb))
+ goto err;
+
+ skb_push(skb, FRAME_DESC_SZ);
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ msg = (__le16 *)skb->data;
+
+ if (skb->len > MAX_MGMT_PKT_SIZE) {
+ rsi_dbg(INFO_ZONE, "%s: Dropping mgmt pkt > 512\n", __func__);
+ goto err;
+ }
+
+ msg[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) |
+ (RSI_WIFI_MGMT_Q << 12));
+ msg[1] = cpu_to_le16(TX_DOT11_MGMT);
+ msg[2] = cpu_to_le16(MIN_802_11_HDR_LEN << 8);
+ msg[3] = cpu_to_le16(RATE_INFO_ENABLE);
+ msg[6] = cpu_to_le16(le16_to_cpu(wh->seq_ctrl) >> 4);
+
+ if (wh->addr1[0] & BIT(0))
+ msg[3] |= cpu_to_le16(RSI_BROADCAST_PKT);
+
+ if (common->band == NL80211_BAND_2GHZ)
+ msg[4] = cpu_to_le16(RSI_11B_MODE);
+ else
+ msg[4] = cpu_to_le16((RSI_RATE_6 & 0x0f) | RSI_11G_MODE);
+
+ if (conf_is_ht40(conf)) {
+ msg[4] = cpu_to_le16(0xB | RSI_11G_MODE);
+ msg[5] = cpu_to_le16(0x6);
+ }
+
+ /* Indicate to firmware to give cfm */
+ if ((skb->data[16] == IEEE80211_STYPE_PROBE_REQ) && (!bss->assoc)) {
+ msg[1] |= cpu_to_le16(BIT(10));
+ msg[7] = cpu_to_le16(PROBEREQ_CONFIRM);
+ common->mgmt_q_block = true;
+ }
+
+ msg[7] |= cpu_to_le16(vap_id << 8);
+
+ status = adapter->host_intf_ops->write_pkt(common->priv, (u8 *)msg,
+ skb->len);
+ if (status)
+ rsi_dbg(ERR_ZONE, "%s: Failed to write the packet\n", __func__);
+
+err:
+ rsi_indicate_tx_status(common->priv, skb, status);
+ return status;
+}
+
+static void bl_cmd_timeout(unsigned long priv)
+{
+ struct rsi_hw *adapter = (struct rsi_hw *)priv;
+
+ adapter->blcmd_timer_expired = true;
+ del_timer(&adapter->bl_cmd_timer);
+}
+
+static int bl_start_cmd_timer(struct rsi_hw *adapter, u32 timeout)
+{
+ init_timer(&adapter->bl_cmd_timer);
+ adapter->bl_cmd_timer.data = (unsigned long)adapter;
+ adapter->bl_cmd_timer.function = (void *)&bl_cmd_timeout;
+ adapter->bl_cmd_timer.expires = (msecs_to_jiffies(timeout) + jiffies);
+
+ adapter->blcmd_timer_expired = false;
+ add_timer(&adapter->bl_cmd_timer);
+
+ return 0;
+}
+
+static int bl_stop_cmd_timer(struct rsi_hw *adapter)
+{
+ adapter->blcmd_timer_expired = false;
+ if (timer_pending(&adapter->bl_cmd_timer))
+ del_timer(&adapter->bl_cmd_timer);
+
+ return 0;
+}
+
+static int bl_write_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp,
+ u16 *cmd_resp)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ u32 regin_val = 0, regout_val = 0;
+ u32 regin_input = 0;
+ u8 output = 0;
+ int status;
+
+ regin_input = (REGIN_INPUT | adapter->priv->coex_mode);
+
+ while (!adapter->blcmd_timer_expired) {
+ regin_val = 0;
+ status = hif_ops->master_reg_read(adapter, SWBL_REGIN,
+ &regin_val, 2);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGIN reading failed..\n",
+ __func__, cmd);
+ return status;
+ }
+ mdelay(1);
+ if ((regin_val >> 12) != REGIN_VALID)
+ break;
+ }
+ if (adapter->blcmd_timer_expired) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGIN reading timed out..\n",
+ __func__, cmd);
+ return -ETIMEDOUT;
+ }
+
+ rsi_dbg(INFO_ZONE,
+ "Issuing write to Regin val:%0x sending cmd:%0x\n",
+ regin_val, (cmd | regin_input << 8));
+ status = hif_ops->master_reg_write(adapter, SWBL_REGIN,
+ (cmd | regin_input << 8), 2);
+ if (status < 0)
+ return status;
+ mdelay(1);
+
+ if (cmd == LOAD_HOSTED_FW || cmd == JUMP_TO_ZERO_PC) {
+ /* JUMP_TO_ZERO_PC doesn't expect
+ * any response. So return from here
+ */
+ return 0;
+ }
+
+ while (!adapter->blcmd_timer_expired) {
+ regout_val = 0;
+ status = hif_ops->master_reg_read(adapter, SWBL_REGOUT,
+ &regout_val, 2);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGOUT reading failed..\n",
+ __func__, cmd);
+ return status;
+ }
+ mdelay(1);
+ if ((regout_val >> 8) == REGOUT_VALID)
+ break;
+ }
+ if (adapter->blcmd_timer_expired) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGOUT reading timed out..\n",
+ __func__, cmd);
+ return status;
+ }
+
+ *cmd_resp = ((u16 *)&regout_val)[0] & 0xffff;
+
+ output = ((u8 *)&regout_val)[0] & 0xff;
+
+ status = hif_ops->master_reg_write(adapter, SWBL_REGOUT,
+ (cmd | REGOUT_INVALID << 8), 2);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGOUT writing failed..\n",
+ __func__, cmd);
+ return status;
+ }
+ mdelay(1);
+
+ if (output != exp_resp) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Recvd resp %x for cmd %0x\n",
+ __func__, output, cmd);
+ return -EINVAL;
+ }
+ rsi_dbg(INFO_ZONE,
+ "%s: Recvd Expected resp %x for cmd %0x\n",
+ __func__, output, cmd);
+
+ return 0;
+}
+
+static int bl_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp, char *str)
+{
+ u16 regout_val = 0;
+ u32 timeout;
+ int status;
+
+ if ((cmd == EOF_REACHED) || (cmd == PING_VALID) || (cmd == PONG_VALID))
+ timeout = BL_BURN_TIMEOUT;
+ else
+ timeout = BL_CMD_TIMEOUT;
+
+ bl_start_cmd_timer(adapter, timeout);
+ status = bl_write_cmd(adapter, cmd, exp_resp, &regout_val);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %s (%0x) writing failed..\n",
+ __func__, str, cmd);
+ return status;
+ }
+ bl_stop_cmd_timer(adapter);
+ return 0;
+}
+
+#define CHECK_SUM_OFFSET 20
+#define LEN_OFFSET 8
+#define ADDR_OFFSET 16
+static int bl_write_header(struct rsi_hw *adapter, u8 *flash_content,
+ u32 content_size)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ struct bl_header bl_hdr;
+ u32 write_addr, write_len;
+ int status;
+
+ bl_hdr.flags = 0;
+ bl_hdr.image_no = cpu_to_le32(adapter->priv->coex_mode);
+ bl_hdr.check_sum = cpu_to_le32(
+ *(u32 *)&flash_content[CHECK_SUM_OFFSET]);
+ bl_hdr.flash_start_address = cpu_to_le32(
+ *(u32 *)&flash_content[ADDR_OFFSET]);
+ bl_hdr.flash_len = cpu_to_le32(*(u32 *)&flash_content[LEN_OFFSET]);
+ write_len = sizeof(struct bl_header);
+
+ if (adapter->rsi_host_intf == RSI_HOST_INTF_USB) {
+ write_addr = PING_BUFFER_ADDRESS;
+ status = hif_ops->write_reg_multiple(adapter, write_addr,
+ (u8 *)&bl_hdr, write_len);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to load Version/CRC structure\n",
+ __func__);
+ return status;
+ }
+ } else {
+ write_addr = PING_BUFFER_ADDRESS >> 16;
+ status = hif_ops->master_access_msword(adapter, write_addr);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word to common reg\n",
+ __func__);
+ return status;
+ }
+ write_addr = RSI_SD_REQUEST_MASTER |
+ (PING_BUFFER_ADDRESS & 0xFFFF);
+ status = hif_ops->write_reg_multiple(adapter, write_addr,
+ (u8 *)&bl_hdr, write_len);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to load Version/CRC structure\n",
+ __func__);
+ return status;
+ }
+ }
+ return 0;
+}
+
+static u32 read_flash_capacity(struct rsi_hw *adapter)
+{
+ u32 flash_sz = 0;
+
+ if ((adapter->host_intf_ops->master_reg_read(adapter, FLASH_SIZE_ADDR,
+ &flash_sz, 2)) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash size reading failed..\n",
+ __func__);
+ return 0;
+ }
+ rsi_dbg(INIT_ZONE, "Flash capacity: %d KiloBytes\n", flash_sz);
+
+ return (flash_sz * 1024); /* Return size in kbytes */
+}
+
+static int ping_pong_write(struct rsi_hw *adapter, u8 cmd, u8 *addr, u32 size)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ u32 block_size = adapter->block_size;
+ u32 cmd_addr;
+ u16 cmd_resp, cmd_req;
+ u8 *str;
+ int status;
+
+ if (cmd == PING_WRITE) {
+ cmd_addr = PING_BUFFER_ADDRESS;
+ cmd_resp = PONG_AVAIL;
+ cmd_req = PING_VALID;
+ str = "PING_VALID";
+ } else {
+ cmd_addr = PONG_BUFFER_ADDRESS;
+ cmd_resp = PING_AVAIL;
+ cmd_req = PONG_VALID;
+ str = "PONG_VALID";
+ }
+
+ status = hif_ops->load_data_master_write(adapter, cmd_addr, size,
+ block_size, addr);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to write blk at addr %0x\n",
+ __func__, *addr);
+ return status;
+ }
+
+ status = bl_cmd(adapter, cmd_req, cmd_resp, str);
+ if (status) {
+ bl_stop_cmd_timer(adapter);
+ return status;
+ }
+ return 0;
+}
+
+static int auto_fw_upgrade(struct rsi_hw *adapter, u8 *flash_content,
+ u32 content_size)
+{
+ u8 cmd, *temp_flash_content;
+ u32 temp_content_size, num_flash, index;
+ u32 flash_start_address;
+ int status;
+
+ temp_flash_content = flash_content;
+
+ if (content_size > MAX_FLASH_FILE_SIZE) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash Content size is more than 400K %u\n",
+ __func__, MAX_FLASH_FILE_SIZE);
+ return -EINVAL;
+ }
+
+ flash_start_address = *(u32 *)&flash_content[FLASH_START_ADDRESS];
+ rsi_dbg(INFO_ZONE, "flash start address: %08x\n", flash_start_address);
+
+ if (flash_start_address < FW_IMAGE_MIN_ADDRESS) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Fw image Flash Start Address is less than 64K\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (flash_start_address % FLASH_SECTOR_SIZE) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash Start Address is not multiple of 4K\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if ((flash_start_address + content_size) > adapter->flash_capacity) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash Content will cross max flash size\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ temp_content_size = content_size;
+ num_flash = content_size / FLASH_WRITE_CHUNK_SIZE;
+
+ rsi_dbg(INFO_ZONE, "content_size: %d, num_flash: %d\n",
+ content_size, num_flash);
+
+ for (index = 0; index <= num_flash; index++) {
+ rsi_dbg(INFO_ZONE, "flash index: %d\n", index);
+ if (index != num_flash) {
+ content_size = FLASH_WRITE_CHUNK_SIZE;
+ rsi_dbg(INFO_ZONE, "QSPI content_size:%d\n",
+ content_size);
+ } else {
+ content_size =
+ temp_content_size % FLASH_WRITE_CHUNK_SIZE;
+ rsi_dbg(INFO_ZONE,
+ "Writing last sector content_size:%d\n",
+ content_size);
+ if (!content_size) {
+ rsi_dbg(INFO_ZONE, "instruction size zero\n");
+ break;
+ }
+ }
+
+ if (index % 2)
+ cmd = PING_WRITE;
+ else
+ cmd = PONG_WRITE;
+
+ status = ping_pong_write(adapter, cmd, flash_content,
+ content_size);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to load %d block\n",
+ __func__, index);
+ return status;
+ }
+
+ rsi_dbg(INFO_ZONE,
+ "%s: Successfully loaded %d instructions\n",
+ __func__, index);
+ flash_content += content_size;
+ }
+
+ status = bl_cmd(adapter, EOF_REACHED, FW_LOADING_SUCCESSFUL,
+ "EOF_REACHED");
+ if (status) {
+ bl_stop_cmd_timer(adapter);
+ return status;
+ }
+ rsi_dbg(INFO_ZONE, "FW loading is done and FW is running..\n");
+ return 0;
+}
+
+static int rsi_load_firmware(struct rsi_hw *adapter)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ const struct firmware *fw_entry = NULL;
+ u32 regout_val = 0, content_size;
+ u16 tmp_regout_val = 0;
+ u8 *flash_content = NULL;
+ struct ta_metadata *metadata_p;
+ int status;
+
+ bl_start_cmd_timer(adapter, BL_CMD_TIMEOUT);
+
+ while (!adapter->blcmd_timer_expired) {
+ status = hif_ops->master_reg_read(adapter, SWBL_REGOUT,
+ &regout_val, 2);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: REGOUT read failed\n", __func__);
+ return status;
+ }
+ mdelay(1);
+ if ((regout_val >> 8) == REGOUT_VALID)
+ break;
+ }
+ if (adapter->blcmd_timer_expired) {
+ rsi_dbg(ERR_ZONE, "%s: REGOUT read timedout\n", __func__);
+ rsi_dbg(ERR_ZONE,
+ "%s: Soft boot loader not present\n", __func__);
+ return -ETIMEDOUT;
+ }
+ bl_stop_cmd_timer(adapter);
+
+ rsi_dbg(INFO_ZONE, "Received Board Version Number: %x\n",
+ (regout_val & 0xff));
+
+ status = hif_ops->master_reg_write(adapter, SWBL_REGOUT,
+ (REGOUT_INVALID | REGOUT_INVALID << 8),
+ 2);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: REGOUT writing failed..\n", __func__);
+ return status;
+ }
+ mdelay(1);
+
+ status = bl_cmd(adapter, CONFIG_AUTO_READ_MODE, CMD_PASS,
+ "AUTO_READ_CMD");
+ if (status < 0)
+ return status;
+
+ adapter->flash_capacity = read_flash_capacity(adapter);
+ if (adapter->flash_capacity <= 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to read flash size from EEPROM\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ metadata_p = &metadata_flash_content[adapter->priv->coex_mode];
+
+ rsi_dbg(INIT_ZONE, "%s: Loading file %s\n", __func__, metadata_p->name);
+ adapter->fw_file_name = metadata_p->name;
+
+ status = request_firmware(&fw_entry, metadata_p->name, adapter->device);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to open file %s\n",
+ __func__, metadata_p->name);
+ return status;
+ }
+ flash_content = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
+ if (!flash_content) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to copy firmware\n", __func__);
+ status = -EIO;
+ goto fail;
+ }
+ content_size = fw_entry->size;
+ rsi_dbg(INFO_ZONE, "FW Length = %d bytes\n", content_size);
+
+ status = bl_write_header(adapter, flash_content, content_size);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: RPS Image header loading failed\n",
+ __func__);
+ goto fail;
+ }
+
+ bl_start_cmd_timer(adapter, BL_CMD_TIMEOUT);
+ status = bl_write_cmd(adapter, CHECK_CRC, CMD_PASS, &tmp_regout_val);
+ if (status) {
+ bl_stop_cmd_timer(adapter);
+ rsi_dbg(ERR_ZONE,
+ "%s: CHECK_CRC Command writing failed..\n",
+ __func__);
+ if ((tmp_regout_val & 0xff) == CMD_FAIL) {
+ rsi_dbg(ERR_ZONE,
+ "CRC Fail.. Proceeding to Upgrade mode\n");
+ goto fw_upgrade;
+ }
+ }
+ bl_stop_cmd_timer(adapter);
+
+ status = bl_cmd(adapter, POLLING_MODE, CMD_PASS, "POLLING_MODE");
+ if (status)
+ goto fail;
+
+load_image_cmd:
+ status = bl_cmd(adapter, LOAD_HOSTED_FW, LOADING_INITIATED,
+ "LOAD_HOSTED_FW");
+ if (status)
+ goto fail;
+ rsi_dbg(INFO_ZONE, "Load Image command passed..\n");
+ goto success;
+
+fw_upgrade:
+ status = bl_cmd(adapter, BURN_HOSTED_FW, SEND_RPS_FILE, "FW_UPGRADE");
+ if (status)
+ goto fail;
+
+ rsi_dbg(INFO_ZONE, "Burn Command Pass.. Upgrading the firmware\n");
+
+ status = auto_fw_upgrade(adapter, flash_content, content_size);
+ if (status == 0) {
+ rsi_dbg(ERR_ZONE, "Firmware upgradation Done\n");
+ goto load_image_cmd;
+ }
+ rsi_dbg(ERR_ZONE, "Firmware upgrade failed\n");
+
+ status = bl_cmd(adapter, CONFIG_AUTO_READ_MODE, CMD_PASS,
+ "AUTO_READ_MODE");
+ if (status)
+ goto fail;
+
+success:
+ rsi_dbg(ERR_ZONE, "***** Firmware Loading successful *****\n");
+ kfree(flash_content);
+ release_firmware(fw_entry);
+ return 0;
+
+fail:
+ rsi_dbg(ERR_ZONE, "##### Firmware loading failed #####\n");
+ kfree(flash_content);
+ release_firmware(fw_entry);
+ return status;
+}
+
+int rsi_hal_device_init(struct rsi_hw *adapter)
+{
+ struct rsi_common *common = adapter->priv;
+
+ common->coex_mode = RSI_DEV_COEX_MODE_WIFI_ALONE;
+ common->oper_mode = RSI_DEV_OPMODE_WIFI_ALONE;
+ adapter->device_model = RSI_DEV_9113;
+
+ switch (adapter->device_model) {
+ case RSI_DEV_9113:
+ if (rsi_load_firmware(adapter)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to load TA instructions\n",
+ __func__);
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ common->fsm_state = FSM_CARD_NOT_READY;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rsi_hal_device_init);
+
diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index 8810862..f1cde0c 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -123,9 +123,16 @@ int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len)
queueno = rsi_get_queueno(frame_desc, offset);
length = rsi_get_length(frame_desc, offset);
- extended_desc = rsi_get_extended_desc(frame_desc, offset);
+
+ /* Extended descriptor is valid for WLAN queues only */
+ if (queueno == RSI_WIFI_DATA_Q || queueno == RSI_WIFI_MGMT_Q)
+ extended_desc = rsi_get_extended_desc(frame_desc,
+ offset);
switch (queueno) {
+ case RSI_COEX_Q:
+ rsi_mgmt_pkt_recv(common, (frame_desc + offset));
+ break;
case RSI_WIFI_DATA_Q:
skb = rsi_prepare_skb(common,
(frame_desc + offset),
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index fac87c0..d4d365b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -45,10 +45,10 @@ static struct bootup_params boot_params_20 = {
}
},
.switch_clk_g = {
- .switch_clk_info = cpu_to_le16(BIT(3)),
- .bbp_lmac_clk_reg_val = cpu_to_le16(0x121),
- .umac_clock_reg_config = 0x0,
- .qspi_uart_clock_reg_config = 0x0
+ .switch_clk_info = cpu_to_le16(0xb),
+ .bbp_lmac_clk_reg_val = cpu_to_le16(0x111),
+ .umac_clock_reg_config = cpu_to_le16(0x48),
+ .qspi_uart_clock_reg_config = cpu_to_le16(0x1211)
}
},
{
@@ -106,7 +106,10 @@ static struct bootup_params boot_params_20 = {
.wdt_prog_value = 0x0,
.wdt_soc_rst_delay = 0x0,
.dcdc_operation_mode = 0x0,
- .soc_reset_wait_cnt = 0x0
+ .soc_reset_wait_cnt = 0x0,
+ .waiting_time_at_fresh_sleep = 0x0,
+ .max_threshold_to_avoid_sleep = 0x0,
+ .beacon_resedue_alg_en = 0,
};
static struct bootup_params boot_params_40 = {
@@ -139,7 +142,7 @@ static struct bootup_params boot_params_40 = {
.switch_clk_info = cpu_to_le16(0x09),
.bbp_lmac_clk_reg_val = cpu_to_le16(0x1121),
.umac_clock_reg_config = cpu_to_le16(0x48),
- .qspi_uart_clock_reg_config = 0x0
+ .qspi_uart_clock_reg_config = cpu_to_le16(0x1211)
}
},
{
@@ -197,7 +200,10 @@ static struct bootup_params boot_params_40 = {
.wdt_prog_value = 0x0,
.wdt_soc_rst_delay = 0x0,
.dcdc_operation_mode = 0x0,
- .soc_reset_wait_cnt = 0x0
+ .soc_reset_wait_cnt = 0x0,
+ .waiting_time_at_fresh_sleep = 0x0,
+ .max_threshold_to_avoid_sleep = 0x0,
+ .beacon_resedue_alg_en = 0,
};
static u16 mcs[] = {13, 26, 39, 52, 78, 104, 117, 130};
@@ -218,6 +224,12 @@ static void rsi_set_default_parameters(struct rsi_common *common)
common->fsm_state = FSM_CARD_NOT_READY;
common->iface_down = true;
common->endpoint = EP_2GHZ_20MHZ;
+ common->driver_mode = 1; /* End to end mode */
+ common->lp_ps_handshake_mode = 0; /* Default no handShake mode*/
+ common->ulp_ps_handshake_mode = 2; /* Default PKT handShake mode*/
+ common->rf_power_val = 0; /* Default 1.9V */
+ common->wlan_rf_power_mode = 0;
+ common->obm_ant_sel_val = 2;
}
/**
@@ -389,9 +401,7 @@ static int rsi_mgmt_pkt_to_core(struct rsi_common *common,
struct ieee80211_tx_info *info;
struct skb_info *rx_params;
u8 pad_bytes = msg[4];
- u8 pkt_recv;
struct sk_buff *skb;
- char *buffer;
if (type == RX_DOT11_MGMT) {
if (!adapter->sc_nvifs)
@@ -412,13 +422,9 @@ static int rsi_mgmt_pkt_to_core(struct rsi_common *common,
return -ENOMEM;
}
- buffer = skb_put(skb, msg_len);
-
- memcpy(buffer,
- (u8 *)(msg + FRAME_DESC_SZ + pad_bytes),
- msg_len);
-
- pkt_recv = buffer[0];
+ skb_put_data(skb,
+ (u8 *)(msg + FRAME_DESC_SZ + pad_bytes),
+ msg_len);
info = IEEE80211_SKB_CB(skb);
rx_params = (struct skb_info *)info->driver_data;
@@ -756,6 +762,53 @@ int rsi_hal_load_key(struct rsi_common *common,
}
/*
+ * This function sends the common device configuration parameters to device.
+ * This frame includes the useful information to make device works on
+ * specific operating mode.
+ */
+static int rsi_send_common_dev_params(struct rsi_common *common)
+{
+ struct sk_buff *skb;
+ u16 frame_len;
+ struct rsi_config_vals *dev_cfgs;
+
+ frame_len = sizeof(struct rsi_config_vals);
+
+ rsi_dbg(MGMT_TX_ZONE, "Sending common device config params\n");
+ skb = dev_alloc_skb(frame_len);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to allocate skb\n", __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, frame_len);
+
+ dev_cfgs = (struct rsi_config_vals *)skb->data;
+ memset(dev_cfgs, 0, (sizeof(struct rsi_config_vals)));
+
+ rsi_set_len_qno(&dev_cfgs->len_qno, (frame_len - FRAME_DESC_SZ),
+ RSI_COEX_Q);
+ dev_cfgs->pkt_type = COMMON_DEV_CONFIG;
+
+ dev_cfgs->lp_ps_handshake = common->lp_ps_handshake_mode;
+ dev_cfgs->ulp_ps_handshake = common->ulp_ps_handshake_mode;
+
+ dev_cfgs->unused_ulp_gpio = RSI_UNUSED_ULP_GPIO_BITMAP;
+ dev_cfgs->unused_soc_gpio_bitmap =
+ cpu_to_le32(RSI_UNUSED_SOC_GPIO_BITMAP);
+
+ dev_cfgs->opermode = common->oper_mode;
+ dev_cfgs->wlan_rf_pwr_mode = common->wlan_rf_power_mode;
+ dev_cfgs->driver_mode = common->driver_mode;
+ dev_cfgs->region_code = NL80211_DFS_FCC;
+ dev_cfgs->antenna_sel_val = common->obm_ant_sel_val;
+
+ skb_put(skb, frame_len);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/*
* rsi_load_bootup_params() - This function send bootup params to the firmware.
* @common: Pointer to the driver private structure.
*
@@ -1487,6 +1540,40 @@ out:
return -EINVAL;
}
+static int rsi_handle_card_ready(struct rsi_common *common, u8 *msg)
+{
+ switch (common->fsm_state) {
+ case FSM_CARD_NOT_READY:
+ rsi_dbg(INIT_ZONE, "Card ready indication from Common HAL\n");
+ rsi_set_default_parameters(common);
+ if (rsi_send_common_dev_params(common) < 0)
+ return -EINVAL;
+ common->fsm_state = FSM_COMMON_DEV_PARAMS_SENT;
+ break;
+ case FSM_COMMON_DEV_PARAMS_SENT:
+ rsi_dbg(INIT_ZONE, "Card ready indication from WLAN HAL\n");
+
+ /* Get usb buffer status register address */
+ common->priv->usb_buffer_status_reg = *(u32 *)&msg[8];
+ rsi_dbg(INFO_ZONE, "USB buffer status register = %x\n",
+ common->priv->usb_buffer_status_reg);
+
+ if (rsi_load_bootup_params(common)) {
+ common->fsm_state = FSM_CARD_NOT_READY;
+ return -EINVAL;
+ }
+ common->fsm_state = FSM_BOOT_PARAMS_SENT;
+ break;
+ default:
+ rsi_dbg(ERR_ZONE,
+ "%s: card ready indication in invalid state %d.\n",
+ __func__, common->fsm_state);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/**
* rsi_mgmt_pkt_recv() - This function processes the management packets
* recieved from the hardware.
@@ -1499,7 +1586,6 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
{
s32 msg_len = (le16_to_cpu(*(__le16 *)&msg[0]) & 0x0fff);
u16 msg_type = (msg[2]);
- int ret;
rsi_dbg(FSM_ZONE, "%s: Msg Len: %d, Msg Type: %4x\n",
__func__, msg_len, msg_type);
@@ -1509,17 +1595,7 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
} else if (msg_type == CARD_READY_IND) {
rsi_dbg(FSM_ZONE, "%s: Card ready indication received\n",
__func__);
- if (common->fsm_state == FSM_CARD_NOT_READY) {
- rsi_set_default_parameters(common);
-
- ret = rsi_load_bootup_params(common);
- if (ret)
- return ret;
- else
- common->fsm_state = FSM_BOOT_PARAMS_SENT;
- } else {
- return -EINVAL;
- }
+ return rsi_handle_card_ready(common, msg);
} else if (msg_type == TX_STATUS_IND) {
if (msg[15] == PROBEREQ_CONFIRM) {
common->mgmt_q_block = false;
diff --git a/drivers/net/wireless/rsi/rsi_91x_pkt.c b/drivers/net/wireless/rsi/rsi_91x_pkt.c
deleted file mode 100644
index 02920c9..0000000
--- a/drivers/net/wireless/rsi/rsi_91x_pkt.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/**
- * Copyright (c) 2014 Redpine Signals Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "rsi_mgmt.h"
-
-/**
- * rsi_send_data_pkt() - This function sends the recieved data packet from
- * driver to device.
- * @common: Pointer to the driver private structure.
- * @skb: Pointer to the socket buffer structure.
- *
- * Return: status: 0 on success, -1 on failure.
- */
-int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
-{
- struct rsi_hw *adapter = common->priv;
- struct ieee80211_hdr *tmp_hdr;
- struct ieee80211_tx_info *info;
- struct skb_info *tx_params;
- struct ieee80211_bss_conf *bss;
- int status;
- u8 ieee80211_size = MIN_802_11_HDR_LEN;
- u8 extnd_size;
- __le16 *frame_desc;
- u16 seq_num;
-
- info = IEEE80211_SKB_CB(skb);
- bss = &info->control.vif->bss_conf;
- tx_params = (struct skb_info *)info->driver_data;
-
- if (!bss->assoc) {
- status = -EINVAL;
- goto err;
- }
-
- tmp_hdr = (struct ieee80211_hdr *)&skb->data[0];
- seq_num = (le16_to_cpu(tmp_hdr->seq_ctrl) >> 4);
-
- extnd_size = ((uintptr_t)skb->data & 0x3);
-
- if ((FRAME_DESC_SZ + extnd_size) > skb_headroom(skb)) {
- rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__);
- status = -ENOSPC;
- goto err;
- }
-
- skb_push(skb, (FRAME_DESC_SZ + extnd_size));
- frame_desc = (__le16 *)&skb->data[0];
- memset((u8 *)frame_desc, 0, FRAME_DESC_SZ);
-
- if (ieee80211_is_data_qos(tmp_hdr->frame_control)) {
- ieee80211_size += 2;
- frame_desc[6] |= cpu_to_le16(BIT(12));
- }
-
- if ((!(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) &&
- (common->secinfo.security_enable)) {
- if (rsi_is_cipher_wep(common))
- ieee80211_size += 4;
- else
- ieee80211_size += 8;
- frame_desc[6] |= cpu_to_le16(BIT(15));
- }
-
- frame_desc[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) |
- (RSI_WIFI_DATA_Q << 12));
- frame_desc[2] = cpu_to_le16((extnd_size) | (ieee80211_size) << 8);
-
- if (common->min_rate != 0xffff) {
- /* Send fixed rate */
- frame_desc[3] = cpu_to_le16(RATE_INFO_ENABLE);
- frame_desc[4] = cpu_to_le16(common->min_rate);
-
- if (conf_is_ht40(&common->priv->hw->conf))
- frame_desc[5] = cpu_to_le16(FULL40M_ENABLE);
-
- if (common->vif_info[0].sgi) {
- if (common->min_rate & 0x100) /* Only MCS rates */
- frame_desc[4] |=
- cpu_to_le16(ENABLE_SHORTGI_RATE);
- }
-
- }
-
- frame_desc[6] |= cpu_to_le16(seq_num & 0xfff);
- frame_desc[7] = cpu_to_le16(((tx_params->tid & 0xf) << 4) |
- (skb->priority & 0xf) |
- (tx_params->sta_id << 8));
-
- status = adapter->host_intf_write_pkt(common->priv,
- skb->data,
- skb->len);
- if (status)
- rsi_dbg(ERR_ZONE, "%s: Failed to write pkt\n",
- __func__);
-
-err:
- ++common->tx_stats.total_tx_pkt_freed[skb->priority];
- rsi_indicate_tx_status(common->priv, skb, status);
- return status;
-}
-
-/**
- * rsi_send_mgmt_pkt() - This functions sends the received management packet
- * from driver to device.
- * @common: Pointer to the driver private structure.
- * @skb: Pointer to the socket buffer structure.
- *
- * Return: status: 0 on success, -1 on failure.
- */
-int rsi_send_mgmt_pkt(struct rsi_common *common,
- struct sk_buff *skb)
-{
- struct rsi_hw *adapter = common->priv;
- struct ieee80211_hdr *wh;
- struct ieee80211_tx_info *info;
- struct ieee80211_bss_conf *bss;
- struct ieee80211_hw *hw = adapter->hw;
- struct ieee80211_conf *conf = &hw->conf;
- struct skb_info *tx_params;
- int status = -E2BIG;
- __le16 *msg;
- u8 extnd_size;
- u8 vap_id = 0;
-
- info = IEEE80211_SKB_CB(skb);
- tx_params = (struct skb_info *)info->driver_data;
- extnd_size = ((uintptr_t)skb->data & 0x3);
-
- if (tx_params->flags & INTERNAL_MGMT_PKT) {
- if ((extnd_size) > skb_headroom(skb)) {
- rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__);
- dev_kfree_skb(skb);
- return -ENOSPC;
- }
- skb_push(skb, extnd_size);
- skb->data[extnd_size + 4] = extnd_size;
- status = adapter->host_intf_write_pkt(common->priv,
- (u8 *)skb->data,
- skb->len);
- if (status) {
- rsi_dbg(ERR_ZONE,
- "%s: Failed to write the packet\n", __func__);
- }
- dev_kfree_skb(skb);
- return status;
- }
-
- bss = &info->control.vif->bss_conf;
- wh = (struct ieee80211_hdr *)&skb->data[0];
-
- if (FRAME_DESC_SZ > skb_headroom(skb))
- goto err;
-
- skb_push(skb, FRAME_DESC_SZ);
- memset(skb->data, 0, FRAME_DESC_SZ);
- msg = (__le16 *)skb->data;
-
- if (skb->len > MAX_MGMT_PKT_SIZE) {
- rsi_dbg(INFO_ZONE, "%s: Dropping mgmt pkt > 512\n", __func__);
- goto err;
- }
-
- msg[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) |
- (RSI_WIFI_MGMT_Q << 12));
- msg[1] = cpu_to_le16(TX_DOT11_MGMT);
- msg[2] = cpu_to_le16(MIN_802_11_HDR_LEN << 8);
- msg[3] = cpu_to_le16(RATE_INFO_ENABLE);
- msg[6] = cpu_to_le16(le16_to_cpu(wh->seq_ctrl) >> 4);
-
- if (wh->addr1[0] & BIT(0))
- msg[3] |= cpu_to_le16(RSI_BROADCAST_PKT);
-
- if (common->band == NL80211_BAND_2GHZ)
- msg[4] = cpu_to_le16(RSI_11B_MODE);
- else
- msg[4] = cpu_to_le16((RSI_RATE_6 & 0x0f) | RSI_11G_MODE);
-
- if (conf_is_ht40(conf)) {
- msg[4] = cpu_to_le16(0xB | RSI_11G_MODE);
- msg[5] = cpu_to_le16(0x6);
- }
-
- /* Indicate to firmware to give cfm */
- if ((skb->data[16] == IEEE80211_STYPE_PROBE_REQ) && (!bss->assoc)) {
- msg[1] |= cpu_to_le16(BIT(10));
- msg[7] = cpu_to_le16(PROBEREQ_CONFIRM);
- common->mgmt_q_block = true;
- }
-
- msg[7] |= cpu_to_le16(vap_id << 8);
-
- status = adapter->host_intf_write_pkt(common->priv,
- (u8 *)msg,
- skb->len);
- if (status)
- rsi_dbg(ERR_ZONE, "%s: Failed to write the packet\n", __func__);
-
-err:
- rsi_indicate_tx_status(common->priv, skb, status);
- return status;
-}
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 8428858..e5ea99b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include "rsi_sdio.h"
#include "rsi_common.h"
+#include "rsi_hal.h"
/**
* rsi_sdio_set_cmd52_arg() - This function prepares cmd 52 read/write arg.
@@ -138,6 +139,8 @@ static void rsi_handle_interrupt(struct sdio_func *function)
{
struct rsi_hw *adapter = sdio_get_drvdata(function);
+ if (adapter->priv->fsm_state == FSM_FW_NOT_LOADED)
+ return;
sdio_release_host(function);
rsi_interrupt_handler(adapter);
sdio_claim_host(function);
@@ -365,6 +368,7 @@ static int rsi_setblocklength(struct rsi_hw *adapter, u32 length)
status = sdio_set_block_size(dev->pfunction, length);
dev->pfunction->max_blksize = 256;
+ adapter->block_size = dev->pfunction->max_blksize;
rsi_dbg(INFO_ZONE,
"%s: Operational blk length is %d\n", __func__, length);
@@ -487,8 +491,8 @@ void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit)
*/
static int rsi_sdio_read_register_multiple(struct rsi_hw *adapter,
u32 addr,
- u32 count,
- u8 *data)
+ u8 *data,
+ u16 count)
{
struct rsi_91x_sdiodev *dev =
(struct rsi_91x_sdiodev *)adapter->rsi_dev;
@@ -518,7 +522,7 @@ static int rsi_sdio_read_register_multiple(struct rsi_hw *adapter,
int rsi_sdio_write_register_multiple(struct rsi_hw *adapter,
u32 addr,
u8 *data,
- u32 count)
+ u16 count)
{
struct rsi_91x_sdiodev *dev =
(struct rsi_91x_sdiodev *)adapter->rsi_dev;
@@ -552,6 +556,182 @@ int rsi_sdio_write_register_multiple(struct rsi_hw *adapter,
return status;
}
+static int rsi_sdio_load_data_master_write(struct rsi_hw *adapter,
+ u32 base_address,
+ u32 instructions_sz,
+ u16 block_size,
+ u8 *ta_firmware)
+{
+ u32 num_blocks, offset, i;
+ u16 msb_address, lsb_address;
+ u8 temp_buf[block_size];
+ int status;
+
+ num_blocks = instructions_sz / block_size;
+ msb_address = base_address >> 16;
+
+ rsi_dbg(INFO_ZONE, "ins_size: %d, num_blocks: %d\n",
+ instructions_sz, num_blocks);
+
+ /* Loading DM ms word in the sdio slave */
+ status = rsi_sdio_master_access_msword(adapter, msb_address);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", __func__);
+ return status;
+ }
+
+ for (offset = 0, i = 0; i < num_blocks; i++, offset += block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf, ta_firmware + offset, block_size);
+ lsb_address = (u16)base_address;
+ status = rsi_sdio_write_register_multiple
+ (adapter,
+ lsb_address | RSI_SD_REQUEST_MASTER,
+ temp_buf, block_size);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: failed to write\n", __func__);
+ return status;
+ }
+ rsi_dbg(INFO_ZONE, "%s: loading block: %d\n", __func__, i);
+ base_address += block_size;
+
+ if ((base_address >> 16) != msb_address) {
+ msb_address += 1;
+
+ /* Loading DM ms word in the sdio slave */
+ status = rsi_sdio_master_access_msword(adapter,
+ msb_address);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word reg\n",
+ __func__);
+ return status;
+ }
+ }
+ }
+
+ if (instructions_sz % block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf, ta_firmware + offset,
+ instructions_sz % block_size);
+ lsb_address = (u16)base_address;
+ status = rsi_sdio_write_register_multiple
+ (adapter,
+ lsb_address | RSI_SD_REQUEST_MASTER,
+ temp_buf,
+ instructions_sz % block_size);
+ if (status < 0)
+ return status;
+ rsi_dbg(INFO_ZONE,
+ "Written Last Block in Address 0x%x Successfully\n",
+ offset | RSI_SD_REQUEST_MASTER);
+ }
+ return 0;
+}
+
+#define FLASH_SIZE_ADDR 0x04000016
+static int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr,
+ u32 *read_buf, u16 size)
+{
+ u32 addr_on_bus, *data;
+ u32 align[2] = {};
+ u16 ms_addr;
+ int status;
+
+ data = PTR_ALIGN(&align[0], 8);
+
+ ms_addr = (addr >> 16);
+ status = rsi_sdio_master_access_msword(adapter, ms_addr);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word to common reg\n",
+ __func__);
+ return status;
+ }
+ addr &= 0xFFFF;
+
+ addr_on_bus = (addr & 0xFF000000);
+ if ((addr_on_bus == (FLASH_SIZE_ADDR & 0xFF000000)) ||
+ (addr_on_bus == 0x0))
+ addr_on_bus = (addr & ~(0x3));
+ else
+ addr_on_bus = addr;
+
+ /* Bring TA out of reset */
+ status = rsi_sdio_read_register_multiple
+ (adapter,
+ (addr_on_bus | RSI_SD_REQUEST_MASTER),
+ (u8 *)data, 4);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: AHB register read failed\n", __func__);
+ return status;
+ }
+ if (size == 2) {
+ if ((addr & 0x3) == 0)
+ *read_buf = *data;
+ else
+ *read_buf = (*data >> 16);
+ *read_buf = (*read_buf & 0xFFFF);
+ } else if (size == 1) {
+ if ((addr & 0x3) == 0)
+ *read_buf = *data;
+ else if ((addr & 0x3) == 1)
+ *read_buf = (*data >> 8);
+ else if ((addr & 0x3) == 2)
+ *read_buf = (*data >> 16);
+ else
+ *read_buf = (*data >> 24);
+ *read_buf = (*read_buf & 0xFF);
+ } else {
+ *read_buf = *data;
+ }
+
+ return 0;
+}
+
+static int rsi_sdio_master_reg_write(struct rsi_hw *adapter,
+ unsigned long addr,
+ unsigned long data, u16 size)
+{
+ unsigned long data1[2], *data_aligned;
+ int status;
+
+ data_aligned = PTR_ALIGN(&data1[0], 8);
+
+ if (size == 2) {
+ *data_aligned = ((data << 16) | (data & 0xFFFF));
+ } else if (size == 1) {
+ u32 temp_data = data & 0xFF;
+
+ *data_aligned = ((temp_data << 24) | (temp_data << 16) |
+ (temp_data << 8) | temp_data);
+ } else {
+ *data_aligned = data;
+ }
+ size = 4;
+
+ status = rsi_sdio_master_access_msword(adapter, (addr >> 16));
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word to common reg\n",
+ __func__);
+ return -EIO;
+ }
+ addr = addr & 0xFFFF;
+
+ /* Bring TA out of reset */
+ status = rsi_sdio_write_register_multiple
+ (adapter,
+ (addr | RSI_SD_REQUEST_MASTER),
+ (u8 *)data_aligned, size);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to do AHB reg write\n", __func__);
+ return status;
+ }
+ return 0;
+}
+
/**
* rsi_sdio_host_intf_write_pkt() - This function writes the packet to device.
* @adapter: Pointer to the adapter structure.
@@ -614,8 +794,8 @@ int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter,
status = rsi_sdio_read_register_multiple(adapter,
length,
- length, /*num of bytes*/
- (u8 *)pkt);
+ (u8 *)pkt,
+ length); /*num of bytes*/
if (status)
rsi_dbg(ERR_ZONE, "%s: Failed to read frame: %d\n", __func__,
@@ -676,8 +856,6 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter,
}
sdio_release_host(pfunction);
- adapter->host_intf_write_pkt = rsi_sdio_host_intf_write_pkt;
- adapter->host_intf_read_pkt = rsi_sdio_host_intf_read_pkt;
adapter->determine_event_timeout = rsi_sdio_determine_event_timeout;
adapter->check_hw_queue_status = rsi_sdio_read_buffer_status_register;
@@ -691,6 +869,17 @@ fail:
return status;
}
+static struct rsi_host_intf_ops sdio_host_intf_ops = {
+ .write_pkt = rsi_sdio_host_intf_write_pkt,
+ .read_pkt = rsi_sdio_host_intf_read_pkt,
+ .master_access_msword = rsi_sdio_master_access_msword,
+ .read_reg_multiple = rsi_sdio_read_register_multiple,
+ .write_reg_multiple = rsi_sdio_write_register_multiple,
+ .master_reg_read = rsi_sdio_master_reg_read,
+ .master_reg_write = rsi_sdio_master_reg_write,
+ .load_data_master_write = rsi_sdio_load_data_master_write,
+};
+
/**
* rsi_probe() - This function is called by kernel when the driver provided
* Vendor and device IDs are matched. All the initialization
@@ -713,31 +902,38 @@ static int rsi_probe(struct sdio_func *pfunction,
__func__);
return 1;
}
+ adapter->rsi_host_intf = RSI_HOST_INTF_SDIO;
+ adapter->host_intf_ops = &sdio_host_intf_ops;
if (rsi_init_sdio_interface(adapter, pfunction)) {
rsi_dbg(ERR_ZONE, "%s: Failed to init sdio interface\n",
__func__);
goto fail;
}
+ sdio_claim_host(pfunction);
+ if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to request IRQ\n", __func__);
+ sdio_release_host(pfunction);
+ goto fail;
+ }
+ sdio_release_host(pfunction);
+ rsi_dbg(INIT_ZONE, "%s: Registered Interrupt handler\n", __func__);
- if (rsi_sdio_device_init(adapter->priv)) {
+ if (rsi_hal_device_init(adapter)) {
rsi_dbg(ERR_ZONE, "%s: Failed in device init\n", __func__);
sdio_claim_host(pfunction);
+ sdio_release_irq(pfunction);
sdio_disable_func(pfunction);
sdio_release_host(pfunction);
goto fail;
}
+ rsi_dbg(INFO_ZONE, "===> RSI Device Init Done <===\n");
- sdio_claim_host(pfunction);
- if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
- rsi_dbg(ERR_ZONE, "%s: Failed to request IRQ\n", __func__);
- sdio_release_host(pfunction);
- goto fail;
+ if (rsi_sdio_master_access_msword(adapter, MISC_CFG_BASE_ADDR)) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", __func__);
+ return -EIO;
}
- sdio_release_host(pfunction);
- rsi_dbg(INIT_ZONE, "%s: Registered Interrupt handler\n", __func__);
-
return 0;
fail:
rsi_91x_deinit(adapter);
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index 40d7231..df2a63b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -27,8 +27,7 @@
*
* Return: status: 0 on success, -1 on failure.
*/
-static int rsi_sdio_master_access_msword(struct rsi_hw *adapter,
- u16 ms_word)
+int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word)
{
u8 byte;
u8 function = 0;
@@ -61,171 +60,6 @@ static int rsi_sdio_master_access_msword(struct rsi_hw *adapter,
}
/**
- * rsi_copy_to_card() - This function includes the actual funtionality of
- * copying the TA firmware to the card.Basically this
- * function includes opening the TA file,reading the
- * TA file and writing their values in blocks of data.
- * @common: Pointer to the driver private structure.
- * @fw: Pointer to the firmware value to be written.
- * @len: length of firmware file.
- * @num_blocks: Number of blocks to be written to the card.
- *
- * Return: 0 on success and -1 on failure.
- */
-static int rsi_copy_to_card(struct rsi_common *common,
- const u8 *fw,
- u32 len,
- u32 num_blocks)
-{
- struct rsi_hw *adapter = common->priv;
- struct rsi_91x_sdiodev *dev =
- (struct rsi_91x_sdiodev *)adapter->rsi_dev;
- u32 indx, ii;
- u32 block_size = dev->tx_blk_size;
- u32 lsb_address;
- __le32 data[] = { TA_HOLD_THREAD_VALUE, TA_SOFT_RST_CLR,
- TA_PC_ZERO, TA_RELEASE_THREAD_VALUE };
- u32 address[] = { TA_HOLD_THREAD_REG, TA_SOFT_RESET_REG,
- TA_TH0_PC_REG, TA_RELEASE_THREAD_REG };
- u32 base_address;
- u16 msb_address;
-
- base_address = TA_LOAD_ADDRESS;
- msb_address = base_address >> 16;
-
- for (indx = 0, ii = 0; ii < num_blocks; ii++, indx += block_size) {
- lsb_address = ((u16) base_address | RSI_SD_REQUEST_MASTER);
- if (rsi_sdio_write_register_multiple(adapter,
- lsb_address,
- (u8 *)(fw + indx),
- block_size)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to load %s blk\n", __func__,
- FIRMWARE_RSI9113);
- return -1;
- }
- rsi_dbg(INIT_ZONE, "%s: loading block: %d\n", __func__, ii);
- base_address += block_size;
- if ((base_address >> 16) != msb_address) {
- msb_address += 1;
- if (rsi_sdio_master_access_msword(adapter,
- msb_address)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to set ms word reg\n",
- __func__);
- return -1;
- }
- }
- }
-
- if (len % block_size) {
- lsb_address = ((u16) base_address | RSI_SD_REQUEST_MASTER);
- if (rsi_sdio_write_register_multiple(adapter,
- lsb_address,
- (u8 *)(fw + indx),
- len % block_size)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to load f/w\n", __func__);
- return -1;
- }
- }
- rsi_dbg(INIT_ZONE,
- "%s: Succesfully loaded TA instructions\n", __func__);
-
- if (rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to set ms word to common reg\n",
- __func__);
- return -1;
- }
-
- for (ii = 0; ii < ARRAY_SIZE(data); ii++) {
- /* Bringing TA out of reset */
- if (rsi_sdio_write_register_multiple(adapter,
- (address[ii] |
- RSI_SD_REQUEST_MASTER),
- (u8 *)&data[ii],
- 4)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to hold TA threads\n", __func__);
- return -1;
- }
- }
-
- rsi_dbg(INIT_ZONE, "%s: loaded firmware\n", __func__);
- return 0;
-}
-
-/**
- * rsi_load_ta_instructions() - This function includes the actual funtionality
- * of loading the TA firmware.This function also
- * includes opening the TA file,reading the TA
- * file and writing their value in blocks of data.
- * @common: Pointer to the driver private structure.
- *
- * Return: status: 0 on success, -1 on failure.
- */
-static int rsi_load_ta_instructions(struct rsi_common *common)
-{
- struct rsi_hw *adapter = common->priv;
- struct rsi_91x_sdiodev *dev =
- (struct rsi_91x_sdiodev *)adapter->rsi_dev;
- u32 len;
- u32 num_blocks;
- const u8 *fw;
- const struct firmware *fw_entry = NULL;
- u32 block_size = dev->tx_blk_size;
- int status = 0;
- u32 base_address;
- u16 msb_address;
-
- if (rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to set ms word to common reg\n",
- __func__);
- return -1;
- }
- base_address = TA_LOAD_ADDRESS;
- msb_address = (base_address >> 16);
-
- if (rsi_sdio_master_access_msword(adapter, msb_address)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to set ms word reg\n", __func__);
- return -1;
- }
-
- status = request_firmware(&fw_entry, FIRMWARE_RSI9113, adapter->device);
- if (status < 0) {
- rsi_dbg(ERR_ZONE, "%s Firmware file %s not found\n",
- __func__, FIRMWARE_RSI9113);
- return status;
- }
-
- /* Copy firmware into DMA-accessible memory */
- fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
- if (!fw) {
- status = -ENOMEM;
- goto out;
- }
- len = fw_entry->size;
-
- if (len % 4)
- len += (4 - (len % 4));
-
- num_blocks = (len / block_size);
-
- rsi_dbg(INIT_ZONE, "%s: Instruction size:%d\n", __func__, len);
- rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks);
-
- status = rsi_copy_to_card(common, fw, len, num_blocks);
- kfree(fw);
-
-out:
- release_firmware(fw_entry);
- return status;
-}
-
-/**
* rsi_process_pkt() - This Function reads rx_blocks register and figures out
* the size of the rx pkt.
* @common: Pointer to the driver private structure.
@@ -472,28 +306,6 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
}
/**
- * rsi_device_init() - This Function Initializes The HAL.
- * @common: Pointer to the driver private structure.
- *
- * Return: 0 on success, -1 on failure.
- */
-int rsi_sdio_device_init(struct rsi_common *common)
-{
- if (rsi_load_ta_instructions(common))
- return -1;
-
- if (rsi_sdio_master_access_msword(common->priv, MISC_CFG_BASE_ADDR)) {
- rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n",
- __func__);
- return -1;
- }
- rsi_dbg(INIT_ZONE,
- "%s: Setting ms word to 0x41050000\n", __func__);
-
- return 0;
-}
-
-/**
* rsi_sdio_read_buffer_status_register() - This function is used to the read
* buffer status register and set
* relevant fields in
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index cc8deec..bcd7f45 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include "rsi_usb.h"
+#include "rsi_hal.h"
/**
* rsi_usb_card_write() - This function writes to the USB Card.
@@ -141,6 +142,9 @@ static int rsi_find_bulk_in_and_out_endpoints(struct usb_interface *interface,
return 0;
}
+#define RSI_USB_REQ_OUT (USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE)
+#define RSI_USB_REQ_IN (USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE)
+
/* rsi_usb_reg_read() - This function reads data from given register address.
* @usbdev: Pointer to the usb_device structure.
* @reg: Address of the register to be read.
@@ -164,11 +168,11 @@ static int rsi_usb_reg_read(struct usb_device *usbdev,
status = usb_control_msg(usbdev,
usb_rcvctrlpipe(usbdev, 0),
USB_VENDOR_REGISTER_READ,
- USB_TYPE_VENDOR,
+ RSI_USB_REQ_IN,
((reg & 0xffff0000) >> 16), (reg & 0xffff),
(void *)buf,
len,
- HZ * 5);
+ USB_CTRL_GET_TIMEOUT);
*value = (buf[0] | (buf[1] << 8));
if (status < 0) {
@@ -211,12 +215,12 @@ static int rsi_usb_reg_write(struct usb_device *usbdev,
status = usb_control_msg(usbdev,
usb_sndctrlpipe(usbdev, 0),
USB_VENDOR_REGISTER_WRITE,
- USB_TYPE_VENDOR,
+ RSI_USB_REQ_OUT,
((reg & 0xffff0000) >> 16),
(reg & 0xffff),
(void *)usb_reg_buf,
len,
- HZ * 5);
+ USB_CTRL_SET_TIMEOUT);
if (status < 0) {
rsi_dbg(ERR_ZONE,
"%s: Reg write failed with error code :%d\n",
@@ -273,6 +277,46 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter)
return status;
}
+static int rsi_usb_read_register_multiple(struct rsi_hw *adapter, u32 addr,
+ u8 *data, u16 count)
+{
+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+ u8 *buf;
+ u16 transfer;
+ int status;
+
+ if (!addr)
+ return -EINVAL;
+
+ buf = kzalloc(RSI_USB_BUF_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ while (count) {
+ transfer = min_t(u16, count, RSI_USB_BUF_SIZE);
+ status = usb_control_msg(dev->usbdev,
+ usb_rcvctrlpipe(dev->usbdev, 0),
+ USB_VENDOR_REGISTER_READ,
+ RSI_USB_REQ_IN,
+ ((addr & 0xffff0000) >> 16),
+ (addr & 0xffff), (void *)buf,
+ transfer, USB_CTRL_GET_TIMEOUT);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "Reg read failed with error code :%d\n",
+ status);
+ kfree(buf);
+ return status;
+ }
+ memcpy(data, buf, transfer);
+ count -= transfer;
+ data += transfer;
+ addr += transfer;
+ }
+ kfree(buf);
+ return 0;
+}
+
/**
* rsi_usb_write_register_multiple() - This function writes multiple bytes of
* information to multiple registers.
@@ -283,41 +327,40 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter)
*
* Return: status: 0 on success, a negative error code on failure.
*/
-int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
- u32 addr,
- u8 *data,
- u32 count)
+static int rsi_usb_write_register_multiple(struct rsi_hw *adapter, u32 addr,
+ u8 *data, u16 count)
{
struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
u8 *buf;
- u8 transfer;
+ u16 transfer;
int status = 0;
- buf = kzalloc(4096, GFP_KERNEL);
+ buf = kzalloc(RSI_USB_BUF_SIZE, GFP_KERNEL);
if (!buf)
return -ENOMEM;
while (count) {
- transfer = (u8)(min_t(u32, count, 4096));
+ transfer = min_t(u16, count, RSI_USB_BUF_SIZE);
memcpy(buf, data, transfer);
status = usb_control_msg(dev->usbdev,
usb_sndctrlpipe(dev->usbdev, 0),
USB_VENDOR_REGISTER_WRITE,
- USB_TYPE_VENDOR,
+ RSI_USB_REQ_OUT,
((addr & 0xffff0000) >> 16),
(addr & 0xffff),
(void *)buf,
transfer,
- HZ * 5);
+ USB_CTRL_SET_TIMEOUT);
if (status < 0) {
rsi_dbg(ERR_ZONE,
"Reg write failed with error code :%d\n",
status);
- } else {
- count -= transfer;
- data += transfer;
- addr += transfer;
+ kfree(buf);
+ return status;
}
+ count -= transfer;
+ data += transfer;
+ addr += transfer;
}
kfree(buf);
@@ -348,6 +391,77 @@ static int rsi_usb_host_intf_write_pkt(struct rsi_hw *adapter,
len);
}
+static int rsi_usb_master_reg_read(struct rsi_hw *adapter, u32 reg,
+ u32 *value, u16 len)
+{
+ struct usb_device *usbdev =
+ ((struct rsi_91x_usbdev *)adapter->rsi_dev)->usbdev;
+
+ return rsi_usb_reg_read(usbdev, reg, (u16 *)value, len);
+}
+
+static int rsi_usb_master_reg_write(struct rsi_hw *adapter,
+ unsigned long reg,
+ unsigned long value, u16 len)
+{
+ struct usb_device *usbdev =
+ ((struct rsi_91x_usbdev *)adapter->rsi_dev)->usbdev;
+
+ return rsi_usb_reg_write(usbdev, reg, value, len);
+}
+
+static int rsi_usb_load_data_master_write(struct rsi_hw *adapter,
+ u32 base_address,
+ u32 instructions_sz, u16 block_size,
+ u8 *ta_firmware)
+{
+ u16 num_blocks;
+ u32 cur_indx, i;
+ u8 temp_buf[256];
+ int status;
+
+ num_blocks = instructions_sz / block_size;
+ rsi_dbg(INFO_ZONE, "num_blocks: %d\n", num_blocks);
+
+ for (cur_indx = 0, i = 0; i < num_blocks; i++, cur_indx += block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf, ta_firmware + cur_indx, block_size);
+ status = rsi_usb_write_register_multiple(adapter, base_address,
+ (u8 *)(temp_buf),
+ block_size);
+ if (status < 0)
+ return status;
+
+ rsi_dbg(INFO_ZONE, "%s: loading block: %d\n", __func__, i);
+ base_address += block_size;
+ }
+
+ if (instructions_sz % block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf, ta_firmware + cur_indx,
+ instructions_sz % block_size);
+ status = rsi_usb_write_register_multiple
+ (adapter, base_address,
+ (u8 *)temp_buf,
+ instructions_sz % block_size);
+ if (status < 0)
+ return status;
+ rsi_dbg(INFO_ZONE,
+ "Written Last Block in Address 0x%x Successfully\n",
+ cur_indx);
+ }
+ return 0;
+}
+
+static struct rsi_host_intf_ops usb_host_intf_ops = {
+ .write_pkt = rsi_usb_host_intf_write_pkt,
+ .read_reg_multiple = rsi_usb_read_register_multiple,
+ .write_reg_multiple = rsi_usb_write_register_multiple,
+ .master_reg_read = rsi_usb_master_reg_read,
+ .master_reg_write = rsi_usb_master_reg_write,
+ .load_data_master_write = rsi_usb_load_data_master_write,
+};
+
/**
* rsi_deinit_usb_interface() - This function deinitializes the usb interface.
* @adapter: Pointer to the adapter structure.
@@ -410,12 +524,14 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
}
rsi_dev->rx_usb_urb[0]->transfer_buffer = adapter->priv->rx_data_pkt;
rsi_dev->tx_blk_size = 252;
+ adapter->block_size = rsi_dev->tx_blk_size;
/* Initializing function callbacks */
adapter->rx_urb_submit = rsi_rx_urb_submit;
- adapter->host_intf_write_pkt = rsi_usb_host_intf_write_pkt;
adapter->check_hw_queue_status = rsi_usb_check_queue_status;
adapter->determine_event_timeout = rsi_usb_event_timeout;
+ adapter->rsi_host_intf = RSI_HOST_INTF_USB;
+ adapter->host_intf_ops = &usb_host_intf_ops;
rsi_init_event(&rsi_dev->rx_thread.event);
status = rsi_create_kthread(common, &rsi_dev->rx_thread,
@@ -467,6 +583,7 @@ static int rsi_probe(struct usb_interface *pfunction,
__func__);
return -ENOMEM;
}
+ adapter->rsi_host_intf = RSI_HOST_INTF_USB;
status = rsi_init_usb_interface(adapter, pfunction);
if (status) {
@@ -480,25 +597,20 @@ static int rsi_probe(struct usb_interface *pfunction,
dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
status = rsi_usb_reg_read(dev->usbdev, FW_STATUS_REG, &fw_status, 2);
- if (status)
+ if (status < 0)
goto err1;
else
fw_status &= 1;
if (!fw_status) {
- status = rsi_usb_device_init(adapter->priv);
+ rsi_dbg(INIT_ZONE, "Loading firmware...\n");
+ status = rsi_hal_device_init(adapter);
if (status) {
rsi_dbg(ERR_ZONE, "%s: Failed in device init\n",
__func__);
goto err1;
}
-
- status = rsi_usb_reg_write(dev->usbdev,
- USB_INTERNAL_REG_1,
- RSI_USB_READY_MAGIC_NUM, 1);
- if (status)
- goto err1;
- rsi_dbg(INIT_ZONE, "%s: Performed device init\n", __func__);
+ rsi_dbg(INIT_ZONE, "%s: Device Init Done\n", __func__);
}
status = rsi_rx_urb_submit(adapter);
@@ -554,6 +666,7 @@ static const struct usb_device_id rsi_dev_table[] = {
{ USB_DEVICE(0x041B, 0x0301) },
{ USB_DEVICE(0x041B, 0x0201) },
{ USB_DEVICE(0x041B, 0x9330) },
+ { USB_DEVICE(0x1618, 0x9113) },
{ /* Blank */},
};
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
index de49008..d3e0a07 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
@@ -19,67 +19,6 @@
#include "rsi_usb.h"
/**
- * rsi_copy_to_card() - This function includes the actual funtionality of
- * copying the TA firmware to the card.Basically this
- * function includes opening the TA file,reading the TA
- * file and writing their values in blocks of data.
- * @common: Pointer to the driver private structure.
- * @fw: Pointer to the firmware value to be written.
- * @len: length of firmware file.
- * @num_blocks: Number of blocks to be written to the card.
- *
- * Return: 0 on success and -1 on failure.
- */
-static int rsi_copy_to_card(struct rsi_common *common,
- const u8 *fw,
- u32 len,
- u32 num_blocks)
-{
- struct rsi_hw *adapter = common->priv;
- struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
- u32 indx, ii;
- u32 block_size = dev->tx_blk_size;
- u32 lsb_address;
- u32 base_address;
-
- base_address = TA_LOAD_ADDRESS;
-
- for (indx = 0, ii = 0; ii < num_blocks; ii++, indx += block_size) {
- lsb_address = base_address;
- if (rsi_usb_write_register_multiple(adapter,
- lsb_address,
- (u8 *)(fw + indx),
- block_size)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to load %s blk\n", __func__,
- FIRMWARE_RSI9113);
- return -EIO;
- }
- rsi_dbg(INIT_ZONE, "%s: loading block: %d\n", __func__, ii);
- base_address += block_size;
- }
-
- if (len % block_size) {
- lsb_address = base_address;
- if (rsi_usb_write_register_multiple(adapter,
- lsb_address,
- (u8 *)(fw + indx),
- len % block_size)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to load %s blk\n", __func__,
- FIRMWARE_RSI9113);
- return -EIO;
- }
- }
- rsi_dbg(INIT_ZONE,
- "%s: Succesfully loaded %s instructions\n", __func__,
- FIRMWARE_RSI9113);
-
- rsi_dbg(INIT_ZONE, "%s: loaded firmware\n", __func__);
- return 0;
-}
-
-/**
* rsi_usb_rx_thread() - This is a kernel thread to receive the packets from
* the USB device.
* @common: Pointer to the driver private structure.
@@ -119,67 +58,3 @@ out:
complete_and_exit(&dev->rx_thread.completion, 0);
}
-
-/**
- * rsi_load_ta_instructions() - This function includes the actual funtionality
- * of loading the TA firmware.This function also
- * includes opening the TA file,reading the TA
- * file and writing their value in blocks of data.
- * @common: Pointer to the driver private structure.
- *
- * Return: status: 0 on success, -1 on failure.
- */
-static int rsi_load_ta_instructions(struct rsi_common *common)
-{
- struct rsi_hw *adapter = common->priv;
- struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
- const struct firmware *fw_entry = NULL;
- u32 block_size = dev->tx_blk_size;
- const u8 *fw;
- u32 num_blocks, len;
- int status = 0;
-
- status = request_firmware(&fw_entry, FIRMWARE_RSI9113, adapter->device);
- if (status < 0) {
- rsi_dbg(ERR_ZONE, "%s Firmware file %s not found\n",
- __func__, FIRMWARE_RSI9113);
- return status;
- }
-
- /* Copy firmware into DMA-accessible memory */
- fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
- if (!fw) {
- status = -ENOMEM;
- goto out;
- }
- len = fw_entry->size;
-
- if (len % 4)
- len += (4 - (len % 4));
-
- num_blocks = (len / block_size);
-
- rsi_dbg(INIT_ZONE, "%s: Instruction size:%d\n", __func__, len);
- rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks);
-
- status = rsi_copy_to_card(common, fw, len, num_blocks);
- kfree(fw);
-
-out:
- release_firmware(fw_entry);
- return status;
-}
-
-/**
- * rsi_device_init() - This Function Initializes The HAL.
- * @common: Pointer to the driver private structure.
- *
- * Return: 0 on success, -1 on failure.
- */
-int rsi_usb_device_init(struct rsi_common *common)
-{
- if (rsi_load_ta_instructions(common))
- return -EIO;
-
- return 0;
- }
diff --git a/drivers/net/wireless/rsi/rsi_boot_params.h b/drivers/net/wireless/rsi/rsi_boot_params.h
index 5e2721f..238ee96 100644
--- a/drivers/net/wireless/rsi/rsi_boot_params.h
+++ b/drivers/net/wireless/rsi/rsi_boot_params.h
@@ -24,19 +24,19 @@
#define WIFI_AFEPLL_CONFIGS BIT(7)
#define WIFI_SWITCH_CLK_CONFIGS BIT(8)
-#define TA_PLL_M_VAL_20 8
-#define TA_PLL_N_VAL_20 1
+#define TA_PLL_M_VAL_20 9
+#define TA_PLL_N_VAL_20 0
#define TA_PLL_P_VAL_20 4
#define PLL960_M_VAL_20 0x14
#define PLL960_N_VAL_20 0
#define PLL960_P_VAL_20 5
-#define UMAC_CLK_40MHZ 40
+#define UMAC_CLK_40MHZ 80
-#define TA_PLL_M_VAL_40 46
-#define TA_PLL_N_VAL_40 3
-#define TA_PLL_P_VAL_40 3
+#define TA_PLL_M_VAL_40 9
+#define TA_PLL_N_VAL_40 0
+#define TA_PLL_P_VAL_40 4
#define PLL960_M_VAL_40 0x14
#define PLL960_N_VAL_40 0
@@ -122,5 +122,8 @@ struct bootup_params {
/* dcdc modes configs */
__le32 dcdc_operation_mode;
__le32 soc_reset_wait_cnt;
+ __le32 waiting_time_at_fresh_sleep;
+ __le32 max_threshold_to_avoid_sleep;
+ u8 beacon_resedue_alg_en;
} __packed;
#endif
diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h
index d3fbe33..4434969 100644
--- a/drivers/net/wireless/rsi/rsi_common.h
+++ b/drivers/net/wireless/rsi/rsi_common.h
@@ -20,8 +20,7 @@
#include <linux/kthread.h>
#define EVENT_WAIT_FOREVER 0
-#define TA_LOAD_ADDRESS 0x00
-#define FIRMWARE_RSI9113 "rsi_91x.fw"
+#define FIRMWARE_RSI9113 "rs9113_wlan_qspi.rps"
#define QUEUE_NOT_FULL 1
#define QUEUE_FULL 0
diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h
new file mode 100644
index 0000000..902dc54
--- /dev/null
+++ b/drivers/net/wireless/rsi/rsi_hal.h
@@ -0,0 +1,84 @@
+/**
+ * Copyright (c) 2017 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __RSI_HAL_H__
+#define __RSI_HAL_H__
+
+#define FLASH_WRITE_CHUNK_SIZE (4 * 1024)
+#define FLASH_SECTOR_SIZE (4 * 1024)
+
+#define FLASH_SIZE_ADDR 0x04000016
+#define PING_BUFFER_ADDRESS 0x19000
+#define PONG_BUFFER_ADDRESS 0x1a000
+#define SWBL_REGIN 0x41050034
+#define SWBL_REGOUT 0x4105003c
+#define PING_WRITE 0x1
+#define PONG_WRITE 0x2
+
+#define BL_CMD_TIMEOUT 2000
+#define BL_BURN_TIMEOUT (50 * 1000)
+
+#define REGIN_VALID 0xA
+#define REGIN_INPUT 0xA0
+#define REGOUT_VALID 0xAB
+#define REGOUT_INVALID (~0xAB)
+#define CMD_PASS 0xAA
+#define CMD_FAIL 0xCC
+
+#define LOAD_HOSTED_FW 'A'
+#define BURN_HOSTED_FW 'B'
+#define PING_VALID 'I'
+#define PONG_VALID 'O'
+#define PING_AVAIL 'I'
+#define PONG_AVAIL 'O'
+#define EOF_REACHED 'E'
+#define CHECK_CRC 'K'
+#define POLLING_MODE 'P'
+#define CONFIG_AUTO_READ_MODE 'R'
+#define JUMP_TO_ZERO_PC 'J'
+#define FW_LOADING_SUCCESSFUL 'S'
+#define LOADING_INITIATED '1'
+
+/* Boot loader commands */
+#define SEND_RPS_FILE '2'
+
+#define FW_IMAGE_MIN_ADDRESS (68 * 1024)
+#define MAX_FLASH_FILE_SIZE (400 * 1024) //400K
+#define FLASH_START_ADDRESS 16
+
+#define COMMON_HAL_CARD_READY_IND 0x0
+
+#define COMMAN_HAL_WAIT_FOR_CARD_READY 1
+
+#define RSI_DEV_OPMODE_WIFI_ALONE 1
+#define RSI_DEV_COEX_MODE_WIFI_ALONE 1
+
+struct bl_header {
+ __le32 flags;
+ __le32 image_no;
+ __le32 check_sum;
+ __le32 flash_start_address;
+ __le32 flash_len;
+} __packed;
+
+struct ta_metadata {
+ char *name;
+ unsigned int address;
+};
+
+int rsi_hal_device_init(struct rsi_hw *adapter);
+
+#endif
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 1d5904b..f398525 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -31,13 +31,17 @@
#define FSM_ZONE BIT(7) /* For State Machine Msgs */
#define ISR_ZONE BIT(8) /* For Interrupt Msgs */
-#define FSM_CARD_NOT_READY 0
-#define FSM_BOOT_PARAMS_SENT 1
-#define FSM_EEPROM_READ_MAC_ADDR 2
-#define FSM_RESET_MAC_SENT 3
-#define FSM_RADIO_CAPS_SENT 4
-#define FSM_BB_RF_PROG_SENT 5
-#define FSM_MAC_INIT_DONE 6
+enum RSI_FSM_STATES {
+ FSM_FW_NOT_LOADED,
+ FSM_CARD_NOT_READY,
+ FSM_COMMON_DEV_PARAMS_SENT,
+ FSM_BOOT_PARAMS_SENT,
+ FSM_EEPROM_READ_MAC_ADDR,
+ FSM_RESET_MAC_SENT,
+ FSM_RADIO_CAPS_SENT,
+ FSM_BB_RF_PROG_SENT,
+ FSM_MAC_INIT_DONE
+};
extern u32 rsi_zone_enabled;
extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
@@ -60,6 +64,7 @@ extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
#define MAX_CONTINUOUS_VI_PKTS 4
/* Queue information */
+#define RSI_COEX_Q 0x0
#define RSI_WIFI_MGMT_Q 0x4
#define RSI_WIFI_DATA_Q 0x5
#define IEEE80211_MGMT_FRAME 0x00
@@ -82,6 +87,8 @@ extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
((_q) == VI_Q) ? IEEE80211_AC_VI : \
IEEE80211_AC_VO)
+#define RSI_DEV_9113 1
+
struct version_info {
u16 major;
u16 minor;
@@ -204,13 +211,26 @@ struct rsi_common {
struct cqm_info cqm_info;
bool hw_data_qs_blocked;
-
+ u8 driver_mode;
+ u8 coex_mode;
+ u16 oper_mode;
+ u8 lp_ps_handshake_mode;
+ u8 ulp_ps_handshake_mode;
+ u8 rf_power_val;
+ u8 wlan_rf_power_mode;
+ u8 obm_ant_sel_val;
int tx_power;
u8 ant_in_use;
};
+enum host_intf {
+ RSI_HOST_INTF_SDIO = 0,
+ RSI_HOST_INTF_USB
+};
+
struct rsi_hw {
struct rsi_common *priv;
+ u8 device_model;
struct ieee80211_hw *hw;
struct ieee80211_vif *vifs[RSI_MAX_VIFS];
struct ieee80211_tx_queue_params edca_params[NUM_EDCA_QUEUES];
@@ -219,16 +239,40 @@ struct rsi_hw {
struct device *device;
u8 sc_nvifs;
+ enum host_intf rsi_host_intf;
+ u16 block_size;
+ u32 usb_buffer_status_reg;
#ifdef CONFIG_RSI_DEBUGFS
struct rsi_debugfs *dfsentry;
u8 num_debugfs_entries;
#endif
+ char *fw_file_name;
+ struct timer_list bl_cmd_timer;
+ bool blcmd_timer_expired;
+ u32 flash_capacity;
u8 dfs_region;
void *rsi_dev;
- int (*host_intf_read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
- int (*host_intf_write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+ struct rsi_host_intf_ops *host_intf_ops;
int (*check_hw_queue_status)(struct rsi_hw *adapter, u8 q_num);
int (*rx_urb_submit)(struct rsi_hw *adapter);
int (*determine_event_timeout)(struct rsi_hw *adapter);
};
+
+struct rsi_host_intf_ops {
+ int (*read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+ int (*write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+ int (*master_access_msword)(struct rsi_hw *adapter, u16 ms_word);
+ int (*read_reg_multiple)(struct rsi_hw *adapter, u32 addr,
+ u8 *data, u16 count);
+ int (*write_reg_multiple)(struct rsi_hw *adapter, u32 addr,
+ u8 *data, u16 count);
+ int (*master_reg_read)(struct rsi_hw *adapter, u32 addr,
+ u32 *read_buf, u16 size);
+ int (*master_reg_write)(struct rsi_hw *adapter,
+ unsigned long addr, unsigned long data,
+ u16 size);
+ int (*load_data_master_write)(struct rsi_hw *adapter, u32 addr,
+ u32 instructions_size, u16 block_size,
+ u8 *fw);
+};
#endif
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index dfbf7a5..dcb6db7 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -205,6 +205,7 @@ enum cmd_frame_type {
CW_MODE_REQ,
PER_CMD_PKT,
ANT_SEL_FRAME = 0x20,
+ COMMON_DEV_CONFIG = 0x28,
RADIO_PARAMS_UPDATE = 0x29
};
@@ -282,6 +283,76 @@ struct rsi_radio_caps {
__le16 preamble_type;
} __packed;
+/* ULP GPIO flags */
+#define RSI_GPIO_MOTION_SENSOR_ULP_WAKEUP BIT(0)
+#define RSI_GPIO_SLEEP_IND_FROM_DEVICE BIT(1)
+#define RSI_GPIO_2_ULP BIT(2)
+#define RSI_GPIO_PUSH_BUTTON_ULP_WAKEUP BIT(3)
+
+/* SOC GPIO flags */
+#define RSI_GPIO_0_PSPI_CSN_0 BIT(0)
+#define RSI_GPIO_1_PSPI_CSN_1 BIT(1)
+#define RSI_GPIO_2_HOST_WAKEUP_INTR BIT(2)
+#define RSI_GPIO_3_PSPI_DATA_0 BIT(3)
+#define RSI_GPIO_4_PSPI_DATA_1 BIT(4)
+#define RSI_GPIO_5_PSPI_DATA_2 BIT(5)
+#define RSI_GPIO_6_PSPI_DATA_3 BIT(6)
+#define RSI_GPIO_7_I2C_SCL BIT(7)
+#define RSI_GPIO_8_I2C_SDA BIT(8)
+#define RSI_GPIO_9_UART1_RX BIT(9)
+#define RSI_GPIO_10_UART1_TX BIT(10)
+#define RSI_GPIO_11_UART1_RTS_I2S_CLK BIT(11)
+#define RSI_GPIO_12_UART1_CTS_I2S_WS BIT(12)
+#define RSI_GPIO_13_DBG_UART_RX_I2S_DIN BIT(13)
+#define RSI_GPIO_14_DBG_UART_RX_I2S_DOUT BIT(14)
+#define RSI_GPIO_15_LP_WAKEUP_BOOT_BYPASS BIT(15)
+#define RSI_GPIO_16_LED_0 BIT(16)
+#define RSI_GPIO_17_BTCOEX_WLAN_ACT_EXT_ANT_SEL BIT(17)
+#define RSI_GPIO_18_BTCOEX_BT_PRIO_EXT_ANT_SEL BIT(18)
+#define RSI_GPIO_19_BTCOEX_BT_ACT_EXT_ON_OFF BIT(19)
+#define RSI_GPIO_20_RF_RESET BIT(20)
+#define RSI_GPIO_21_SLEEP_IND_FROM_DEVICE BIT(21)
+
+#define RSI_UNUSED_SOC_GPIO_BITMAP (RSI_GPIO_9_UART1_RX | \
+ RSI_GPIO_10_UART1_TX | \
+ RSI_GPIO_11_UART1_RTS_I2S_CLK | \
+ RSI_GPIO_12_UART1_CTS_I2S_WS | \
+ RSI_GPIO_13_DBG_UART_RX_I2S_DIN | \
+ RSI_GPIO_14_DBG_UART_RX_I2S_DOUT | \
+ RSI_GPIO_15_LP_WAKEUP_BOOT_BYPASS | \
+ RSI_GPIO_17_BTCOEX_WLAN_ACT_EXT_ANT_SEL | \
+ RSI_GPIO_18_BTCOEX_BT_PRIO_EXT_ANT_SEL | \
+ RSI_GPIO_19_BTCOEX_BT_ACT_EXT_ON_OFF | \
+ RSI_GPIO_21_SLEEP_IND_FROM_DEVICE)
+
+#define RSI_UNUSED_ULP_GPIO_BITMAP (RSI_GPIO_MOTION_SENSOR_ULP_WAKEUP | \
+ RSI_GPIO_SLEEP_IND_FROM_DEVICE | \
+ RSI_GPIO_2_ULP | \
+ RSI_GPIO_PUSH_BUTTON_ULP_WAKEUP);
+struct rsi_config_vals {
+ __le16 len_qno;
+ u8 pkt_type;
+ u8 misc_flags;
+ __le16 reserved1[6];
+ u8 lp_ps_handshake;
+ u8 ulp_ps_handshake;
+ u8 sleep_config_params; /* 0 for no handshake,
+ * 1 for GPIO based handshake,
+ * 2 packet handshake
+ */
+ u8 unused_ulp_gpio;
+ __le32 unused_soc_gpio_bitmap;
+ u8 ext_pa_or_bt_coex_en;
+ u8 opermode;
+ u8 wlan_rf_pwr_mode;
+ u8 bt_rf_pwr_mode;
+ u8 zigbee_rf_pwr_mode;
+ u8 driver_mode;
+ u8 region_code;
+ u8 antenna_sel_val;
+ u8 reserved2[16];
+} __packed;
+
static inline u32 rsi_get_queueno(u8 *addr, u16 offset)
{
return (le16_to_cpu(*(__le16 *)&addr[offset]) & 0x7000) >> 12;
@@ -307,6 +378,11 @@ static inline u8 rsi_get_channel(u8 *addr)
return *(char *)(addr + 15);
}
+static inline void rsi_set_len_qno(__le16 *addr, u16 len, u8 qno)
+{
+ *addr = cpu_to_le16(len | ((qno & 7) << 12));
+}
+
int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg);
int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode,
u8 vap_status);
diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h
index c7e8f2b..9fb73f6 100644
--- a/drivers/net/wireless/rsi/rsi_sdio.h
+++ b/drivers/net/wireless/rsi/rsi_sdio.h
@@ -110,19 +110,19 @@ struct rsi_91x_sdiodev {
u8 sdio_clock_speed;
u32 cardcapability;
u8 prev_desc[16];
- u32 tx_blk_size;
+ u16 tx_blk_size;
u8 write_fail;
};
void rsi_interrupt_handler(struct rsi_hw *adapter);
int rsi_init_sdio_slave_regs(struct rsi_hw *adapter);
-int rsi_sdio_device_init(struct rsi_common *common);
int rsi_sdio_read_register(struct rsi_hw *adapter, u32 addr, u8 *data);
int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter, u8 *pkt, u32 length);
int rsi_sdio_write_register(struct rsi_hw *adapter, u8 function,
u32 addr, u8 *data);
int rsi_sdio_write_register_multiple(struct rsi_hw *adapter, u32 addr,
- u8 *data, u32 count);
+ u8 *data, u16 count);
+int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word);
void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit);
int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter);
int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num);
diff --git a/drivers/net/wireless/rsi/rsi_usb.h b/drivers/net/wireless/rsi/rsi_usb.h
index ebea0c4..59513ac 100644
--- a/drivers/net/wireless/rsi/rsi_usb.h
+++ b/drivers/net/wireless/rsi/rsi_usb.h
@@ -35,6 +35,8 @@
#define MGMT_EP 1
#define DATA_EP 2
+#define RSI_USB_BUF_SIZE 4096
+
struct rsi_91x_usbdev {
struct rsi_thread rx_thread;
u8 endpoint;
@@ -61,8 +63,5 @@ static inline int rsi_usb_event_timeout(struct rsi_hw *adapter)
return EVENT_WAIT_FOREVER;
}
-int rsi_usb_device_init(struct rsi_common *common);
-int rsi_usb_write_register_multiple(struct rsi_hw *adapter, u32 addr,
- u8 *data, u32 count);
void rsi_usb_rx_thread(struct rsi_common *common);
#endif
diff --git a/drivers/net/wireless/st/cw1200/cw1200_sdio.c b/drivers/net/wireless/st/cw1200/cw1200_sdio.c
index 709f56e..1037ec6 100644
--- a/drivers/net/wireless/st/cw1200/cw1200_sdio.c
+++ b/drivers/net/wireless/st/cw1200/cw1200_sdio.c
@@ -266,7 +266,7 @@ static int cw1200_sdio_pm(struct hwbus_priv *self, bool suspend)
return ret;
}
-static struct hwbus_ops cw1200_sdio_hwbus_ops = {
+static const struct hwbus_ops cw1200_sdio_hwbus_ops = {
.hwbus_memcpy_fromio = cw1200_sdio_memcpy_fromio,
.hwbus_memcpy_toio = cw1200_sdio_memcpy_toio,
.lock = cw1200_sdio_lock,
diff --git a/drivers/net/wireless/st/cw1200/cw1200_spi.c b/drivers/net/wireless/st/cw1200/cw1200_spi.c
index 63f95e9..412fb6e4 100644
--- a/drivers/net/wireless/st/cw1200/cw1200_spi.c
+++ b/drivers/net/wireless/st/cw1200/cw1200_spi.c
@@ -352,7 +352,7 @@ static int cw1200_spi_pm(struct hwbus_priv *self, bool suspend)
return irq_set_irq_wake(self->func->irq, suspend);
}
-static struct hwbus_ops cw1200_spi_hwbus_ops = {
+static const struct hwbus_ops cw1200_spi_hwbus_ops = {
.hwbus_memcpy_fromio = cw1200_spi_memcpy_fromio,
.hwbus_memcpy_toio = cw1200_spi_memcpy_toio,
.lock = cw1200_spi_lock,
diff --git a/drivers/net/wireless/st/cw1200/scan.c b/drivers/net/wireless/st/cw1200/scan.c
index 0a0ff7e..cc2ce60 100644
--- a/drivers/net/wireless/st/cw1200/scan.c
+++ b/drivers/net/wireless/st/cw1200/scan.c
@@ -84,7 +84,7 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
return -ENOMEM;
if (req->ie_len)
- memcpy(skb_put(frame.skb, req->ie_len), req->ie, req->ie_len);
+ skb_put_data(frame.skb, req->ie, req->ie_len);
/* will be unlocked in cw1200_scan_work() */
down(&priv->scan.lock);
diff --git a/drivers/net/wireless/st/cw1200/txrx.c b/drivers/net/wireless/st/cw1200/txrx.c
index cd63ffe..e9050b4 100644
--- a/drivers/net/wireless/st/cw1200/txrx.c
+++ b/drivers/net/wireless/st/cw1200/txrx.c
@@ -574,7 +574,7 @@ cw1200_tx_h_wsm(struct cw1200_common *priv,
return NULL;
}
- wsm = (struct wsm_tx *)skb_push(t->skb, sizeof(struct wsm_tx));
+ wsm = skb_push(t->skb, sizeof(struct wsm_tx));
t->txpriv.offset += sizeof(struct wsm_tx);
memset(wsm, 0, sizeof(*wsm));
wsm->hdr.len = __cpu_to_le16(t->skb->len);
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index bbf7604..08f0477 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -1036,7 +1036,7 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
goto out_idle;
}
if (req->ie_len)
- memcpy(skb_put(skb, req->ie_len), req->ie, req->ie_len);
+ skb_put_data(skb, req->ie, req->ie_len);
ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, skb->data,
skb->len);
diff --git a/drivers/net/wireless/ti/wl1251/tx.c b/drivers/net/wireless/ti/wl1251/tx.c
index 81de83c..de2fa67 100644
--- a/drivers/net/wireless/ti/wl1251/tx.c
+++ b/drivers/net/wireless/ti/wl1251/tx.c
@@ -161,8 +161,7 @@ static int wl1251_tx_fill_hdr(struct wl1251 *wl, struct sk_buff *skb,
return id;
fc = *(u16 *)skb->data;
- tx_hdr = (struct tx_double_buffer_desc *) skb_push(skb,
- sizeof(*tx_hdr));
+ tx_hdr = skb_push(skb, sizeof(*tx_hdr));
tx_hdr->length = cpu_to_le16(skb->len - sizeof(*tx_hdr));
rate = ieee80211_get_tx_rate(wl->hw, control);
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index d1aa3ee..0cf3b40 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -793,9 +793,13 @@ static int wl18xx_set_clk(struct wl1271 *wl)
ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2,
(wl18xx_clk_table[clk_freq].p >> 16) &
PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK);
+ if (ret < 0)
+ goto out;
} else {
ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN,
PLLSH_WCS_PLL_SWALLOW_EN_VAL2);
+ if (ret < 0)
+ goto out;
}
/* choose WCS PLL */
@@ -819,8 +823,6 @@ static int wl18xx_set_clk(struct wl1271 *wl)
/* reset the swallowing logic */
ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_SWALLOW_EN,
PLLSH_COEX_PLL_SWALLOW_EN_VAL2);
- if (ret < 0)
- goto out;
out:
return ret;
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 7f4da72..2bfc12f 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -1156,9 +1156,9 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
goto out;
}
if (ie0_len)
- memcpy(skb_put(skb, ie0_len), ie0, ie0_len);
+ skb_put_data(skb, ie0, ie0_len);
if (ie1_len)
- memcpy(skb_put(skb, ie1_len), ie1, ie1_len);
+ skb_put_data(skb, ie1, ie1_len);
if (sched_scan &&
(wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL)) {
@@ -1233,8 +1233,7 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif)
skb_reserve(skb, sizeof(*hdr) + WL1271_EXTRA_SPACE_MAX);
- tmpl = (struct wl12xx_arp_rsp_template *)skb_put(skb, sizeof(*tmpl));
- memset(tmpl, 0, sizeof(*tmpl));
+ tmpl = skb_put_zero(skb, sizeof(*tmpl));
/* llc layer */
memcpy(tmpl->llc_hdr, rfc1042_header, sizeof(rfc1042_header));
@@ -1283,7 +1282,7 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif)
memset(skb_push(skb, sizeof(__le16)), 0, sizeof(__le16));
/* mac80211 header */
- hdr = (struct ieee80211_hdr_3addr *)skb_push(skb, sizeof(*hdr));
+ hdr = skb_push(skb, sizeof(*hdr));
memset(hdr, 0, sizeof(*hdr));
fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS;
if (wlvif->sta.qos)
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c
index de7e2a5..a2cb408 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@ -1149,15 +1149,9 @@ static ssize_t dev_mem_write(struct file *file, const char __user *user_buf,
part.mem.start = *ppos;
part.mem.size = bytes;
- buf = kmalloc(bytes, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- ret = copy_from_user(buf, user_buf, bytes);
- if (ret) {
- ret = -EFAULT;
- goto err_out;
- }
+ buf = memdup_user(user_buf, bytes);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
mutex_lock(&wl->mutex);
@@ -1197,7 +1191,6 @@ skip_write:
if (ret == 0)
*ppos += bytes;
-err_out:
kfree(buf);
return ((ret == 0) ? bytes : ret);
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 382ec15..60aaa85 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -1308,13 +1308,12 @@ static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl)
skb_reserve(skb, sizeof(struct wl1271_tx_hw_descr));
- hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr));
- memset(hdr, 0, sizeof(*hdr));
+ hdr = skb_put_zero(skb, sizeof(*hdr));
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
IEEE80211_STYPE_NULLFUNC |
IEEE80211_FCTL_TODS);
- memset(skb_put(skb, dummy_packet_size), 0, dummy_packet_size);
+ skb_put_zero(skb, dummy_packet_size);
/* Dummy packets require the TID to be management */
skb->priority = WL1271_TID_MGMT;
diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c
index 52a55f9..0f15696 100644
--- a/drivers/net/wireless/ti/wlcore/rx.c
+++ b/drivers/net/wireless/ti/wlcore/rx.c
@@ -117,7 +117,6 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
struct wl1271_rx_descriptor *desc;
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
- u8 *buf;
u8 beacon = 0;
u8 is_data = 0;
u8 reserved = 0, offset_to_data = 0;
@@ -174,15 +173,13 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
/* reserve the unaligned payload(if any) */
skb_reserve(skb, reserved);
- buf = skb_put(skb, pkt_data_len);
-
/*
* Copy packets from aggregation buffer to the skbs without rx
* descriptor and with packet payload aligned care. In case of unaligned
* packets copy the packets in offset of 2 bytes guarantee IP header
* payload aligned to 4 bytes.
*/
- memcpy(buf, data + sizeof(*desc), pkt_data_len);
+ skb_put_data(skb, data + sizeof(*desc), pkt_data_len);
if (rx_align == WLCORE_RX_BUF_PADDED)
skb_pull(skb, RX_BUF_ALIGN);
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index 287023e..2fb3871 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -237,6 +237,7 @@ static const struct of_device_id wlcore_sdio_of_match_table[] = {
{ .compatible = "ti,wl1273", .data = &wl127x_data },
{ .compatible = "ti,wl1281", .data = &wl128x_data },
{ .compatible = "ti,wl1283", .data = &wl128x_data },
+ { .compatible = "ti,wl1285", .data = &wl128x_data },
{ .compatible = "ti,wl1801", .data = &wl18xx_data },
{ .compatible = "ti,wl1805", .data = &wl18xx_data },
{ .compatible = "ti,wl1807", .data = &wl18xx_data },
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c
index f949ad2b..fdabb92 100644
--- a/drivers/net/wireless/ti/wlcore/spi.c
+++ b/drivers/net/wireless/ti/wlcore/spi.c
@@ -70,10 +70,10 @@
#define WSPI_MAX_CHUNK_SIZE 4092
/*
- * wl18xx driver aggregation buffer size is (13 * PAGE_SIZE) compared to
- * (4 * PAGE_SIZE) for wl12xx, so use the larger buffer needed for wl18xx
+ * wl18xx driver aggregation buffer size is (13 * 4K) compared to
+ * (4 * 4K) for wl12xx, so use the larger buffer needed for wl18xx
*/
-#define SPI_AGGR_BUFFER_SIZE (13 * PAGE_SIZE)
+#define SPI_AGGR_BUFFER_SIZE (13 * SZ_4K)
/* Maximum number of SPI write chunks */
#define WSPI_MAX_NUM_OF_CHUNKS \
@@ -366,17 +366,14 @@ static int __wl12xx_spi_raw_write(struct device *child, int addr,
static int __must_check wl12xx_spi_raw_write(struct device *child, int addr,
void *buf, size_t len, bool fixed)
{
- int ret;
-
/* The ELP wakeup write may fail the first time due to internal
* hardware latency. It is safer to send the wakeup command twice to
* avoid unexpected failures.
*/
if (addr == HW_ACCESS_ELP_CTRL_REG)
- ret = __wl12xx_spi_raw_write(child, addr, buf, len, fixed);
- ret = __wl12xx_spi_raw_write(child, addr, buf, len, fixed);
+ __wl12xx_spi_raw_write(child, addr, buf, len, fixed);
- return ret;
+ return __wl12xx_spi_raw_write(child, addr, buf, len, fixed);
}
/**
@@ -433,6 +430,7 @@ static const struct of_device_id wlcore_spi_of_match_table[] = {
{ .compatible = "ti,wl1273", .data = &wl127x_data},
{ .compatible = "ti,wl1281", .data = &wl128x_data},
{ .compatible = "ti,wl1283", .data = &wl128x_data},
+ { .compatible = "ti,wl1285", .data = &wl128x_data},
{ .compatible = "ti,wl1801", .data = &wl18xx_data},
{ .compatible = "ti,wl1805", .data = &wl18xx_data},
{ .compatible = "ti,wl1807", .data = &wl18xx_data},
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index c1b8e4e..a3f5e9c 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -223,8 +223,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
total_blocks = wlcore_hw_calc_tx_blocks(wl, total_len, spare_blocks);
if (total_blocks <= wl->tx_blocks_available) {
- desc = (struct wl1271_tx_hw_descr *)skb_push(
- skb, total_len - skb->len);
+ desc = skb_push(skb, total_len - skb->len);
wlcore_hw_set_tx_desc_blocks(wl, desc, total_blocks,
spare_blocks);
diff --git a/drivers/net/wireless/zydas/zd1201.c b/drivers/net/wireless/zydas/zd1201.c
index de7ff39..7f586d7 100644
--- a/drivers/net/wireless/zydas/zd1201.c
+++ b/drivers/net/wireless/zydas/zd1201.c
@@ -326,13 +326,13 @@ static void zd1201_usbrx(struct urb *urb)
if (!(skb = dev_alloc_skb(datalen+24)))
goto resubmit;
- memcpy(skb_put(skb, 2), &data[datalen-16], 2);
- memcpy(skb_put(skb, 2), &data[datalen-2], 2);
- memcpy(skb_put(skb, 6), &data[datalen-14], 6);
- memcpy(skb_put(skb, 6), &data[datalen-22], 6);
- memcpy(skb_put(skb, 6), &data[datalen-8], 6);
- memcpy(skb_put(skb, 2), &data[datalen-24], 2);
- memcpy(skb_put(skb, len), data, len);
+ skb_put_data(skb, &data[datalen - 16], 2);
+ skb_put_data(skb, &data[datalen - 2], 2);
+ skb_put_data(skb, &data[datalen - 14], 6);
+ skb_put_data(skb, &data[datalen - 22], 6);
+ skb_put_data(skb, &data[datalen - 8], 6);
+ skb_put_data(skb, &data[datalen - 24], 2);
+ skb_put_data(skb, data, len);
skb->protocol = eth_type_trans(skb, zd->dev);
zd->dev->stats.rx_packets++;
zd->dev->stats.rx_bytes += skb->len;
@@ -359,9 +359,9 @@ static void zd1201_usbrx(struct urb *urb)
frag->skb = skb;
frag->seq = seq & IEEE80211_SCTL_SEQ;
skb_reserve(skb, 2);
- memcpy(skb_put(skb, 12), &data[datalen-14], 12);
- memcpy(skb_put(skb, 2), &data[6], 2);
- memcpy(skb_put(skb, len), data+8, len);
+ skb_put_data(skb, &data[datalen - 14], 12);
+ skb_put_data(skb, &data[6], 2);
+ skb_put_data(skb, data + 8, len);
hlist_add_head(&frag->fnode, &zd->fraglist);
goto resubmit;
}
@@ -385,9 +385,9 @@ static void zd1201_usbrx(struct urb *urb)
if (!skb)
goto resubmit;
skb_reserve(skb, 2);
- memcpy(skb_put(skb, 12), &data[datalen-14], 12);
- memcpy(skb_put(skb, 2), &data[6], 2);
- memcpy(skb_put(skb, len), data+8, len);
+ skb_put_data(skb, &data[datalen - 14], 12);
+ skb_put_data(skb, &data[6], 2);
+ skb_put_data(skb, data + 8, len);
}
skb->protocol = eth_type_trans(skb, zd->dev);
zd->dev->stats.rx_packets++;
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
index fe6517a6..b785742 100644
--- a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
@@ -868,8 +868,7 @@ static int fill_ctrlset(struct zd_mac *mac,
unsigned int frag_len = skb->len + FCS_LEN;
unsigned int packet_length;
struct ieee80211_rate *txrate;
- struct zd_ctrlset *cs = (struct zd_ctrlset *)
- skb_push(skb, sizeof(struct zd_ctrlset));
+ struct zd_ctrlset *cs = skb_push(skb, sizeof(struct zd_ctrlset));
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
ZD_ASSERT(frag_len <= 0xffff);
@@ -1103,7 +1102,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
}
/* FIXME : could we avoid this big memcpy ? */
- memcpy(skb_put(skb, length), buffer, length);
+ skb_put_data(skb, buffer, length);
memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats));
ieee80211_rx_irqsafe(hw, skb);
OpenPOWER on IntegriCloud