diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-04 20:41:05 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-04 20:41:05 +0300 |
commit | b0f85fa11aefc4f3e03306b4cd47f113bd57dcba (patch) | |
tree | 1333d36d99fde3f97210795941fc246f0ad08a75 /drivers/net/wireless | |
parent | ccc9d4a6d640cbde05d519edeb727881646cf71b (diff) | |
parent | f32bfb9a8ca083f8d148ea90ae5ba66f4831836e (diff) | |
download | linux-b0f85fa11aefc4f3e03306b4cd47f113bd57dcba.tar.xz |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller:
Changes of note:
1) Allow to schedule ICMP packets in IPVS, from Alex Gartrell.
2) Provide FIB table ID in ipv4 route dumps just as ipv6 does, from
David Ahern.
3) Allow the user to ask for the statistics to be filtered out of
ipv4/ipv6 address netlink dumps. From Sowmini Varadhan.
4) More work to pass the network namespace context around deep into
various packet path APIs, starting with the netfilter hooks. From
Eric W Biederman.
5) Add layer 2 TX/RX checksum offloading to qeth driver, from Thomas
Richter.
6) Use usec resolution for SYN/ACK RTTs in TCP, from Yuchung Cheng.
7) Support Very High Throughput in wireless MESH code, from Bob
Copeland.
8) Allow setting the ageing_time in switchdev/rocker. From Scott
Feldman.
9) Properly autoload L2TP type modules, from Stephen Hemminger.
10) Fix and enable offload features by default in 8139cp driver, from
David Woodhouse.
11) Support both ipv4 and ipv6 sockets in a single vxlan device, from
Jiri Benc.
12) Fix CWND limiting of thin streams in TCP, from Bendik Rønning
Opstad.
13) Fix IPSEC flowcache overflows on large systems, from Steffen
Klassert.
14) Convert bridging to track VLANs using rhashtable entries rather than
a bitmap. From Nikolay Aleksandrov.
15) Make TCP listener handling completely lockless, this is a major
accomplishment. Incoming request sockets now live in the
established hash table just like any other socket too.
From Eric Dumazet.
15) Provide more bridging attributes to netlink, from Nikolay
Aleksandrov.
16) Use hash based algorithm for ipv4 multipath routing, this was very
long overdue. From Peter Nørlund.
17) Several y2038 cures, mostly avoiding timespec. From Arnd Bergmann.
18) Allow non-root execution of EBPF programs, from Alexei Starovoitov.
19) Support SO_INCOMING_CPU as setsockopt, from Eric Dumazet. This
influences the port binding selection logic used by SO_REUSEPORT.
20) Add ipv6 support to VRF, from David Ahern.
21) Add support for Mellanox Spectrum switch ASIC, from Jiri Pirko.
22) Add rtl8xxxu Realtek wireless driver, from Jes Sorensen.
23) Implement RACK loss recovery in TCP, from Yuchung Cheng.
24) Support multipath routes in MPLS, from Roopa Prabhu.
25) Fix POLLOUT notification for listening sockets in AF_UNIX, from Eric
Dumazet.
26) Add new QED Qlogic river, from Yuval Mintz, Manish Chopra, and
Sudarsana Kalluru.
27) Don't fetch timestamps on AF_UNIX sockets, from Hannes Frederic
Sowa.
28) Support ipv6 geneve tunnels, from John W Linville.
29) Add flood control support to switchdev layer, from Ido Schimmel.
30) Fix CHECKSUM_PARTIAL handling of potentially fragmented frames, from
Hannes Frederic Sowa.
31) Support persistent maps and progs in bpf, from Daniel Borkmann.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1790 commits)
sh_eth: use DMA barriers
switchdev: respect SKIP_EOPNOTSUPP flag in case there is no recursion
net: sched: kill dead code in sch_choke.c
irda: Delete an unnecessary check before the function call "irlmp_unregister_service"
net: dsa: mv88e6xxx: include DSA ports in VLANs
net: dsa: mv88e6xxx: disable SA learning for DSA and CPU ports
net/core: fix for_each_netdev_feature
vlan: Invoke driver vlan hooks only if device is present
arcnet/com20020: add LEDS_CLASS dependency
bpf, verifier: annotate verbose printer with __printf
dp83640: Only wait for timestamps for packets with timestamping enabled.
ptp: Change ptp_class to a proper bitmask
dp83640: Prune rx timestamp list before reading from it
dp83640: Delay scheduled work.
dp83640: Include hash in timestamp/packet matching
ipv6: fix tunnel error handling
net/mlx5e: Fix LSO vlan insertion
net/mlx5e: Re-eanble client vlan TX acceleration
net/mlx5e: Return error in case mlx5e_set_features() fails
net/mlx5e: Don't allow more than max supported channels
...
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/Kconfig | 7 | ||||
-rw-r--r-- | drivers/net/wireless/Makefile | 4 | ||||
-rw-r--r-- | drivers/net/wireless/airo.c | 139 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/bmi.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/ce.c | 67 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/ce.h | 23 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/core.c | 387 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/core.h | 69 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/debug.c | 516 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/debug.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/hif.h | 26 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/htc.c | 51 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/htc.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/htt.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/htt_rx.c | 48 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/htt_tx.c | 112 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/hw.h | 35 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/mac.c | 640 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/pci.c | 333 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/pci.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/targaddrs.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/testmode.c | 202 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/thermal.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/txrx.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi-ops.h | 57 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi-tlv.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi.c | 979 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi.h | 195 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.c | 149 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/core.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/debug.c | 55 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/debug.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/htc_mbox.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/init.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9002_phy.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_calib.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_hw.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_phy.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/common-debug.c | 14 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/debug.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hif_usb.c | 106 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hif_usb.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_init.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/init.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.h | 18 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/carl9170/main.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/carl9170/rx.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/dfs_pattern_detector.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath/dfs_pattern_detector.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ath/dfs_pri_detector.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/dxe.c | 61 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/dxe.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/main.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/debugfs.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/interrupt.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/main.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/pcie_bus.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/pmc.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/rx_reorder.c | 26 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx.c | 92 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wil6210.h | 14 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wil_crash_dump.c | 115 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wmi.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/b43/Kconfig | 20 | ||||
-rw-r--r-- | drivers/net/wireless/b43/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/b43/pcmcia.c | 145 | ||||
-rw-r--r-- | drivers/net/wireless/b43/pcmcia.h | 20 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/bcdc.c | 28 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/btcoex.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/bus.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 279 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/chip.c | 130 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/chip.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/common.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/core.c | 179 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/core.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/debug.c | 42 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/debug.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/feature.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/firmware.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/flowring.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/flowring.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/fweh.c | 42 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/fweh.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/fwil.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 57 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 145 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/p2p.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/pcie.c | 178 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/proto.h | 18 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/sdio.c | 55 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/usb.c | 29 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmsmac/main.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/include/brcm_hw_ids.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/cw1200/sta.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/cw1200/sta.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/ipw2200.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/libipw_rx.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlegacy/4965-mac.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlegacy/4965.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/mac80211.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-7000.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-8000.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-config.h | 12 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-drv.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h | 16 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-fw-file.h | 36 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-fw.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-io.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-io.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-nvm-parse.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-op-mode.h | 19 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/constants.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/d3.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | 100 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/debugfs.c | 134 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h | 238 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h | 41 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw-api.h | 259 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw.c | 24 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 39 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 95 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 70 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/nvm.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/ops.c | 179 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/power.c | 109 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/rs.c | 122 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/rx.c | 67 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/scan.c | 122 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/sta.c | 88 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/time-event.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/tof.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/tof.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/tt.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/tx.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/utils.c | 141 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/trans.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt7601u/main.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/11n_aggr.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/11n_rxreorder.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/Kconfig | 4 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/debugfs.c | 66 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/fw.h | 34 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/init.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.c | 81 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.h | 25 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/pcie.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/scan.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sdio.c | 29 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_cmd.c | 34 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_cmdresp.c | 36 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_event.c | 78 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_tx.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/tdls.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/txrx.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/uap_cmd.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/uap_event.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/uap_txrx.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/usb.c | 238 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/usb.h | 20 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/wmm.c | 69 | ||||
-rw-r--r-- | drivers/net/wireless/mwl8k.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco/cfg.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco/orinoco_usb.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/Makefile | 9 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/Kconfig (renamed from drivers/net/wireless/rtl818x/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/Makefile (renamed from drivers/net/wireless/rtl818x/Makefile) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile (renamed from drivers/net/wireless/rtl818x/rtl8180/Makefile) | 2 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c (renamed from drivers/net/wireless/rtl818x/rtl8180/dev.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.c (renamed from drivers/net/wireless/rtl818x/rtl8180/grf5101.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.h (renamed from drivers/net/wireless/rtl818x/rtl8180/grf5101.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.c (renamed from drivers/net/wireless/rtl818x/rtl8180/max2820.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.h (renamed from drivers/net/wireless/rtl818x/rtl8180/max2820.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8180.h (renamed from drivers/net/wireless/rtl818x/rtl8180/rtl8180.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.c (renamed from drivers/net/wireless/rtl818x/rtl8180/rtl8225.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.h (renamed from drivers/net/wireless/rtl818x/rtl8180/rtl8225.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c (renamed from drivers/net/wireless/rtl818x/rtl8180/rtl8225se.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.h (renamed from drivers/net/wireless/rtl818x/rtl8180/rtl8225se.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.c (renamed from drivers/net/wireless/rtl818x/rtl8180/sa2400.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.h (renamed from drivers/net/wireless/rtl818x/rtl8180/sa2400.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile (renamed from drivers/net/wireless/rtl818x/rtl8187/Makefile) | 2 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c (renamed from drivers/net/wireless/rtl818x/rtl8187/dev.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8187/leds.c (renamed from drivers/net/wireless/rtl818x/rtl8187/leds.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8187/leds.h (renamed from drivers/net/wireless/rtl818x/rtl8187/leds.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.c (renamed from drivers/net/wireless/rtl818x/rtl8187/rfkill.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.h (renamed from drivers/net/wireless/rtl818x/rtl8187/rfkill.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8187.h (renamed from drivers/net/wireless/rtl818x/rtl8187/rtl8187.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c (renamed from drivers/net/wireless/rtl818x/rtl8187/rtl8225.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.h (renamed from drivers/net/wireless/rtl818x/rtl8187/rtl8225.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl818x/rtl818x.h (renamed from drivers/net/wireless/rtl818x/rtl818x.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl8xxxu/Kconfig | 34 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl8xxxu/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 5993 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 676 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 981 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/Kconfig (renamed from drivers/net/wireless/rtlwifi/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/Makefile (renamed from drivers/net/wireless/rtlwifi/Makefile) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/base.c (renamed from drivers/net/wireless/rtlwifi/base.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/base.h (renamed from drivers/net/wireless/rtlwifi/base.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/Makefile (renamed from drivers/net/wireless/rtlwifi/btcoexist/Makefile) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbt_precomp.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c (renamed from drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h (renamed from drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/cam.c (renamed from drivers/net/wireless/rtlwifi/cam.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/cam.h (renamed from drivers/net/wireless/rtlwifi/cam.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/core.c (renamed from drivers/net/wireless/rtlwifi/core.c) | 2 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/core.h (renamed from drivers/net/wireless/rtlwifi/core.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/debug.c (renamed from drivers/net/wireless/rtlwifi/debug.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/debug.h (renamed from drivers/net/wireless/rtlwifi/debug.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/efuse.c (renamed from drivers/net/wireless/rtlwifi/efuse.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/efuse.h (renamed from drivers/net/wireless/rtlwifi/efuse.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/pci.c (renamed from drivers/net/wireless/rtlwifi/pci.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/pci.h (renamed from drivers/net/wireless/rtlwifi/pci.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/ps.c (renamed from drivers/net/wireless/rtlwifi/ps.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/ps.h (renamed from drivers/net/wireless/rtlwifi/ps.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h (renamed from drivers/net/wireless/rtlwifi/pwrseqcmd.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rc.c (renamed from drivers/net/wireless/rtlwifi/rc.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rc.h (renamed from drivers/net/wireless/rtlwifi/rc.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/regd.c (renamed from drivers/net/wireless/rtlwifi/regd.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/regd.h (renamed from drivers/net/wireless/rtlwifi/regd.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/Makefile) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/def.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/dm.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/dm.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/fw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/fw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/hw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/hw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/led.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/led.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/phy.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/phy.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/reg.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/rf.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/rf.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/sw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/sw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/table.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/table.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/trx.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8188ee/trx.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192c/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8192c/Makefile) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c (renamed from drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h (renamed from drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c (renamed from drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h (renamed from drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c (renamed from drivers/net/wireless/rtlwifi/rtl8192c/main.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c (renamed from drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h (renamed from drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/Makefile) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/def.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/dm.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/dm.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/hw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/hw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/led.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/led.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/phy.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/phy.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/reg.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/rf.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/rf.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/sw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/sw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/table.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/table.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/trx.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ce/trx.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/Makefile) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/def.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/dm.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/dm.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/hw.c) | 8 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/hw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/led.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/led.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/mac.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/mac.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/phy.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/phy.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/reg.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/rf.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/rf.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/sw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/sw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/table.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/table.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/trx.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8192cu/trx.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8192de/Makefile) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/def.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/dm.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/dm.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/fw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/fw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/hw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/hw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/led.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/led.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/phy.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/phy.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/reg.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/rf.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/rf.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/sw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/sw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/table.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/table.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8192de/trx.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8192de/trx.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/Makefile) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/def.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/dm.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/dm.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/fw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/fw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/hw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/hw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/led.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/led.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/phy.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/phy.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/reg.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/rf.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/rf.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/sw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/sw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/table.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/table.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/trx.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8192ee/trx.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8192se/Makefile) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/def.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/dm.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/dm.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/fw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/fw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/hw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/hw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/led.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/led.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/phy.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/phy.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/reg.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/rf.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/rf.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/sw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/sw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/table.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/table.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8192se/trx.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8192se/trx.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/Makefile) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/btc.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/def.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/dm.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/dm.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/fw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/fw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/hw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/hw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/led.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/led.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/phy.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/phy.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/reg.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/rf.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/rf.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/sw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/sw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/table.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/table.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/trx.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8723ae/trx.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8723be/Makefile) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/def.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/dm.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/dm.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/fw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/fw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/hw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/hw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/led.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/led.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/phy.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/phy.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/reg.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/rf.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/rf.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/sw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/sw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/table.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/table.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8723be/trx.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8723be/trx.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723com/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8723com/Makefile) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c (renamed from drivers/net/wireless/rtlwifi/rtl8723com/dm_common.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h (renamed from drivers/net/wireless/rtlwifi/rtl8723com/dm_common.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c (renamed from drivers/net/wireless/rtlwifi/rtl8723com/fw_common.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h (renamed from drivers/net/wireless/rtlwifi/rtl8723com/fw_common.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c (renamed from drivers/net/wireless/rtlwifi/rtl8723com/main.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c (renamed from drivers/net/wireless/rtlwifi/rtl8723com/phy_common.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h (renamed from drivers/net/wireless/rtlwifi/rtl8723com/phy_common.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/Makefile (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/Makefile) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/def.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/dm.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/dm.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/fw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/fw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/hw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/hw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/led.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/led.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/phy.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/phy.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/reg.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/rf.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/rf.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/sw.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/sw.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/table.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/table.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/trx.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h (renamed from drivers/net/wireless/rtlwifi/rtl8821ae/trx.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/stats.c (renamed from drivers/net/wireless/rtlwifi/stats.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/stats.h (renamed from drivers/net/wireless/rtlwifi/stats.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/usb.c (renamed from drivers/net/wireless/rtlwifi/usb.c) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/usb.h (renamed from drivers/net/wireless/rtlwifi/usb.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/wifi.h (renamed from drivers/net/wireless/rtlwifi/wifi.h) | 0 | ||||
-rw-r--r-- | drivers/net/wireless/rndis_wlan.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rsi/rsi_91x_mac80211.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00config.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wl12xx/scan.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wl18xx/main.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wl18xx/scan.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/main.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/wlcore.h | 2 |
489 files changed, 14230 insertions, 2823 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index a63ab2e83105..f9f94229bf1b 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -214,8 +214,6 @@ config USB_NET_RNDIS_WLAN If you choose to build a module, it'll be called rndis_wlan. -source "drivers/net/wireless/rtl818x/Kconfig" - config ADM8211 tristate "ADMtek ADM8211 support" depends on MAC80211 && PCI @@ -243,6 +241,8 @@ config ADM8211 Thanks to Infineon-ADMtek for their support of this driver. +source "drivers/net/wireless/realtek/rtl818x/Kconfig" + config MAC80211_HWSIM tristate "Simulated radio testing tool for mac80211" depends on MAC80211 @@ -278,7 +278,8 @@ source "drivers/net/wireless/orinoco/Kconfig" source "drivers/net/wireless/p54/Kconfig" source "drivers/net/wireless/rt2x00/Kconfig" source "drivers/net/wireless/mediatek/Kconfig" -source "drivers/net/wireless/rtlwifi/Kconfig" +source "drivers/net/wireless/realtek/rtlwifi/Kconfig" +source "drivers/net/wireless/realtek/rtl8xxxu/Kconfig" source "drivers/net/wireless/ti/Kconfig" source "drivers/net/wireless/zd1211rw/Kconfig" source "drivers/net/wireless/mwifiex/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 6b9e729dd8ac..740fdd353c5d 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -22,9 +22,7 @@ obj-$(CONFIG_HOSTAP) += hostap/ obj-$(CONFIG_B43) += b43/ obj-$(CONFIG_B43LEGACY) += b43legacy/ obj-$(CONFIG_ZD1211RW) += zd1211rw/ -obj-$(CONFIG_RTL8180) += rtl818x/ -obj-$(CONFIG_RTL8187) += rtl818x/ -obj-$(CONFIG_RTLWIFI) += rtlwifi/ +obj-$(CONFIG_WLAN) += realtek/ # 16-bit wireless PCMCIA client drivers obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index d0c97c220026..17c40f06f13e 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -1231,12 +1231,13 @@ struct airo_info { dma_addr_t shared_dma; pm_message_t power; SsidRid *SSID; - APListRid *APList; + APListRid APList; #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE char proc_name[IFNAMSIZ]; int wep_capable; int max_wep_idx; + int last_auth; /* WPA-related stuff */ unsigned int bssListFirst; @@ -1847,11 +1848,6 @@ static int readStatusRid(struct airo_info *ai, StatusRid *statr, int lock) return PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock); } -static int readAPListRid(struct airo_info *ai, APListRid *aplr) -{ - return PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr), 1); -} - static int writeAPListRid(struct airo_info *ai, APListRid *aplr, int lock) { return PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock); @@ -2412,7 +2408,6 @@ void stop_airo_card( struct net_device *dev, int freeres ) kfree(ai->flash); kfree(ai->rssi); - kfree(ai->APList); kfree(ai->SSID); if (freeres) { /* PCMCIA frees this stuff, so only for PCI and ISA */ @@ -2808,6 +2803,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, init_waitqueue_head (&ai->thr_wait); ai->tfm = NULL; add_airo_dev(ai); + ai->APList.len = cpu_to_le16(sizeof(struct APListRid)); if (airo_networks_allocate (ai)) goto err_out_free; @@ -3041,6 +3037,11 @@ static void airo_process_scan_results (struct airo_info *ai) { } out: + /* write APList back (we cleared it in airo_set_scan) */ + disable_MAC(ai, 2); + writeAPListRid(ai, &ai->APList, 0); + enable_MAC(ai, 0); + ai->scan_timeout = 0; clear_bit(JOB_SCAN_RESULTS, &ai->jobs); up(&ai->sem); @@ -3266,6 +3267,7 @@ static void airo_handle_link(struct airo_info *ai) wake_up_interruptible(&ai->thr_wait); } else airo_send_event(ai->dev); + netif_carrier_on(ai->dev); } else if (!scan_forceloss) { if (auto_wep && !ai->expires) { ai->expires = RUN_AT(3*HZ); @@ -3276,6 +3278,9 @@ static void airo_handle_link(struct airo_info *ai) eth_zero_addr(wrqu.ap_addr.sa_data); wrqu.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(ai->dev, SIOCGIWAP, &wrqu, NULL); + netif_carrier_off(ai->dev); + } else { + netif_carrier_off(ai->dev); } } @@ -3608,16 +3613,18 @@ static void disable_MAC( struct airo_info *ai, int lock ) { Cmd cmd; Resp rsp; - if (lock && down_interruptible(&ai->sem)) + if (lock == 1 && down_interruptible(&ai->sem)) return; if (test_bit(FLAG_ENABLED, &ai->flags)) { + if (lock != 2) /* lock == 2 means don't disable carrier */ + netif_carrier_off(ai->dev); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = MAC_DISABLE; // disable in case already enabled issuecommand(ai, &cmd, &rsp); clear_bit(FLAG_ENABLED, &ai->flags); } - if (lock) + if (lock == 1) up(&ai->sem); } @@ -3786,6 +3793,16 @@ badrx: } } +static inline void set_auth_type(struct airo_info *local, int auth_type) +{ + local->config.authType = auth_type; + /* Cache the last auth type used (of AUTH_OPEN and AUTH_ENCRYPT). + * Used by airo_set_auth() + */ + if (auth_type == AUTH_OPEN || auth_type == AUTH_ENCRYPT) + local->last_auth = auth_type; +} + static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) { Cmd cmd; @@ -3836,8 +3853,6 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) tdsRssiRid rssi_rid; CapabilityRid cap_rid; - kfree(ai->APList); - ai->APList = NULL; kfree(ai->SSID); ai->SSID = NULL; // general configuration (read/modify/write) @@ -3862,7 +3877,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) "level scale"); } ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS; - ai->config.authType = AUTH_OPEN; + set_auth_type(ai, AUTH_OPEN); ai->config.modulation = MOD_CCK; if (le16_to_cpu(cap_rid.len) >= sizeof(cap_rid) && @@ -4880,13 +4895,13 @@ static void proc_config_on_close(struct inode *inode, struct file *file) line += 5; switch( line[0] ) { case 's': - ai->config.authType = AUTH_SHAREDKEY; + set_auth_type(ai, AUTH_SHAREDKEY); break; case 'e': - ai->config.authType = AUTH_ENCRYPT; + set_auth_type(ai, AUTH_ENCRYPT); break; default: - ai->config.authType = AUTH_OPEN; + set_auth_type(ai, AUTH_OPEN); break; } set_bit (FLAG_COMMIT, &ai->flags); @@ -5114,31 +5129,31 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) { struct proc_data *data = file->private_data; struct net_device *dev = PDE_DATA(inode); struct airo_info *ai = dev->ml_priv; - APListRid APList_rid; + APListRid *APList_rid = &ai->APList; int i; if ( !data->writelen ) return; - memset( &APList_rid, 0, sizeof(APList_rid) ); - APList_rid.len = cpu_to_le16(sizeof(APList_rid)); + memset(APList_rid, 0, sizeof(*APList_rid)); + APList_rid->len = cpu_to_le16(sizeof(*APList_rid)); for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) { int j; for( j = 0; j < 6*3 && data->wbuffer[j+i*6*3]; j++ ) { switch(j%3) { case 0: - APList_rid.ap[i][j/3]= + APList_rid->ap[i][j/3]= hex_to_bin(data->wbuffer[j+i*6*3])<<4; break; case 1: - APList_rid.ap[i][j/3]|= + APList_rid->ap[i][j/3]|= hex_to_bin(data->wbuffer[j+i*6*3]); break; } } } disable_MAC(ai, 1); - writeAPListRid(ai, &APList_rid, 1); + writeAPListRid(ai, APList_rid, 1); enable_MAC(ai, 1); } @@ -5392,7 +5407,7 @@ static int proc_APList_open( struct inode *inode, struct file *file ) { struct airo_info *ai = dev->ml_priv; int i; char *ptr; - APListRid APList_rid; + APListRid *APList_rid = &ai->APList; if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; @@ -5410,13 +5425,12 @@ static int proc_APList_open( struct inode *inode, struct file *file ) { } data->on_close = proc_APList_on_close; - readAPListRid(ai, &APList_rid); ptr = data->rbuffer; for( i = 0; i < 4; i++ ) { // We end when we find a zero MAC - if ( !*(int*)APList_rid.ap[i] && - !*(int*)&APList_rid.ap[i][2]) break; - ptr += sprintf(ptr, "%pM\n", APList_rid.ap[i]); + if ( !*(int*)APList_rid->ap[i] && + !*(int*)&APList_rid->ap[i][2]) break; + ptr += sprintf(ptr, "%pM\n", APList_rid->ap[i]); } if (i==0) ptr += sprintf(ptr, "Not using specific APs\n"); @@ -5580,15 +5594,10 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) Cmd cmd; Resp rsp; - if (!ai->APList) - ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL); - if (!ai->APList) - return -ENOMEM; if (!ai->SSID) ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL); if (!ai->SSID) return -ENOMEM; - readAPListRid(ai, ai->APList); readSsidRid(ai, ai->SSID); memset(&cmd, 0, sizeof(cmd)); /* the lock will be released at the end of the resume callback */ @@ -5636,11 +5645,7 @@ static int airo_pci_resume(struct pci_dev *pdev) kfree(ai->SSID); ai->SSID = NULL; } - if (ai->APList) { - writeAPListRid(ai, ai->APList, 0); - kfree(ai->APList); - ai->APList = NULL; - } + writeAPListRid(ai, &ai->APList, 0); writeConfigRid(ai, 0); enable_MAC(ai, 0); ai->power = PMSG_ON; @@ -5938,7 +5943,7 @@ static int airo_set_wap(struct net_device *dev, struct airo_info *local = dev->ml_priv; Cmd cmd; Resp rsp; - APListRid APList_rid; + APListRid *APList_rid = &local->APList; if (awrq->sa_family != ARPHRD_ETHER) return -EINVAL; @@ -5951,11 +5956,11 @@ static int airo_set_wap(struct net_device *dev, issuecommand(local, &cmd, &rsp); up(&local->sem); } else { - memset(&APList_rid, 0, sizeof(APList_rid)); - APList_rid.len = cpu_to_le16(sizeof(APList_rid)); - memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN); + memset(APList_rid, 0, sizeof(*APList_rid)); + APList_rid->len = cpu_to_le16(sizeof(*APList_rid)); + memcpy(APList_rid->ap[0], awrq->sa_data, ETH_ALEN); disable_MAC(local, 1); - writeAPListRid(local, &APList_rid, 1); + writeAPListRid(local, APList_rid, 1); enable_MAC(local, 1); } return 0; @@ -6368,9 +6373,8 @@ static int airo_set_encode(struct net_device *dev, * should be enabled (user may turn it off later) * This is also how "iwconfig ethX key on" works */ if((index == current_index) && (key.len > 0) && - (local->config.authType == AUTH_OPEN)) { - local->config.authType = AUTH_ENCRYPT; - } + (local->config.authType == AUTH_OPEN)) + set_auth_type(local, AUTH_ENCRYPT); } else { /* Do we want to just set the transmit key index ? */ int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; @@ -6389,12 +6393,12 @@ static int airo_set_encode(struct net_device *dev, } } /* Read the flags */ - if(dwrq->flags & IW_ENCODE_DISABLED) - local->config.authType = AUTH_OPEN; // disable encryption + if (dwrq->flags & IW_ENCODE_DISABLED) + set_auth_type(local, AUTH_OPEN); /* disable encryption */ if(dwrq->flags & IW_ENCODE_RESTRICTED) - local->config.authType = AUTH_SHAREDKEY; // Only Both - if(dwrq->flags & IW_ENCODE_OPEN) - local->config.authType = AUTH_ENCRYPT; // Only Wep + set_auth_type(local, AUTH_SHAREDKEY); /* Only Both */ + if (dwrq->flags & IW_ENCODE_OPEN) + set_auth_type(local, AUTH_ENCRYPT); /* Only Wep */ /* Commit the changes to flags if needed */ if (local->config.authType != currentAuthType) set_bit (FLAG_COMMIT, &local->flags); @@ -6549,12 +6553,12 @@ static int airo_set_encodeext(struct net_device *dev, } /* Read the flags */ - if(encoding->flags & IW_ENCODE_DISABLED) - local->config.authType = AUTH_OPEN; // disable encryption + if (encoding->flags & IW_ENCODE_DISABLED) + set_auth_type(local, AUTH_OPEN); /* disable encryption */ if(encoding->flags & IW_ENCODE_RESTRICTED) - local->config.authType = AUTH_SHAREDKEY; // Only Both - if(encoding->flags & IW_ENCODE_OPEN) - local->config.authType = AUTH_ENCRYPT; // Only Wep + set_auth_type(local, AUTH_SHAREDKEY); /* Only Both */ + if (encoding->flags & IW_ENCODE_OPEN) + set_auth_type(local, AUTH_ENCRYPT); /* Commit the changes to flags if needed */ if (local->config.authType != currentAuthType) set_bit (FLAG_COMMIT, &local->flags); @@ -6659,9 +6663,9 @@ static int airo_set_auth(struct net_device *dev, if (param->value) { /* Only change auth type if unencrypted */ if (currentAuthType == AUTH_OPEN) - local->config.authType = AUTH_ENCRYPT; + set_auth_type(local, AUTH_ENCRYPT); } else { - local->config.authType = AUTH_OPEN; + set_auth_type(local, AUTH_OPEN); } /* Commit the changes to flags if needed */ @@ -6670,13 +6674,14 @@ static int airo_set_auth(struct net_device *dev, break; case IW_AUTH_80211_AUTH_ALG: { - /* FIXME: What about AUTH_OPEN? This API seems to - * disallow setting our auth to AUTH_OPEN. - */ if (param->value & IW_AUTH_ALG_SHARED_KEY) { - local->config.authType = AUTH_SHAREDKEY; + set_auth_type(local, AUTH_SHAREDKEY); } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { - local->config.authType = AUTH_ENCRYPT; + /* We don't know here if WEP open system or + * unencrypted mode was requested - so use the + * last mode (of these two) used last time + */ + set_auth_type(local, local->last_auth); } else return -EINVAL; @@ -7217,6 +7222,7 @@ static int airo_set_scan(struct net_device *dev, Cmd cmd; Resp rsp; int wake = 0; + APListRid APList_rid_empty; /* Note : you may have realised that, as this is a SET operation, * this is privileged and therefore a normal user can't @@ -7234,6 +7240,13 @@ static int airo_set_scan(struct net_device *dev, if (ai->scan_timeout > 0) goto out; + /* Clear APList as it affects scan results */ + memset(&APList_rid_empty, 0, sizeof(APList_rid_empty)); + APList_rid_empty.len = cpu_to_le16(sizeof(APList_rid_empty)); + disable_MAC(ai, 2); + writeAPListRid(ai, &APList_rid_empty, 0); + enable_MAC(ai, 0); + /* Initiate a scan command */ ai->scan_timeout = RUN_AT(3*HZ); memset(&cmd, 0, sizeof(cmd)); @@ -7489,10 +7502,8 @@ static int airo_config_commit(struct net_device *dev, * parameters. It's now time to commit them in the card */ disable_MAC(local, 1); if (test_bit (FLAG_RESET, &local->flags)) { - APListRid APList_rid; SsidRid SSID_rid; - readAPListRid(local, &APList_rid); readSsidRid(local, &SSID_rid); if (test_bit(FLAG_MPI,&local->flags)) setup_card(local, dev->dev_addr, 1 ); @@ -7500,7 +7511,7 @@ static int airo_config_commit(struct net_device *dev, reset_airo_card(dev); disable_MAC(local, 1); writeSsidRid(local, &SSID_rid, 1); - writeAPListRid(local, &APList_rid, 1); + writeAPListRid(local, &local->APList, 1); } if (down_interruptible(&local->sem)) return -ERESTARTSYS; diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h index df7c7616533b..7d3231acfb24 100644 --- a/drivers/net/wireless/ath/ath10k/bmi.h +++ b/drivers/net/wireless/ath/ath10k/bmi.h @@ -82,6 +82,16 @@ enum bmi_cmd_id { #define BMI_NVRAM_SEG_NAME_SZ 16 +#define BMI_PARAM_GET_EEPROM_BOARD_ID 0x10 + +#define ATH10K_BMI_BOARD_ID_FROM_OTP_MASK 0x7c00 +#define ATH10K_BMI_BOARD_ID_FROM_OTP_LSB 10 + +#define ATH10K_BMI_CHIP_ID_FROM_OTP_MASK 0x18000 +#define ATH10K_BMI_CHIP_ID_FROM_OTP_LSB 15 + +#define ATH10K_BMI_BOARD_ID_STATUS_MASK 0xff + struct bmi_cmd { __le32 id; /* enum bmi_cmd_id */ union { diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index cf28fbebaedc..edf3629288bc 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -274,7 +274,7 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, { struct ath10k *ar = ce_state->ar; struct ath10k_ce_ring *src_ring = ce_state->src_ring; - struct ce_desc *desc, *sdesc; + struct ce_desc *desc, sdesc; unsigned int nentries_mask = src_ring->nentries_mask; unsigned int sw_index = src_ring->sw_index; unsigned int write_index = src_ring->write_index; @@ -294,7 +294,6 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, desc = CE_SRC_RING_TO_DESC(src_ring->base_addr_owner_space, write_index); - sdesc = CE_SRC_RING_TO_DESC(src_ring->shadow_base, write_index); desc_flags |= SM(transfer_id, CE_DESC_FLAGS_META_DATA); @@ -303,11 +302,11 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, if (flags & CE_SEND_FLAG_BYTE_SWAP) desc_flags |= CE_DESC_FLAGS_BYTE_SWAP; - sdesc->addr = __cpu_to_le32(buffer); - sdesc->nbytes = __cpu_to_le16(nbytes); - sdesc->flags = __cpu_to_le16(desc_flags); + sdesc.addr = __cpu_to_le32(buffer); + sdesc.nbytes = __cpu_to_le16(nbytes); + sdesc.flags = __cpu_to_le16(desc_flags); - *desc = *sdesc; + *desc = sdesc; src_ring->per_transfer_context[write_index] = per_transfer_context; @@ -413,7 +412,7 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) lockdep_assert_held(&ar_pci->ce_lock); if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0) - return -EIO; + return -ENOSPC; desc->addr = __cpu_to_le32(paddr); desc->nbytes = 0; @@ -579,17 +578,13 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, * The caller takes responsibility for any necessary locking. */ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, - void **per_transfer_contextp, - u32 *bufferp, - unsigned int *nbytesp, - unsigned int *transfer_idp) + void **per_transfer_contextp) { struct ath10k_ce_ring *src_ring = ce_state->src_ring; u32 ctrl_addr = ce_state->ctrl_addr; struct ath10k *ar = ce_state->ar; unsigned int nentries_mask = src_ring->nentries_mask; unsigned int sw_index = src_ring->sw_index; - struct ce_desc *sdesc, *sbase; unsigned int read_index; if (src_ring->hw_index == sw_index) { @@ -614,15 +609,6 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, if (read_index == sw_index) return -EIO; - sbase = src_ring->shadow_base; - sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index); - - /* Return data from completed source descriptor */ - *bufferp = __le32_to_cpu(sdesc->addr); - *nbytesp = __le16_to_cpu(sdesc->nbytes); - *transfer_idp = MS(__le16_to_cpu(sdesc->flags), - CE_DESC_FLAGS_META_DATA); - if (per_transfer_contextp) *per_transfer_contextp = src_ring->per_transfer_context[sw_index]; @@ -697,10 +683,7 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, } int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, - void **per_transfer_contextp, - u32 *bufferp, - unsigned int *nbytesp, - unsigned int *transfer_idp) + void **per_transfer_contextp) { struct ath10k *ar = ce_state->ar; struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -708,9 +691,7 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, spin_lock_bh(&ar_pci->ce_lock); ret = ath10k_ce_completed_send_next_nolock(ce_state, - per_transfer_contextp, - bufferp, nbytesp, - transfer_idp); + per_transfer_contextp); spin_unlock_bh(&ar_pci->ce_lock); return ret; @@ -940,27 +921,6 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id, src_ring->base_addr_ce_space_unaligned, CE_DESC_RING_ALIGN); - /* - * Also allocate a shadow src ring in regular - * mem to use for faster access. - */ - src_ring->shadow_base_unaligned = - kmalloc((nentries * sizeof(struct ce_desc) + - CE_DESC_RING_ALIGN), GFP_KERNEL); - if (!src_ring->shadow_base_unaligned) { - dma_free_coherent(ar->dev, - (nentries * sizeof(struct ce_desc) + - CE_DESC_RING_ALIGN), - src_ring->base_addr_owner_space, - src_ring->base_addr_ce_space); - kfree(src_ring); - return ERR_PTR(-ENOMEM); - } - - src_ring->shadow_base = PTR_ALIGN( - src_ring->shadow_base_unaligned, - CE_DESC_RING_ALIGN); - return src_ring; } @@ -1076,9 +1036,7 @@ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id) } int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, - const struct ce_attr *attr, - void (*send_cb)(struct ath10k_ce_pipe *), - void (*recv_cb)(struct ath10k_ce_pipe *)) + const struct ce_attr *attr) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; @@ -1104,10 +1062,10 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, ce_state->src_sz_max = attr->src_sz_max; if (attr->src_nentries) - ce_state->send_cb = send_cb; + ce_state->send_cb = attr->send_cb; if (attr->dest_nentries) - ce_state->recv_cb = recv_cb; + ce_state->recv_cb = attr->recv_cb; if (attr->src_nentries) { ce_state->src_ring = ath10k_ce_alloc_src_ring(ar, ce_id, attr); @@ -1141,7 +1099,6 @@ void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id) struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; if (ce_state->src_ring) { - kfree(ce_state->src_ring->shadow_base_unaligned); dma_free_coherent(ar->dev, (ce_state->src_ring->nentries * sizeof(struct ce_desc) + diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 5c903e15dd65..47b734ce7ecf 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -100,12 +100,6 @@ struct ath10k_ce_ring { /* CE address space */ u32 base_addr_ce_space; - /* - * Start of shadow copy of descriptors, within regular memory. - * Aligned to descriptor-size boundary. - */ - void *shadow_base_unaligned; - struct ce_desc *shadow_base; /* keep last */ void *per_transfer_context[0]; @@ -192,16 +186,10 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state, * Pops 1 completed send buffer from Source ring. */ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, - void **per_transfer_contextp, - u32 *bufferp, - unsigned int *nbytesp, - unsigned int *transfer_idp); + void **per_transfer_contextp); int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, - void **per_transfer_contextp, - u32 *bufferp, - unsigned int *nbytesp, - unsigned int *transfer_idp); + void **per_transfer_contextp); /*==================CE Engine Initialization=======================*/ @@ -209,9 +197,7 @@ int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, const struct ce_attr *attr); void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id); int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, - const struct ce_attr *attr, - void (*send_cb)(struct ath10k_ce_pipe *), - void (*recv_cb)(struct ath10k_ce_pipe *)); + const struct ce_attr *attr); void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id); /*==================CE Engine Shutdown=======================*/ @@ -277,6 +263,9 @@ struct ce_attr { /* #entries in destination ring - Must be a power of 2 */ unsigned int dest_nentries; + + void (*send_cb)(struct ath10k_ce_pipe *); + void (*recv_cb)(struct ath10k_ce_pipe *); }; #define SR_BA_ADDRESS 0x0000 diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index b87b98617073..aa9bd92ac4ed 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -34,16 +34,19 @@ unsigned int ath10k_debug_mask; static unsigned int ath10k_cryptmode_param; static bool uart_print; static bool skip_otp; +static bool rawmode; module_param_named(debug_mask, ath10k_debug_mask, uint, 0644); module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644); module_param(uart_print, bool, 0644); module_param(skip_otp, bool, 0644); +module_param(rawmode, bool, 0644); MODULE_PARM_DESC(debug_mask, "Debugging mask"); MODULE_PARM_DESC(uart_print, "Uart target debugging"); MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode"); MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software"); +MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath"); static const struct ath10k_hw_params ath10k_hw_params_list[] = { { @@ -54,6 +57,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .has_shifted_cc_wraparound = true, .otp_exe_param = 0, .channel_counters_freq_hz = 88000, + .max_probe_resp_desc_thres = 0, .fw = { .dir = QCA988X_HW_2_0_FW_DIR, .fw = QCA988X_HW_2_0_FW_FILE, @@ -70,6 +74,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .uart_pin = 6, .otp_exe_param = 0, .channel_counters_freq_hz = 88000, + .max_probe_resp_desc_thres = 0, .fw = { .dir = QCA6174_HW_2_1_FW_DIR, .fw = QCA6174_HW_2_1_FW_FILE, @@ -86,6 +91,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .uart_pin = 6, .otp_exe_param = 0, .channel_counters_freq_hz = 88000, + .max_probe_resp_desc_thres = 0, .fw = { .dir = QCA6174_HW_3_0_FW_DIR, .fw = QCA6174_HW_3_0_FW_FILE, @@ -102,6 +108,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .uart_pin = 6, .otp_exe_param = 0, .channel_counters_freq_hz = 88000, + .max_probe_resp_desc_thres = 0, .fw = { /* uses same binaries as hw3.0 */ .dir = QCA6174_HW_3_0_FW_DIR, @@ -120,6 +127,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .otp_exe_param = 0x00000700, .continuous_frag_desc = true, .channel_counters_freq_hz = 150000, + .max_probe_resp_desc_thres = 24, .fw = { .dir = QCA99X0_HW_2_0_FW_DIR, .fw = QCA99X0_HW_2_0_FW_FILE, @@ -129,6 +137,21 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, }, }, + { + .id = QCA9377_HW_1_0_DEV_VERSION, + .name = "qca9377 hw1.0", + .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR, + .uart_pin = 7, + .otp_exe_param = 0, + .fw = { + .dir = QCA9377_HW_1_0_FW_DIR, + .fw = QCA9377_HW_1_0_FW_FILE, + .otp = QCA9377_HW_1_0_OTP_FILE, + .board = QCA9377_HW_1_0_BOARD_DATA_FILE, + .board_size = QCA9377_BOARD_DATA_SZ, + .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, + }, + }, }; static const char *const ath10k_core_fw_feature_str[] = { @@ -142,12 +165,18 @@ static const char *const ath10k_core_fw_feature_str[] = { [ATH10K_FW_FEATURE_IGNORE_OTP_RESULT] = "ignore-otp", [ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING] = "no-4addr-pad", [ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init", + [ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode", + [ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca", }; static unsigned int ath10k_core_get_fw_feature_str(char *buf, size_t buf_len, enum ath10k_fw_features feat) { + /* make sure that ath10k_core_fw_feature_str[] gets updated */ + BUILD_BUG_ON(ARRAY_SIZE(ath10k_core_fw_feature_str) != + ATH10K_FW_FEATURE_COUNT); + if (feat >= ARRAY_SIZE(ath10k_core_fw_feature_str) || WARN_ON(!ath10k_core_fw_feature_str[feat])) { return scnprintf(buf, buf_len, "bit%d", feat); @@ -435,6 +464,56 @@ out: return ret; } +static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) +{ + u32 result, address; + u8 board_id, chip_id; + int ret; + + address = ar->hw_params.patch_load_addr; + + if (!ar->otp_data || !ar->otp_len) { + ath10k_warn(ar, + "failed to retrieve board id because of invalid otp\n"); + return -ENODATA; + } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "boot upload otp to 0x%x len %zd for board id\n", + address, ar->otp_len); + + ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len); + if (ret) { + ath10k_err(ar, "could not write otp for board id check: %d\n", + ret); + return ret; + } + + ret = ath10k_bmi_execute(ar, address, BMI_PARAM_GET_EEPROM_BOARD_ID, + &result); + if (ret) { + ath10k_err(ar, "could not execute otp for board id check: %d\n", + ret); + return ret; + } + + board_id = MS(result, ATH10K_BMI_BOARD_ID_FROM_OTP); + chip_id = MS(result, ATH10K_BMI_CHIP_ID_FROM_OTP); + + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "boot get otp board id result 0x%08x board_id %d chip_id %d\n", + result, board_id, chip_id); + + if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0) + return -EOPNOTSUPP; + + ar->id.bmi_ids_valid = true; + ar->id.bmi_board_id = board_id; + ar->id.bmi_chip_id = chip_id; + + return 0; +} + static int ath10k_download_and_run_otp(struct ath10k *ar) { u32 result, address = ar->hw_params.patch_load_addr; @@ -473,8 +552,8 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT, - ar->fw_features)) - && result != 0) { + ar->fw_features)) && + result != 0) { ath10k_err(ar, "otp calibration failed: %d", result); return -EINVAL; } @@ -497,7 +576,7 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode) data_len = ar->firmware_len; mode_name = "normal"; ret = ath10k_swap_code_seg_configure(ar, - ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW); + ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW); if (ret) { ath10k_err(ar, "failed to configure fw code swap: %d\n", ret); @@ -505,8 +584,8 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode) } break; case ATH10K_FIRMWARE_MODE_UTF: - data = ar->testmode.utf->data; - data_len = ar->testmode.utf->size; + data = ar->testmode.utf_firmware_data; + data_len = ar->testmode.utf_firmware_len; mode_name = "utf"; break; default: @@ -528,11 +607,18 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode) return ret; } -static void ath10k_core_free_firmware_files(struct ath10k *ar) +static void ath10k_core_free_board_files(struct ath10k *ar) { if (!IS_ERR(ar->board)) release_firmware(ar->board); + ar->board = NULL; + ar->board_data = NULL; + ar->board_len = 0; +} + +static void ath10k_core_free_firmware_files(struct ath10k *ar) +{ if (!IS_ERR(ar->otp)) release_firmware(ar->otp); @@ -544,10 +630,6 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) ath10k_swap_code_seg_release(ar); - ar->board = NULL; - ar->board_data = NULL; - ar->board_len = 0; - ar->otp = NULL; ar->otp_data = NULL; ar->otp_len = 0; @@ -557,7 +639,6 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) ar->firmware_len = 0; ar->cal_file = NULL; - } static int ath10k_fetch_cal_file(struct ath10k *ar) @@ -579,68 +660,251 @@ static int ath10k_fetch_cal_file(struct ath10k *ar) return 0; } -static int ath10k_core_fetch_spec_board_file(struct ath10k *ar) +static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar) { - char filename[100]; - - scnprintf(filename, sizeof(filename), "board-%s-%s.bin", - ath10k_bus_str(ar->hif.bus), ar->spec_board_id); + if (!ar->hw_params.fw.board) { + ath10k_err(ar, "failed to find board file fw entry\n"); + return -EINVAL; + } - ar->board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, filename); + ar->board = ath10k_fetch_fw_file(ar, + ar->hw_params.fw.dir, + ar->hw_params.fw.board); if (IS_ERR(ar->board)) return PTR_ERR(ar->board); ar->board_data = ar->board->data; ar->board_len = ar->board->size; - ar->spec_board_loaded = true; return 0; } -static int ath10k_core_fetch_generic_board_file(struct ath10k *ar) +static int ath10k_core_parse_bd_ie_board(struct ath10k *ar, + const void *buf, size_t buf_len, + const char *boardname) { - if (!ar->hw_params.fw.board) { - ath10k_err(ar, "failed to find board file fw entry\n"); - return -EINVAL; + const struct ath10k_fw_ie *hdr; + bool name_match_found; + int ret, board_ie_id; + size_t board_ie_len; + const void *board_ie_data; + + name_match_found = false; + + /* go through ATH10K_BD_IE_BOARD_ elements */ + while (buf_len > sizeof(struct ath10k_fw_ie)) { + hdr = buf; + board_ie_id = le32_to_cpu(hdr->id); + board_ie_len = le32_to_cpu(hdr->len); + board_ie_data = hdr->data; + + buf_len -= sizeof(*hdr); + buf += sizeof(*hdr); + + if (buf_len < ALIGN(board_ie_len, 4)) { + ath10k_err(ar, "invalid ATH10K_BD_IE_BOARD length: %zu < %zu\n", + buf_len, ALIGN(board_ie_len, 4)); + ret = -EINVAL; + goto out; + } + + switch (board_ie_id) { + case ATH10K_BD_IE_BOARD_NAME: + ath10k_dbg_dump(ar, ATH10K_DBG_BOOT, "board name", "", + board_ie_data, board_ie_len); + + if (board_ie_len != strlen(boardname)) + break; + + ret = memcmp(board_ie_data, boardname, strlen(boardname)); + if (ret) + break; + + name_match_found = true; + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "boot found match for name '%s'", + boardname); + break; + case ATH10K_BD_IE_BOARD_DATA: + if (!name_match_found) + /* no match found */ + break; + + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "boot found board data for '%s'", + boardname); + + ar->board_data = board_ie_data; + ar->board_len = board_ie_len; + + ret = 0; + goto out; + default: + ath10k_warn(ar, "unknown ATH10K_BD_IE_BOARD found: %d\n", + board_ie_id); + break; + } + + /* jump over the padding */ + board_ie_len = ALIGN(board_ie_len, 4); + + buf_len -= board_ie_len; + buf += board_ie_len; } - ar->board = ath10k_fetch_fw_file(ar, - ar->hw_params.fw.dir, - ar->hw_params.fw.board); + /* no match found */ + ret = -ENOENT; + +out: + return ret; +} + +static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar, + const char *boardname, + const char *filename) +{ + size_t len, magic_len, ie_len; + struct ath10k_fw_ie *hdr; + const u8 *data; + int ret, ie_id; + + ar->board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, filename); if (IS_ERR(ar->board)) return PTR_ERR(ar->board); - ar->board_data = ar->board->data; - ar->board_len = ar->board->size; - ar->spec_board_loaded = false; + data = ar->board->data; + len = ar->board->size; + + /* magic has extra null byte padded */ + magic_len = strlen(ATH10K_BOARD_MAGIC) + 1; + if (len < magic_len) { + ath10k_err(ar, "failed to find magic value in %s/%s, file too short: %zu\n", + ar->hw_params.fw.dir, filename, len); + ret = -EINVAL; + goto err; + } + + if (memcmp(data, ATH10K_BOARD_MAGIC, magic_len)) { + ath10k_err(ar, "found invalid board magic\n"); + ret = -EINVAL; + goto err; + } + + /* magic is padded to 4 bytes */ + magic_len = ALIGN(magic_len, 4); + if (len < magic_len) { + ath10k_err(ar, "failed: %s/%s too small to contain board data, len: %zu\n", + ar->hw_params.fw.dir, filename, len); + ret = -EINVAL; + goto err; + } + + data += magic_len; + len -= magic_len; + + while (len > sizeof(struct ath10k_fw_ie)) { + hdr = (struct ath10k_fw_ie *)data; + ie_id = le32_to_cpu(hdr->id); + ie_len = le32_to_cpu(hdr->len); + + len -= sizeof(*hdr); + data = hdr->data; + + if (len < ALIGN(ie_len, 4)) { + ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n", + ie_id, ie_len, len); + ret = -EINVAL; + goto err; + } + + switch (ie_id) { + case ATH10K_BD_IE_BOARD: + ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len, + boardname); + if (ret == -ENOENT) + /* no match found, continue */ + break; + else if (ret) + /* there was an error, bail out */ + goto err; + + /* board data found */ + goto out; + } + + /* jump over the padding */ + ie_len = ALIGN(ie_len, 4); + + len -= ie_len; + data += ie_len; + } + +out: + if (!ar->board_data || !ar->board_len) { + ath10k_err(ar, + "failed to fetch board data for %s from %s/%s\n", + ar->hw_params.fw.dir, boardname, filename); + ret = -ENODATA; + goto err; + } + + return 0; + +err: + ath10k_core_free_board_files(ar); + return ret; +} + +static int ath10k_core_create_board_name(struct ath10k *ar, char *name, + size_t name_len) +{ + if (ar->id.bmi_ids_valid) { + scnprintf(name, name_len, + "bus=%s,bmi-chip-id=%d,bmi-board-id=%d", + ath10k_bus_str(ar->hif.bus), + ar->id.bmi_chip_id, + ar->id.bmi_board_id); + goto out; + } + + scnprintf(name, name_len, + "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x", + ath10k_bus_str(ar->hif.bus), + ar->id.vendor, ar->id.device, + ar->id.subsystem_vendor, ar->id.subsystem_device); + +out: + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using board name '%s'\n", name); return 0; } static int ath10k_core_fetch_board_file(struct ath10k *ar) { + char boardname[100]; int ret; - if (strlen(ar->spec_board_id) > 0) { - ret = ath10k_core_fetch_spec_board_file(ar); - if (ret) { - ath10k_info(ar, "failed to load spec board file, falling back to generic: %d\n", - ret); - goto generic; - } - - ath10k_dbg(ar, ATH10K_DBG_BOOT, "found specific board file for %s\n", - ar->spec_board_id); - return 0; + ret = ath10k_core_create_board_name(ar, boardname, sizeof(boardname)); + if (ret) { + ath10k_err(ar, "failed to create board name: %d", ret); + return ret; } -generic: - ret = ath10k_core_fetch_generic_board_file(ar); + ar->bd_api = 2; + ret = ath10k_core_fetch_board_data_api_n(ar, boardname, + ATH10K_BOARD_API2_FILE); + if (!ret) + goto success; + + ar->bd_api = 1; + ret = ath10k_core_fetch_board_data_api_1(ar); if (ret) { - ath10k_err(ar, "failed to fetch generic board data: %d\n", ret); + ath10k_err(ar, "failed to fetch board data\n"); return ret; } +success: + ath10k_dbg(ar, ATH10K_DBG_BOOT, "using board api %d\n", ar->bd_api); return 0; } @@ -872,12 +1136,6 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) /* calibration file is optional, don't check for any errors */ ath10k_fetch_cal_file(ar); - ret = ath10k_core_fetch_board_file(ar); - if (ret) { - ath10k_err(ar, "failed to fetch board file: %d\n", ret); - return ret; - } - ar->fw_api = 5; ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); @@ -1117,6 +1375,15 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT; ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT; + if (rawmode) { + if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT, + ar->fw_features)) { + ath10k_err(ar, "rawmode = 1 requires support from firmware"); + return -EINVAL; + } + set_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags); + } + if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_RAW; @@ -1241,10 +1508,10 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) goto err; /* Some of of qca988x solutions are having global reset issue - * during target initialization. Bypassing PLL setting before - * downloading firmware and letting the SoC run on REF_CLK is - * fixing the problem. Corresponding firmware change is also needed - * to set the clock source once the target is initialized. + * during target initialization. Bypassing PLL setting before + * downloading firmware and letting the SoC run on REF_CLK is + * fixing the problem. Corresponding firmware change is also needed + * to set the clock source once the target is initialized. */ if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT, ar->fw_features)) { @@ -1478,6 +1745,19 @@ static int ath10k_core_probe_fw(struct ath10k *ar) goto err_power_down; } + ret = ath10k_core_get_board_id_from_otp(ar); + if (ret && ret != -EOPNOTSUPP) { + ath10k_err(ar, "failed to get board id from otp for qca99x0: %d\n", + ret); + return ret; + } + + ret = ath10k_core_fetch_board_file(ar); + if (ret) { + ath10k_err(ar, "failed to fetch board file: %d\n", ret); + goto err_free_firmware_files; + } + ret = ath10k_core_init_firmware_features(ar); if (ret) { ath10k_err(ar, "fatal problem with firmware features: %d\n", @@ -1605,6 +1885,7 @@ void ath10k_core_unregister(struct ath10k *ar) ath10k_testmode_destroy(ar); ath10k_core_free_firmware_files(ar); + ath10k_core_free_board_files(ar); ath10k_debug_unregister(ar); } @@ -1635,6 +1916,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ar->hw_values = &qca988x_values; break; case ATH10K_HW_QCA6174: + case ATH10K_HW_QCA9377: ar->regs = &qca6174_regs; ar->hw_values = &qca6174_values; break; @@ -1714,6 +1996,7 @@ void ath10k_core_destroy(struct ath10k *ar) destroy_workqueue(ar->workqueue_aux); ath10k_debug_destroy(ar); + ath10k_wmi_free_host_mem(ar); ath10k_mac_destroy(ar); } EXPORT_SYMBOL(ath10k_core_destroy); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 12542144fe12..4a2301589902 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -214,6 +214,7 @@ struct ath10k_fw_stats_pdev { s32 hw_queued; s32 hw_reaped; s32 underrun; + u32 hw_paused; s32 tx_abort; s32 mpdus_requed; u32 tx_ko; @@ -226,6 +227,16 @@ struct ath10k_fw_stats_pdev { u32 pdev_resets; u32 phy_underrun; u32 txop_ovf; + u32 seq_posted; + u32 seq_failed_queueing; + u32 seq_completed; + u32 seq_restarted; + u32 mu_seq_posted; + u32 mpdus_sw_flush; + u32 mpdus_hw_filter; + u32 mpdus_truncated; + u32 mpdus_ack_failed; + u32 mpdus_expired; /* PDEV RX stats */ s32 mid_ppdu_route_change; @@ -242,6 +253,7 @@ struct ath10k_fw_stats_pdev { s32 phy_errs; s32 phy_err_drop; s32 mpdu_errs; + s32 rx_ovfl_errs; }; struct ath10k_fw_stats { @@ -250,6 +262,30 @@ struct ath10k_fw_stats { struct list_head peers; }; +#define ATH10K_TPC_TABLE_TYPE_FLAG 1 +#define ATH10K_TPC_PREAM_TABLE_END 0xFFFF + +struct ath10k_tpc_table { + u32 pream_idx[WMI_TPC_RATE_MAX]; + u8 rate_code[WMI_TPC_RATE_MAX]; + char tpc_value[WMI_TPC_RATE_MAX][WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE]; +}; + +struct ath10k_tpc_stats { + u32 reg_domain; + u32 chan_freq; + u32 phy_mode; + u32 twice_antenna_reduction; + u32 twice_max_rd_power; + s32 twice_antenna_gain; + u32 power_limit; + u32 num_tx_chain; + u32 ctl; + u32 rate_max; + u8 flag[WMI_TPC_FLAG]; + struct ath10k_tpc_table tpc_table[WMI_TPC_FLAG]; +}; + struct ath10k_dfs_stats { u32 phy_errors; u32 pulses_total; @@ -378,6 +414,11 @@ struct ath10k_debug { struct ath10k_dfs_stats dfs_stats; struct ath_dfs_pool_stats dfs_pool_stats; + /* used for tpc-dump storage, protected by data-lock */ + struct ath10k_tpc_stats *tpc_stats; + + struct completion tpc_complete; + /* protected by conf_mutex */ u32 fw_dbglog_mask; u32 fw_dbglog_level; @@ -468,6 +509,9 @@ enum ath10k_fw_features { */ ATH10K_FW_FEATURE_RAW_MODE_SUPPORT = 10, + /* Firmware Supports Adaptive CCA*/ + ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA = 11, + /* keep last */ ATH10K_FW_FEATURE_COUNT, }; @@ -612,6 +656,11 @@ struct ath10k { u32 channel_counters_freq_hz; + /* Mgmt tx descriptors threshold for limiting probe response + * frames. + */ + u32 max_probe_resp_desc_thres; + struct ath10k_hw_params_fw { const char *dir; const char *fw; @@ -642,10 +691,19 @@ struct ath10k { struct ath10k_swap_code_seg_info *firmware_swap_code_seg_info; } swap; - char spec_board_id[100]; - bool spec_board_loaded; + struct { + u32 vendor; + u32 device; + u32 subsystem_vendor; + u32 subsystem_device; + + bool bmi_ids_valid; + u8 bmi_board_id; + u8 bmi_chip_id; + } id; int fw_api; + int bd_api; enum ath10k_cal_mode cal_mode; struct { @@ -687,8 +745,6 @@ struct ath10k { int num_started_vdevs; /* Protected by conf-mutex */ - u8 supp_tx_chainmask; - u8 supp_rx_chainmask; u8 cfg_tx_chainmask; u8 cfg_rx_chainmask; @@ -771,9 +827,12 @@ struct ath10k { struct { /* protected by conf_mutex */ const struct firmware *utf; + char utf_version[32]; + const void *utf_firmware_data; + size_t utf_firmware_len; DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT); enum ath10k_fw_wmi_op_version orig_wmi_op_version; - + enum ath10k_fw_wmi_op_version op_version; /* protected by data_lock */ bool utf_monitor; } testmode; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index bf033f46f8aa..6cc1aa3449c8 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -125,19 +125,25 @@ EXPORT_SYMBOL(ath10k_info); void ath10k_print_driver_info(struct ath10k *ar) { char fw_features[128] = {}; + char boardinfo[100]; ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features)); - ath10k_info(ar, "%s (0x%08x, 0x%08x%s%s%s) fw %s api %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n", + if (ar->id.bmi_ids_valid) + scnprintf(boardinfo, sizeof(boardinfo), "bmi %d:%d", + ar->id.bmi_chip_id, ar->id.bmi_board_id); + else + scnprintf(boardinfo, sizeof(boardinfo), "sub %04x:%04x", + ar->id.subsystem_vendor, ar->id.subsystem_device); + + ath10k_info(ar, "%s (0x%08x, 0x%08x %s) fw %s fwapi %d bdapi %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n", ar->hw_params.name, ar->target_version, ar->chip_id, - (strlen(ar->spec_board_id) > 0 ? ", " : ""), - ar->spec_board_id, - (strlen(ar->spec_board_id) > 0 && !ar->spec_board_loaded - ? " fallback" : ""), + boardinfo, ar->hw->wiphy->fw_version, ar->fw_api, + ar->bd_api, ar->htt.target_version_major, ar->htt.target_version_minor, ar->wmi.op_version, @@ -285,28 +291,6 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar) spin_unlock_bh(&ar->data_lock); } -static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head) -{ - struct ath10k_fw_stats_peer *i; - size_t num = 0; - - list_for_each_entry(i, head, list) - ++num; - - return num; -} - -static size_t ath10k_debug_fw_stats_num_vdevs(struct list_head *head) -{ - struct ath10k_fw_stats_vdev *i; - size_t num = 0; - - list_for_each_entry(i, head, list) - ++num; - - return num; -} - void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) { struct ath10k_fw_stats stats = {}; @@ -343,8 +327,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) goto free; } - num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers); - num_vdevs = ath10k_debug_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs); + num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers); + num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs); is_start = (list_empty(&ar->debug.fw_stats.pdevs) && !list_empty(&stats.pdevs)); is_end = (!list_empty(&ar->debug.fw_stats.pdevs) && @@ -429,240 +413,6 @@ static int ath10k_debug_fw_stats_request(struct ath10k *ar) return 0; } -/* FIXME: How to calculate the buffer size sanely? */ -#define ATH10K_FW_STATS_BUF_SIZE (1024*1024) - -static void ath10k_fw_stats_fill(struct ath10k *ar, - struct ath10k_fw_stats *fw_stats, - char *buf) -{ - unsigned int len = 0; - unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE; - const struct ath10k_fw_stats_pdev *pdev; - const struct ath10k_fw_stats_vdev *vdev; - const struct ath10k_fw_stats_peer *peer; - size_t num_peers; - size_t num_vdevs; - int i; - - spin_lock_bh(&ar->data_lock); - - pdev = list_first_entry_or_null(&fw_stats->pdevs, - struct ath10k_fw_stats_pdev, list); - if (!pdev) { - ath10k_warn(ar, "failed to get pdev stats\n"); - goto unlock; - } - - num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers); - num_vdevs = ath10k_debug_fw_stats_num_vdevs(&fw_stats->vdevs); - - len += scnprintf(buf + len, buf_len - len, "\n"); - len += scnprintf(buf + len, buf_len - len, "%30s\n", - "ath10k PDEV stats"); - len += scnprintf(buf + len, buf_len - len, "%30s\n\n", - "================="); - - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Channel noise floor", pdev->ch_noise_floor); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "Channel TX power", pdev->chan_tx_power); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "TX frame count", pdev->tx_frame_count); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "RX frame count", pdev->rx_frame_count); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "RX clear count", pdev->rx_clear_count); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "Cycle count", pdev->cycle_count); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "PHY error count", pdev->phy_err_count); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "RTS bad count", pdev->rts_bad); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "RTS good count", pdev->rts_good); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "FCS bad count", pdev->fcs_bad); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "No beacon count", pdev->no_beacons); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "MIB int count", pdev->mib_int_count); - - len += scnprintf(buf + len, buf_len - len, "\n"); - len += scnprintf(buf + len, buf_len - len, "%30s\n", - "ath10k PDEV TX stats"); - len += scnprintf(buf + len, buf_len - len, "%30s\n\n", - "================="); - - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "HTT cookies queued", pdev->comp_queued); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "HTT cookies disp.", pdev->comp_delivered); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MSDU queued", pdev->msdu_enqued); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDU queued", pdev->mpdu_enqued); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MSDUs dropped", pdev->wmm_drop); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Local enqued", pdev->local_enqued); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Local freed", pdev->local_freed); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "HW queued", pdev->hw_queued); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PPDUs reaped", pdev->hw_reaped); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Num underruns", pdev->underrun); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PPDUs cleaned", pdev->tx_abort); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDUs requed", pdev->mpdus_requed); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Excessive retries", pdev->tx_ko); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "HW rate", pdev->data_rc); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Sched self tiggers", pdev->self_triggers); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Dropped due to SW retries", - pdev->sw_retry_failure); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Illegal rate phy errors", - pdev->illgl_rate_phy_err); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Pdev continous xretry", pdev->pdev_cont_xretry); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "TX timeout", pdev->pdev_tx_timeout); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PDEV resets", pdev->pdev_resets); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PHY underrun", pdev->phy_underrun); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDU is more than txop limit", pdev->txop_ovf); - - len += scnprintf(buf + len, buf_len - len, "\n"); - len += scnprintf(buf + len, buf_len - len, "%30s\n", - "ath10k PDEV RX stats"); - len += scnprintf(buf + len, buf_len - len, "%30s\n\n", - "================="); - - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Mid PPDU route change", - pdev->mid_ppdu_route_change); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Tot. number of statuses", pdev->status_rcvd); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Extra frags on rings 0", pdev->r0_frags); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Extra frags on rings 1", pdev->r1_frags); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Extra frags on rings 2", pdev->r2_frags); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Extra frags on rings 3", pdev->r3_frags); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MSDUs delivered to HTT", pdev->htt_msdus); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDUs delivered to HTT", pdev->htt_mpdus); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MSDUs delivered to stack", pdev->loc_msdus); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDUs delivered to stack", pdev->loc_mpdus); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Oversized AMSUs", pdev->oversize_amsdu); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PHY errors", pdev->phy_errs); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PHY errors drops", pdev->phy_err_drop); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs); - - len += scnprintf(buf + len, buf_len - len, "\n"); - len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", - "ath10k VDEV stats", num_vdevs); - len += scnprintf(buf + len, buf_len - len, "%30s\n\n", - "================="); - - list_for_each_entry(vdev, &fw_stats->vdevs, list) { - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "vdev id", vdev->vdev_id); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "beacon snr", vdev->beacon_snr); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "data snr", vdev->data_snr); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "num rx frames", vdev->num_rx_frames); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "num rts fail", vdev->num_rts_fail); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "num rts success", vdev->num_rts_success); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "num rx err", vdev->num_rx_err); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "num rx discard", vdev->num_rx_discard); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "num tx not acked", vdev->num_tx_not_acked); - - for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames); i++) - len += scnprintf(buf + len, buf_len - len, - "%25s [%02d] %u\n", - "num tx frames", i, - vdev->num_tx_frames[i]); - - for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_retries); i++) - len += scnprintf(buf + len, buf_len - len, - "%25s [%02d] %u\n", - "num tx frames retries", i, - vdev->num_tx_frames_retries[i]); - - for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_failures); i++) - len += scnprintf(buf + len, buf_len - len, - "%25s [%02d] %u\n", - "num tx frames failures", i, - vdev->num_tx_frames_failures[i]); - - for (i = 0 ; i < ARRAY_SIZE(vdev->tx_rate_history); i++) - len += scnprintf(buf + len, buf_len - len, - "%25s [%02d] 0x%08x\n", - "tx rate history", i, - vdev->tx_rate_history[i]); - - for (i = 0 ; i < ARRAY_SIZE(vdev->beacon_rssi_history); i++) - len += scnprintf(buf + len, buf_len - len, - "%25s [%02d] %u\n", - "beacon rssi history", i, - vdev->beacon_rssi_history[i]); - - len += scnprintf(buf + len, buf_len - len, "\n"); - } - - len += scnprintf(buf + len, buf_len - len, "\n"); - len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", - "ath10k PEER stats", num_peers); - len += scnprintf(buf + len, buf_len - len, "%30s\n\n", - "================="); - - list_for_each_entry(peer, &fw_stats->peers, list) { - len += scnprintf(buf + len, buf_len - len, "%30s %pM\n", - "Peer MAC address", peer->peer_macaddr); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "Peer RSSI", peer->peer_rssi); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "Peer TX rate", peer->peer_tx_rate); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "Peer RX rate", peer->peer_rx_rate); - len += scnprintf(buf + len, buf_len - len, "\n"); - } - -unlock: - spin_unlock_bh(&ar->data_lock); - - if (len >= buf_len) - buf[len - 1] = 0; - else - buf[len] = 0; -} - static int ath10k_fw_stats_open(struct inode *inode, struct file *file) { struct ath10k *ar = inode->i_private; @@ -688,7 +438,12 @@ static int ath10k_fw_stats_open(struct inode *inode, struct file *file) goto err_free; } - ath10k_fw_stats_fill(ar, &ar->debug.fw_stats, buf); + ret = ath10k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, buf); + if (ret) { + ath10k_warn(ar, "failed to fill fw stats: %d\n", ret); + goto err_free; + } + file->private_data = buf; mutex_unlock(&ar->conf_mutex); @@ -1843,6 +1598,233 @@ static const struct file_operations fops_nf_cal_period = { .llseek = default_llseek, }; +#define ATH10K_TPC_CONFIG_BUF_SIZE (1024 * 1024) + +static int ath10k_debug_tpc_stats_request(struct ath10k *ar) +{ + int ret; + unsigned long time_left; + + lockdep_assert_held(&ar->conf_mutex); + + reinit_completion(&ar->debug.tpc_complete); + + ret = ath10k_wmi_pdev_get_tpc_config(ar, WMI_TPC_CONFIG_PARAM); + if (ret) { + ath10k_warn(ar, "failed to request tpc config: %d\n", ret); + return ret; + } + + time_left = wait_for_completion_timeout(&ar->debug.tpc_complete, + 1 * HZ); + if (time_left == 0) + return -ETIMEDOUT; + + return 0; +} + +void ath10k_debug_tpc_stats_process(struct ath10k *ar, + struct ath10k_tpc_stats *tpc_stats) +{ + spin_lock_bh(&ar->data_lock); + + kfree(ar->debug.tpc_stats); + ar->debug.tpc_stats = tpc_stats; + complete(&ar->debug.tpc_complete); + + spin_unlock_bh(&ar->data_lock); +} + +static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats, + unsigned int j, char *buf, unsigned int *len) +{ + unsigned int i, buf_len; + static const char table_str[][5] = { "CDD", + "STBC", + "TXBF" }; + static const char pream_str[][6] = { "CCK", + "OFDM", + "HT20", + "HT40", + "VHT20", + "VHT40", + "VHT80", + "HTCUP" }; + + buf_len = ATH10K_TPC_CONFIG_BUF_SIZE; + *len += scnprintf(buf + *len, buf_len - *len, + "********************************\n"); + *len += scnprintf(buf + *len, buf_len - *len, + "******************* %s POWER TABLE ****************\n", + table_str[j]); + *len += scnprintf(buf + *len, buf_len - *len, + "********************************\n"); + *len += scnprintf(buf + *len, buf_len - *len, + "No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3\n"); + + for (i = 0; i < tpc_stats->rate_max; i++) { + *len += scnprintf(buf + *len, buf_len - *len, + "%8d %s 0x%2x %s\n", i, + pream_str[tpc_stats->tpc_table[j].pream_idx[i]], + tpc_stats->tpc_table[j].rate_code[i], + tpc_stats->tpc_table[j].tpc_value[i]); + } + + *len += scnprintf(buf + *len, buf_len - *len, + "***********************************\n"); +} + +static void ath10k_tpc_stats_fill(struct ath10k *ar, + struct ath10k_tpc_stats *tpc_stats, + char *buf) +{ + unsigned int len, j, buf_len; + + len = 0; + buf_len = ATH10K_TPC_CONFIG_BUF_SIZE; + + spin_lock_bh(&ar->data_lock); + + if (!tpc_stats) { + ath10k_warn(ar, "failed to get tpc stats\n"); + goto unlock; + } + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, + "*************************************\n"); + len += scnprintf(buf + len, buf_len - len, + "TPC config for channel %4d mode %d\n", + tpc_stats->chan_freq, + tpc_stats->phy_mode); + len += scnprintf(buf + len, buf_len - len, + "*************************************\n"); + len += scnprintf(buf + len, buf_len - len, + "CTL = 0x%2x Reg. Domain = %2d\n", + tpc_stats->ctl, + tpc_stats->reg_domain); + len += scnprintf(buf + len, buf_len - len, + "Antenna Gain = %2d Reg. Max Antenna Gain = %2d\n", + tpc_stats->twice_antenna_gain, + tpc_stats->twice_antenna_reduction); + len += scnprintf(buf + len, buf_len - len, + "Power Limit = %2d Reg. Max Power = %2d\n", + tpc_stats->power_limit, + tpc_stats->twice_max_rd_power / 2); + len += scnprintf(buf + len, buf_len - len, + "Num tx chains = %2d Num supported rates = %2d\n", + tpc_stats->num_tx_chain, + tpc_stats->rate_max); + + for (j = 0; j < tpc_stats->num_tx_chain ; j++) { + switch (j) { + case WMI_TPC_TABLE_TYPE_CDD: + if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) { + len += scnprintf(buf + len, buf_len - len, + "CDD not supported\n"); + break; + } + + ath10k_tpc_stats_print(tpc_stats, j, buf, &len); + break; + case WMI_TPC_TABLE_TYPE_STBC: + if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) { + len += scnprintf(buf + len, buf_len - len, + "STBC not supported\n"); + break; + } + + ath10k_tpc_stats_print(tpc_stats, j, buf, &len); + break; + case WMI_TPC_TABLE_TYPE_TXBF: + if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) { + len += scnprintf(buf + len, buf_len - len, + "TXBF not supported\n***************************\n"); + break; + } + + ath10k_tpc_stats_print(tpc_stats, j, buf, &len); + break; + default: + len += scnprintf(buf + len, buf_len - len, + "Invalid Type\n"); + break; + } + } + +unlock: + spin_unlock_bh(&ar->data_lock); + + if (len >= buf_len) + buf[len - 1] = 0; + else + buf[len] = 0; +} + +static int ath10k_tpc_stats_open(struct inode *inode, struct file *file) +{ + struct ath10k *ar = inode->i_private; + void *buf = NULL; + int ret; + + mutex_lock(&ar->conf_mutex); + + if (ar->state != ATH10K_STATE_ON) { + ret = -ENETDOWN; + goto err_unlock; + } + + buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE); + if (!buf) { + ret = -ENOMEM; + goto err_unlock; + } + + ret = ath10k_debug_tpc_stats_request(ar); + if (ret) { + ath10k_warn(ar, "failed to request tpc config stats: %d\n", + ret); + goto err_free; + } + + ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf); + file->private_data = buf; + + mutex_unlock(&ar->conf_mutex); + return 0; + +err_free: + vfree(buf); + +err_unlock: + mutex_unlock(&ar->conf_mutex); + return ret; +} + +static int ath10k_tpc_stats_release(struct inode *inode, struct file *file) +{ + vfree(file->private_data); + + return 0; +} + +static ssize_t ath10k_tpc_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + const char *buf = file->private_data; + unsigned int len = strlen(buf); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_tpc_stats = { + .open = ath10k_tpc_stats_open, + .release = ath10k_tpc_stats_release, + .read = ath10k_tpc_stats_read, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + int ath10k_debug_start(struct ath10k *ar) { int ret; @@ -2111,6 +2093,8 @@ void ath10k_debug_destroy(struct ath10k *ar) ar->debug.fw_crash_data = NULL; ath10k_debug_fw_stats_reset(ar); + + kfree(ar->debug.tpc_stats); } int ath10k_debug_register(struct ath10k *ar) @@ -2127,6 +2111,7 @@ int ath10k_debug_register(struct ath10k *ar) INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork, ath10k_debug_htt_stats_dwork); + init_completion(&ar->debug.tpc_complete); init_completion(&ar->debug.fw_stats_complete); debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar, @@ -2195,6 +2180,9 @@ int ath10k_debug_register(struct ath10k *ar) debugfs_create_file("quiet_period", S_IRUGO | S_IWUSR, ar->debug.debugfs_phy, ar, &fops_quiet_period); + debugfs_create_file("tpc_stats", S_IRUSR, + ar->debug.debugfs_phy, ar, &fops_tpc_stats); + return 0; } diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 53bd6a19eab6..7de780c4ec8d 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -55,6 +55,9 @@ enum ath10k_dbg_aggr_mode { ATH10K_DBG_AGGR_MODE_MAX, }; +/* FIXME: How to calculate the buffer size sanely? */ +#define ATH10K_FW_STATS_BUF_SIZE (1024*1024) + extern unsigned int ath10k_debug_mask; __printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...); @@ -70,6 +73,8 @@ void ath10k_debug_destroy(struct ath10k *ar); int ath10k_debug_register(struct ath10k *ar); void ath10k_debug_unregister(struct ath10k *ar); void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb); +void ath10k_debug_tpc_stats_process(struct ath10k *ar, + struct ath10k_tpc_stats *tpc_stats); struct ath10k_fw_crash_data * ath10k_debug_get_new_fw_crash_data(struct ath10k *ar); @@ -117,6 +122,12 @@ static inline void ath10k_debug_fw_stats_process(struct ath10k *ar, { } +static inline void ath10k_debug_tpc_stats_process(struct ath10k *ar, + struct ath10k_tpc_stats *tpc_stats) +{ + kfree(tpc_stats); +} + static inline void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len) { diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h index 0c92e0251e84..89e7076c919f 100644 --- a/drivers/net/wireless/ath/ath10k/hif.h +++ b/drivers/net/wireless/ath/ath10k/hif.h @@ -30,13 +30,6 @@ struct ath10k_hif_sg_item { u16 len; }; -struct ath10k_hif_cb { - int (*tx_completion)(struct ath10k *ar, - struct sk_buff *wbuf); - int (*rx_completion)(struct ath10k *ar, - struct sk_buff *wbuf); -}; - struct ath10k_hif_ops { /* send a scatter-gather list to the target */ int (*tx_sg)(struct ath10k *ar, u8 pipe_id, @@ -65,8 +58,7 @@ struct ath10k_hif_ops { void (*stop)(struct ath10k *ar); int (*map_service_to_pipe)(struct ath10k *ar, u16 service_id, - u8 *ul_pipe, u8 *dl_pipe, - int *ul_is_polled, int *dl_is_polled); + u8 *ul_pipe, u8 *dl_pipe); void (*get_default_pipe)(struct ath10k *ar, u8 *ul_pipe, u8 *dl_pipe); @@ -80,9 +72,6 @@ struct ath10k_hif_ops { */ void (*send_complete_check)(struct ath10k *ar, u8 pipe_id, int force); - void (*set_callbacks)(struct ath10k *ar, - struct ath10k_hif_cb *callbacks); - u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id); u32 (*read32)(struct ath10k *ar, u32 address); @@ -142,13 +131,10 @@ static inline void ath10k_hif_stop(struct ath10k *ar) static inline int ath10k_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, - u8 *ul_pipe, u8 *dl_pipe, - int *ul_is_polled, - int *dl_is_polled) + u8 *ul_pipe, u8 *dl_pipe) { return ar->hif.ops->map_service_to_pipe(ar, service_id, - ul_pipe, dl_pipe, - ul_is_polled, dl_is_polled); + ul_pipe, dl_pipe); } static inline void ath10k_hif_get_default_pipe(struct ath10k *ar, @@ -163,12 +149,6 @@ static inline void ath10k_hif_send_complete_check(struct ath10k *ar, ar->hif.ops->send_complete_check(ar, pipe_id, force); } -static inline void ath10k_hif_set_callbacks(struct ath10k *ar, - struct ath10k_hif_cb *callbacks) -{ - ar->hif.ops->set_callbacks(ar, callbacks); -} - static inline u16 ath10k_hif_get_free_queue_number(struct ath10k *ar, u8 pipe_id) { diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index 32d9ff1b19dc..5b3c6bcf9598 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -23,16 +23,6 @@ /* Send */ /********/ -static inline void ath10k_htc_send_complete_check(struct ath10k_htc_ep *ep, - int force) -{ - /* - * Check whether HIF has any prior sends that have finished, - * have not had the post-processing done. - */ - ath10k_hif_send_complete_check(ep->htc->ar, ep->ul_pipe_id, force); -} - static void ath10k_htc_control_tx_complete(struct ath10k *ar, struct sk_buff *skb) { @@ -181,24 +171,22 @@ err_pull: return ret; } -static int ath10k_htc_tx_completion_handler(struct ath10k *ar, - struct sk_buff *skb) +void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb) { struct ath10k_htc *htc = &ar->htc; struct ath10k_skb_cb *skb_cb; struct ath10k_htc_ep *ep; if (WARN_ON_ONCE(!skb)) - return 0; + return; skb_cb = ATH10K_SKB_CB(skb); ep = &htc->endpoint[skb_cb->eid]; ath10k_htc_notify_tx_completion(ep, skb); /* the skb now belongs to the completion handler */ - - return 0; } +EXPORT_SYMBOL(ath10k_htc_tx_completion_handler); /***********/ /* Receive */ @@ -304,8 +292,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc, return status; } -static int ath10k_htc_rx_completion_handler(struct ath10k *ar, - struct sk_buff *skb) +void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb) { int status = 0; struct ath10k_htc *htc = &ar->htc; @@ -326,21 +313,11 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar, ath10k_warn(ar, "HTC Rx: invalid eid %d\n", eid); ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad header", "", hdr, sizeof(*hdr)); - status = -EINVAL; goto out; } ep = &htc->endpoint[eid]; - /* - * If this endpoint that received a message from the target has - * a to-target HIF pipe whose send completions are polled rather - * than interrupt-driven, this is a good point to ask HIF to check - * whether it has any completed sends to handle. - */ - if (ep->ul_is_polled) - ath10k_htc_send_complete_check(ep, 1); - payload_len = __le16_to_cpu(hdr->len); if (payload_len + sizeof(*hdr) > ATH10K_HTC_MAX_LEN) { @@ -348,7 +325,6 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar, payload_len + sizeof(*hdr)); ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len", "", hdr, sizeof(*hdr)); - status = -EINVAL; goto out; } @@ -358,7 +334,6 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar, skb->len, payload_len); ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len", "", hdr, sizeof(*hdr)); - status = -EINVAL; goto out; } @@ -374,7 +349,6 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar, (trailer_len > payload_len)) { ath10k_warn(ar, "Invalid trailer length: %d\n", trailer_len); - status = -EPROTO; goto out; } @@ -407,7 +381,6 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar, * sending unsolicited messages on the ep 0 */ ath10k_warn(ar, "HTC rx ctrl still processing\n"); - status = -EINVAL; complete(&htc->ctl_resp); goto out; } @@ -439,9 +412,8 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar, skb = NULL; out: kfree_skb(skb); - - return status; } +EXPORT_SYMBOL(ath10k_htc_rx_completion_handler); static void ath10k_htc_control_rx_complete(struct ath10k *ar, struct sk_buff *skb) @@ -767,9 +739,7 @@ setup: status = ath10k_hif_map_service_to_pipe(htc->ar, ep->service_id, &ep->ul_pipe_id, - &ep->dl_pipe_id, - &ep->ul_is_polled, - &ep->dl_is_polled); + &ep->dl_pipe_id); if (status) return status; @@ -778,10 +748,6 @@ setup: htc_service_name(ep->service_id), ep->ul_pipe_id, ep->dl_pipe_id, ep->eid); - ath10k_dbg(ar, ATH10K_DBG_BOOT, - "boot htc ep %d ul polled %d dl polled %d\n", - ep->eid, ep->ul_is_polled, ep->dl_is_polled); - if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) { ep->tx_credit_flow_enabled = false; ath10k_dbg(ar, ATH10K_DBG_BOOT, @@ -841,7 +807,6 @@ 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_hif_cb htc_callbacks; struct ath10k_htc_ep *ep = NULL; struct ath10k_htc *htc = &ar->htc; @@ -849,15 +814,11 @@ int ath10k_htc_init(struct ath10k *ar) ath10k_htc_reset_endpoint_states(htc); - /* setup HIF layer callbacks */ - htc_callbacks.rx_completion = ath10k_htc_rx_completion_handler; - htc_callbacks.tx_completion = ath10k_htc_tx_completion_handler; htc->ar = ar; /* Get HIF default pipe for HTC message exchange */ ep = &htc->endpoint[ATH10K_HTC_EP_0]; - ath10k_hif_set_callbacks(ar, &htc_callbacks); ath10k_hif_get_default_pipe(ar, &ep->ul_pipe_id, &ep->dl_pipe_id); init_completion(&htc->ctl_resp); diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h index 527179c0edce..e70aa38e6e05 100644 --- a/drivers/net/wireless/ath/ath10k/htc.h +++ b/drivers/net/wireless/ath/ath10k/htc.h @@ -312,8 +312,6 @@ struct ath10k_htc_ep { int max_ep_message_len; u8 ul_pipe_id; u8 dl_pipe_id; - int ul_is_polled; /* call HIF to get tx completions */ - int dl_is_polled; /* call HIF to fetch rx (not implemented) */ u8 seq_no; /* for debugging */ int tx_credits; @@ -355,5 +353,7 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc, int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid, struct sk_buff *packet); 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); #endif diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 573187512895..2bad50e520b5 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1485,9 +1485,9 @@ struct ath10k_htt { spinlock_t tx_lock; int max_num_pending_tx; int num_pending_tx; + int num_pending_mgmt_tx; struct idr pending_tx; wait_queue_head_t empty_tx_wq; - struct dma_pool *tx_pool; /* set if host-fw communication goes haywire * used to avoid further failures */ @@ -1508,6 +1508,11 @@ struct ath10k_htt { dma_addr_t paddr; struct htt_msdu_ext_desc *vaddr; } frag_desc; + + struct { + dma_addr_t paddr; + struct ath10k_htt_txbuf *vaddr; + } txbuf; }; #define RX_HTT_HDR_STATUS_LEN 64 @@ -1586,8 +1591,9 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt); int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, u8 max_subfrms_ampdu, u8 max_subfrms_amsdu); +void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb); -void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt); +void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc); int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb); void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id); int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *); diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 1b7a04366256..6060dda4e910 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -643,6 +643,8 @@ struct amsdu_subframe_hdr { __be16 len; } __packed; +#define GROUP_ID_IS_SU_MIMO(x) ((x) == 0 || (x) == 63) + static void ath10k_htt_rx_h_rates(struct ath10k *ar, struct ieee80211_rx_status *status, struct htt_rx_desc *rxd) @@ -650,6 +652,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, struct ieee80211_supported_band *sband; u8 cck, rate, bw, sgi, mcs, nss; u8 preamble = 0; + u8 group_id; u32 info1, info2, info3; info1 = __le32_to_cpu(rxd->ppdu_start.info1); @@ -692,10 +695,50 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, case HTT_RX_VHT_WITH_TXBF: /* VHT-SIG-A1 in info2, VHT-SIG-A2 in info3 TODO check this */ - mcs = (info3 >> 4) & 0x0F; - nss = ((info2 >> 10) & 0x07) + 1; bw = info2 & 3; sgi = info3 & 1; + group_id = (info2 >> 4) & 0x3F; + + if (GROUP_ID_IS_SU_MIMO(group_id)) { + mcs = (info3 >> 4) & 0x0F; + nss = ((info2 >> 10) & 0x07) + 1; + } else { + /* Hardware doesn't decode VHT-SIG-B into Rx descriptor + * so it's impossible to decode MCS. Also since + * firmware consumes Group Id Management frames host + * has no knowledge regarding group/user position + * mapping so it's impossible to pick the correct Nsts + * from VHT-SIG-A1. + * + * Bandwidth and SGI are valid so report the rateinfo + * on best-effort basis. + */ + mcs = 0; + nss = 1; + } + + if (mcs > 0x09) { + ath10k_warn(ar, "invalid MCS received %u\n", mcs); + ath10k_warn(ar, "rxd %08x mpdu start %08x %08x msdu start %08x %08x ppdu start %08x %08x %08x %08x %08x\n", + __le32_to_cpu(rxd->attention.flags), + __le32_to_cpu(rxd->mpdu_start.info0), + __le32_to_cpu(rxd->mpdu_start.info1), + __le32_to_cpu(rxd->msdu_start.common.info0), + __le32_to_cpu(rxd->msdu_start.common.info1), + rxd->ppdu_start.info0, + __le32_to_cpu(rxd->ppdu_start.info1), + __le32_to_cpu(rxd->ppdu_start.info2), + __le32_to_cpu(rxd->ppdu_start.info3), + __le32_to_cpu(rxd->ppdu_start.info4)); + + ath10k_warn(ar, "msdu end %08x mpdu end %08x\n", + __le32_to_cpu(rxd->msdu_end.common.info0), + __le32_to_cpu(rxd->mpdu_end.info0)); + + ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, + "rx desc msdu payload: ", + rxd->msdu_payload, 50); + } status->rate_idx = mcs; status->vht_nss = nss; @@ -2082,6 +2125,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) /* Free the indication buffer */ dev_kfree_skb_any(skb); } +EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler); static void ath10k_htt_txrx_compl_task(unsigned long ptr) { diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 43aa5e2d1b87..16823970dbfd 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -22,22 +22,28 @@ #include "txrx.h" #include "debug.h" -void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) +void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc) { + if (limit_mgmt_desc) + htt->num_pending_mgmt_tx--; + htt->num_pending_tx--; if (htt->num_pending_tx == htt->max_num_pending_tx - 1) ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); } -static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) +static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, + bool limit_mgmt_desc) { spin_lock_bh(&htt->tx_lock); - __ath10k_htt_tx_dec_pending(htt); + __ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); spin_unlock_bh(&htt->tx_lock); } -static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt) +static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt, + bool limit_mgmt_desc, bool is_probe_resp) { + struct ath10k *ar = htt->ar; int ret = 0; spin_lock_bh(&htt->tx_lock); @@ -47,6 +53,15 @@ static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt) goto exit; } + if (limit_mgmt_desc) { + if (is_probe_resp && (htt->num_pending_mgmt_tx > + ar->hw_params.max_probe_resp_desc_thres)) { + ret = -EBUSY; + goto exit; + } + htt->num_pending_mgmt_tx++; + } + htt->num_pending_tx++; if (htt->num_pending_tx == htt->max_num_pending_tx) ath10k_mac_tx_lock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); @@ -93,9 +108,12 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) spin_lock_init(&htt->tx_lock); idr_init(&htt->pending_tx); - htt->tx_pool = dma_pool_create("ath10k htt tx pool", htt->ar->dev, - sizeof(struct ath10k_htt_txbuf), 4, 0); - if (!htt->tx_pool) { + size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf); + htt->txbuf.vaddr = dma_alloc_coherent(ar->dev, size, + &htt->txbuf.paddr, + GFP_DMA); + if (!htt->txbuf.vaddr) { + ath10k_err(ar, "failed to alloc tx buffer\n"); ret = -ENOMEM; goto free_idr_pending_tx; } @@ -110,14 +128,17 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) if (!htt->frag_desc.vaddr) { ath10k_warn(ar, "failed to alloc fragment desc memory\n"); ret = -ENOMEM; - goto free_tx_pool; + goto free_txbuf; } skip_frag_desc_alloc: return 0; -free_tx_pool: - dma_pool_destroy(htt->tx_pool); +free_txbuf: + size = htt->max_num_pending_tx * + sizeof(struct ath10k_htt_txbuf); + dma_free_coherent(htt->ar->dev, size, htt->txbuf.vaddr, + htt->txbuf.paddr); free_idr_pending_tx: idr_destroy(&htt->pending_tx); return ret; @@ -145,7 +166,13 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt) idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar); idr_destroy(&htt->pending_tx); - dma_pool_destroy(htt->tx_pool); + + if (htt->txbuf.vaddr) { + size = htt->max_num_pending_tx * + sizeof(struct ath10k_htt_txbuf); + dma_free_coherent(htt->ar->dev, size, htt->txbuf.vaddr, + htt->txbuf.paddr); + } if (htt->frag_desc.vaddr) { size = htt->max_num_pending_tx * @@ -160,6 +187,12 @@ void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) dev_kfree_skb_any(skb); } +void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb) +{ + dev_kfree_skb_any(skb); +} +EXPORT_SYMBOL(ath10k_htt_hif_tx_complete); + int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt) { struct ath10k *ar = htt->ar; @@ -417,8 +450,19 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) int len = 0; int msdu_id = -1; int res; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; + bool limit_mgmt_desc = false; + bool is_probe_resp = false; + + if (ar->hw_params.max_probe_resp_desc_thres) { + limit_mgmt_desc = true; + + if (ieee80211_is_probe_resp(hdr->frame_control)) + is_probe_resp = true; + } + + res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp); - res = ath10k_htt_tx_inc_pending(htt); if (res) goto err; @@ -428,9 +472,9 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) spin_lock_bh(&htt->tx_lock); res = ath10k_htt_tx_alloc_msdu_id(htt, msdu); spin_unlock_bh(&htt->tx_lock); - if (res < 0) { + if (res < 0) goto err_tx_dec; - } + msdu_id = res; txdesc = ath10k_htc_alloc_skb(ar, len); @@ -476,7 +520,7 @@ err_free_msdu_id: ath10k_htt_tx_free_msdu_id(htt, msdu_id); spin_unlock_bh(&htt->tx_lock); err_tx_dec: - ath10k_htt_tx_dec_pending(htt); + ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); err: return res; } @@ -495,32 +539,37 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) int res; u8 flags0 = 0; u16 msdu_id, flags1 = 0; - dma_addr_t paddr = 0; u32 frags_paddr = 0; struct htt_msdu_ext_desc *ext_desc = NULL; + bool limit_mgmt_desc = false; + bool is_probe_resp = false; + + if (unlikely(ieee80211_is_mgmt(hdr->frame_control)) && + ar->hw_params.max_probe_resp_desc_thres) { + limit_mgmt_desc = true; + + if (ieee80211_is_probe_resp(hdr->frame_control)) + is_probe_resp = true; + } - res = ath10k_htt_tx_inc_pending(htt); + res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp); if (res) goto err; spin_lock_bh(&htt->tx_lock); res = ath10k_htt_tx_alloc_msdu_id(htt, msdu); spin_unlock_bh(&htt->tx_lock); - if (res < 0) { + if (res < 0) goto err_tx_dec; - } + msdu_id = res; prefetch_len = min(htt->prefetch_len, msdu->len); prefetch_len = roundup(prefetch_len, 4); - skb_cb->htt.txbuf = dma_pool_alloc(htt->tx_pool, GFP_ATOMIC, - &paddr); - if (!skb_cb->htt.txbuf) { - res = -ENOMEM; - goto err_free_msdu_id; - } - skb_cb->htt.txbuf_paddr = paddr; + skb_cb->htt.txbuf = &htt->txbuf.vaddr[msdu_id]; + skb_cb->htt.txbuf_paddr = htt->txbuf.paddr + + (sizeof(struct ath10k_htt_txbuf) * msdu_id); if ((ieee80211_is_action(hdr->frame_control) || ieee80211_is_deauth(hdr->frame_control) || @@ -528,7 +577,8 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ieee80211_has_protected(hdr->frame_control)) { skb_put(msdu, IEEE80211_CCMP_MIC_LEN); } else if (!skb_cb->htt.nohwcrypt && - skb_cb->txmode == ATH10K_HW_TXRX_RAW) { + skb_cb->txmode == ATH10K_HW_TXRX_RAW && + ieee80211_has_protected(hdr->frame_control)) { skb_put(msdu, IEEE80211_CCMP_MIC_LEN); } @@ -537,7 +587,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) res = dma_mapping_error(dev, skb_cb->paddr); if (res) { res = -EIO; - goto err_free_txbuf; + goto err_free_msdu_id; } switch (skb_cb->txmode) { @@ -669,16 +719,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) err_unmap_msdu: dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); -err_free_txbuf: - dma_pool_free(htt->tx_pool, - skb_cb->htt.txbuf, - skb_cb->htt.txbuf_paddr); err_free_msdu_id: spin_lock_bh(&htt->tx_lock); ath10k_htt_tx_free_msdu_id(htt, msdu_id); spin_unlock_bh(&htt->tx_lock); err_tx_dec: - ath10k_htt_tx_dec_pending(htt); + ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); err: return res; } diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 678d72af4a9d..39966a05c1cc 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -84,6 +84,15 @@ enum qca6174_chip_id_rev { #define QCA99X0_HW_2_0_BOARD_DATA_FILE "board.bin" #define QCA99X0_HW_2_0_PATCH_LOAD_ADDR 0x1234 +/* QCA9377 1.0 definitions */ +#define QCA9377_HW_1_0_DEV_VERSION 0x05020001 +#define QCA9377_HW_1_0_CHIP_ID_REV 0x1 +#define QCA9377_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9377/hw1.0" +#define QCA9377_HW_1_0_FW_FILE "firmware.bin" +#define QCA9377_HW_1_0_OTP_FILE "otp.bin" +#define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin" +#define QCA9377_HW_1_0_PATCH_LOAD_ADDR 0x1234 + #define ATH10K_FW_API2_FILE "firmware-2.bin" #define ATH10K_FW_API3_FILE "firmware-3.bin" @@ -94,9 +103,13 @@ enum qca6174_chip_id_rev { #define ATH10K_FW_API5_FILE "firmware-5.bin" #define ATH10K_FW_UTF_FILE "utf.bin" +#define ATH10K_FW_UTF_API2_FILE "utf-2.bin" /* includes also the null byte */ #define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K" +#define ATH10K_BOARD_MAGIC "QCA-ATH10K-BOARD" + +#define ATH10K_BOARD_API2_FILE "board-2.bin" #define REG_DUMP_COUNT_QCA988X 60 @@ -159,10 +172,21 @@ enum ath10k_fw_htt_op_version { ATH10K_FW_HTT_OP_VERSION_MAX, }; +enum ath10k_bd_ie_type { + /* contains sub IEs of enum ath10k_bd_ie_board_type */ + ATH10K_BD_IE_BOARD = 0, +}; + +enum ath10k_bd_ie_board_type { + ATH10K_BD_IE_BOARD_NAME = 0, + ATH10K_BD_IE_BOARD_DATA = 1, +}; + enum ath10k_hw_rev { ATH10K_HW_QCA988X, ATH10K_HW_QCA6174, ATH10K_HW_QCA99X0, + ATH10K_HW_QCA9377, }; struct ath10k_hw_regs { @@ -215,6 +239,7 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, #define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X) #define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174) #define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0) +#define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377) /* Known pecularities: * - raw appears in nwifi decap, raw and nwifi appear in ethernet decap @@ -414,16 +439,6 @@ enum ath10k_hw_rate_cck { #define CE_COUNT ar->hw_values->ce_count /* - * Total number of PCIe MSI interrupts requested for all interrupt sources. - * PCIe standard forces this to be a power of 2. - * Some Host OS's limit MSI requests that can be granted to 8 - * so for now we abide by this limit and avoid requesting more - * than that. - */ -#define MSI_NUM_REQUEST_LOG2 3 -#define MSI_NUM_REQUEST (1<<MSI_NUM_REQUEST_LOG2) - -/* * Granted MSIs are assigned as follows: * Firmware uses the first * Remaining MSIs, if any, are used by Copy Engines diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 64674c955d44..a7411fe90cc4 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -197,9 +197,8 @@ static int ath10k_send_key(struct ath10k_vif *arvif, return -EOPNOTSUPP; } - if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { + if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - } if (cmd == DISABLE_KEY) { arg.key_cipher = WMI_CIPHER_NONE; @@ -1070,6 +1069,7 @@ static bool ath10k_mac_monitor_vdev_is_needed(struct ath10k *ar) return false; return ar->monitor || + ar->filter_flags & FIF_OTHER_BSS || test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); } @@ -1110,7 +1110,8 @@ static int ath10k_monitor_recalc(struct ath10k *ar) ret = ath10k_monitor_stop(ar); if (ret) - ath10k_warn(ar, "failed to stop disallowed monitor: %d\n", ret); + ath10k_warn(ar, "failed to stop disallowed monitor: %d\n", + ret); /* not serious */ } @@ -2083,7 +2084,8 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar, enum ieee80211_band band; const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; - int i, n, max_nss; + int i, n; + u8 max_nss; u32 stbc; lockdep_assert_held(&ar->conf_mutex); @@ -2168,7 +2170,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar, arg->peer_ht_rates.rates[i] = i; } else { arg->peer_ht_rates.num_rates = n; - arg->peer_num_spatial_streams = max_nss; + arg->peer_num_spatial_streams = min(sta->rx_nss, max_nss); } ath10k_dbg(ar, ATH10K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n", @@ -3617,9 +3619,6 @@ static int ath10k_start_scan(struct ath10k *ar, } spin_unlock_bh(&ar->data_lock); - /* Add a 200ms margin to account for event/command processing */ - ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout, - msecs_to_jiffies(arg->max_scan_time+200)); return 0; } @@ -3737,13 +3736,8 @@ static int ath10k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) mutex_lock(&ar->conf_mutex); - if (ar->cfg_tx_chainmask) { - *tx_ant = ar->cfg_tx_chainmask; - *rx_ant = ar->cfg_rx_chainmask; - } else { - *tx_ant = ar->supp_tx_chainmask; - *rx_ant = ar->supp_rx_chainmask; - } + *tx_ant = ar->cfg_tx_chainmask; + *rx_ant = ar->cfg_rx_chainmask; mutex_unlock(&ar->conf_mutex); @@ -3763,6 +3757,169 @@ static void ath10k_check_chain_mask(struct ath10k *ar, u32 cm, const char *dbg) dbg, cm); } +static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar) +{ + int nsts = ar->vht_cap_info; + + nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; + nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; + + /* If firmware does not deliver to host number of space-time + * streams supported, assume it support up to 4 BF STS and return + * the value for VHT CAP: nsts-1) + */ + if (nsts == 0) + return 3; + + return nsts; +} + +static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar) +{ + int sound_dim = ar->vht_cap_info; + + sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; + sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; + + /* If the sounding dimension is not advertised by the firmware, + * let's use a default value of 1 + */ + if (sound_dim == 0) + return 1; + + return sound_dim; +} + +static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) +{ + struct ieee80211_sta_vht_cap vht_cap = {0}; + u16 mcs_map; + u32 val; + int i; + + vht_cap.vht_supported = 1; + vht_cap.cap = ar->vht_cap_info; + + if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | + IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) { + val = ath10k_mac_get_vht_cap_bf_sts(ar); + val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; + val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; + + vht_cap.cap |= val; + } + + if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | + IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) { + val = ath10k_mac_get_vht_cap_bf_sound_dim(ar); + val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; + val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; + + vht_cap.cap |= val; + } + + mcs_map = 0; + for (i = 0; i < 8; i++) { + if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i))) + mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2); + else + mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2); + } + + vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); + vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); + + return vht_cap; +} + +static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar) +{ + int i; + struct ieee80211_sta_ht_cap ht_cap = {0}; + + if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED)) + return ht_cap; + + ht_cap.ht_supported = 1; + ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; + ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; + ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40; + ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT; + + if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI) + ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; + + if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI) + ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + + if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) { + u32 smps; + + smps = WLAN_HT_CAP_SM_PS_DYNAMIC; + smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT; + + ht_cap.cap |= smps; + } + + if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC) + ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; + + if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) { + u32 stbc; + + stbc = ar->ht_cap_info; + stbc &= WMI_HT_CAP_RX_STBC; + stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT; + stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT; + stbc &= IEEE80211_HT_CAP_RX_STBC; + + ht_cap.cap |= stbc; + } + + if (ar->ht_cap_info & WMI_HT_CAP_LDPC) + ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; + + if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT) + ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT; + + /* max AMSDU is implicitly taken from vht_cap_info */ + if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK) + ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; + + for (i = 0; i < ar->num_rf_chains; i++) { + if (ar->cfg_rx_chainmask & BIT(i)) + ht_cap.mcs.rx_mask[i] = 0xFF; + } + + ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; + + return ht_cap; +} + +static void ath10k_mac_setup_ht_vht_cap(struct ath10k *ar) +{ + struct ieee80211_supported_band *band; + struct ieee80211_sta_vht_cap vht_cap; + struct ieee80211_sta_ht_cap ht_cap; + + ht_cap = ath10k_get_ht_cap(ar); + vht_cap = ath10k_create_vht_cap(ar); + + if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) { + band = &ar->mac.sbands[IEEE80211_BAND_2GHZ]; + band->ht_cap = ht_cap; + + /* Enable the VHT support at 2.4 GHz */ + band->vht_cap = vht_cap; + } + if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) { + band = &ar->mac.sbands[IEEE80211_BAND_5GHZ]; + band->ht_cap = ht_cap; + band->vht_cap = vht_cap; + } +} + static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant) { int ret; @@ -3795,6 +3952,9 @@ static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant) return ret; } + /* Reload HT/VHT capability */ + ath10k_mac_setup_ht_vht_cap(ar); + return 0; } @@ -3885,9 +4045,7 @@ static int ath10k_start(struct ieee80211_hw *hw) } } - if (ar->cfg_tx_chainmask) - __ath10k_set_antenna(ar, ar->cfg_tx_chainmask, - ar->cfg_rx_chainmask); + __ath10k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask); /* * By default FW set ARP frames ac to voice (6). In that case ARP @@ -3906,6 +4064,18 @@ static int ath10k_start(struct ieee80211_hw *hw) goto err_core_stop; } + if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA, + ar->fw_features)) { + ret = ath10k_wmi_pdev_enable_adaptive_cca(ar, 1, + WMI_CCA_DETECT_LEVEL_AUTO, + WMI_CCA_DETECT_MARGIN_AUTO); + if (ret) { + ath10k_warn(ar, "failed to enable adaptive cca: %d\n", + ret); + goto err_core_stop; + } + } + ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->ani_enable, 1); if (ret) { @@ -4068,17 +4238,21 @@ static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif) { u32 value = 0; struct ath10k *ar = arvif->ar; + int nsts; + int sound_dim; if (ath10k_wmi_get_txbf_conf_scheme(ar) != WMI_TXBF_CONF_BEFORE_ASSOC) return 0; + nsts = ath10k_mac_get_vht_cap_bf_sts(ar); if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) - value |= SM((ar->num_rf_chains - 1), WMI_TXBF_STS_CAP_OFFSET); + value |= SM(nsts, WMI_TXBF_STS_CAP_OFFSET); + sound_dim = ath10k_mac_get_vht_cap_bf_sound_dim(ar); if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) - value |= SM((ar->num_rf_chains - 1), WMI_BF_SOUND_DIM_OFFSET); + value |= SM(sound_dim, WMI_BF_SOUND_DIM_OFFSET); if (!value) return 0; @@ -4175,6 +4349,14 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, case NL80211_IFTYPE_ADHOC: arvif->vdev_type = WMI_VDEV_TYPE_IBSS; break; + case NL80211_IFTYPE_MESH_POINT: + if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { + ret = -EINVAL; + ath10k_warn(ar, "must load driver with rawmode=1 to add mesh interfaces\n"); + goto err; + } + arvif->vdev_type = WMI_VDEV_TYPE_AP; + break; case NL80211_IFTYPE_AP: arvif->vdev_type = WMI_VDEV_TYPE_AP; @@ -4215,6 +4397,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, * become corrupted, e.g. have garbled IEs or out-of-date TIM bitmap. */ if (vif->type == NL80211_IFTYPE_ADHOC || + vif->type == NL80211_IFTYPE_MESH_POINT || vif->type == NL80211_IFTYPE_AP) { arvif->beacon_buf = dma_zalloc_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, @@ -4554,6 +4737,13 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, if (ret) ath10k_warn(ar, "failed to update beacon template: %d\n", ret); + + if (ieee80211_vif_is_mesh(vif)) { + /* mesh doesn't use SSID but firmware needs it */ + strncpy(arvif->u.ap.ssid, "mesh", + sizeof(arvif->u.ap.ssid)); + arvif->u.ap.ssid_len = 4; + } } if (changed & BSS_CHANGED_AP_PROBE_RESP) { @@ -4607,7 +4797,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, info->use_cts_prot ? 1 : 0); if (ret) ath10k_warn(ar, "failed to set protection mode %d on vdev %i: %d\n", - info->use_cts_prot, arvif->vdev_id, ret); + info->use_cts_prot, arvif->vdev_id, ret); } if (changed & BSS_CHANGED_ERP_SLOT) { @@ -4751,6 +4941,11 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw, spin_unlock_bh(&ar->data_lock); } + /* Add a 200ms margin to account for event/command processing */ + ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout, + msecs_to_jiffies(arg.max_scan_time + + 200)); + exit: mutex_unlock(&ar->conf_mutex); return ret; @@ -5293,6 +5488,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, } else if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC && (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT || vif->type == NL80211_IFTYPE_ADHOC)) { /* * New association. @@ -5328,6 +5524,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, } else if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTH && (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT || vif->type == NL80211_IFTYPE_ADHOC)) { /* * Disassociation. @@ -5901,7 +6098,7 @@ ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar, } static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif, - u8 rate, u8 nss, u8 sgi) + u8 rate, u8 nss, u8 sgi, u8 ldpc) { struct ath10k *ar = arvif->ar; u32 vdev_param; @@ -5934,6 +6131,13 @@ static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif, return ret; } + vdev_param = ar->wmi.vdev_param->ldpc; + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, ldpc); + if (ret) { + ath10k_warn(ar, "failed to set ldpc param %d: %d\n", ldpc, ret); + return ret; + } + return 0; } @@ -5997,6 +6201,7 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, u8 rate; u8 nss; u8 sgi; + u8 ldpc; int single_nss; int ret; @@ -6006,6 +6211,7 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, band = def.chan->band; ht_mcs_mask = mask->control[band].ht_mcs; vht_mcs_mask = mask->control[band].vht_mcs; + ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC); sgi = mask->control[band].gi; if (sgi == NL80211_TXRATE_FORCE_LGI) @@ -6044,7 +6250,7 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); - ret = ath10k_mac_set_fixed_rate_params(arvif, rate, nss, sgi); + ret = ath10k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc); if (ret) { ath10k_warn(ar, "failed to set fixed rate params on vdev %i: %d\n", arvif->vdev_id, ret); @@ -6144,7 +6350,7 @@ static int ath10k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct ath10k *ar = hw->priv; struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); @@ -6203,8 +6409,8 @@ ath10k_mac_update_rx_channel(struct ath10k *ar, rcu_read_lock(); if (!ctx && ath10k_mac_num_chanctxs(ar) == 1) { ieee80211_iter_chan_contexts_atomic(ar->hw, - ath10k_mac_get_any_chandef_iter, - &def); + ath10k_mac_get_any_chandef_iter, + &def); if (vifs) def = &vifs[0].new_ctx->def; @@ -6218,6 +6424,94 @@ ath10k_mac_update_rx_channel(struct ath10k *ar, rcu_read_unlock(); } +static void +ath10k_mac_update_vif_chan(struct ath10k *ar, + struct ieee80211_vif_chanctx_switch *vifs, + int n_vifs) +{ + struct ath10k_vif *arvif; + int ret; + int i; + + lockdep_assert_held(&ar->conf_mutex); + + /* First stop monitor interface. Some FW versions crash if there's a + * lone monitor interface. + */ + if (ar->monitor_started) + ath10k_monitor_stop(ar); + + for (i = 0; i < n_vifs; i++) { + arvif = ath10k_vif_to_arvif(vifs[i].vif); + + ath10k_dbg(ar, ATH10K_DBG_MAC, + "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n", + arvif->vdev_id, + vifs[i].old_ctx->def.chan->center_freq, + vifs[i].new_ctx->def.chan->center_freq, + vifs[i].old_ctx->def.width, + vifs[i].new_ctx->def.width); + + if (WARN_ON(!arvif->is_started)) + continue; + + if (WARN_ON(!arvif->is_up)) + continue; + + ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); + if (ret) { + ath10k_warn(ar, "failed to down vdev %d: %d\n", + arvif->vdev_id, ret); + continue; + } + } + + /* All relevant vdevs are downed and associated channel resources + * should be available for the channel switch now. + */ + + spin_lock_bh(&ar->data_lock); + ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs); + spin_unlock_bh(&ar->data_lock); + + for (i = 0; i < n_vifs; i++) { + arvif = ath10k_vif_to_arvif(vifs[i].vif); + + if (WARN_ON(!arvif->is_started)) + continue; + + if (WARN_ON(!arvif->is_up)) + continue; + + ret = ath10k_mac_setup_bcn_tmpl(arvif); + if (ret) + ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n", + ret); + + ret = ath10k_mac_setup_prb_tmpl(arvif); + if (ret) + ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n", + ret); + + ret = ath10k_vdev_restart(arvif, &vifs[i].new_ctx->def); + if (ret) { + ath10k_warn(ar, "failed to restart vdev %d: %d\n", + arvif->vdev_id, ret); + continue; + } + + ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, + arvif->bssid); + if (ret) { + ath10k_warn(ar, "failed to bring vdev up %d: %d\n", + arvif->vdev_id, ret); + continue; + } + } + + ath10k_monitor_recalc(ar); +} + static int ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) @@ -6264,12 +6558,52 @@ ath10k_mac_op_remove_chanctx(struct ieee80211_hw *hw, mutex_unlock(&ar->conf_mutex); } +struct ath10k_mac_change_chanctx_arg { + struct ieee80211_chanctx_conf *ctx; + struct ieee80211_vif_chanctx_switch *vifs; + int n_vifs; + int next_vif; +}; + +static void +ath10k_mac_change_chanctx_cnt_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct ath10k_mac_change_chanctx_arg *arg = data; + + if (rcu_access_pointer(vif->chanctx_conf) != arg->ctx) + return; + + arg->n_vifs++; +} + +static void +ath10k_mac_change_chanctx_fill_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct ath10k_mac_change_chanctx_arg *arg = data; + struct ieee80211_chanctx_conf *ctx; + + ctx = rcu_access_pointer(vif->chanctx_conf); + if (ctx != arg->ctx) + return; + + if (WARN_ON(arg->next_vif == arg->n_vifs)) + return; + + arg->vifs[arg->next_vif].vif = vif; + arg->vifs[arg->next_vif].old_ctx = ctx; + arg->vifs[arg->next_vif].new_ctx = ctx; + arg->next_vif++; +} + static void ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx, u32 changed) { struct ath10k *ar = hw->priv; + struct ath10k_mac_change_chanctx_arg arg = { .ctx = ctx }; mutex_lock(&ar->conf_mutex); @@ -6283,6 +6617,30 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw, if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL)) goto unlock; + if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) { + ieee80211_iterate_active_interfaces_atomic( + hw, + IEEE80211_IFACE_ITER_NORMAL, + ath10k_mac_change_chanctx_cnt_iter, + &arg); + if (arg.n_vifs == 0) + goto radar; + + arg.vifs = kcalloc(arg.n_vifs, sizeof(arg.vifs[0]), + GFP_KERNEL); + if (!arg.vifs) + goto radar; + + ieee80211_iterate_active_interfaces_atomic( + hw, + IEEE80211_IFACE_ITER_NORMAL, + ath10k_mac_change_chanctx_fill_iter, + &arg); + ath10k_mac_update_vif_chan(ar, arg.vifs, arg.n_vifs); + kfree(arg.vifs); + } + +radar: ath10k_recalc_radar_detection(ar); /* FIXME: How to configure Rx chains properly? */ @@ -6402,91 +6760,13 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, enum ieee80211_chanctx_switch_mode mode) { struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif; - int ret; - int i; mutex_lock(&ar->conf_mutex); ath10k_dbg(ar, ATH10K_DBG_MAC, "mac chanctx switch n_vifs %d mode %d\n", n_vifs, mode); - - /* First stop monitor interface. Some FW versions crash if there's a - * lone monitor interface. - */ - if (ar->monitor_started) - ath10k_monitor_stop(ar); - - for (i = 0; i < n_vifs; i++) { - arvif = ath10k_vif_to_arvif(vifs[i].vif); - - ath10k_dbg(ar, ATH10K_DBG_MAC, - "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n", - arvif->vdev_id, - vifs[i].old_ctx->def.chan->center_freq, - vifs[i].new_ctx->def.chan->center_freq, - vifs[i].old_ctx->def.width, - vifs[i].new_ctx->def.width); - - if (WARN_ON(!arvif->is_started)) - continue; - - if (WARN_ON(!arvif->is_up)) - continue; - - ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); - if (ret) { - ath10k_warn(ar, "failed to down vdev %d: %d\n", - arvif->vdev_id, ret); - continue; - } - } - - /* All relevant vdevs are downed and associated channel resources - * should be available for the channel switch now. - */ - - spin_lock_bh(&ar->data_lock); - ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs); - spin_unlock_bh(&ar->data_lock); - - for (i = 0; i < n_vifs; i++) { - arvif = ath10k_vif_to_arvif(vifs[i].vif); - - if (WARN_ON(!arvif->is_started)) - continue; - - if (WARN_ON(!arvif->is_up)) - continue; - - ret = ath10k_mac_setup_bcn_tmpl(arvif); - if (ret) - ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n", - ret); - - ret = ath10k_mac_setup_prb_tmpl(arvif); - if (ret) - ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n", - ret); - - ret = ath10k_vdev_restart(arvif, &vifs[i].new_ctx->def); - if (ret) { - ath10k_warn(ar, "failed to restart vdev %d: %d\n", - arvif->vdev_id, ret); - continue; - } - - ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, - arvif->bssid); - if (ret) { - ath10k_warn(ar, "failed to bring vdev up %d: %d\n", - arvif->vdev_id, ret); - continue; - } - } - - ath10k_monitor_recalc(ar); + ath10k_mac_update_vif_chan(ar, vifs, n_vifs); mutex_unlock(&ar->conf_mutex); return 0; @@ -6642,6 +6922,9 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = { { .max = 7, .types = BIT(NL80211_IFTYPE_AP) +#ifdef CONFIG_MAC80211_MESH + | BIT(NL80211_IFTYPE_MESH_POINT) +#endif }, }; @@ -6649,6 +6932,9 @@ static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = { { .max = 8, .types = BIT(NL80211_IFTYPE_AP) +#ifdef CONFIG_MAC80211_MESH + | BIT(NL80211_IFTYPE_MESH_POINT) +#endif }, }; @@ -6686,6 +6972,9 @@ static const struct ieee80211_iface_limit ath10k_tlv_if_limit[] = { { .max = 2, .types = BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO), }, @@ -6707,6 +6996,9 @@ static const struct ieee80211_iface_limit ath10k_tlv_qcs_if_limit[] = { { .max = 1, .types = BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif BIT(NL80211_IFTYPE_P2P_GO), }, { @@ -6773,6 +7065,9 @@ static const struct ieee80211_iface_limit ath10k_10_4_if_limits[] = { { .max = 16, .types = BIT(NL80211_IFTYPE_AP) +#ifdef CONFIG_MAC80211_MESH + | BIT(NL80211_IFTYPE_MESH_POINT) +#endif }, }; @@ -6792,111 +7087,6 @@ static const struct ieee80211_iface_combination ath10k_10_4_if_comb[] = { }, }; -static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) -{ - struct ieee80211_sta_vht_cap vht_cap = {0}; - u16 mcs_map; - u32 val; - int i; - - vht_cap.vht_supported = 1; - vht_cap.cap = ar->vht_cap_info; - - if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | - IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) { - val = ar->num_rf_chains - 1; - val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; - val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; - - vht_cap.cap |= val; - } - - if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | - IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) { - val = ar->num_rf_chains - 1; - val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; - val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; - - vht_cap.cap |= val; - } - - mcs_map = 0; - for (i = 0; i < 8; i++) { - if (i < ar->num_rf_chains) - mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2); - else - mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2); - } - - vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); - vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); - - return vht_cap; -} - -static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar) -{ - int i; - struct ieee80211_sta_ht_cap ht_cap = {0}; - - if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED)) - return ht_cap; - - ht_cap.ht_supported = 1; - ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; - ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; - ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; - ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40; - ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT; - - if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI) - ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; - - if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI) - ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; - - if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) { - u32 smps; - - smps = WLAN_HT_CAP_SM_PS_DYNAMIC; - smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT; - - ht_cap.cap |= smps; - } - - if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC) - ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; - - if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) { - u32 stbc; - - stbc = ar->ht_cap_info; - stbc &= WMI_HT_CAP_RX_STBC; - stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT; - stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT; - stbc &= IEEE80211_HT_CAP_RX_STBC; - - ht_cap.cap |= stbc; - } - - if (ar->ht_cap_info & WMI_HT_CAP_LDPC) - ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - - if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT) - ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT; - - /* max AMSDU is implicitly taken from vht_cap_info */ - if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK) - ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; - - for (i = 0; i < ar->num_rf_chains; i++) - ht_cap.mcs.rx_mask[i] = 0xFF; - - ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; - - return ht_cap; -} - static void ath10k_get_arvif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { @@ -6938,8 +7128,6 @@ int ath10k_mac_register(struct ath10k *ar) WLAN_CIPHER_SUITE_AES_CMAC, }; struct ieee80211_supported_band *band; - struct ieee80211_sta_vht_cap vht_cap; - struct ieee80211_sta_ht_cap ht_cap; void *channels; int ret; @@ -6947,9 +7135,6 @@ int ath10k_mac_register(struct ath10k *ar) SET_IEEE80211_DEV(ar->hw, ar->dev); - ht_cap = ath10k_get_ht_cap(ar); - vht_cap = ath10k_create_vht_cap(ar); - BUILD_BUG_ON((ARRAY_SIZE(ath10k_2ghz_channels) + ARRAY_SIZE(ath10k_5ghz_channels)) != ATH10K_NUM_CHANS); @@ -6968,10 +7153,6 @@ int ath10k_mac_register(struct ath10k *ar) band->channels = channels; band->n_bitrates = ath10k_g_rates_size; band->bitrates = ath10k_g_rates; - band->ht_cap = ht_cap; - - /* Enable the VHT support at 2.4 GHz */ - band->vht_cap = vht_cap; ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band; } @@ -6990,17 +7171,18 @@ int ath10k_mac_register(struct ath10k *ar) band->channels = channels; band->n_bitrates = ath10k_a_rates_size; band->bitrates = ath10k_a_rates; - band->ht_cap = ht_cap; - band->vht_cap = vht_cap; ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band; } + ath10k_mac_setup_ht_vht_cap(ar); + ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP); + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_MESH_POINT); - ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask; - ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask; + ar->hw->wiphy->available_antennas_rx = ar->cfg_rx_chainmask; + ar->hw->wiphy->available_antennas_tx = ar->cfg_tx_chainmask; if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features)) ar->hw->wiphy->interface_modes |= @@ -7146,7 +7328,7 @@ int ath10k_mac_register(struct ath10k *ar) ath10k_reg_notifier); if (ret) { ath10k_err(ar, "failed to initialise regulatory: %i\n", ret); - goto err_free; + goto err_dfs_detector_exit; } ar->hw->wiphy->cipher_suites = cipher_suites; @@ -7155,7 +7337,7 @@ int ath10k_mac_register(struct ath10k *ar) ret = ieee80211_register_hw(ar->hw); if (ret) { ath10k_err(ar, "failed to register ieee80211: %d\n", ret); - goto err_free; + goto err_dfs_detector_exit; } if (!ath_is_world_regd(&ar->ath_common.regulatory)) { @@ -7169,10 +7351,16 @@ int ath10k_mac_register(struct ath10k *ar) err_unregister: ieee80211_unregister_hw(ar->hw); + +err_dfs_detector_exit: + if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) + ar->dfs_detector->exit(ar->dfs_detector); + err_free: kfree(ar->mac.sbands[IEEE80211_BAND_2GHZ].channels); kfree(ar->mac.sbands[IEEE80211_BAND_5GHZ].channels); + SET_IEEE80211_DEV(ar->hw, NULL); return ret; } diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 1046ab65b9ab..3fca200b986c 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -61,12 +61,14 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)"); #define QCA6164_2_1_DEVICE_ID (0x0041) #define QCA6174_2_1_DEVICE_ID (0x003e) #define QCA99X0_2_0_DEVICE_ID (0x0040) +#define QCA9377_1_0_DEVICE_ID (0x0042) static const struct pci_device_id ath10k_pci_id_table[] = { { PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */ { PCI_VDEVICE(ATHEROS, QCA6164_2_1_DEVICE_ID) }, /* PCI-E QCA6164 V2.1 */ { PCI_VDEVICE(ATHEROS, QCA6174_2_1_DEVICE_ID) }, /* PCI-E QCA6174 V2.1 */ { PCI_VDEVICE(ATHEROS, QCA99X0_2_0_DEVICE_ID) }, /* PCI-E QCA99X0 V2 */ + { PCI_VDEVICE(ATHEROS, QCA9377_1_0_DEVICE_ID) }, /* PCI-E QCA9377 V1 */ {0} }; @@ -90,6 +92,7 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = { { QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_2_CHIP_ID_REV }, { QCA99X0_2_0_DEVICE_ID, QCA99X0_HW_2_0_CHIP_ID_REV }, + { QCA9377_1_0_DEVICE_ID, QCA9377_HW_1_0_CHIP_ID_REV }, }; static void ath10k_pci_buffer_cleanup(struct ath10k *ar); @@ -104,6 +107,10 @@ static int ath10k_pci_bmi_wait(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); +static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state); +static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state); +static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state); +static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state); static const struct ce_attr host_ce_config_wlan[] = { /* CE0: host->target HTC control and raw streams */ @@ -112,6 +119,7 @@ static const struct ce_attr host_ce_config_wlan[] = { .src_nentries = 16, .src_sz_max = 256, .dest_nentries = 0, + .send_cb = ath10k_pci_htc_tx_cb, }, /* CE1: target->host HTT + HTC control */ @@ -120,6 +128,7 @@ static const struct ce_attr host_ce_config_wlan[] = { .src_nentries = 0, .src_sz_max = 2048, .dest_nentries = 512, + .recv_cb = ath10k_pci_htc_rx_cb, }, /* CE2: target->host WMI */ @@ -128,6 +137,7 @@ static const struct ce_attr host_ce_config_wlan[] = { .src_nentries = 0, .src_sz_max = 2048, .dest_nentries = 128, + .recv_cb = ath10k_pci_htc_rx_cb, }, /* CE3: host->target WMI */ @@ -136,6 +146,7 @@ static const struct ce_attr host_ce_config_wlan[] = { .src_nentries = 32, .src_sz_max = 2048, .dest_nentries = 0, + .send_cb = ath10k_pci_htc_tx_cb, }, /* CE4: host->target HTT */ @@ -144,14 +155,16 @@ static const struct ce_attr host_ce_config_wlan[] = { .src_nentries = CE_HTT_H2T_MSG_SRC_NENTRIES, .src_sz_max = 256, .dest_nentries = 0, + .send_cb = ath10k_pci_htt_tx_cb, }, - /* CE5: unused */ + /* CE5: target->host HTT (HIF->HTT) */ { .flags = CE_ATTR_FLAGS, .src_nentries = 0, - .src_sz_max = 0, - .dest_nentries = 0, + .src_sz_max = 512, + .dest_nentries = 512, + .recv_cb = ath10k_pci_htt_rx_cb, }, /* CE6: target autonomous hif_memcpy */ @@ -257,12 +270,12 @@ static const struct ce_pipe_config target_ce_config_wlan[] = { /* NB: 50% of src nentries, since tx has 2 frags */ - /* CE5: unused */ + /* CE5: target->host HTT (HIF->HTT) */ { .pipenum = __cpu_to_le32(5), - .pipedir = __cpu_to_le32(PIPEDIR_OUT), + .pipedir = __cpu_to_le32(PIPEDIR_IN), .nentries = __cpu_to_le32(32), - .nbytes_max = __cpu_to_le32(2048), + .nbytes_max = __cpu_to_le32(512), .flags = __cpu_to_le32(CE_ATTR_FLAGS), .reserved = __cpu_to_le32(0), }, @@ -396,7 +409,7 @@ static const struct service_to_pipe target_service_to_ce_map_wlan[] = { { __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA_MSG), __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ - __cpu_to_le32(1), + __cpu_to_le32(5), }, /* (Additions here) */ @@ -452,8 +465,12 @@ static int ath10k_pci_wake_wait(struct ath10k *ar) int curr_delay = 5; while (tot_delay < PCIE_WAKE_TIMEOUT) { - if (ath10k_pci_is_awake(ar)) + 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", + tot_delay / 1000); return 0; + } udelay(curr_delay); tot_delay += curr_delay; @@ -465,12 +482,53 @@ static int ath10k_pci_wake_wait(struct ath10k *ar) return -ETIMEDOUT; } +static int ath10k_pci_force_wake(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&ar_pci->ps_lock, flags); + + if (!ar_pci->ps_awake) { + iowrite32(PCIE_SOC_WAKE_V_MASK, + ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS); + + ret = ath10k_pci_wake_wait(ar); + if (ret == 0) + ar_pci->ps_awake = true; + } + + spin_unlock_irqrestore(&ar_pci->ps_lock, flags); + + return ret; +} + +static void ath10k_pci_force_sleep(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + unsigned long flags; + + spin_lock_irqsave(&ar_pci->ps_lock, flags); + + iowrite32(PCIE_SOC_WAKE_RESET, + ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS); + ar_pci->ps_awake = false; + + spin_unlock_irqrestore(&ar_pci->ps_lock, flags); +} + static int ath10k_pci_wake(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); unsigned long flags; int ret = 0; + if (ar_pci->pci_ps == 0) + return ret; + spin_lock_irqsave(&ar_pci->ps_lock, flags); ath10k_dbg(ar, ATH10K_DBG_PCI_PS, "pci ps wake refcount %lu awake %d\n", @@ -502,6 +560,9 @@ static void ath10k_pci_sleep(struct ath10k *ar) struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); unsigned long flags; + if (ar_pci->pci_ps == 0) + return; + spin_lock_irqsave(&ar_pci->ps_lock, flags); ath10k_dbg(ar, ATH10K_DBG_PCI_PS, "pci ps sleep refcount %lu awake %d\n", @@ -544,6 +605,11 @@ static void ath10k_pci_sleep_sync(struct ath10k *ar) struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); unsigned long flags; + if (ar_pci->pci_ps == 0) { + ath10k_pci_force_sleep(ar); + return; + } + del_timer_sync(&ar_pci->ps_timer); spin_lock_irqsave(&ar_pci->ps_lock, flags); @@ -682,8 +748,6 @@ static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe) dma_addr_t paddr; int ret; - lockdep_assert_held(&ar_pci->ce_lock); - skb = dev_alloc_skb(pipe->buf_sz); if (!skb) return -ENOMEM; @@ -701,9 +765,10 @@ static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe) ATH10K_SKB_RXCB(skb)->paddr = paddr; + spin_lock_bh(&ar_pci->ce_lock); ret = __ath10k_ce_rx_post_buf(ce_pipe, skb, paddr); + spin_unlock_bh(&ar_pci->ce_lock); if (ret) { - ath10k_warn(ar, "failed to post pci rx buf: %d\n", ret); dma_unmap_single(ar->dev, paddr, skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); dev_kfree_skb_any(skb); @@ -713,25 +778,27 @@ static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe) return 0; } -static void __ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) +static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) { struct ath10k *ar = pipe->hif_ce_state; struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_ce_pipe *ce_pipe = pipe->ce_hdl; int ret, num; - lockdep_assert_held(&ar_pci->ce_lock); - if (pipe->buf_sz == 0) return; if (!ce_pipe->dest_ring) return; + spin_lock_bh(&ar_pci->ce_lock); num = __ath10k_ce_rx_num_free_bufs(ce_pipe); + spin_unlock_bh(&ar_pci->ce_lock); while (num--) { ret = __ath10k_pci_rx_post_buf(pipe); if (ret) { + if (ret == -ENOSPC) + break; ath10k_warn(ar, "failed to post pci rx buf: %d\n", ret); mod_timer(&ar_pci->rx_post_retry, jiffies + ATH10K_PCI_RX_POST_RETRY_MS); @@ -740,25 +807,13 @@ static void __ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) } } -static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) -{ - struct ath10k *ar = pipe->hif_ce_state; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - - spin_lock_bh(&ar_pci->ce_lock); - __ath10k_pci_rx_post_pipe(pipe); - spin_unlock_bh(&ar_pci->ce_lock); -} - static void ath10k_pci_rx_post(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int i; - spin_lock_bh(&ar_pci->ce_lock); for (i = 0; i < CE_COUNT; i++) - __ath10k_pci_rx_post_pipe(&ar_pci->pipe_info[i]); - spin_unlock_bh(&ar_pci->ce_lock); + ath10k_pci_rx_post_pipe(&ar_pci->pipe_info[i]); } static void ath10k_pci_rx_replenish_retry(unsigned long ptr) @@ -775,6 +830,7 @@ static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr) switch (ar->hw_rev) { case ATH10K_HW_QCA988X: case ATH10K_HW_QCA6174: + case ATH10K_HW_QCA9377: val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS) & 0x7ff) << 21; @@ -858,9 +914,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, goto done; i = 0; - while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf, - &completed_nbytes, - &id) != 0) { + while (ath10k_ce_completed_send_next_nolock(ce_diag, + NULL) != 0) { mdelay(1); if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { ret = -EBUSY; @@ -868,16 +923,6 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, } } - if (nbytes != completed_nbytes) { - ret = -EIO; - goto done; - } - - if (buf != (u32)address) { - ret = -EIO; - goto done; - } - i = 0; while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, &completed_nbytes, @@ -1031,9 +1076,8 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, goto done; i = 0; - while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf, - &completed_nbytes, - &id) != 0) { + while (ath10k_ce_completed_send_next_nolock(ce_diag, + NULL) != 0) { mdelay(1); if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { @@ -1042,16 +1086,6 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, } } - if (nbytes != completed_nbytes) { - ret = -EIO; - goto done; - } - - if (buf != ce_data) { - ret = -EIO; - goto done; - } - i = 0; while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, &completed_nbytes, @@ -1102,20 +1136,14 @@ static int ath10k_pci_diag_write32(struct ath10k *ar, u32 address, u32 value) } /* Called by lower (CE) layer when a send to Target completes. */ -static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state) +static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state) { struct ath10k *ar = ce_state->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current; struct sk_buff_head list; struct sk_buff *skb; - u32 ce_data; - unsigned int nbytes; - unsigned int transfer_id; __skb_queue_head_init(&list); - while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data, - &nbytes, &transfer_id) == 0) { + while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) { /* no need to call tx completion for NULL pointers */ if (skb == NULL) continue; @@ -1124,16 +1152,16 @@ static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state) } while ((skb = __skb_dequeue(&list))) - cb->tx_completion(ar, skb); + ath10k_htc_tx_completion_handler(ar, skb); } -/* Called by lower (CE) layer when data is received from the Target. */ -static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state) +static void ath10k_pci_process_rx_cb(struct ath10k_ce_pipe *ce_state, + void (*callback)(struct ath10k *ar, + struct sk_buff *skb)) { struct ath10k *ar = ce_state->ar; struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci_pipe *pipe_info = &ar_pci->pipe_info[ce_state->id]; - struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current; struct sk_buff *skb; struct sk_buff_head list; void *transfer_context; @@ -1168,12 +1196,52 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state) ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ", skb->data, skb->len); - cb->rx_completion(ar, skb); + callback(ar, skb); } ath10k_pci_rx_post_pipe(pipe_info); } +/* Called by lower (CE) layer when data is received from the Target. */ +static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state) +{ + ath10k_pci_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler); +} + +/* Called by lower (CE) layer when a send to HTT Target completes. */ +static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state) +{ + struct ath10k *ar = ce_state->ar; + struct sk_buff *skb; + + while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) { + /* no need to call tx completion for NULL pointers */ + if (!skb) + continue; + + dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr, + skb->len, DMA_TO_DEVICE); + ath10k_htt_hif_tx_complete(ar, skb); + } +} + +static void ath10k_pci_htt_rx_deliver(struct ath10k *ar, struct sk_buff *skb) +{ + skb_pull(skb, sizeof(struct ath10k_htc_hdr)); + ath10k_htt_t2h_msg_handler(ar, skb); +} + +/* Called by lower (CE) layer when HTT data is received from the Target. */ +static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state) +{ + /* CE4 polling needs to be done whenever CE pipe which transports + * HTT Rx (target->host) is processed. + */ + ath10k_ce_per_engine_service(ce_state->ar, 4); + + ath10k_pci_process_rx_cb(ce_state, ath10k_pci_htt_rx_deliver); +} + static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, struct ath10k_hif_sg_item *items, int n_items) { @@ -1343,17 +1411,6 @@ static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, ath10k_ce_per_engine_service(ar, pipe); } -static void ath10k_pci_hif_set_callbacks(struct ath10k *ar, - struct ath10k_hif_cb *callbacks) -{ - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - - ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif set callbacks\n"); - - memcpy(&ar_pci->msg_callbacks_current, callbacks, - sizeof(ar_pci->msg_callbacks_current)); -} - static void ath10k_pci_kill_tasklet(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -1368,10 +1425,8 @@ static void ath10k_pci_kill_tasklet(struct ath10k *ar) del_timer_sync(&ar_pci->rx_post_retry); } -static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, - u16 service_id, u8 *ul_pipe, - u8 *dl_pipe, int *ul_is_polled, - int *dl_is_polled) +static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, + u8 *ul_pipe, u8 *dl_pipe) { const struct service_to_pipe *entry; bool ul_set = false, dl_set = false; @@ -1379,9 +1434,6 @@ static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif map service\n"); - /* polling for received messages not supported */ - *dl_is_polled = 0; - for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) { entry = &target_service_to_ce_map_wlan[i]; @@ -1415,25 +1467,17 @@ static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, if (WARN_ON(!ul_set || !dl_set)) return -ENOENT; - *ul_is_polled = - (host_ce_config_wlan[*ul_pipe].flags & CE_ATTR_DIS_INTR) != 0; - return 0; } static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, u8 *ul_pipe, u8 *dl_pipe) { - int ul_is_polled, dl_is_polled; - ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif get default pipe\n"); (void)ath10k_pci_hif_map_service_to_pipe(ar, ATH10K_HTC_SVC_ID_RSVD_CTRL, - ul_pipe, - dl_pipe, - &ul_is_polled, - &dl_is_polled); + ul_pipe, dl_pipe); } static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) @@ -1443,6 +1487,7 @@ static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) switch (ar->hw_rev) { case ATH10K_HW_QCA988X: case ATH10K_HW_QCA6174: + case ATH10K_HW_QCA9377: val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS); val &= ~CORE_CTRL_PCIE_REG_31_MASK; @@ -1464,6 +1509,7 @@ static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar) switch (ar->hw_rev) { case ATH10K_HW_QCA988X: case ATH10K_HW_QCA6174: + case ATH10K_HW_QCA9377: val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS); val |= CORE_CTRL_PCIE_REG_31_MASK; @@ -1504,6 +1550,7 @@ static void ath10k_pci_irq_enable(struct ath10k *ar) static int ath10k_pci_hif_start(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif start\n"); ath10k_pci_irq_enable(ar); @@ -1553,7 +1600,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) struct ath10k_pci *ar_pci; struct ath10k_ce_pipe *ce_pipe; struct ath10k_ce_ring *ce_ring; - struct ce_desc *ce_desc; struct sk_buff *skb; int i; @@ -1568,10 +1614,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) if (!pci_pipe->buf_sz) return; - ce_desc = ce_ring->shadow_base; - if (WARN_ON(!ce_desc)) - return; - for (i = 0; i < ce_ring->nentries; i++) { skb = ce_ring->per_transfer_context[i]; if (!skb) @@ -1579,7 +1621,7 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) ce_ring->per_transfer_context[i] = NULL; - ar_pci->msg_callbacks_current.tx_completion(ar, skb); + ath10k_htc_tx_completion_handler(ar, skb); } } @@ -1745,12 +1787,8 @@ err_dma: static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state) { struct bmi_xfer *xfer; - u32 ce_data; - unsigned int nbytes; - unsigned int transfer_id; - if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer, &ce_data, - &nbytes, &transfer_id)) + if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer)) return; xfer->tx_done = true; @@ -1840,6 +1878,8 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar) return 9; } break; + case QCA9377_1_0_DEVICE_ID: + return 2; } ath10k_warn(ar, "unknown number of banks, assuming 1\n"); @@ -1999,9 +2039,7 @@ static int ath10k_pci_alloc_pipes(struct ath10k *ar) pipe->pipe_num = i; pipe->hif_ce_state = ar; - ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i], - ath10k_pci_ce_send_done, - ath10k_pci_ce_recv_data); + ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i]); if (ret) { ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n", i, ret); @@ -2257,7 +2295,7 @@ static int ath10k_pci_qca6174_chip_reset(struct ath10k *ar) ret = ath10k_pci_wait_for_target_init(ar); if (ret) { ath10k_warn(ar, "failed to wait for target after cold reset: %d\n", - ret); + ret); return ret; } @@ -2302,6 +2340,8 @@ static int ath10k_pci_chip_reset(struct ath10k *ar) return ath10k_pci_qca988x_chip_reset(ar); else if (QCA_REV_6174(ar)) return ath10k_pci_qca6174_chip_reset(ar); + else if (QCA_REV_9377(ar)) + return ath10k_pci_qca6174_chip_reset(ar); else if (QCA_REV_99X0(ar)) return ath10k_pci_qca99x0_chip_reset(ar); else @@ -2397,6 +2437,15 @@ static int ath10k_pci_hif_resume(struct ath10k *ar) struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct pci_dev *pdev = ar_pci->pdev; u32 val; + int ret = 0; + + if (ar_pci->pci_ps == 0) { + ret = ath10k_pci_force_wake(ar); + if (ret) { + ath10k_err(ar, "failed to wake up target: %d\n", ret); + return ret; + } + } /* Suspend/Resume resets the PCI configuration space, so we have to * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries @@ -2407,7 +2456,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar) if ((val & 0x0000ff00) != 0) pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - return 0; + return ret; } #endif @@ -2421,7 +2470,6 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = { .map_service_to_pipe = ath10k_pci_hif_map_service_to_pipe, .get_default_pipe = ath10k_pci_hif_get_default_pipe, .send_complete_check = ath10k_pci_hif_send_complete_check, - .set_callbacks = ath10k_pci_hif_set_callbacks, .get_free_queue_number = ath10k_pci_hif_get_free_queue_number, .power_up = ath10k_pci_hif_power_up, .power_down = ath10k_pci_hif_power_down, @@ -2501,6 +2549,16 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg) { struct ath10k *ar = arg; struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret; + + if (ar_pci->pci_ps == 0) { + ret = ath10k_pci_force_wake(ar); + if (ret) { + ath10k_warn(ar, "failed to wake device up on irq: %d\n", + ret); + return IRQ_NONE; + } + } if (ar_pci->num_msi_intrs == 0) { if (!ath10k_pci_irq_pending(ar)) @@ -2609,12 +2667,9 @@ static int ath10k_pci_request_irq(struct ath10k *ar) return ath10k_pci_request_irq_legacy(ar); case 1: return ath10k_pci_request_irq_msi(ar); - case MSI_NUM_REQUEST: + default: return ath10k_pci_request_irq_msix(ar); } - - ath10k_warn(ar, "unknown irq configuration upon request\n"); - return -EINVAL; } static void ath10k_pci_free_irq(struct ath10k *ar) @@ -2657,7 +2712,7 @@ static int ath10k_pci_init_irq(struct ath10k *ar) /* Try MSI-X */ if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO) { - ar_pci->num_msi_intrs = MSI_NUM_REQUEST; + ar_pci->num_msi_intrs = MSI_ASSIGN_CE_MAX + 1; ret = pci_enable_msi_range(ar_pci->pdev, ar_pci->num_msi_intrs, ar_pci->num_msi_intrs); if (ret > 0) @@ -2705,18 +2760,13 @@ static int ath10k_pci_deinit_irq(struct ath10k *ar) switch (ar_pci->num_msi_intrs) { case 0: ath10k_pci_deinit_irq_legacy(ar); - return 0; - case 1: - /* fall-through */ - case MSI_NUM_REQUEST: - pci_disable_msi(ar_pci->pdev); - return 0; + break; default: pci_disable_msi(ar_pci->pdev); + break; } - ath10k_warn(ar, "unknown irq configuration upon deinit\n"); - return -EINVAL; + return 0; } static int ath10k_pci_wait_for_target_init(struct ath10k *ar) @@ -2908,17 +2958,25 @@ static int ath10k_pci_probe(struct pci_dev *pdev, struct ath10k_pci *ar_pci; enum ath10k_hw_rev hw_rev; u32 chip_id; + bool pci_ps; switch (pci_dev->device) { case QCA988X_2_0_DEVICE_ID: hw_rev = ATH10K_HW_QCA988X; + pci_ps = false; break; case QCA6164_2_1_DEVICE_ID: case QCA6174_2_1_DEVICE_ID: hw_rev = ATH10K_HW_QCA6174; + pci_ps = true; break; case QCA99X0_2_0_DEVICE_ID: hw_rev = ATH10K_HW_QCA99X0; + pci_ps = false; + break; + case QCA9377_1_0_DEVICE_ID: + hw_rev = ATH10K_HW_QCA9377; + pci_ps = true; break; default: WARN_ON(1); @@ -2932,19 +2990,21 @@ static int ath10k_pci_probe(struct pci_dev *pdev, return -ENOMEM; } - ath10k_dbg(ar, ATH10K_DBG_PCI, "pci probe\n"); + ath10k_dbg(ar, ATH10K_DBG_BOOT, "pci probe %04x:%04x %04x:%04x\n", + pdev->vendor, pdev->device, + pdev->subsystem_vendor, pdev->subsystem_device); ar_pci = ath10k_pci_priv(ar); ar_pci->pdev = pdev; ar_pci->dev = &pdev->dev; ar_pci->ar = ar; ar->dev_id = pci_dev->device; + ar_pci->pci_ps = pci_ps; - if (pdev->subsystem_vendor || pdev->subsystem_device) - scnprintf(ar->spec_board_id, sizeof(ar->spec_board_id), - "%04x:%04x:%04x:%04x", - pdev->vendor, pdev->device, - pdev->subsystem_vendor, pdev->subsystem_device); + ar->id.vendor = pdev->vendor; + ar->id.device = pdev->device; + ar->id.subsystem_vendor = pdev->subsystem_vendor; + ar->id.subsystem_device = pdev->subsystem_device; spin_lock_init(&ar_pci->ce_lock); spin_lock_init(&ar_pci->ps_lock); @@ -2970,6 +3030,14 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ath10k_pci_ce_deinit(ar); ath10k_pci_irq_disable(ar); + if (ar_pci->pci_ps == 0) { + ret = ath10k_pci_force_wake(ar); + if (ret) { + ath10k_warn(ar, "failed to wake up device : %d\n", ret); + goto err_free_pipes; + } + } + ret = ath10k_pci_init_irq(ar); if (ret) { ath10k_err(ar, "failed to init irqs: %d\n", ret); @@ -3098,13 +3166,20 @@ MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API3_FILE); MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API4_FILE); MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API5_FILE); MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE); +MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_BOARD_API2_FILE); /* QCA6174 2.1 firmware files */ MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API4_FILE); MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API5_FILE); MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" QCA6174_HW_2_1_BOARD_DATA_FILE); +MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_BOARD_API2_FILE); /* QCA6174 3.1 firmware files */ MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API4_FILE); MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API5_FILE); MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" QCA6174_HW_3_0_BOARD_DATA_FILE); +MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_BOARD_API2_FILE); + +/* QCA9377 1.0 firmware files */ +MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" ATH10K_FW_API5_FILE); +MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" QCA9377_HW_1_0_BOARD_DATA_FILE); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 8d364fb8f743..f91bf333cb75 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -175,8 +175,6 @@ struct ath10k_pci { struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX]; - struct ath10k_hif_cb msg_callbacks_current; - /* Copy Engine used for Diagnostic Accesses */ struct ath10k_ce_pipe *ce_diag; @@ -221,6 +219,12 @@ struct ath10k_pci { * powersave register state changes. */ bool ps_awake; + + /* pci power save, disable for QCA988X and QCA99X0. + * Writing 'false' to this variable avoids frequent locking + * on MMIO read/write. + */ + bool pci_ps; }; static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) @@ -230,7 +234,8 @@ static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) #define ATH10K_PCI_RX_POST_RETRY_MS 50 #define ATH_PCI_RESET_WAIT_MAX 10 /* ms */ -#define PCIE_WAKE_TIMEOUT 10000 /* 10ms */ +#define PCIE_WAKE_TIMEOUT 30000 /* 30ms */ +#define PCIE_WAKE_LATE_US 10000 /* 10ms */ #define BAR_NUM 0 diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h index 768bef629099..05a421bc322a 100644 --- a/drivers/net/wireless/ath/ath10k/targaddrs.h +++ b/drivers/net/wireless/ath/ath10k/targaddrs.h @@ -450,6 +450,9 @@ Fw Mode/SubMode Mask #define QCA6174_BOARD_DATA_SZ 8192 #define QCA6174_BOARD_EXT_DATA_SZ 0 +#define QCA9377_BOARD_DATA_SZ QCA6174_BOARD_DATA_SZ +#define QCA9377_BOARD_EXT_DATA_SZ 0 + #define QCA99X0_BOARD_DATA_SZ 12288 #define QCA99X0_BOARD_EXT_DATA_SZ 0 diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index b084f88da102..1d5a2fdcbf56 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -139,11 +139,181 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[]) return cfg80211_testmode_reply(skb); } -static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) +static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) +{ + size_t len, magic_len, ie_len; + struct ath10k_fw_ie *hdr; + char filename[100]; + __le32 *version; + const u8 *data; + int ie_id, ret; + + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_FILE); + + /* load utf firmware image */ + ret = request_firmware(&ar->testmode.utf, filename, ar->dev); + if (ret) { + ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", + filename, ret); + return ret; + } + + data = ar->testmode.utf->data; + len = ar->testmode.utf->size; + + /* FIXME: call release_firmware() in error cases */ + + /* magic also includes the null byte, check that as well */ + magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1; + + if (len < magic_len) { + ath10k_err(ar, "utf firmware file is too small to contain magic\n"); + ret = -EINVAL; + goto err; + } + + if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) { + ath10k_err(ar, "invalid firmware magic\n"); + ret = -EINVAL; + goto err; + } + + /* jump over the padding */ + magic_len = ALIGN(magic_len, 4); + + len -= magic_len; + data += magic_len; + + /* loop elements */ + while (len > sizeof(struct ath10k_fw_ie)) { + hdr = (struct ath10k_fw_ie *)data; + + ie_id = le32_to_cpu(hdr->id); + ie_len = le32_to_cpu(hdr->len); + + len -= sizeof(*hdr); + data += sizeof(*hdr); + + if (len < ie_len) { + ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n", + ie_id, len, ie_len); + ret = -EINVAL; + goto err; + } + + switch (ie_id) { + case ATH10K_FW_IE_FW_VERSION: + if (ie_len > sizeof(ar->testmode.utf_version) - 1) + break; + + memcpy(ar->testmode.utf_version, data, ie_len); + ar->testmode.utf_version[ie_len] = '\0'; + + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, + "testmode found fw utf version %s\n", + ar->testmode.utf_version); + break; + case ATH10K_FW_IE_TIMESTAMP: + /* ignore timestamp, but don't warn about it either */ + break; + case ATH10K_FW_IE_FW_IMAGE: + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, + "testmode found fw image ie (%zd B)\n", + ie_len); + + ar->testmode.utf_firmware_data = data; + ar->testmode.utf_firmware_len = ie_len; + break; + case ATH10K_FW_IE_WMI_OP_VERSION: + if (ie_len != sizeof(u32)) + break; + version = (__le32 *)data; + ar->testmode.op_version = le32_to_cpup(version); + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw ie wmi op version %d\n", + ar->testmode.op_version); + break; + default: + ath10k_warn(ar, "Unknown testmode FW IE: %u\n", + le32_to_cpu(hdr->id)); + break; + } + /* jump over the padding */ + ie_len = ALIGN(ie_len, 4); + + len -= ie_len; + data += ie_len; + } + + if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) { + ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n"); + ret = -EINVAL; + goto err; + } + + return 0; + +err: + release_firmware(ar->testmode.utf); + + return ret; +} + +static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar) { char filename[100]; int ret; + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); + + /* load utf firmware image */ + ret = request_firmware(&ar->testmode.utf, filename, ar->dev); + if (ret) { + ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", + filename, ret); + return ret; + } + + /* We didn't find FW UTF API 1 ("utf.bin") does not advertise + * firmware features. Do an ugly hack where we force the firmware + * features to match with 10.1 branch so that wmi.c will use the + * correct WMI interface. + */ + + ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; + ar->testmode.utf_firmware_data = ar->testmode.utf->data; + ar->testmode.utf_firmware_len = ar->testmode.utf->size; + + return 0; +} + +static int ath10k_tm_fetch_firmware(struct ath10k *ar) +{ + int ret; + + ret = ath10k_tm_fetch_utf_firmware_api_2(ar); + if (ret == 0) { + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2"); + return 0; + } + + ret = ath10k_tm_fetch_utf_firmware_api_1(ar); + if (ret) { + ath10k_err(ar, "failed to fetch utf firmware binary: %d", ret); + return ret; + } + + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using utf api 1"); + + return 0; +} + +static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) +{ + const char *ver; + int ret; + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n"); mutex_lock(&ar->conf_mutex); @@ -165,36 +335,27 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) goto err; } - snprintf(filename, sizeof(filename), "%s/%s", - ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); - - /* load utf firmware image */ - ret = request_firmware(&ar->testmode.utf, filename, ar->dev); + ret = ath10k_tm_fetch_firmware(ar); if (ret) { - ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", - filename, ret); + ath10k_err(ar, "failed to fetch UTF firmware: %d", ret); goto err; } spin_lock_bh(&ar->data_lock); - ar->testmode.utf_monitor = true; - spin_unlock_bh(&ar->data_lock); - BUILD_BUG_ON(sizeof(ar->fw_features) != sizeof(ar->testmode.orig_fw_features)); memcpy(ar->testmode.orig_fw_features, ar->fw_features, sizeof(ar->fw_features)); ar->testmode.orig_wmi_op_version = ar->wmi.op_version; - - /* utf.bin firmware image does not advertise firmware features. Do - * an ugly hack where we force the firmware features so that wmi.c - * will use the correct WMI interface. - */ memset(ar->fw_features, 0, sizeof(ar->fw_features)); - ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; + + ar->wmi.op_version = ar->testmode.op_version; + + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n", + ar->wmi.op_version); ret = ath10k_hif_power_up(ar); if (ret) { @@ -212,7 +373,12 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) ar->state = ATH10K_STATE_UTF; - ath10k_info(ar, "UTF firmware started\n"); + if (strlen(ar->testmode.utf_version) > 0) + ver = ar->testmode.utf_version; + else + ver = "API 1"; + + ath10k_info(ar, "UTF firmware %s started\n", ver); mutex_unlock(&ar->conf_mutex); diff --git a/drivers/net/wireless/ath/ath10k/thermal.c b/drivers/net/wireless/ath/ath10k/thermal.c index 1a899d70dc5d..60fe562e3041 100644 --- a/drivers/net/wireless/ath/ath10k/thermal.c +++ b/drivers/net/wireless/ath/ath10k/thermal.c @@ -215,6 +215,6 @@ err_cooling_destroy: void ath10k_thermal_unregister(struct ath10k *ar) { - thermal_cooling_device_unregister(ar->thermal.cdev); sysfs_remove_link(&ar->dev->kobj, "cooling_device"); + thermal_cooling_device_unregister(ar->thermal.cdev); } diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index e4a9c4c8d0cb..6d1105ab4592 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -52,6 +52,9 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct ieee80211_tx_info *info; struct ath10k_skb_cb *skb_cb; struct sk_buff *msdu; + struct ieee80211_hdr *hdr; + __le16 fc; + bool limit_mgmt_desc = false; ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d success %d\n", @@ -72,21 +75,23 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, spin_unlock_bh(&htt->tx_lock); return; } + + hdr = (struct ieee80211_hdr *)msdu->data; + fc = hdr->frame_control; + + if (unlikely(ieee80211_is_mgmt(fc)) && + ar->hw_params.max_probe_resp_desc_thres) + limit_mgmt_desc = true; + ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); - __ath10k_htt_tx_dec_pending(htt); + __ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); if (htt->num_pending_tx == 0) wake_up(&htt->empty_tx_wq); spin_unlock_bh(&htt->tx_lock); skb_cb = ATH10K_SKB_CB(msdu); - dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); - if (skb_cb->htt.txbuf) - dma_pool_free(htt->tx_pool, - skb_cb->htt.txbuf, - skb_cb->htt.txbuf_paddr); - ath10k_report_offchan_tx(htt->ar, msdu); info = IEEE80211_SKB_CB(msdu); diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index 248ffc3d6620..8f4f6a892581 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -177,6 +177,15 @@ struct wmi_ops { const struct wmi_tdls_peer_capab_arg *cap, const struct wmi_channel_arg *chan); struct sk_buff *(*gen_adaptive_qcs)(struct ath10k *ar, bool enable); + struct sk_buff *(*gen_pdev_get_tpc_config)(struct ath10k *ar, + u32 param); + void (*fw_stats_fill)(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf); + struct sk_buff *(*gen_pdev_enable_adaptive_cca)(struct ath10k *ar, + u8 enable, + u32 detect_level, + u32 detect_margin); }; int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); @@ -1270,4 +1279,52 @@ ath10k_wmi_adaptive_qcs(struct ath10k *ar, bool enable) return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->adaptive_qcs_cmdid); } +static inline int +ath10k_wmi_pdev_get_tpc_config(struct ath10k *ar, u32 param) +{ + struct sk_buff *skb; + + if (!ar->wmi.ops->gen_pdev_get_tpc_config) + return -EOPNOTSUPP; + + skb = ar->wmi.ops->gen_pdev_get_tpc_config(ar, param); + + if (IS_ERR(skb)) + return PTR_ERR(skb); + + return ath10k_wmi_cmd_send(ar, skb, + ar->wmi.cmd->pdev_get_tpc_config_cmdid); +} + +static inline int +ath10k_wmi_fw_stats_fill(struct ath10k *ar, struct ath10k_fw_stats *fw_stats, + char *buf) +{ + if (!ar->wmi.ops->fw_stats_fill) + return -EOPNOTSUPP; + + ar->wmi.ops->fw_stats_fill(ar, fw_stats, buf); + return 0; +} + +static inline int +ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable, + u32 detect_level, u32 detect_margin) +{ + struct sk_buff *skb; + + if (!ar->wmi.ops->gen_pdev_enable_adaptive_cca) + return -EOPNOTSUPP; + + skb = ar->wmi.ops->gen_pdev_enable_adaptive_cca(ar, enable, + detect_level, + detect_margin); + + if (IS_ERR(skb)) + return PTR_ERR(skb); + + return ath10k_wmi_cmd_send(ar, skb, + ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid); +} + #endif diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index b5849b3fd2f0..6fbd17b69469 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -23,6 +23,7 @@ #include "wmi-ops.h" #include "wmi-tlv.h" #include "p2p.h" +#include "testmode.h" /***************/ /* TLV helpers */ @@ -419,6 +420,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) { struct wmi_cmd_hdr *cmd_hdr; enum wmi_tlv_event_id id; + bool consumed; cmd_hdr = (struct wmi_cmd_hdr *)skb->data; id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); @@ -428,6 +430,18 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) trace_ath10k_wmi_event(ar, id, skb->data, skb->len); + consumed = ath10k_tm_event_wmi(ar, id, skb); + + /* Ready event must be handled normally also in UTF mode so that we + * know the UTF firmware has booted, others we are just bypass WMI + * events to testmode. + */ + if (consumed && id != WMI_TLV_READY_EVENTID) { + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi tlv testmode consumed 0x%x\n", id); + goto out; + } + switch (id) { case WMI_TLV_MGMT_RX_EVENTID: ath10k_wmi_event_mgmt_rx(ar, skb); @@ -3468,6 +3482,7 @@ static const struct wmi_ops wmi_tlv_ops = { .gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state, .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update, .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs, + .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, }; /************/ diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index ce01107ef37a..7569db0f69b5 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -148,6 +148,7 @@ static struct wmi_cmd_map wmi_cmd_map = { .gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID, .gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID, .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED, + .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED, .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, @@ -313,6 +314,7 @@ static struct wmi_cmd_map wmi_10x_cmd_map = { .gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID, .gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID, .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED, + .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED, .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, @@ -477,6 +479,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd_map = { .gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID, .gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID, .pdev_get_temperature_cmdid = WMI_10_2_PDEV_GET_TEMPERATURE_CMDID, + .pdev_enable_adaptive_cca_cmdid = WMI_10_2_SET_CCA_PARAMS, .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, @@ -1407,6 +1410,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = { .gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID, .gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID, .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED, + .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED, .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, @@ -2475,6 +2479,47 @@ void ath10k_wmi_pull_pdev_stats_tx(const struct wmi_pdev_stats_tx *src, dst->txop_ovf = __le32_to_cpu(src->txop_ovf); } +static void +ath10k_wmi_10_4_pull_pdev_stats_tx(const struct wmi_10_4_pdev_stats_tx *src, + struct ath10k_fw_stats_pdev *dst) +{ + dst->comp_queued = __le32_to_cpu(src->comp_queued); + dst->comp_delivered = __le32_to_cpu(src->comp_delivered); + dst->msdu_enqued = __le32_to_cpu(src->msdu_enqued); + dst->mpdu_enqued = __le32_to_cpu(src->mpdu_enqued); + dst->wmm_drop = __le32_to_cpu(src->wmm_drop); + dst->local_enqued = __le32_to_cpu(src->local_enqued); + dst->local_freed = __le32_to_cpu(src->local_freed); + dst->hw_queued = __le32_to_cpu(src->hw_queued); + dst->hw_reaped = __le32_to_cpu(src->hw_reaped); + dst->underrun = __le32_to_cpu(src->underrun); + dst->tx_abort = __le32_to_cpu(src->tx_abort); + dst->mpdus_requed = __le32_to_cpu(src->mpdus_requed); + dst->tx_ko = __le32_to_cpu(src->tx_ko); + dst->data_rc = __le32_to_cpu(src->data_rc); + dst->self_triggers = __le32_to_cpu(src->self_triggers); + dst->sw_retry_failure = __le32_to_cpu(src->sw_retry_failure); + dst->illgl_rate_phy_err = __le32_to_cpu(src->illgl_rate_phy_err); + dst->pdev_cont_xretry = __le32_to_cpu(src->pdev_cont_xretry); + dst->pdev_tx_timeout = __le32_to_cpu(src->pdev_tx_timeout); + dst->pdev_resets = __le32_to_cpu(src->pdev_resets); + dst->phy_underrun = __le32_to_cpu(src->phy_underrun); + dst->txop_ovf = __le32_to_cpu(src->txop_ovf); + dst->hw_paused = __le32_to_cpu(src->hw_paused); + dst->seq_posted = __le32_to_cpu(src->seq_posted); + dst->seq_failed_queueing = + __le32_to_cpu(src->seq_failed_queueing); + dst->seq_completed = __le32_to_cpu(src->seq_completed); + dst->seq_restarted = __le32_to_cpu(src->seq_restarted); + dst->mu_seq_posted = __le32_to_cpu(src->mu_seq_posted); + dst->mpdus_sw_flush = __le32_to_cpu(src->mpdus_sw_flush); + dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter); + dst->mpdus_truncated = __le32_to_cpu(src->mpdus_truncated); + dst->mpdus_ack_failed = __le32_to_cpu(src->mpdus_ack_failed); + dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter); + dst->mpdus_expired = __le32_to_cpu(src->mpdus_expired); +} + void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src, struct ath10k_fw_stats_pdev *dst) { @@ -2785,6 +2830,86 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar, return 0; } +static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar, + struct sk_buff *skb, + struct ath10k_fw_stats *stats) +{ + const struct wmi_10_2_stats_event *ev = (void *)skb->data; + u32 num_pdev_stats; + u32 num_pdev_ext_stats; + u32 num_vdev_stats; + u32 num_peer_stats; + int i; + + if (!skb_pull(skb, sizeof(*ev))) + return -EPROTO; + + num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); + num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats); + num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); + num_peer_stats = __le32_to_cpu(ev->num_peer_stats); + + for (i = 0; i < num_pdev_stats; i++) { + const struct wmi_10_4_pdev_stats *src; + struct ath10k_fw_stats_pdev *dst; + + src = (void *)skb->data; + if (!skb_pull(skb, sizeof(*src))) + return -EPROTO; + + dst = kzalloc(sizeof(*dst), GFP_ATOMIC); + if (!dst) + continue; + + ath10k_wmi_pull_pdev_stats_base(&src->base, dst); + ath10k_wmi_10_4_pull_pdev_stats_tx(&src->tx, dst); + ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst); + dst->rx_ovfl_errs = __le32_to_cpu(src->rx_ovfl_errs); + ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst); + + list_add_tail(&dst->list, &stats->pdevs); + } + + for (i = 0; i < num_pdev_ext_stats; i++) { + const struct wmi_10_2_pdev_ext_stats *src; + + src = (void *)skb->data; + if (!skb_pull(skb, sizeof(*src))) + return -EPROTO; + + /* FIXME: expose values to userspace + * + * Note: Even though this loop seems to do nothing it is + * required to parse following sub-structures properly. + */ + } + + /* fw doesn't implement vdev stats */ + + for (i = 0; i < num_peer_stats; i++) { + const struct wmi_10_4_peer_stats *src; + struct ath10k_fw_stats_peer *dst; + + src = (void *)skb->data; + if (!skb_pull(skb, sizeof(*src))) + return -EPROTO; + + dst = kzalloc(sizeof(*dst), GFP_ATOMIC); + if (!dst) + continue; + + ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr); + dst->peer_rssi = __le32_to_cpu(src->peer_rssi); + dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate); + dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); + /* FIXME: expose 10.4 specific values */ + + list_add_tail(&dst->list, &stats->peers); + } + + return 0; +} + void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb) { ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n"); @@ -3018,8 +3143,6 @@ static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif, memcpy(skb_put(bcn, arvif->u.ap.noa_len), arvif->u.ap.noa_data, arvif->u.ap.noa_len); - - return; } static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb, @@ -3507,7 +3630,7 @@ void ath10k_wmi_event_spectral_scan(struct ath10k *ar, tsf); if (res < 0) { ath10k_dbg(ar, ATH10K_DBG_WMI, "failed to process fft report: %d\n", - res); + res); return; } break; @@ -3835,9 +3958,258 @@ void ath10k_wmi_event_dcs_interference(struct ath10k *ar, struct sk_buff *skb) ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_DCS_INTERFERENCE_EVENTID\n"); } +static u8 ath10k_tpc_config_get_rate(struct ath10k *ar, + struct wmi_pdev_tpc_config_event *ev, + u32 rate_idx, u32 num_chains, + u32 rate_code, u8 type) +{ + u8 tpc, num_streams, preamble, ch, stm_idx; + + num_streams = ATH10K_HW_NSS(rate_code); + preamble = ATH10K_HW_PREAMBLE(rate_code); + ch = num_chains - 1; + + tpc = min_t(u8, ev->rates_array[rate_idx], ev->max_reg_allow_pow[ch]); + + if (__le32_to_cpu(ev->num_tx_chain) <= 1) + goto out; + + if (preamble == WMI_RATE_PREAMBLE_CCK) + goto out; + + stm_idx = num_streams - 1; + if (num_chains <= num_streams) + goto out; + + switch (type) { + case WMI_TPC_TABLE_TYPE_STBC: + tpc = min_t(u8, tpc, + ev->max_reg_allow_pow_agstbc[ch - 1][stm_idx]); + break; + case WMI_TPC_TABLE_TYPE_TXBF: + tpc = min_t(u8, tpc, + ev->max_reg_allow_pow_agtxbf[ch - 1][stm_idx]); + break; + case WMI_TPC_TABLE_TYPE_CDD: + tpc = min_t(u8, tpc, + ev->max_reg_allow_pow_agcdd[ch - 1][stm_idx]); + break; + default: + ath10k_warn(ar, "unknown wmi tpc table type: %d\n", type); + tpc = 0; + break; + } + +out: + return tpc; +} + +static void ath10k_tpc_config_disp_tables(struct ath10k *ar, + struct wmi_pdev_tpc_config_event *ev, + struct ath10k_tpc_stats *tpc_stats, + u8 *rate_code, u16 *pream_table, u8 type) +{ + u32 i, j, pream_idx, flags; + u8 tpc[WMI_TPC_TX_N_CHAIN]; + char tpc_value[WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE]; + char buff[WMI_TPC_BUF_SIZE]; + + flags = __le32_to_cpu(ev->flags); + + switch (type) { + case WMI_TPC_TABLE_TYPE_CDD: + if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_CDD)) { + ath10k_dbg(ar, ATH10K_DBG_WMI, "CDD not supported\n"); + tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG; + return; + } + break; + case WMI_TPC_TABLE_TYPE_STBC: + if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_STBC)) { + ath10k_dbg(ar, ATH10K_DBG_WMI, "STBC not supported\n"); + tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG; + return; + } + break; + case WMI_TPC_TABLE_TYPE_TXBF: + if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_TXBF)) { + ath10k_dbg(ar, ATH10K_DBG_WMI, "TXBF not supported\n"); + tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG; + return; + } + break; + default: + ath10k_dbg(ar, ATH10K_DBG_WMI, + "invalid table type in wmi tpc event: %d\n", type); + return; + } + + pream_idx = 0; + for (i = 0; i < __le32_to_cpu(ev->rate_max); i++) { + memset(tpc_value, 0, sizeof(tpc_value)); + memset(buff, 0, sizeof(buff)); + if (i == pream_table[pream_idx]) + pream_idx++; + + for (j = 0; j < WMI_TPC_TX_N_CHAIN; j++) { + if (j >= __le32_to_cpu(ev->num_tx_chain)) + break; + + tpc[j] = ath10k_tpc_config_get_rate(ar, ev, i, j + 1, + rate_code[i], + type); + snprintf(buff, sizeof(buff), "%8d ", tpc[j]); + strncat(tpc_value, buff, strlen(buff)); + } + tpc_stats->tpc_table[type].pream_idx[i] = pream_idx; + tpc_stats->tpc_table[type].rate_code[i] = rate_code[i]; + memcpy(tpc_stats->tpc_table[type].tpc_value[i], + tpc_value, sizeof(tpc_value)); + } +} + void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb) { - ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PDEV_TPC_CONFIG_EVENTID\n"); + u32 i, j, pream_idx, num_tx_chain; + u8 rate_code[WMI_TPC_RATE_MAX], rate_idx; + u16 pream_table[WMI_TPC_PREAM_TABLE_MAX]; + struct wmi_pdev_tpc_config_event *ev; + struct ath10k_tpc_stats *tpc_stats; + + ev = (struct wmi_pdev_tpc_config_event *)skb->data; + + tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC); + if (!tpc_stats) + return; + + /* Create the rate code table based on the chains supported */ + rate_idx = 0; + pream_idx = 0; + + /* Fill CCK rate code */ + for (i = 0; i < 4; i++) { + rate_code[rate_idx] = + ATH10K_HW_RATECODE(i, 0, WMI_RATE_PREAMBLE_CCK); + rate_idx++; + } + pream_table[pream_idx] = rate_idx; + pream_idx++; + + /* Fill OFDM rate code */ + for (i = 0; i < 8; i++) { + rate_code[rate_idx] = + ATH10K_HW_RATECODE(i, 0, WMI_RATE_PREAMBLE_OFDM); + rate_idx++; + } + pream_table[pream_idx] = rate_idx; + pream_idx++; + + num_tx_chain = __le32_to_cpu(ev->num_tx_chain); + + /* Fill HT20 rate code */ + for (i = 0; i < num_tx_chain; i++) { + for (j = 0; j < 8; j++) { + rate_code[rate_idx] = + ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_HT); + rate_idx++; + } + } + pream_table[pream_idx] = rate_idx; + pream_idx++; + + /* Fill HT40 rate code */ + for (i = 0; i < num_tx_chain; i++) { + for (j = 0; j < 8; j++) { + rate_code[rate_idx] = + ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_HT); + rate_idx++; + } + } + pream_table[pream_idx] = rate_idx; + pream_idx++; + + /* Fill VHT20 rate code */ + for (i = 0; i < __le32_to_cpu(ev->num_tx_chain); i++) { + for (j = 0; j < 10; j++) { + rate_code[rate_idx] = + ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT); + rate_idx++; + } + } + pream_table[pream_idx] = rate_idx; + pream_idx++; + + /* Fill VHT40 rate code */ + for (i = 0; i < num_tx_chain; i++) { + for (j = 0; j < 10; j++) { + rate_code[rate_idx] = + ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT); + rate_idx++; + } + } + pream_table[pream_idx] = rate_idx; + pream_idx++; + + /* Fill VHT80 rate code */ + for (i = 0; i < num_tx_chain; i++) { + for (j = 0; j < 10; j++) { + rate_code[rate_idx] = + ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT); + rate_idx++; + } + } + pream_table[pream_idx] = rate_idx; + pream_idx++; + + rate_code[rate_idx++] = + ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_CCK); + rate_code[rate_idx++] = + ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM); + rate_code[rate_idx++] = + ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_CCK); + rate_code[rate_idx++] = + ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM); + rate_code[rate_idx++] = + ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM); + + pream_table[pream_idx] = ATH10K_TPC_PREAM_TABLE_END; + + tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq); + tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode); + tpc_stats->ctl = __le32_to_cpu(ev->ctl); + tpc_stats->reg_domain = __le32_to_cpu(ev->reg_domain); + tpc_stats->twice_antenna_gain = a_sle32_to_cpu(ev->twice_antenna_gain); + tpc_stats->twice_antenna_reduction = + __le32_to_cpu(ev->twice_antenna_reduction); + tpc_stats->power_limit = __le32_to_cpu(ev->power_limit); + tpc_stats->twice_max_rd_power = __le32_to_cpu(ev->twice_max_rd_power); + tpc_stats->num_tx_chain = __le32_to_cpu(ev->num_tx_chain); + tpc_stats->rate_max = __le32_to_cpu(ev->rate_max); + + ath10k_tpc_config_disp_tables(ar, ev, tpc_stats, + rate_code, pream_table, + WMI_TPC_TABLE_TYPE_CDD); + ath10k_tpc_config_disp_tables(ar, ev, tpc_stats, + rate_code, pream_table, + WMI_TPC_TABLE_TYPE_STBC); + ath10k_tpc_config_disp_tables(ar, ev, tpc_stats, + rate_code, pream_table, + WMI_TPC_TABLE_TYPE_TXBF); + + ath10k_debug_tpc_stats_process(ar, tpc_stats); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi event tpc config channel %d mode %d ctl %d regd %d gain %d %d limit %d max_power %d tx_chanins %d rates %d\n", + __le32_to_cpu(ev->chan_freq), + __le32_to_cpu(ev->phy_mode), + __le32_to_cpu(ev->ctl), + __le32_to_cpu(ev->reg_domain), + a_sle32_to_cpu(ev->twice_antenna_gain), + __le32_to_cpu(ev->twice_antenna_reduction), + __le32_to_cpu(ev->power_limit), + __le32_to_cpu(ev->twice_max_rd_power) / 2, + __le32_to_cpu(ev->num_tx_chain), + __le32_to_cpu(ev->rate_max)); } void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, struct sk_buff *skb) @@ -3917,6 +4289,53 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id, return 0; } +static bool +ath10k_wmi_is_host_mem_allocated(struct ath10k *ar, + const struct wlan_host_mem_req **mem_reqs, + u32 num_mem_reqs) +{ + u32 req_id, num_units, unit_size, num_unit_info; + u32 pool_size; + int i, j; + bool found; + + if (ar->wmi.num_mem_chunks != num_mem_reqs) + return false; + + for (i = 0; i < num_mem_reqs; ++i) { + req_id = __le32_to_cpu(mem_reqs[i]->req_id); + num_units = __le32_to_cpu(mem_reqs[i]->num_units); + unit_size = __le32_to_cpu(mem_reqs[i]->unit_size); + num_unit_info = __le32_to_cpu(mem_reqs[i]->num_unit_info); + + if (num_unit_info & NUM_UNITS_IS_NUM_ACTIVE_PEERS) { + if (ar->num_active_peers) + num_units = ar->num_active_peers + 1; + else + num_units = ar->max_num_peers + 1; + } else if (num_unit_info & NUM_UNITS_IS_NUM_PEERS) { + num_units = ar->max_num_peers + 1; + } else if (num_unit_info & NUM_UNITS_IS_NUM_VDEVS) { + num_units = ar->max_num_vdevs + 1; + } + + found = false; + for (j = 0; j < ar->wmi.num_mem_chunks; j++) { + if (ar->wmi.mem_chunks[j].req_id == req_id) { + pool_size = num_units * round_up(unit_size, 4); + if (ar->wmi.mem_chunks[j].len == pool_size) { + found = true; + break; + } + } + } + if (!found) + return false; + } + + return true; +} + static int ath10k_wmi_main_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb, struct wmi_svc_rdy_ev_arg *arg) @@ -3997,6 +4416,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) struct wmi_svc_rdy_ev_arg arg = {}; u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i; int ret; + bool allocated; if (!skb) { ath10k_warn(ar, "invalid service ready event skb\n"); @@ -4040,8 +4460,10 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) ar->num_rf_chains = ar->max_spatial_stream; } - ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1; - ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1; + if (!ar->cfg_tx_chainmask) { + ar->cfg_tx_chainmask = (1 << ar->num_rf_chains) - 1; + ar->cfg_rx_chainmask = (1 << ar->num_rf_chains) - 1; + } if (strlen(ar->hw->wiphy->fw_version) == 0) { snprintf(ar->hw->wiphy->fw_version, @@ -4073,6 +4495,18 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) * and WMI_SERVICE_IRAM_TIDS, etc. */ + allocated = ath10k_wmi_is_host_mem_allocated(ar, arg.mem_reqs, + num_mem_reqs); + if (allocated) + goto skip_mem_alloc; + + /* Either this event is received during boot time or there is a change + * in memory requirement from firmware when compared to last request. + * Free any old memory and do a fresh allocation based on the current + * memory requirement. + */ + ath10k_wmi_free_host_mem(ar); + for (i = 0; i < num_mem_reqs; ++i) { req_id = __le32_to_cpu(arg.mem_reqs[i]->req_id); num_units = __le32_to_cpu(arg.mem_reqs[i]->num_units); @@ -4108,6 +4542,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) return; } +skip_mem_alloc: ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x fw_build 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n", __le32_to_cpu(arg.min_tx_power), @@ -4623,6 +5058,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb) ath10k_dbg(ar, ATH10K_DBG_WMI, "received event id %d not implemented\n", id); break; + case WMI_10_4_UPDATE_STATS_EVENTID: + ath10k_wmi_event_update_stats(ar, skb); + break; default: ath10k_warn(ar, "Unknown eventid: %d\n", id); break; @@ -5029,7 +5467,7 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar) config.rx_timeout_pri[2] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_LO_PRI); config.rx_timeout_pri[3] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_HI_PRI); - config.rx_decap_mode = __cpu_to_le32(TARGET_10_4_RX_DECAP_MODE); + config.rx_decap_mode = __cpu_to_le32(ar->wmi.rx_decap_mode); config.scan_max_pending_req = __cpu_to_le32(TARGET_10_4_SCAN_MAX_REQS); config.bmiss_offload_max_vdev = __cpu_to_le32(TARGET_10_4_BMISS_OFFLOAD_MAX_VDEV); @@ -6295,6 +6733,505 @@ ath10k_wmi_op_gen_delba_send(struct ath10k *ar, u32 vdev_id, const u8 *mac, return skb; } +static struct sk_buff * +ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config(struct ath10k *ar, u32 param) +{ + struct wmi_pdev_get_tpc_config_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); + if (!skb) + return ERR_PTR(-ENOMEM); + + cmd = (struct wmi_pdev_get_tpc_config_cmd *)skb->data; + cmd->param = __cpu_to_le32(param); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi pdev get tcp config param:%d\n", param); + return skb; +} + +size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head) +{ + struct ath10k_fw_stats_peer *i; + size_t num = 0; + + list_for_each_entry(i, head, list) + ++num; + + return num; +} + +size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head) +{ + struct ath10k_fw_stats_vdev *i; + size_t num = 0; + + list_for_each_entry(i, head, list) + ++num; + + return num; +} + +static void +ath10k_wmi_fw_pdev_base_stats_fill(const struct ath10k_fw_stats_pdev *pdev, + char *buf, u32 *length) +{ + u32 len = *length; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s\n", + "ath10k PDEV stats"); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Channel noise floor", pdev->ch_noise_floor); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "Channel TX power", pdev->chan_tx_power); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "TX frame count", pdev->tx_frame_count); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "RX frame count", pdev->rx_frame_count); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "RX clear count", pdev->rx_clear_count); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "Cycle count", pdev->cycle_count); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "PHY error count", pdev->phy_err_count); + + *length = len; +} + +static void +ath10k_wmi_fw_pdev_extra_stats_fill(const struct ath10k_fw_stats_pdev *pdev, + char *buf, u32 *length) +{ + u32 len = *length; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "RTS bad count", pdev->rts_bad); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "RTS good count", pdev->rts_good); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "FCS bad count", pdev->fcs_bad); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "No beacon count", pdev->no_beacons); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "MIB int count", pdev->mib_int_count); + + len += scnprintf(buf + len, buf_len - len, "\n"); + *length = len; +} + +static void +ath10k_wmi_fw_pdev_tx_stats_fill(const struct ath10k_fw_stats_pdev *pdev, + char *buf, u32 *length) +{ + u32 len = *length; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + + len += scnprintf(buf + len, buf_len - len, "\n%30s\n", + "ath10k PDEV TX stats"); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "HTT cookies queued", pdev->comp_queued); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "HTT cookies disp.", pdev->comp_delivered); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MSDU queued", pdev->msdu_enqued); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDU queued", pdev->mpdu_enqued); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MSDUs dropped", pdev->wmm_drop); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Local enqued", pdev->local_enqued); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Local freed", pdev->local_freed); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "HW queued", pdev->hw_queued); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PPDUs reaped", pdev->hw_reaped); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Num underruns", pdev->underrun); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PPDUs cleaned", pdev->tx_abort); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs requed", pdev->mpdus_requed); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Excessive retries", pdev->tx_ko); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "HW rate", pdev->data_rc); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Sched self tiggers", pdev->self_triggers); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Dropped due to SW retries", + pdev->sw_retry_failure); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Illegal rate phy errors", + pdev->illgl_rate_phy_err); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Pdev continuous xretry", pdev->pdev_cont_xretry); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "TX timeout", pdev->pdev_tx_timeout); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PDEV resets", pdev->pdev_resets); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PHY underrun", pdev->phy_underrun); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDU is more than txop limit", pdev->txop_ovf); + *length = len; +} + +static void +ath10k_wmi_fw_pdev_rx_stats_fill(const struct ath10k_fw_stats_pdev *pdev, + char *buf, u32 *length) +{ + u32 len = *length; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + + len += scnprintf(buf + len, buf_len - len, "\n%30s\n", + "ath10k PDEV RX stats"); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Mid PPDU route change", + pdev->mid_ppdu_route_change); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Tot. number of statuses", pdev->status_rcvd); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Extra frags on rings 0", pdev->r0_frags); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Extra frags on rings 1", pdev->r1_frags); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Extra frags on rings 2", pdev->r2_frags); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Extra frags on rings 3", pdev->r3_frags); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MSDUs delivered to HTT", pdev->htt_msdus); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs delivered to HTT", pdev->htt_mpdus); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MSDUs delivered to stack", pdev->loc_msdus); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs delivered to stack", pdev->loc_mpdus); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Oversized AMSUs", pdev->oversize_amsdu); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PHY errors", pdev->phy_errs); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PHY errors drops", pdev->phy_err_drop); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs); + *length = len; +} + +static void +ath10k_wmi_fw_vdev_stats_fill(const struct ath10k_fw_stats_vdev *vdev, + char *buf, u32 *length) +{ + u32 len = *length; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + int i; + + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "vdev id", vdev->vdev_id); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "beacon snr", vdev->beacon_snr); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "data snr", vdev->data_snr); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "num rx frames", vdev->num_rx_frames); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "num rts fail", vdev->num_rts_fail); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "num rts success", vdev->num_rts_success); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "num rx err", vdev->num_rx_err); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "num rx discard", vdev->num_rx_discard); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "num tx not acked", vdev->num_tx_not_acked); + + for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames); i++) + len += scnprintf(buf + len, buf_len - len, + "%25s [%02d] %u\n", + "num tx frames", i, + vdev->num_tx_frames[i]); + + for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_retries); i++) + len += scnprintf(buf + len, buf_len - len, + "%25s [%02d] %u\n", + "num tx frames retries", i, + vdev->num_tx_frames_retries[i]); + + for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_failures); i++) + len += scnprintf(buf + len, buf_len - len, + "%25s [%02d] %u\n", + "num tx frames failures", i, + vdev->num_tx_frames_failures[i]); + + for (i = 0 ; i < ARRAY_SIZE(vdev->tx_rate_history); i++) + len += scnprintf(buf + len, buf_len - len, + "%25s [%02d] 0x%08x\n", + "tx rate history", i, + vdev->tx_rate_history[i]); + + for (i = 0 ; i < ARRAY_SIZE(vdev->beacon_rssi_history); i++) + len += scnprintf(buf + len, buf_len - len, + "%25s [%02d] %u\n", + "beacon rssi history", i, + vdev->beacon_rssi_history[i]); + + len += scnprintf(buf + len, buf_len - len, "\n"); + *length = len; +} + +static void +ath10k_wmi_fw_peer_stats_fill(const struct ath10k_fw_stats_peer *peer, + char *buf, u32 *length) +{ + u32 len = *length; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + + len += scnprintf(buf + len, buf_len - len, "%30s %pM\n", + "Peer MAC address", peer->peer_macaddr); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "Peer RSSI", peer->peer_rssi); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "Peer TX rate", peer->peer_tx_rate); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "Peer RX rate", peer->peer_rx_rate); + len += scnprintf(buf + len, buf_len - len, "\n"); + *length = len; +} + +void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf) +{ + u32 len = 0; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + const struct ath10k_fw_stats_pdev *pdev; + const struct ath10k_fw_stats_vdev *vdev; + const struct ath10k_fw_stats_peer *peer; + size_t num_peers; + size_t num_vdevs; + + spin_lock_bh(&ar->data_lock); + + pdev = list_first_entry_or_null(&fw_stats->pdevs, + struct ath10k_fw_stats_pdev, list); + if (!pdev) { + ath10k_warn(ar, "failed to get pdev stats\n"); + goto unlock; + } + + num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers); + num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs); + + ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len); + ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len); + ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len); + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", + "ath10k VDEV stats", num_vdevs); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + list_for_each_entry(vdev, &fw_stats->vdevs, list) { + ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len); + } + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", + "ath10k PEER stats", num_peers); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + list_for_each_entry(peer, &fw_stats->peers, list) { + ath10k_wmi_fw_peer_stats_fill(peer, buf, &len); + } + +unlock: + spin_unlock_bh(&ar->data_lock); + + if (len >= buf_len) + buf[len - 1] = 0; + else + buf[len] = 0; +} + +void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf) +{ + unsigned int len = 0; + unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE; + const struct ath10k_fw_stats_pdev *pdev; + const struct ath10k_fw_stats_vdev *vdev; + const struct ath10k_fw_stats_peer *peer; + size_t num_peers; + size_t num_vdevs; + + spin_lock_bh(&ar->data_lock); + + pdev = list_first_entry_or_null(&fw_stats->pdevs, + struct ath10k_fw_stats_pdev, list); + if (!pdev) { + ath10k_warn(ar, "failed to get pdev stats\n"); + goto unlock; + } + + num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers); + num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs); + + ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len); + ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len); + ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len); + ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len); + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", + "ath10k VDEV stats", num_vdevs); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + list_for_each_entry(vdev, &fw_stats->vdevs, list) { + ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len); + } + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", + "ath10k PEER stats", num_peers); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + list_for_each_entry(peer, &fw_stats->peers, list) { + ath10k_wmi_fw_peer_stats_fill(peer, buf, &len); + } + +unlock: + spin_unlock_bh(&ar->data_lock); + + if (len >= buf_len) + buf[len - 1] = 0; + else + buf[len] = 0; +} + +static struct sk_buff * +ath10k_wmi_op_gen_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable, + u32 detect_level, u32 detect_margin) +{ + struct wmi_pdev_set_adaptive_cca_params *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); + if (!skb) + return ERR_PTR(-ENOMEM); + + cmd = (struct wmi_pdev_set_adaptive_cca_params *)skb->data; + cmd->enable = __cpu_to_le32(enable); + cmd->cca_detect_level = __cpu_to_le32(detect_level); + cmd->cca_detect_margin = __cpu_to_le32(detect_margin); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi pdev set adaptive cca params enable:%d detection level:%d detection margin:%d\n", + enable, detect_level, detect_margin); + return skb; +} + +void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf) +{ + u32 len = 0; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + const struct ath10k_fw_stats_pdev *pdev; + const struct ath10k_fw_stats_vdev *vdev; + const struct ath10k_fw_stats_peer *peer; + size_t num_peers; + size_t num_vdevs; + + spin_lock_bh(&ar->data_lock); + + pdev = list_first_entry_or_null(&fw_stats->pdevs, + struct ath10k_fw_stats_pdev, list); + if (!pdev) { + ath10k_warn(ar, "failed to get pdev stats\n"); + goto unlock; + } + + num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers); + num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs); + + ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len); + ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len); + ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len); + + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "HW paused", pdev->hw_paused); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Seqs posted", pdev->seq_posted); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Seqs failed queueing", pdev->seq_failed_queueing); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Seqs completed", pdev->seq_completed); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Seqs restarted", pdev->seq_restarted); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MU Seqs posted", pdev->mu_seq_posted); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs SW flushed", pdev->mpdus_sw_flush); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs HW filtered", pdev->mpdus_hw_filter); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs truncated", pdev->mpdus_truncated); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs receive no ACK", pdev->mpdus_ack_failed); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs expired", pdev->mpdus_expired); + + ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Num Rx Overflow errors", pdev->rx_ovfl_errs); + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", + "ath10k VDEV stats", num_vdevs); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + list_for_each_entry(vdev, &fw_stats->vdevs, list) { + ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len); + } + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", + "ath10k PEER stats", num_peers); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + list_for_each_entry(peer, &fw_stats->peers, list) { + ath10k_wmi_fw_peer_stats_fill(peer, buf, &len); + } + +unlock: + spin_unlock_bh(&ar->data_lock); + + if (len >= buf_len) + buf[len - 1] = 0; + else + buf[len] = 0; +} + static const struct wmi_ops wmi_ops = { .rx = ath10k_wmi_op_rx, .map_svc = wmi_main_svc_map, @@ -6353,10 +7290,12 @@ static const struct wmi_ops wmi_ops = { .gen_addba_send = ath10k_wmi_op_gen_addba_send, .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, + .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ /* .gen_adaptive_qcs not implemented */ + /* .gen_pdev_enable_adaptive_cca not implemented */ }; static const struct wmi_ops wmi_10_1_ops = { @@ -6418,10 +7357,12 @@ static const struct wmi_ops wmi_10_1_ops = { .gen_addba_send = ath10k_wmi_op_gen_addba_send, .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, + .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ /* .gen_adaptive_qcs not implemented */ + /* .gen_pdev_enable_adaptive_cca not implemented */ }; static const struct wmi_ops wmi_10_2_ops = { @@ -6484,6 +7425,8 @@ static const struct wmi_ops wmi_10_2_ops = { .gen_addba_send = ath10k_wmi_op_gen_addba_send, .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, + .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, + /* .gen_pdev_enable_adaptive_cca not implemented */ }; static const struct wmi_ops wmi_10_2_4_ops = { @@ -6545,6 +7488,10 @@ static const struct wmi_ops wmi_10_2_4_ops = { .gen_addba_send = ath10k_wmi_op_gen_addba_send, .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, + .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config, + .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, + .gen_pdev_enable_adaptive_cca = + ath10k_wmi_op_gen_pdev_enable_adaptive_cca, /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ @@ -6555,6 +7502,7 @@ static const struct wmi_ops wmi_10_4_ops = { .rx = ath10k_wmi_10_4_op_rx, .map_svc = wmi_10_4_svc_map, + .pull_fw_stats = ath10k_wmi_10_4_op_pull_fw_stats, .pull_scan = ath10k_wmi_op_pull_scan_ev, .pull_mgmt_rx = ath10k_wmi_10_4_op_pull_mgmt_rx_ev, .pull_ch_info = ath10k_wmi_10_4_op_pull_ch_info_ev, @@ -6604,9 +7552,11 @@ static const struct wmi_ops wmi_10_4_ops = { .gen_addba_send = ath10k_wmi_op_gen_addba_send, .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, + .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill, /* shared with 10.2 */ .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc, + .gen_request_stats = ath10k_wmi_op_gen_request_stats, }; int ath10k_wmi_attach(struct ath10k *ar) @@ -6660,15 +7610,10 @@ int ath10k_wmi_attach(struct ath10k *ar) return 0; } -void ath10k_wmi_detach(struct ath10k *ar) +void ath10k_wmi_free_host_mem(struct ath10k *ar) { int i; - cancel_work_sync(&ar->svc_rdy_work); - - if (ar->svc_rdy_skb) - dev_kfree_skb(ar->svc_rdy_skb); - /* free the host memory chunks requested by firmware */ for (i = 0; i < ar->wmi.num_mem_chunks; i++) { dma_free_coherent(ar->dev, @@ -6679,3 +7624,11 @@ void ath10k_wmi_detach(struct ath10k *ar) ar->wmi.num_mem_chunks = 0; } + +void ath10k_wmi_detach(struct ath10k *ar) +{ + cancel_work_sync(&ar->svc_rdy_work); + + if (ar->svc_rdy_skb) + dev_kfree_skb(ar->svc_rdy_skb); +} diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 52d35032d53e..72a4ef709577 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -73,6 +73,25 @@ struct wmi_cmd_hdr { #define HTC_PROTOCOL_VERSION 0x0002 #define WMI_PROTOCOL_VERSION 0x0002 +/* + * There is no signed version of __le32, so for a temporary solution come + * up with our own version. The idea is from fs/ntfs/types.h. + * + * Use a_ prefix so that it doesn't conflict if we get proper support to + * linux/types.h. + */ +typedef __s32 __bitwise a_sle32; + +static inline a_sle32 a_cpu_to_sle32(s32 val) +{ + return (__force a_sle32)cpu_to_le32(val); +} + +static inline s32 a_sle32_to_cpu(a_sle32 val) +{ + return le32_to_cpu((__force __le32)val); +} + enum wmi_service { WMI_SERVICE_BEACON_OFFLOAD = 0, WMI_SERVICE_SCAN_OFFLOAD, @@ -753,6 +772,7 @@ struct wmi_cmd_map { u32 mu_cal_start_cmdid; u32 set_cca_params_cmdid; u32 pdev_bss_chan_info_request_cmdid; + u32 pdev_enable_adaptive_cca_cmdid; }; /* @@ -1362,6 +1382,9 @@ enum wmi_10_2_cmd_id { WMI_10_2_VDEV_ATF_REQUEST_CMDID, WMI_10_2_PEER_ATF_REQUEST_CMDID, WMI_10_2_PDEV_GET_TEMPERATURE_CMDID, + WMI_10_2_MU_CAL_START_CMDID, + WMI_10_2_SET_LTEU_CONFIG_CMDID, + WMI_10_2_SET_CCA_PARAMS, WMI_10_2_PDEV_UTF_CMDID = WMI_10_2_END_CMDID - 1, }; @@ -3642,8 +3665,18 @@ struct wmi_pdev_get_tpc_config_cmd { __le32 param; } __packed; +#define WMI_TPC_CONFIG_PARAM 1 #define WMI_TPC_RATE_MAX 160 #define WMI_TPC_TX_N_CHAIN 4 +#define WMI_TPC_PREAM_TABLE_MAX 10 +#define WMI_TPC_FLAG 3 +#define WMI_TPC_BUF_SIZE 10 + +enum wmi_tpc_table_type { + WMI_TPC_TABLE_TYPE_CDD = 0, + WMI_TPC_TABLE_TYPE_STBC = 1, + WMI_TPC_TABLE_TYPE_TXBF = 2, +}; enum wmi_tpc_config_event_flag { WMI_TPC_CONFIG_EVENT_FLAG_TABLE_CDD = 0x1, @@ -3657,7 +3690,7 @@ struct wmi_pdev_tpc_config_event { __le32 phy_mode; __le32 twice_antenna_reduction; __le32 twice_max_rd_power; - s32 twice_antenna_gain; + a_sle32 twice_antenna_gain; __le32 power_limit; __le32 rate_max; __le32 num_tx_chain; @@ -3833,6 +3866,111 @@ struct wmi_pdev_stats_tx { __le32 txop_ovf; } __packed; +struct wmi_10_4_pdev_stats_tx { + /* Num HTT cookies queued to dispatch list */ + __le32 comp_queued; + + /* Num HTT cookies dispatched */ + __le32 comp_delivered; + + /* Num MSDU queued to WAL */ + __le32 msdu_enqued; + + /* Num MPDU queue to WAL */ + __le32 mpdu_enqued; + + /* Num MSDUs dropped by WMM limit */ + __le32 wmm_drop; + + /* Num Local frames queued */ + __le32 local_enqued; + + /* Num Local frames done */ + __le32 local_freed; + + /* Num queued to HW */ + __le32 hw_queued; + + /* Num PPDU reaped from HW */ + __le32 hw_reaped; + + /* Num underruns */ + __le32 underrun; + + /* HW Paused. */ + __le32 hw_paused; + + /* Num PPDUs cleaned up in TX abort */ + __le32 tx_abort; + + /* Num MPDUs requed by SW */ + __le32 mpdus_requed; + + /* excessive retries */ + __le32 tx_ko; + + /* data hw rate code */ + __le32 data_rc; + + /* Scheduler self triggers */ + __le32 self_triggers; + + /* frames dropped due to excessive sw retries */ + __le32 sw_retry_failure; + + /* illegal rate phy errors */ + __le32 illgl_rate_phy_err; + + /* wal pdev continuous xretry */ + __le32 pdev_cont_xretry; + + /* wal pdev tx timeouts */ + __le32 pdev_tx_timeout; + + /* wal pdev resets */ + __le32 pdev_resets; + + /* frames dropped due to non-availability of stateless TIDs */ + __le32 stateless_tid_alloc_failure; + + __le32 phy_underrun; + + /* MPDU is more than txop limit */ + __le32 txop_ovf; + + /* Number of Sequences posted */ + __le32 seq_posted; + + /* Number of Sequences failed queueing */ + __le32 seq_failed_queueing; + + /* Number of Sequences completed */ + __le32 seq_completed; + + /* Number of Sequences restarted */ + __le32 seq_restarted; + + /* Number of MU Sequences posted */ + __le32 mu_seq_posted; + + /* Num MPDUs flushed by SW, HWPAUSED,SW TXABORT(Reset,channel change) */ + __le32 mpdus_sw_flush; + + /* Num MPDUs filtered by HW, all filter condition (TTL expired) */ + __le32 mpdus_hw_filter; + + /* Num MPDUs truncated by PDG + * (TXOP, TBTT, PPDU_duration based on rate, dyn_bw) + */ + __le32 mpdus_truncated; + + /* Num MPDUs that was tried but didn't receive ACK or BA */ + __le32 mpdus_ack_failed; + + /* Num MPDUs that was dropped due to expiry. */ + __le32 mpdus_expired; +} __packed; + struct wmi_pdev_stats_rx { /* Cnts any change in ring routing mid-ppdu */ __le32 mid_ppdu_route_change; @@ -4006,6 +4144,16 @@ struct wmi_10_2_pdev_stats { struct wmi_pdev_stats_extra extra; } __packed; +struct wmi_10_4_pdev_stats { + struct wmi_pdev_stats_base base; + struct wmi_10_4_pdev_stats_tx tx; + struct wmi_pdev_stats_rx rx; + __le32 rx_ovfl_errs; + struct wmi_pdev_stats_mem mem; + __le32 sram_free_size; + struct wmi_pdev_stats_extra extra; +} __packed; + /* * VDEV statistics * TODO: add all VDEV stats here @@ -4047,6 +4195,23 @@ struct wmi_10_2_4_peer_stats { __le32 unknown_value; /* FIXME: what is this word? */ } __packed; +struct wmi_10_4_peer_stats { + struct wmi_mac_addr peer_macaddr; + __le32 peer_rssi; + __le32 peer_rssi_seq_num; + __le32 peer_tx_rate; + __le32 peer_rx_rate; + __le32 current_per; + __le32 retries; + __le32 tx_rate_count; + __le32 max_4ms_frame_len; + __le32 total_sub_frames; + __le32 tx_bytes; + __le32 num_pkt_loss_overflow[4]; + __le32 num_pkt_loss_excess_retry[4]; + __le32 peer_rssi_changed; +} __packed; + struct wmi_10_2_pdev_ext_stats { __le32 rx_rssi_comb; __le32 rx_rssi[4]; @@ -4253,6 +4418,11 @@ enum wmi_rate_preamble { WMI_RATE_PREAMBLE_VHT, }; +#define ATH10K_HW_NSS(rate) (1 + (((rate) >> 4) & 0x3)) +#define ATH10K_HW_PREAMBLE(rate) (((rate) >> 6) & 0x3) +#define ATH10K_HW_RATECODE(rate, nss, preamble) \ + (((preamble) << 6) | ((nss) << 4) | (rate)) + /* Value to disable fixed rate setting */ #define WMI_FIXED_RATE_NONE (0xff) @@ -6060,13 +6230,24 @@ enum wmi_txbf_conf { WMI_TXBF_CONF_AFTER_ASSOC, }; +#define WMI_CCA_DETECT_LEVEL_AUTO 0 +#define WMI_CCA_DETECT_MARGIN_AUTO 0 + +struct wmi_pdev_set_adaptive_cca_params { + __le32 enable; + __le32 cca_detect_level; + __le32 cca_detect_margin; +} __packed; + struct ath10k; struct ath10k_vif; struct ath10k_fw_stats_pdev; struct ath10k_fw_stats_peer; +struct ath10k_fw_stats; int ath10k_wmi_attach(struct ath10k *ar); void ath10k_wmi_detach(struct ath10k *ar); +void ath10k_wmi_free_host_mem(struct ath10k *ar); int ath10k_wmi_wait_for_service_ready(struct ath10k *ar); int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar); @@ -6144,4 +6325,16 @@ void ath10k_wmi_event_service_ready(struct ath10k *ar, struct sk_buff *skb); int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb); int ath10k_wmi_op_pull_phyerr_ev(struct ath10k *ar, const void *phyerr_buf, int left_len, struct wmi_phyerr_ev_arg *arg); +void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf); +void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf); +size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head); +size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head); +void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf); + #endif /* _WMI_H_ */ diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index a511ef3614b9..81ac8c59f0ec 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2217,7 +2217,7 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) /* enter / leave wow suspend on first vif always */ first_vif = ath6kl_vif_first(ar); - if (WARN_ON(unlikely(!first_vif)) || + if (WARN_ON(!first_vif) || !ath6kl_cfg80211_ready(first_vif)) return -EIO; @@ -2297,7 +2297,7 @@ static int ath6kl_wow_resume(struct ath6kl *ar) int ret; vif = ath6kl_vif_first(ar); - if (WARN_ON(unlikely(!vif)) || + if (WARN_ON(!vif) || !ath6kl_cfg80211_ready(vif)) return -EIO; @@ -3231,6 +3231,15 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, wait, buf, len, no_cck); } +static int ath6kl_get_antenna(struct wiphy *wiphy, + u32 *tx_ant, u32 *rx_ant) +{ + struct ath6kl *ar = wiphy_priv(wiphy); + *tx_ant = ar->hw.tx_ant; + *rx_ant = ar->hw.rx_ant; + return 0; +} + static void ath6kl_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, u16 frame_type, bool reg) @@ -3312,7 +3321,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, } /* fw uses seconds, also make sure that it's >0 */ - interval = max_t(u16, 1, request->interval / 1000); + interval = max_t(u16, 1, request->scan_plans[0].interval); ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, interval, interval, @@ -3447,6 +3456,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel, .mgmt_tx = ath6kl_mgmt_tx, .mgmt_frame_register = ath6kl_mgmt_frame_register, + .get_antenna = ath6kl_get_antenna, .sched_scan_start = ath6kl_cfg80211_sscan_start, .sched_scan_stop = ath6kl_cfg80211_sscan_stop, .set_bitrate_mask = ath6kl_cfg80211_set_bitrate, @@ -3634,6 +3644,127 @@ void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif) ar->num_vif--; } +static const char ath6kl_gstrings_sta_stats[][ETH_GSTRING_LEN] = { + /* Common stats names used by many drivers. */ + "tx_pkts_nic", "tx_bytes_nic", "rx_pkts_nic", "rx_bytes_nic", + + /* TX stats. */ + "d_tx_ucast_pkts", "d_tx_bcast_pkts", + "d_tx_ucast_bytes", "d_tx_bcast_bytes", + "d_tx_rts_ok", "d_tx_error", "d_tx_fail", + "d_tx_retry", "d_tx_multi_retry", "d_tx_rts_fail", + "d_tx_tkip_counter_measures", + + /* RX Stats. */ + "d_rx_ucast_pkts", "d_rx_ucast_rate", "d_rx_bcast_pkts", + "d_rx_ucast_bytes", "d_rx_bcast_bytes", "d_rx_frag_pkt", + "d_rx_error", "d_rx_crc_err", "d_rx_keycache_miss", + "d_rx_decrypt_crc_err", "d_rx_duplicate_frames", + "d_rx_mic_err", "d_rx_tkip_format_err", "d_rx_ccmp_format_err", + "d_rx_ccmp_replay_err", + + /* Misc stats. */ + "d_beacon_miss", "d_num_connects", "d_num_disconnects", + "d_beacon_avg_rssi", "d_arp_received", "d_arp_matched", + "d_arp_replied" +}; + +#define ATH6KL_STATS_LEN ARRAY_SIZE(ath6kl_gstrings_sta_stats) + +static int ath6kl_get_sset_count(struct net_device *dev, int sset) +{ + int rv = 0; + + if (sset == ETH_SS_STATS) + rv += ATH6KL_STATS_LEN; + + if (rv == 0) + return -EOPNOTSUPP; + return rv; +} + +static void ath6kl_get_stats(struct net_device *dev, + struct ethtool_stats *stats, + u64 *data) +{ + struct ath6kl_vif *vif = netdev_priv(dev); + struct ath6kl *ar = vif->ar; + int i = 0; + struct target_stats *tgt_stats; + + memset(data, 0, sizeof(u64) * ATH6KL_STATS_LEN); + + ath6kl_read_tgt_stats(ar, vif); + + tgt_stats = &vif->target_stats; + + data[i++] = tgt_stats->tx_ucast_pkt + tgt_stats->tx_bcast_pkt; + data[i++] = tgt_stats->tx_ucast_byte + tgt_stats->tx_bcast_byte; + data[i++] = tgt_stats->rx_ucast_pkt + tgt_stats->rx_bcast_pkt; + data[i++] = tgt_stats->rx_ucast_byte + tgt_stats->rx_bcast_byte; + + data[i++] = tgt_stats->tx_ucast_pkt; + data[i++] = tgt_stats->tx_bcast_pkt; + data[i++] = tgt_stats->tx_ucast_byte; + data[i++] = tgt_stats->tx_bcast_byte; + data[i++] = tgt_stats->tx_rts_success_cnt; + data[i++] = tgt_stats->tx_err; + data[i++] = tgt_stats->tx_fail_cnt; + data[i++] = tgt_stats->tx_retry_cnt; + data[i++] = tgt_stats->tx_mult_retry_cnt; + data[i++] = tgt_stats->tx_rts_fail_cnt; + data[i++] = tgt_stats->tkip_cnter_measures_invoked; + + data[i++] = tgt_stats->rx_ucast_pkt; + data[i++] = tgt_stats->rx_ucast_rate; + data[i++] = tgt_stats->rx_bcast_pkt; + data[i++] = tgt_stats->rx_ucast_byte; + data[i++] = tgt_stats->rx_bcast_byte; + data[i++] = tgt_stats->rx_frgment_pkt; + data[i++] = tgt_stats->rx_err; + data[i++] = tgt_stats->rx_crc_err; + data[i++] = tgt_stats->rx_key_cache_miss; + data[i++] = tgt_stats->rx_decrypt_err; + data[i++] = tgt_stats->rx_dupl_frame; + data[i++] = tgt_stats->tkip_local_mic_fail; + data[i++] = tgt_stats->tkip_fmt_err; + data[i++] = tgt_stats->ccmp_fmt_err; + data[i++] = tgt_stats->ccmp_replays; + + data[i++] = tgt_stats->cs_bmiss_cnt; + data[i++] = tgt_stats->cs_connect_cnt; + data[i++] = tgt_stats->cs_discon_cnt; + data[i++] = tgt_stats->cs_ave_beacon_rssi; + data[i++] = tgt_stats->arp_received; + data[i++] = tgt_stats->arp_matched; + data[i++] = tgt_stats->arp_replied; + + if (i != ATH6KL_STATS_LEN) { + WARN_ON_ONCE(1); + ath6kl_err("ethtool stats error, i: %d STATS_LEN: %d\n", + i, (int)ATH6KL_STATS_LEN); + } +} + +/* These stats are per NIC, not really per vdev, so we just ignore dev. */ +static void ath6kl_get_strings(struct net_device *dev, u32 sset, u8 *data) +{ + int sz_sta_stats = 0; + + if (sset == ETH_SS_STATS) { + sz_sta_stats = sizeof(ath6kl_gstrings_sta_stats); + memcpy(data, ath6kl_gstrings_sta_stats, sz_sta_stats); + } +} + +static const struct ethtool_ops ath6kl_ethtool_ops = { + .get_drvinfo = cfg80211_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_strings = ath6kl_get_strings, + .get_ethtool_stats = ath6kl_get_stats, + .get_sset_count = ath6kl_get_sset_count, +}; + struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, unsigned char name_assign_type, enum nl80211_iftype type, @@ -3679,6 +3810,8 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, if (ath6kl_cfg80211_vif_init(vif)) goto err; + netdev_set_default_ethtool_ops(ndev, &ath6kl_ethtool_ops); + if (register_netdevice(ndev)) goto err; @@ -3786,6 +3919,9 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) ath6kl_band_2ghz.ht_cap.ht_supported = false; ath6kl_band_5ghz.ht_cap.cap = 0; ath6kl_band_5ghz.ht_cap.ht_supported = false; + + if (ht) + ath6kl_err("Firmware lacks RSN-CAP-OVERRIDE, so HT (802.11n) is disabled."); } if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES, @@ -3794,11 +3930,18 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff; ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff; + ar->hw.tx_ant = 2; + ar->hw.rx_ant = 2; } else { ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; + ar->hw.tx_ant = 1; + ar->hw.rx_ant = 1; } + wiphy->available_antennas_tx = ar->hw.tx_ant; + wiphy->available_antennas_rx = ar->hw.rx_ant; + if (band_2gig) wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; if (band_5gig) diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 2b78c863d030..5f3acfe6015e 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -782,6 +782,8 @@ struct ath6kl { u32 refclk_hz; u32 uarttx_pin; u32 testscript_addr; + u8 tx_ant; + u8 rx_ant; enum wmi_phy_cap cap; u32 flags; diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 81ba48d2938b..e2b7809d7886 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -98,6 +98,33 @@ void ath6kl_warn(const char *fmt, ...) } EXPORT_SYMBOL(ath6kl_warn); +int ath6kl_read_tgt_stats(struct ath6kl *ar, struct ath6kl_vif *vif) +{ + long left; + + if (down_interruptible(&ar->sem)) + return -EBUSY; + + set_bit(STATS_UPDATE_PEND, &vif->flags); + + if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) { + up(&ar->sem); + return -EIO; + } + + left = wait_event_interruptible_timeout(ar->event_wq, + !test_bit(STATS_UPDATE_PEND, + &vif->flags), WMI_TIMEOUT); + + up(&ar->sem); + + if (left <= 0) + return -ETIMEDOUT; + + return 0; +} +EXPORT_SYMBOL(ath6kl_read_tgt_stats); + #ifdef CONFIG_ATH6KL_DEBUG void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) @@ -544,42 +571,24 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, char *buf; unsigned int len = 0, buf_len = 1500; int i; - long left; ssize_t ret_cnt; + int rv; vif = ath6kl_vif_first(ar); if (!vif) return -EIO; - tgt_stats = &vif->target_stats; - buf = kzalloc(buf_len, GFP_KERNEL); if (!buf) return -ENOMEM; - if (down_interruptible(&ar->sem)) { + rv = ath6kl_read_tgt_stats(ar, vif); + if (rv < 0) { kfree(buf); - return -EBUSY; + return rv; } - set_bit(STATS_UPDATE_PEND, &vif->flags); - - if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) { - up(&ar->sem); - kfree(buf); - return -EIO; - } - - left = wait_event_interruptible_timeout(ar->event_wq, - !test_bit(STATS_UPDATE_PEND, - &vif->flags), WMI_TIMEOUT); - - up(&ar->sem); - - if (left <= 0) { - kfree(buf); - return -ETIMEDOUT; - } + tgt_stats = &vif->target_stats; len += scnprintf(buf + len, buf_len - len, "\n"); len += scnprintf(buf + len, buf_len - len, "%25s\n", diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 19106ed28961..0614393dd7ae 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h @@ -59,6 +59,8 @@ enum ath6kl_war { ATH6KL_WAR_INVALID_RATE, }; +int ath6kl_read_tgt_stats(struct ath6kl *ar, struct ath6kl_vif *vif); + #ifdef CONFIG_ATH6KL_DEBUG void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...); diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c index e481f14b9878..fffb65b3e652 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c +++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c @@ -1085,9 +1085,7 @@ static int htc_setup_tx_complete(struct htc_target *target) send_pkt->completion = NULL; ath6kl_htc_tx_prep_pkt(send_pkt, 0, 0, 0); status = ath6kl_htc_tx_issue(target, send_pkt); - - if (send_pkt != NULL) - htc_reclaim_txctrl_buf(target, send_pkt); + htc_reclaim_txctrl_buf(target, send_pkt); return status; } diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 12241b1c57cd..6ae0734f86e0 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -995,7 +995,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) switch (ie_id) { case ATH6KL_FW_IE_FW_VERSION: strlcpy(ar->wiphy->fw_version, data, - sizeof(ar->wiphy->fw_version)); + min(sizeof(ar->wiphy->fw_version), ie_len+1)); ath6kl_dbg(ATH6KL_DBG_BOOT, "found fw version %s\n", diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index 6314ae2e93e3..9d17a5375f64 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h @@ -610,8 +610,8 @@ #define AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ -127 #define AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ -116 -#define AR_PHY_CCA_NOM_VAL_9287_2GHZ -120 +#define AR_PHY_CCA_NOM_VAL_9287_2GHZ -112 #define AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ -127 -#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ -110 +#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ -97 #endif diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 174442beb952..0c391997a2f7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -1249,7 +1249,8 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0); - if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) { + if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) || + AR_SREV_9561(ah)) { if (is_2g) REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, @@ -1640,7 +1641,8 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, skip_tx_iqcal: if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { - if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) { + if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah) || + AR_SREV_9561(ah)) { for (i = 0; i < AR9300_MAX_CHAINS; i++) { if (!(ah->rxchainmask & (1 << i))) continue; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 79fd3b2dcbde..8b238c15916d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -857,7 +857,7 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) qca956x_1p0_common_rx_gain_table); INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, qca956x_1p0_common_rx_gain_bounds); - INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + INIT_INI_ARRAY(&ah->ini_modes_rxgain_xlna, qca956x_1p0_xlna_only); } else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, @@ -942,7 +942,7 @@ static void ar9003_rx_gain_table_mode2(struct ath_hw *ah) ar9462_2p1_baseband_core_mix_rxgain); INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_postamble, ar9462_2p1_baseband_postamble_mix_rxgain); - INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + INIT_INI_ARRAY(&ah->ini_modes_rxgain_xlna, ar9462_2p1_baseband_postamble_5g_xlna); } else if (AR_SREV_9462_20(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, @@ -951,7 +951,7 @@ static void ar9003_rx_gain_table_mode2(struct ath_hw *ah) ar9462_2p0_baseband_core_mix_rxgain); INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_postamble, ar9462_2p0_baseband_postamble_mix_rxgain); - INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + INIT_INI_ARRAY(&ah->ini_modes_rxgain_xlna, ar9462_2p0_baseband_postamble_5g_xlna); } } @@ -961,12 +961,12 @@ static void ar9003_rx_gain_table_mode3(struct ath_hw *ah) if (AR_SREV_9462_21(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, ar9462_2p1_common_5g_xlna_only_rxgain); - INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + INIT_INI_ARRAY(&ah->ini_modes_rxgain_xlna, ar9462_2p1_baseband_postamble_5g_xlna); } else if (AR_SREV_9462_20(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, ar9462_2p0_common_5g_xlna_only_rxgain); - INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + INIT_INI_ARRAY(&ah->ini_modes_rxgain_xlna, ar9462_2p0_baseband_postamble_5g_xlna); } } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 1ad66b76749b..201425e7f9cb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -926,19 +926,18 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, */ if ((ar9003_hw_get_rx_gain_idx(ah) == 2) || (ar9003_hw_get_rx_gain_idx(ah) == 3)) { - REG_WRITE_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + REG_WRITE_ARRAY(&ah->ini_modes_rxgain_xlna, modesIndex, regWrites); } - - if (AR_SREV_9561(ah) && (ar9003_hw_get_rx_gain_idx(ah) == 0)) - REG_WRITE_ARRAY(&ah->ini_modes_rxgain_5g_xlna, - modesIndex, regWrites); } if (AR_SREV_9550(ah) || AR_SREV_9561(ah)) REG_WRITE_ARRAY(&ah->ini_modes_rx_gain_bounds, modesIndex, regWrites); + if (AR_SREV_9561(ah) && (ar9003_hw_get_rx_gain_idx(ah) == 0)) + REG_WRITE_ARRAY(&ah->ini_modes_rxgain_xlna, + modesIndex, regWrites); /* * TXGAIN initvals. */ diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index c85c47978e1e..b42f4a963ef4 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -635,6 +635,7 @@ struct ath9k_vif_iter_data { int nstations; /* number of station vifs */ int nwds; /* number of WDS vifs */ int nadhocs; /* number of adhoc vifs */ + int nocbs; /* number of OCB vifs */ struct ieee80211_vif *primary_sta; }; diff --git a/drivers/net/wireless/ath/ath9k/common-debug.c b/drivers/net/wireless/ath/ath9k/common-debug.c index 3b289f933405..84afcf78151f 100644 --- a/drivers/net/wireless/ath/ath9k/common-debug.c +++ b/drivers/net/wireless/ath/ath9k/common-debug.c @@ -207,6 +207,7 @@ static ssize_t read_file_phy_err(struct file *file, char __user *user_buf, PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR); PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE); PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR); + PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING); PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); @@ -214,17 +215,24 @@ static ssize_t read_file_phy_err(struct file *file, char __user *user_buf, PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP); PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE); PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART); - PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT); + + PHY_ERR("CCK-BLOCKER ERR", ATH9K_PHYERR_CCK_BLOCKER); PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING); PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC); PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL); - PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE); - PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART); PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP); + PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE); + PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART); + PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR); PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL); + PHY_ERR("HT-ZLF ERR", ATH9K_PHYERR_HT_ZLF); + + PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT); + PHY_ERR("GREEN-FIELD ERR", ATH9K_PHYERR_GREEN_FIELD); + PHY_ERR("SPECTRAL ERR", ATH9K_PHYERR_SPECTRAL); if (len > size) len = size; diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index da32c8faad94..6de64cface3c 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -741,8 +741,8 @@ static int read_file_misc(struct seq_file *file, void *data) i++, (int)(ctx->assigned), iter_data.naps, iter_data.nstations, iter_data.nmeshes, iter_data.nwds); - seq_printf(file, " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n", - iter_data.nadhocs, sc->cur_chan->nvifs, + seq_printf(file, " ADHOC: %i OCB: %i TOTAL: %hi BEACON-VIF: %hi\n", + iter_data.nadhocs, iter_data.nocbs, sc->cur_chan->nvifs, sc->nbcnvifs); } diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 10c02f5cbc5e..165dd202c365 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -17,12 +17,8 @@ #include <asm/unaligned.h> #include "htc.h" -/* identify firmware images */ -#define FIRMWARE_AR7010_1_1 "htc_7010.fw" -#define FIRMWARE_AR9271 "htc_9271.fw" - -MODULE_FIRMWARE(FIRMWARE_AR7010_1_1); -MODULE_FIRMWARE(FIRMWARE_AR9271); +MODULE_FIRMWARE(HTC_7010_MODULE_FW); +MODULE_FIRMWARE(HTC_9271_MODULE_FW); static struct usb_device_id ath9k_hif_usb_ids[] = { { USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */ @@ -1080,12 +1076,88 @@ static void ath9k_hif_usb_firmware_fail(struct hif_device_usb *hif_dev) device_unlock(parent); } +static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context); + +/* taken from iwlwifi */ +static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev, + bool first) +{ + char index[8], *chip; + int ret; + + if (first) { + if (htc_use_dev_fw) { + hif_dev->fw_minor_index = FIRMWARE_MINOR_IDX_MAX + 1; + sprintf(index, "%s", "dev"); + } else { + hif_dev->fw_minor_index = FIRMWARE_MINOR_IDX_MAX; + sprintf(index, "%d", hif_dev->fw_minor_index); + } + } else { + hif_dev->fw_minor_index--; + sprintf(index, "%d", hif_dev->fw_minor_index); + } + + /* test for FW 1.3 */ + if (MAJOR_VERSION_REQ == 1 && hif_dev->fw_minor_index == 3) { + const char *filename; + + if (IS_AR7010_DEVICE(hif_dev->usb_device_id->driver_info)) + filename = FIRMWARE_AR7010_1_1; + else + filename = FIRMWARE_AR9271; + + /* expected fw locations: + * - htc_9271.fw (stable version 1.3, depricated) + */ + snprintf(hif_dev->fw_name, sizeof(hif_dev->fw_name), + "%s", filename); + + } else if (hif_dev->fw_minor_index < FIRMWARE_MINOR_IDX_MIN) { + dev_err(&hif_dev->udev->dev, "no suitable firmware found!\n"); + + return -ENOENT; + } else { + if (IS_AR7010_DEVICE(hif_dev->usb_device_id->driver_info)) + chip = "7010"; + else + chip = "9271"; + + /* expected fw locations: + * - ath9k_htc/htc_9271-1.dev.0.fw (development version) + * - ath9k_htc/htc_9271-1.4.0.fw (stable version) + */ + snprintf(hif_dev->fw_name, sizeof(hif_dev->fw_name), + "%s/htc_%s-%d.%s.0.fw", HTC_FW_PATH, + chip, MAJOR_VERSION_REQ, index); + } + + ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name, + &hif_dev->udev->dev, GFP_KERNEL, + hif_dev, ath9k_hif_usb_firmware_cb); + if (ret) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: Async request for firmware %s failed\n", + hif_dev->fw_name); + return ret; + } + + dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", + hif_dev->fw_name); + + return ret; +} + static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context) { struct hif_device_usb *hif_dev = context; int ret; if (!fw) { + ret = ath9k_hif_request_firmware(hif_dev, false); + if (!ret) + return; + dev_err(&hif_dev->udev->dev, "ath9k_htc: Failed to get firmware %s\n", hif_dev->fw_name); @@ -1215,27 +1287,11 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, init_completion(&hif_dev->fw_done); - /* Find out which firmware to load */ - - if (IS_AR7010_DEVICE(id->driver_info)) - hif_dev->fw_name = FIRMWARE_AR7010_1_1; - else - hif_dev->fw_name = FIRMWARE_AR9271; - - ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name, - &hif_dev->udev->dev, GFP_KERNEL, - hif_dev, ath9k_hif_usb_firmware_cb); - if (ret) { - dev_err(&hif_dev->udev->dev, - "ath9k_htc: Async request for firmware %s failed\n", - hif_dev->fw_name); + ret = ath9k_hif_request_firmware(hif_dev, true); + if (ret) goto err_fw_req; - } - dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", - hif_dev->fw_name); - - return 0; + return ret; err_fw_req: usb_set_intfdata(interface, NULL); diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 51496e74b83e..7c2ef7ecd98b 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -17,8 +17,26 @@ #ifndef HTC_USB_H #define HTC_USB_H +/* old firmware images */ +#define FIRMWARE_AR7010_1_1 "htc_7010.fw" +#define FIRMWARE_AR9271 "htc_9271.fw" + +/* supported Major FW version */ #define MAJOR_VERSION_REQ 1 #define MINOR_VERSION_REQ 3 +/* minimal and maximal supported Minor FW version. */ +#define FIRMWARE_MINOR_IDX_MAX 4 +#define FIRMWARE_MINOR_IDX_MIN 3 +#define HTC_FW_PATH "ath9k_htc" + +#define HTC_9271_MODULE_FW HTC_FW_PATH "/htc_9271-" \ + __stringify(MAJOR_VERSION_REQ) \ + "." __stringify(FIRMWARE_MINOR_IDX_MAX) ".0.fw" +#define HTC_7010_MODULE_FW HTC_FW_PATH "/htc_7010-" \ + __stringify(MAJOR_VERSION_REQ) \ + "." __stringify(FIRMWARE_MINOR_IDX_MAX) ".0.fw" + +extern int htc_use_dev_fw; #define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || ((_v) == AR9287_USB)) @@ -101,7 +119,8 @@ struct hif_device_usb { struct usb_anchor reg_in_submitted; struct usb_anchor mgmt_submitted; struct sk_buff *remain_skb; - const char *fw_name; + char fw_name[32]; + int fw_minor_index; int rx_remain_len; int rx_pkt_len; int rx_transfer_len; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 1e84882f8c5b..8647ab77c019 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -38,6 +38,10 @@ static int ath9k_ps_enable; module_param_named(ps_enable, ath9k_ps_enable, int, 0444); MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave"); +int htc_use_dev_fw = 0; +module_param_named(use_dev_fw, htc_use_dev_fw, int, 0444); +MODULE_PARM_DESC(use_dev_fw, "Use development FW version"); + #ifdef CONFIG_MAC80211_LEDS int ath9k_htc_led_blink = 1; module_param_named(blink, ath9k_htc_led_blink, int, 0444); @@ -736,7 +740,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_MESH_POINT); + BIT(NL80211_IFTYPE_MESH_POINT) | + BIT(NL80211_IFTYPE_OCB); hw->wiphy->iface_combinations = &if_comb; hw->wiphy->n_iface_combinations = 1; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 172a9ff4aaab..a680a970b7f7 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1659,7 +1659,7 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size) + u16 tid, u16 *ssn, u8 buf_size, bool amsdu) { struct ath9k_htc_priv *priv = hw->priv; struct ath9k_htc_sta *ista; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 1dd0339de372..bdfff4641931 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1241,6 +1241,7 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) break; } /* fall through */ + case NL80211_IFTYPE_OCB: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_AP: set |= AR_STA_ID1_STA_AP; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index e8454db17634..4f0a3f6b0c52 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -919,7 +919,7 @@ struct ath_hw { struct ar5416IniArray iniCckfirJapan2484; struct ar5416IniArray iniModes_9271_ANI_reg; struct ar5416IniArray ini_radio_post_sys2ant; - struct ar5416IniArray ini_modes_rxgain_5g_xlna; + struct ar5416IniArray ini_modes_rxgain_xlna; struct ar5416IniArray ini_modes_rxgain_bb_core; struct ar5416IniArray ini_modes_rxgain_bb_postamble; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 90eb75012e4f..2e2b92ba96b8 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -855,7 +855,8 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT) | - BIT(NL80211_IFTYPE_WDS); + BIT(NL80211_IFTYPE_WDS) | + BIT(NL80211_IFTYPE_OCB); if (ath9k_is_chanctx_enabled()) hw->wiphy->interface_modes |= diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index e55fa11894b6..7fbf7f965f61 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -209,21 +209,25 @@ enum ath9k_phyerr { ATH9K_PHYERR_OFDM_POWER_DROP = 21, ATH9K_PHYERR_OFDM_SERVICE = 22, ATH9K_PHYERR_OFDM_RESTART = 23, - ATH9K_PHYERR_FALSE_RADAR_EXT = 24, + ATH9K_PHYERR_CCK_BLOCKER = 24, ATH9K_PHYERR_CCK_TIMING = 25, ATH9K_PHYERR_CCK_HEADER_CRC = 26, ATH9K_PHYERR_CCK_RATE_ILLEGAL = 27, + ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 28, + ATH9K_PHYERR_CCK_POWER_DROP = 29, ATH9K_PHYERR_CCK_SERVICE = 30, ATH9K_PHYERR_CCK_RESTART = 31, - ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 32, - ATH9K_PHYERR_CCK_POWER_DROP = 33, - ATH9K_PHYERR_HT_CRC_ERROR = 34, - ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35, - ATH9K_PHYERR_HT_RATE_ILLEGAL = 36, + ATH9K_PHYERR_HT_CRC_ERROR = 32, + ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 33, + ATH9K_PHYERR_HT_RATE_ILLEGAL = 34, + ATH9K_PHYERR_HT_ZLF = 35, + + ATH9K_PHYERR_FALSE_RADAR_EXT = 36, + ATH9K_PHYERR_GREEN_FIELD = 37, + ATH9K_PHYERR_SPECTRAL = 38, - ATH9K_PHYERR_SPECTRAL = 38, ATH9K_PHYERR_MAX = 39, }; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c27143ba9ffb..d184e682e636 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -938,6 +938,9 @@ static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data, if (avp->assoc && !iter_data->primary_sta) iter_data->primary_sta = vif; break; + case NL80211_IFTYPE_OCB: + iter_data->nocbs++; + break; case NL80211_IFTYPE_ADHOC: iter_data->nadhocs++; if (vif->bss_conf.enable_beacon) @@ -1111,6 +1114,8 @@ void ath9k_calculate_summary_state(struct ath_softc *sc, if (iter_data.nmeshes) ah->opmode = NL80211_IFTYPE_MESH_POINT; + else if (iter_data.nocbs) + ah->opmode = NL80211_IFTYPE_OCB; else if (iter_data.nwds) ah->opmode = NL80211_IFTYPE_AP; else if (iter_data.nadhocs) @@ -1760,7 +1765,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, ath9k_calculate_summary_state(sc, avp->chanctx); } - if (changed & BSS_CHANGED_IBSS) { + if ((changed & BSS_CHANGED_IBSS) || + (changed & BSS_CHANGED_OCB)) { memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); common->curaid = bss_conf->aid; ath9k_hw_write_associd(sc->sc_ah); @@ -1856,7 +1862,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size) + u16 tid, u16 *ssn, u8 buf_size, bool amsdu) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index d3189daf9996..994daf6c6297 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -403,7 +403,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) (sc->cur_chan->nvifs <= 1) && !(sc->cur_chan->rxfilter & FIF_BCN_PRBRESP_PROMISC)) rfilt |= ATH9K_RX_FILTER_MYBEACON; - else + else if (sc->sc_ah->opmode != NL80211_IFTYPE_OCB) rfilt |= ATH9K_RX_FILTER_BEACON; if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 170c209f99b8..19d3d64416bf 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1415,7 +1415,7 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size) + u16 tid, u16 *ssn, u8 buf_size, bool amsdu) { struct ar9170 *ar = hw->priv; struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index 924135b8e575..d66533cbc38a 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c @@ -453,7 +453,7 @@ static void carl9170_rx_phy_status(struct ar9170 *ar, /* post-process RSSI */ for (i = 0; i < 7; i++) if (phy->rssi[i] & 0x80) - phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f; + phy->rssi[i] = ((~phy->rssi[i] & 0x7f) + 1) & 0x7f; /* TODO: we could do something with phy_errors */ status->signal = ar->noise[0] + phy->rssi_combined; diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c index 656ce42b339a..2303ef96299d 100644 --- a/drivers/net/wireless/ath/dfs_pattern_detector.c +++ b/drivers/net/wireless/ath/dfs_pattern_detector.c @@ -21,12 +21,6 @@ #include "dfs_pri_detector.h" #include "ath.h" -/* - * tolerated deviation of radar time stamp in usecs on both sides - * TODO: this might need to be HW-dependent - */ -#define PRI_TOLERANCE 16 - /** * struct radar_types - contains array of patterns defined for one DFS domain * @domain: DFS regulatory domain @@ -121,7 +115,7 @@ static const struct radar_detector_specs jp_radar_ref_types[] = { JP_PATTERN(4, 0, 5, 150, 230, 1, 23, 50, false), JP_PATTERN(5, 6, 10, 200, 500, 1, 16, 50, false), JP_PATTERN(6, 11, 20, 200, 500, 1, 12, 50, false), - JP_PATTERN(7, 50, 100, 1000, 2000, 1, 20, 50, false), + JP_PATTERN(7, 50, 100, 1000, 2000, 1, 3, 50, false), JP_PATTERN(5, 0, 1, 333, 333, 1, 9, 50, false), }; @@ -290,10 +284,10 @@ dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event) if (cd == NULL) return false; - dpd->last_pulse_ts = event->ts; /* reset detector on time stamp wraparound, caused by TSF reset */ if (event->ts < dpd->last_pulse_ts) dpd_reset(dpd); + dpd->last_pulse_ts = event->ts; /* do type individual pattern matching */ for (i = 0; i < dpd->num_radar_types; i++) { diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.h b/drivers/net/wireless/ath/dfs_pattern_detector.h index 25a43d632f90..92be3530e9b5 100644 --- a/drivers/net/wireless/ath/dfs_pattern_detector.h +++ b/drivers/net/wireless/ath/dfs_pattern_detector.h @@ -21,6 +21,11 @@ #include <linux/list.h> #include <linux/nl80211.h> +/* tolerated deviation of radar time stamp in usecs on both sides + * TODO: this might need to be HW-dependent + */ +#define PRI_TOLERANCE 16 + /** * struct ath_dfs_pool_stats - DFS Statistics for global pools */ diff --git a/drivers/net/wireless/ath/dfs_pri_detector.c b/drivers/net/wireless/ath/dfs_pri_detector.c index cc5c592fc4c0..05b0464c6b92 100644 --- a/drivers/net/wireless/ath/dfs_pri_detector.c +++ b/drivers/net/wireless/ath/dfs_pri_detector.c @@ -25,6 +25,9 @@ struct ath_dfs_pool_stats global_dfs_pool_stats = {}; #define DFS_POOL_STAT_INC(c) (global_dfs_pool_stats.c++) #define DFS_POOL_STAT_DEC(c) (global_dfs_pool_stats.c--) +#define GET_PRI_TO_USE(MIN, MAX, RUNTIME) \ + (MIN + PRI_TOLERANCE == MAX - PRI_TOLERANCE ? \ + MIN + PRI_TOLERANCE : RUNTIME) /** * struct pulse_elem - elements in pulse queue @@ -243,7 +246,8 @@ static bool pseq_handler_create_sequences(struct pri_detector *pde, ps.count_falses = 0; ps.first_ts = p->ts; ps.last_ts = ts; - ps.pri = ts - p->ts; + ps.pri = GET_PRI_TO_USE(pde->rs->pri_min, + pde->rs->pri_max, ts - p->ts); ps.dur = ps.pri * (pde->rs->ppb - 1) + 2 * pde->rs->max_pri_tolerance; diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index 086549b732b9..f8dfa05b290a 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -79,6 +79,7 @@ static int wcn36xx_dxe_allocate_ctl_block(struct wcn36xx_dxe_ch *ch) struct wcn36xx_dxe_ctl *cur_ctl = NULL; int i; + spin_lock_init(&ch->lock); for (i = 0; i < ch->desc_num; i++) { cur_ctl = kzalloc(sizeof(*cur_ctl), GFP_KERNEL); if (!cur_ctl) @@ -169,7 +170,7 @@ void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn) wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch); } -static int wcn36xx_dxe_init_descs(struct wcn36xx_dxe_ch *wcn_ch) +static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch) { struct wcn36xx_dxe_desc *cur_dxe = NULL; struct wcn36xx_dxe_desc *prev_dxe = NULL; @@ -178,7 +179,7 @@ static int wcn36xx_dxe_init_descs(struct wcn36xx_dxe_ch *wcn_ch) int i; size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc); - wcn_ch->cpu_addr = dma_alloc_coherent(NULL, size, &wcn_ch->dma_addr, + wcn_ch->cpu_addr = dma_alloc_coherent(dev, size, &wcn_ch->dma_addr, GFP_KERNEL); if (!wcn_ch->cpu_addr) return -ENOMEM; @@ -270,7 +271,7 @@ static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch) return 0; } -static int wcn36xx_dxe_fill_skb(struct wcn36xx_dxe_ctl *ctl) +static int wcn36xx_dxe_fill_skb(struct device *dev, struct wcn36xx_dxe_ctl *ctl) { struct wcn36xx_dxe_desc *dxe = ctl->desc; struct sk_buff *skb; @@ -279,7 +280,7 @@ static int wcn36xx_dxe_fill_skb(struct wcn36xx_dxe_ctl *ctl) if (skb == NULL) return -ENOMEM; - dxe->dst_addr_l = dma_map_single(NULL, + dxe->dst_addr_l = dma_map_single(dev, skb_tail_pointer(skb), WCN36XX_PKT_SIZE, DMA_FROM_DEVICE); @@ -297,7 +298,7 @@ static int wcn36xx_dxe_ch_alloc_skb(struct wcn36xx *wcn, cur_ctl = wcn_ch->head_blk_ctl; for (i = 0; i < wcn_ch->desc_num; i++) { - wcn36xx_dxe_fill_skb(cur_ctl); + wcn36xx_dxe_fill_skb(wcn->dev, cur_ctl); cur_ctl = cur_ctl->next; } @@ -345,7 +346,7 @@ void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status) static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) { - struct wcn36xx_dxe_ctl *ctl = ch->tail_blk_ctl; + struct wcn36xx_dxe_ctl *ctl; struct ieee80211_tx_info *info; unsigned long flags; @@ -354,23 +355,25 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) * completely full head and tail are pointing to the same element * and while-do will not make any cycles. */ + spin_lock_irqsave(&ch->lock, flags); + ctl = ch->tail_blk_ctl; do { if (ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK) break; if (ctl->skb) { - dma_unmap_single(NULL, ctl->desc->src_addr_l, + dma_unmap_single(wcn->dev, ctl->desc->src_addr_l, ctl->skb->len, DMA_TO_DEVICE); info = IEEE80211_SKB_CB(ctl->skb); if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { /* Keep frame until TX status comes */ ieee80211_free_txskb(wcn->hw, ctl->skb); } - spin_lock_irqsave(&ctl->skb_lock, flags); + spin_lock(&ctl->skb_lock); if (wcn->queues_stopped) { wcn->queues_stopped = false; ieee80211_wake_queues(wcn->hw); } - spin_unlock_irqrestore(&ctl->skb_lock, flags); + spin_unlock(&ctl->skb_lock); ctl->skb = NULL; } @@ -379,6 +382,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) !(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)); ch->tail_blk_ctl = ctl; + spin_unlock_irqrestore(&ch->lock, flags); } static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) @@ -474,7 +478,7 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) { skb = ctl->skb; dma_addr = dxe->dst_addr_l; - wcn36xx_dxe_fill_skb(ctl); + wcn36xx_dxe_fill_skb(wcn->dev, ctl); switch (ch->ch_type) { case WCN36XX_DXE_CH_RX_L: @@ -491,7 +495,7 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, wcn36xx_warn("Unknown channel\n"); } - dma_unmap_single(NULL, dma_addr, WCN36XX_PKT_SIZE, + dma_unmap_single(wcn->dev, dma_addr, WCN36XX_PKT_SIZE, DMA_FROM_DEVICE); wcn36xx_rx_skb(wcn, skb); ctl = ctl->next; @@ -540,7 +544,7 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn) 16 - (WCN36XX_BD_CHUNK_SIZE % 8); s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H; - cpu_addr = dma_alloc_coherent(NULL, s, &wcn->mgmt_mem_pool.phy_addr, + cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->mgmt_mem_pool.phy_addr, GFP_KERNEL); if (!cpu_addr) goto out_err; @@ -555,7 +559,7 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn) 16 - (WCN36XX_BD_CHUNK_SIZE % 8); s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L; - cpu_addr = dma_alloc_coherent(NULL, s, &wcn->data_mem_pool.phy_addr, + cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->data_mem_pool.phy_addr, GFP_KERNEL); if (!cpu_addr) goto out_err; @@ -574,13 +578,13 @@ out_err: void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn) { if (wcn->mgmt_mem_pool.virt_addr) - dma_free_coherent(NULL, wcn->mgmt_mem_pool.chunk_size * + dma_free_coherent(wcn->dev, wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H, wcn->mgmt_mem_pool.virt_addr, wcn->mgmt_mem_pool.phy_addr); if (wcn->data_mem_pool.virt_addr) { - dma_free_coherent(NULL, wcn->data_mem_pool.chunk_size * + dma_free_coherent(wcn->dev, wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L, wcn->data_mem_pool.virt_addr, wcn->data_mem_pool.phy_addr); @@ -596,12 +600,14 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, struct wcn36xx_dxe_desc *desc = NULL; struct wcn36xx_dxe_ch *ch = NULL; unsigned long flags; + int ret; ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch; + spin_lock_irqsave(&ch->lock, flags); ctl = ch->head_blk_ctl; - spin_lock_irqsave(&ctl->next->skb_lock, flags); + spin_lock(&ctl->next->skb_lock); /* * If skb is not null that means that we reached the tail of the ring @@ -611,10 +617,11 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, if (NULL != ctl->next->skb) { ieee80211_stop_queues(wcn->hw); wcn->queues_stopped = true; - spin_unlock_irqrestore(&ctl->next->skb_lock, flags); + spin_unlock(&ctl->next->skb_lock); + spin_unlock_irqrestore(&ch->lock, flags); return -EBUSY; } - spin_unlock_irqrestore(&ctl->next->skb_lock, flags); + spin_unlock(&ctl->next->skb_lock); ctl->skb = NULL; desc = ctl->desc; @@ -640,10 +647,11 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, desc = ctl->desc; if (ctl->bd_cpu_addr) { wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n"); - return -EINVAL; + ret = -EINVAL; + goto unlock; } - desc->src_addr_l = dma_map_single(NULL, + desc->src_addr_l = dma_map_single(wcn->dev, ctl->skb->data, ctl->skb->len, DMA_TO_DEVICE); @@ -679,7 +687,10 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, ch->reg_ctrl, ch->def_ctrl); } - return 0; + ret = 0; +unlock: + spin_unlock_irqrestore(&ch->lock, flags); + return ret; } int wcn36xx_dxe_init(struct wcn36xx *wcn) @@ -696,7 +707,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***************************************/ /* Init descriptors for TX LOW channel */ /***************************************/ - wcn36xx_dxe_init_descs(&wcn->dxe_tx_l_ch); + wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_l_ch); wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool); /* Write channel head to a NEXT register */ @@ -714,7 +725,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***************************************/ /* Init descriptors for TX HIGH channel */ /***************************************/ - wcn36xx_dxe_init_descs(&wcn->dxe_tx_h_ch); + wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_h_ch); wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool); /* Write channel head to a NEXT register */ @@ -734,7 +745,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***************************************/ /* Init descriptors for RX LOW channel */ /***************************************/ - wcn36xx_dxe_init_descs(&wcn->dxe_rx_l_ch); + wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_l_ch); /* For RX we need to preallocated buffers */ wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch); @@ -764,7 +775,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***************************************/ /* Init descriptors for RX HIGH channel */ /***************************************/ - wcn36xx_dxe_init_descs(&wcn->dxe_rx_h_ch); + wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_h_ch); /* For RX we need to prealocat buffers */ wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch); diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h index 35ee7e966bd2..3eca4f9594f2 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.h +++ b/drivers/net/wireless/ath/wcn36xx/dxe.h @@ -243,6 +243,7 @@ struct wcn36xx_dxe_ctl { }; struct wcn36xx_dxe_ch { + spinlock_t lock; /* protects head/tail ptrs */ enum wcn36xx_dxe_ch_type ch_type; void *cpu_addr; dma_addr_t dma_addr; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 900e72a089d8..7c169abdbafe 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -859,7 +859,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct wcn36xx *wcn = hw->priv; struct wcn36xx_sta *sta_priv = NULL; diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig index ce8c0381825e..6dfedc8bd6a3 100644 --- a/drivers/net/wireless/ath/wil6210/Kconfig +++ b/drivers/net/wireless/ath/wil6210/Kconfig @@ -1,5 +1,6 @@ config WIL6210 tristate "Wilocity 60g WiFi card wil6210 support" + select WANT_DEV_COREDUMP depends on CFG80211 depends on PCI default n diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile index 64b432625fbb..fdf63d5fe82b 100644 --- a/drivers/net/wireless/ath/wil6210/Makefile +++ b/drivers/net/wireless/ath/wil6210/Makefile @@ -17,6 +17,7 @@ wil6210-y += pmc.o wil6210-$(CONFIG_WIL6210_TRACING) += trace.o wil6210-y += wil_platform.o wil6210-y += ethtool.o +wil6210-y += wil_crash_dump.o # for tracing framework to find trace.h CFLAGS_trace.o := -I$(src) diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index d1a1e160ef31..97bc186f9728 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1373,6 +1373,12 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) } } spin_unlock_bh(&p->tid_rx_lock); + seq_printf(s, + "Rx invalid frame: non-data %lu, short %lu, large %lu\n", + p->stats.rx_non_data_frame, + p->stats.rx_short_frame, + p->stats.rx_large_frame); + seq_puts(s, "Rx/MCS:"); for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs); mcs++) diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index a371f036d054..50c136e843c4 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2015 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 @@ -236,7 +236,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie) isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH); - if (likely(test_bit(wil_status_reset_done, wil->status))) { + if (likely(test_bit(wil_status_fwready, wil->status))) { if (likely(test_bit(wil_status_napi_en, wil->status))) { wil_dbg_txrx(wil, "NAPI(Rx) schedule\n"); need_unmask = false; @@ -286,7 +286,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie) isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; /* clear also all VRING interrupts */ isr &= ~(BIT(25) - 1UL); - if (likely(test_bit(wil_status_reset_done, wil->status))) { + if (likely(test_bit(wil_status_fwready, wil->status))) { wil_dbg_txrx(wil, "NAPI(Tx) schedule\n"); need_unmask = false; napi_schedule(&wil->napi_tx); @@ -347,7 +347,12 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) wil6210_mask_irq_misc(wil); if (isr & ISR_MISC_FW_ERROR) { - wil_err(wil, "Firmware error detected\n"); + u32 fw_assert_code = wil_r(wil, RGF_FW_ASSERT_CODE); + u32 ucode_assert_code = wil_r(wil, RGF_UCODE_ASSERT_CODE); + + wil_err(wil, + "Firmware error detected, assert codes FW 0x%08x, UCODE 0x%08x\n", + fw_assert_code, ucode_assert_code); clear_bit(wil_status_fwready, wil->status); /* * do not clear @isr here - we do 2-nd part in thread @@ -359,7 +364,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) if (isr & ISR_MISC_FW_READY) { wil_dbg_irq(wil, "IRQ: FW ready\n"); wil_cache_mbox_regs(wil); - set_bit(wil_status_reset_done, wil->status); + set_bit(wil_status_mbox_ready, wil->status); /** * Actual FW ready indicated by the * WMI_FW_READY_EVENTID @@ -386,6 +391,7 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr); if (isr & ISR_MISC_FW_ERROR) { + wil_fw_core_dump(wil); wil_notify_fw_error(wil); isr &= ~ISR_MISC_FW_ERROR; wil_fw_error_recovery(wil); diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 2fb04c51da53..bb69a5949aea 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -203,11 +203,13 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, * - disconnect single STA, already disconnected * - disconnect all * - * For "disconnect all", there are 2 options: + * For "disconnect all", there are 3 options: * - bssid == NULL + * - bssid is broadcast address (ff:ff:ff:ff:ff:ff) * - bssid is our MAC address */ - if (bssid && memcmp(ndev->dev_addr, bssid, ETH_ALEN)) { + if (bssid && !is_broadcast_ether_addr(bssid) && + !ether_addr_equal_unaligned(ndev->dev_addr, bssid)) { cid = wil_find_cid(wil, bssid); wil_dbg_misc(wil, "Disconnect %pM, CID=%d, reason=%d\n", bssid, cid, reason_code); @@ -420,7 +422,7 @@ static void wil_connect_worker(struct work_struct *work) wil->sta[cid].status = wil_sta_connected; netif_tx_wake_all_queues(ndev); } else { - wil->sta[cid].status = wil_sta_unused; + wil_disconnect_cid(wil, cid, WLAN_REASON_UNSPECIFIED, true); } } @@ -765,6 +767,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) if (wil->hw_version == HW_VER_UNKNOWN) return -ENODEV; + set_bit(wil_status_resetting, wil->status); + cancel_work_sync(&wil->disconnect_worker); wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); wil_bcast_fini(wil); @@ -851,6 +855,12 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) void wil_fw_error_recovery(struct wil6210_priv *wil) { wil_dbg_misc(wil, "starting fw error recovery\n"); + + if (test_bit(wil_status_resetting, wil->status)) { + wil_info(wil, "Reset already in progress\n"); + return; + } + wil->recovery_state = fw_recovery_pending; schedule_work(&wil->fw_error_worker); } diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index feff1ef10fb3..1a3142c332e1 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c @@ -260,6 +260,7 @@ static const struct pci_device_id wil6210_pcie_ids[] = { MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); #ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int wil6210_suspend(struct device *dev, bool is_runtime) { @@ -307,7 +308,6 @@ static int wil6210_resume(struct device *dev, bool is_runtime) return rc; } -#ifdef CONFIG_PM_SLEEP static int wil6210_pm_suspend(struct device *dev) { return wil6210_suspend(dev, false); diff --git a/drivers/net/wireless/ath/wil6210/pmc.c b/drivers/net/wireless/ath/wil6210/pmc.c index 8a8cdc61b25b..5ca0307a3274 100644 --- a/drivers/net/wireless/ath/wil6210/pmc.c +++ b/drivers/net/wireless/ath/wil6210/pmc.c @@ -110,7 +110,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil, */ for (i = 0; i < num_descriptors; i++) { struct vring_tx_desc *_d = &pmc->pring_va[i]; - struct vring_tx_desc dd, *d = ⅆ + struct vring_tx_desc dd = {}, *d = ⅆ int j = 0; pmc->descriptors[i].va = dma_alloc_coherent(dev, diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index 9238c1ac23dd..e3d1be82f314 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c @@ -205,6 +205,32 @@ out: spin_unlock(&sta->tid_rx_lock); } +/* process BAR frame, called in NAPI context */ +void wil_rx_bar(struct wil6210_priv *wil, u8 cid, u8 tid, u16 seq) +{ + struct wil_sta_info *sta = &wil->sta[cid]; + struct wil_tid_ampdu_rx *r; + + spin_lock(&sta->tid_rx_lock); + + r = sta->tid_rx[tid]; + if (!r) { + wil_err(wil, "BAR for non-existing CID %d TID %d\n", cid, tid); + goto out; + } + if (seq_less(seq, r->head_seq_num)) { + wil_err(wil, "BAR Seq 0x%03x preceding head 0x%03x\n", + seq, r->head_seq_num); + goto out; + } + wil_dbg_txrx(wil, "BAR: CID %d TID %d Seq 0x%03x head 0x%03x\n", + cid, tid, seq, r->head_seq_num); + wil_release_reorder_frames(wil, r, seq); + +out: + spin_unlock(&sta->tid_rx_lock); +} + struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, int size, u16 ssn) { diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 6229110d558a..3bc9bc0efbac 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -358,6 +358,13 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil, } } +/* similar to ieee80211_ version, but FC contain only 1-st byte */ +static inline int wil_is_back_req(u8 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ); +} + /** * reap 1 frame from @swhead * @@ -379,14 +386,16 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, u16 dmalen; u8 ftype; int cid; - int i = (int)vring->swhead; + int i; struct wil_net_stats *stats; BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb)); +again: if (unlikely(wil_vring_is_empty(vring))) return NULL; + i = (int)vring->swhead; _d = &vring->va[i].rx; if (unlikely(!(_d->dma.status & RX_DMA_STATUS_DU))) { /* it is not error, we just reached end of Rx done area */ @@ -398,7 +407,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, wil_vring_advance_head(vring, 1); if (!skb) { wil_err(wil, "No Rx skb at [%d]\n", i); - return NULL; + goto again; } d = wil_skb_rxdesc(skb); *d = *_d; @@ -409,13 +418,17 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, trace_wil6210_rx(i, d); wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", i, dmalen); - wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4, + wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4, (const void *)d, sizeof(*d), false); + cid = wil_rxdesc_cid(d); + stats = &wil->sta[cid].stats; + if (unlikely(dmalen > sz)) { wil_err(wil, "Rx size too large: %d bytes!\n", dmalen); + stats->rx_large_frame++; kfree_skb(skb); - return NULL; + goto again; } skb_trim(skb, dmalen); @@ -424,8 +437,6 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb_headlen(skb), false); - cid = wil_rxdesc_cid(d); - stats = &wil->sta[cid].stats; stats->last_mcs_rx = wil_rxdesc_mcs(d); if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs)) stats->rx_per_mcs[stats->last_mcs_rx]++; @@ -437,24 +448,47 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, /* no extra checks if in sniffer mode */ if (ndev->type != ARPHRD_ETHER) return skb; - /* - * Non-data frames may be delivered through Rx DMA channel (ex: BAR) + /* Non-data frames may be delivered through Rx DMA channel (ex: BAR) * Driver should recognize it by frame type, that is found * in Rx descriptor. If type is not data, it is 802.11 frame as is */ ftype = wil_rxdesc_ftype(d) << 2; if (unlikely(ftype != IEEE80211_FTYPE_DATA)) { - wil_dbg_txrx(wil, "Non-data frame ftype 0x%08x\n", ftype); - /* TODO: process it */ + u8 fc1 = wil_rxdesc_fc1(d); + int mid = wil_rxdesc_mid(d); + int tid = wil_rxdesc_tid(d); + u16 seq = wil_rxdesc_seq(d); + + wil_dbg_txrx(wil, + "Non-data frame FC[7:0] 0x%02x MID %d CID %d TID %d Seq 0x%03x\n", + fc1, mid, cid, tid, seq); + stats->rx_non_data_frame++; + if (wil_is_back_req(fc1)) { + wil_dbg_txrx(wil, + "BAR: MID %d CID %d TID %d Seq 0x%03x\n", + mid, cid, tid, seq); + wil_rx_bar(wil, cid, tid, seq); + } else { + /* print again all info. One can enable only this + * without overhead for printing every Rx frame + */ + wil_dbg_txrx(wil, + "Unhandled non-data frame FC[7:0] 0x%02x MID %d CID %d TID %d Seq 0x%03x\n", + fc1, mid, cid, tid, seq); + wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4, + (const void *)d, sizeof(*d), false); + wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, + skb->data, skb_headlen(skb), false); + } kfree_skb(skb); - return NULL; + goto again; } if (unlikely(skb->len < ETH_HLEN + snaplen)) { wil_err(wil, "Short frame, len = %d\n", skb->len); - /* TODO: process it (i.e. BAR) */ + stats->rx_short_frame++; kfree_skb(skb); - return NULL; + goto again; } /* L4 IDENT is on when HW calculated checksum, check status @@ -1208,6 +1242,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, int tcp_hdr_len; int skb_net_hdr_len; int gso_type; + int rc = -EINVAL; wil_dbg_txrx(wil, "%s() %d bytes to vring %d\n", __func__, skb->len, vring_index); @@ -1299,8 +1334,9 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, len, rem_data, descs_used); if (descs_used == avail) { - wil_err(wil, "TSO: ring overflow\n"); - goto dma_error; + wil_err_ratelimited(wil, "TSO: ring overflow\n"); + rc = -ENOMEM; + goto mem_error; } lenmss = min_t(int, rem_data, len); @@ -1322,8 +1358,10 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, headlen -= lenmss; } - if (unlikely(dma_mapping_error(dev, pa))) - goto dma_error; + if (unlikely(dma_mapping_error(dev, pa))) { + wil_err(wil, "TSO: DMA map page error\n"); + goto mem_error; + } _desc = &vring->va[i].tx; @@ -1422,8 +1460,8 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, } /* advance swhead */ - wil_dbg_txrx(wil, "TSO: Tx swhead %d -> %d\n", swhead, vring->swhead); wil_vring_advance_head(vring, descs_used); + wil_dbg_txrx(wil, "TSO: Tx swhead %d -> %d\n", swhead, vring->swhead); /* make sure all writes to descriptors (shared memory) are done before * committing them to HW @@ -1433,8 +1471,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, wil_w(wil, vring->hwtail, vring->swhead); return 0; -dma_error: - wil_err(wil, "TSO: DMA map page error\n"); +mem_error: while (descs_used > 0) { struct wil_ctx *ctx; @@ -1445,14 +1482,11 @@ dma_error: _desc->dma.status = TX_DMA_STATUS_DU; ctx = &vring->ctx[i]; wil_txdesc_unmap(dev, d, ctx); - if (ctx->skb) - dev_kfree_skb_any(ctx->skb); memset(ctx, 0, sizeof(*ctx)); descs_used--; } - err_exit: - return -EINVAL; + return rc; } static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, @@ -1528,8 +1562,11 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, _d = &vring->va[i].tx; pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, pa))) + if (unlikely(dma_mapping_error(dev, pa))) { + wil_err(wil, "Tx[%2d] failed to map fragment\n", + vring_index); goto dma_error; + } vring->ctx[i].mapped_as = wil_mapped_as_page; wil_tx_desc_map(d, pa, len, vring_index); /* no need to check return code - @@ -1589,9 +1626,6 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, _d->dma.status = TX_DMA_STATUS_DU; wil_txdesc_unmap(dev, d, ctx); - if (ctx->skb) - dev_kfree_skb_any(ctx->skb); - memset(ctx, 0, sizeof(*ctx)); } @@ -1633,7 +1667,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) goto drop; } if (unlikely(!test_bit(wil_status_fwconnected, wil->status))) { - wil_err(wil, "FW not connected\n"); + wil_err_ratelimited(wil, "FW not connected\n"); goto drop; } if (unlikely(wil->wdev->iftype == NL80211_IFTYPE_MONITOR)) { diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index 82a8f9a030e7..ee7c7b4b9a17 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h @@ -464,6 +464,12 @@ static inline int wil_rxdesc_subtype(struct vring_rx_desc *d) return WIL_GET_BITS(d->mac.d0, 12, 15); } +/* 1-st byte (with frame type/subtype) of FC field */ +static inline u8 wil_rxdesc_fc1(struct vring_rx_desc *d) +{ + return (u8)(WIL_GET_BITS(d->mac.d0, 10, 15) << 2); +} + static inline int wil_rxdesc_seq(struct vring_rx_desc *d) { return WIL_GET_BITS(d->mac.d0, 16, 27); @@ -501,6 +507,7 @@ static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb) void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev); void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb); +void wil_rx_bar(struct wil6210_priv *wil, u8 cid, u8 tid, u16 seq); struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, int size, u16 ssn); void wil_tid_ampdu_rx_free(struct wil6210_priv *wil, diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index dd4ea926b8e3..ade5f3b8274b 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -246,6 +246,10 @@ struct RGF_ICR { #define RGF_USER_JTAG_DEV_ID (0x880b34) /* device ID */ #define JTAG_DEV_ID_SPARROW_B0 (0x2632072f) +/* crash codes for FW/Ucode stored here */ +#define RGF_FW_ASSERT_CODE (0x91f020) +#define RGF_UCODE_ASSERT_CODE (0x91f028) + enum { HW_VER_UNKNOWN, HW_VER_SPARROW_B0, /* JTAG_DEV_ID_SPARROW_B0 */ @@ -398,13 +402,14 @@ struct vring_tx_data { }; enum { /* for wil6210_priv.status */ - wil_status_fwready = 0, + wil_status_fwready = 0, /* FW operational */ wil_status_fwconnecting, wil_status_fwconnected, wil_status_dontscan, - wil_status_reset_done, + wil_status_mbox_ready, /* MBOX structures ready */ 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_last /* keep last */ }; @@ -465,6 +470,9 @@ struct wil_net_stats { unsigned long tx_bytes; unsigned long tx_errors; unsigned long rx_dropped; + unsigned long rx_non_data_frame; + unsigned long rx_short_frame; + unsigned long rx_large_frame; u16 last_mcs_rx; u64 rx_per_mcs[WIL_MCS_MAX + 1]; }; @@ -820,4 +828,6 @@ 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); +void wil_fw_core_dump(struct wil6210_priv *wil); + #endif /* __WIL6210_H__ */ diff --git a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c new file mode 100644 index 000000000000..7e70934990ae --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2015 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 "wil6210.h" +#include <linux/devcoredump.h> + +static int wil_fw_get_crash_dump_bounds(struct wil6210_priv *wil, + u32 *out_dump_size, u32 *out_host_min) +{ + int i; + const struct fw_map *map; + u32 host_min, host_max, tmp_max; + + if (!out_dump_size) + return -EINVAL; + + /* calculate the total size of the unpacked crash dump */ + BUILD_BUG_ON(ARRAY_SIZE(fw_mapping) == 0); + map = &fw_mapping[0]; + host_min = map->host; + host_max = map->host + (map->to - map->from); + + for (i = 1; i < ARRAY_SIZE(fw_mapping); i++) { + map = &fw_mapping[i]; + + if (map->host < host_min) + host_min = map->host; + + tmp_max = map->host + (map->to - map->from); + if (tmp_max > host_max) + host_max = tmp_max; + } + + *out_dump_size = host_max - host_min; + if (out_host_min) + *out_host_min = host_min; + + return 0; +} + +static int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, + u32 size) +{ + int i; + const struct fw_map *map; + void *data; + u32 host_min, dump_size, offset, len; + + if (wil_fw_get_crash_dump_bounds(wil, &dump_size, &host_min)) { + wil_err(wil, "%s: fail to obtain crash dump size\n", __func__); + return -EINVAL; + } + + if (dump_size > size) { + wil_err(wil, "%s: not enough space for dump. Need %d have %d\n", + __func__, dump_size, size); + return -EINVAL; + } + + /* copy to crash dump area */ + for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { + map = &fw_mapping[i]; + + data = (void * __force)wil->csr + HOSTADDR(map->host); + len = map->to - map->from; + offset = map->host - host_min; + + wil_dbg_misc(wil, "%s() - dump %s, size %d, offset %d\n", + __func__, fw_mapping[i].name, len, offset); + + wil_memcpy_fromio_32((void * __force)(dest + offset), + (const void __iomem * __force)data, len); + } + + return 0; +} + +void wil_fw_core_dump(struct wil6210_priv *wil) +{ + void *fw_dump_data; + u32 fw_dump_size; + + if (wil_fw_get_crash_dump_bounds(wil, &fw_dump_size, NULL)) { + wil_err(wil, "%s: fail to get fw dump size\n", __func__); + return; + } + + fw_dump_data = vzalloc(fw_dump_size); + if (!fw_dump_data) + return; + + if (wil_fw_copy_crash_dump(wil, fw_dump_data, fw_dump_size)) { + vfree(fw_dump_data); + return; + } + /* fw_dump_data will be free in device coredump release function + * after 5 min + */ + dev_coredumpv(wil_to_dev(wil), fw_dump_data, fw_dump_size, GFP_KERNEL); + wil_info(wil, "%s: fw core dumped, size %d bytes\n", __func__, + fw_dump_size); +} diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 2f35d4c51f34..6ed26baca0e5 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -293,12 +293,6 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) /* ignore MAC address, we already have it from the boot loader */ snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version), "%d", wil->fw_version); -} - -static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d, - int len) -{ - wil_dbg_wmi(wil, "WMI: got FW ready event\n"); wil_set_recovery_state(wil, fw_recovery_idle); set_bit(wil_status_fwready, wil->status); @@ -684,13 +678,22 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) spin_unlock_bh(&sta->tid_rx_lock); } +/** + * Some events are ignored for purpose; and need not be interpreted as + * "unhandled events" + */ +static void wmi_evt_ignore(struct wil6210_priv *wil, int id, void *d, int len) +{ + wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len); +} + static const struct { int eventid; void (*handler)(struct wil6210_priv *wil, int eventid, void *data, int data_len); } wmi_evt_handlers[] = { {WMI_READY_EVENTID, wmi_evt_ready}, - {WMI_FW_READY_EVENTID, wmi_evt_fw_ready}, + {WMI_FW_READY_EVENTID, wmi_evt_ignore}, {WMI_RX_MGMT_PACKET_EVENTID, wmi_evt_rx_mgmt}, {WMI_TX_MGMT_PACKET_EVENTID, wmi_evt_tx_mgmt}, {WMI_SCAN_COMPLETE_EVENTID, wmi_evt_scan_complete}, @@ -701,6 +704,7 @@ static const struct { {WMI_RCP_ADDBA_REQ_EVENTID, wmi_evt_addba_rx_req}, {WMI_DELBA_EVENTID, wmi_evt_delba}, {WMI_VRING_EN_EVENTID, wmi_evt_vring_en}, + {WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_ignore}, }; /* @@ -720,7 +724,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) ulong flags; unsigned n; - if (!test_bit(wil_status_reset_done, wil->status)) { + if (!test_bit(wil_status_mbox_ready, wil->status)) { wil_err(wil, "Reset in progress. Cannot handle WMI event\n"); return; } @@ -1120,7 +1124,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP); cmd.sniffer_cfg.phy_support = cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL) - ? WMI_SNIFFER_CP : WMI_SNIFFER_DP); + ? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS); } else { /* Initialize offload (in non-sniffer mode). * Linux IP stack always calculates IP checksum diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 759fb8d41fc9..fba856032ca5 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -71,26 +71,6 @@ config B43_PCICORE_AUTOSELECT select SSB_DRIVER_PCICORE default y -config B43_PCMCIA - bool "Broadcom 43xx PCMCIA device support" - depends on B43 && B43_SSB && SSB_PCMCIAHOST_POSSIBLE - select SSB_PCMCIAHOST - ---help--- - Broadcom 43xx PCMCIA device support. - - Support for 16bit PCMCIA devices. - Please note that most PC-CARD devices are _NOT_ 16bit PCMCIA - devices, but 32bit CardBUS devices. CardBUS devices are supported - out of the box by b43. - - With this config option you can drive b43 cards in - CompactFlash formfactor in a PCMCIA adaptor. - CF b43 cards can sometimes be found in handheld PCs. - - It's safe to select Y here, even if you don't have a B43 PCMCIA device. - - If unsure, say N. - config B43_SDIO bool "Broadcom 43xx SDIO device support" depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index c624d4d90e4f..ddc4df46656f 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile @@ -21,7 +21,6 @@ b43-y += pio.o b43-y += rfkill.o b43-y += ppr.o b43-$(CONFIG_B43_LEDS) += leds.o -b43-$(CONFIG_B43_PCMCIA) += pcmcia.o b43-$(CONFIG_B43_SDIO) += sdio.o b43-$(CONFIG_B43_DEBUG) += debugfs.o diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 71d3e9adbf3c..ec013fbd6a81 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -56,7 +56,6 @@ #include "sysfs.h" #include "xmit.h" #include "lo.h" -#include "pcmcia.h" #include "sdio.h" #include <linux/mmc/sdio_func.h> @@ -5850,12 +5849,9 @@ static int __init b43_init(void) int err; b43_debugfs_init(); - err = b43_pcmcia_init(); - if (err) - goto err_dfs_exit; err = b43_sdio_init(); if (err) - goto err_pcmcia_exit; + goto err_dfs_exit; #ifdef CONFIG_B43_BCMA err = bcma_driver_register(&b43_bcma_driver); if (err) @@ -5878,8 +5874,6 @@ err_bcma_driver_exit: err_sdio_exit: #endif b43_sdio_exit(); -err_pcmcia_exit: - b43_pcmcia_exit(); err_dfs_exit: b43_debugfs_exit(); return err; @@ -5894,7 +5888,6 @@ static void __exit b43_exit(void) bcma_driver_unregister(&b43_bcma_driver); #endif b43_sdio_exit(); - b43_pcmcia_exit(); b43_debugfs_exit(); } diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c deleted file mode 100644 index 55f2bd7f8f74..000000000000 --- a/drivers/net/wireless/b43/pcmcia.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - - Broadcom B43 wireless driver - - Copyright (c) 2007 Michael Buesch <m@bues.ch> - - 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. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "pcmcia.h" - -#include <linux/ssb/ssb.h> -#include <linux/slab.h> -#include <linux/module.h> - -#include <pcmcia/cistpl.h> -#include <pcmcia/ciscode.h> -#include <pcmcia/ds.h> -#include <pcmcia/cisreg.h> - - -static const struct pcmcia_device_id b43_pcmcia_tbl[] = { - PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448), - PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476), - PCMCIA_DEVICE_NULL, -}; - -MODULE_DEVICE_TABLE(pcmcia, b43_pcmcia_tbl); - -#ifdef CONFIG_PM -static int b43_pcmcia_suspend(struct pcmcia_device *dev) -{ - struct ssb_bus *ssb = dev->priv; - - return ssb_bus_suspend(ssb); -} - -static int b43_pcmcia_resume(struct pcmcia_device *dev) -{ - struct ssb_bus *ssb = dev->priv; - - return ssb_bus_resume(ssb); -} -#else /* CONFIG_PM */ -# define b43_pcmcia_suspend NULL -# define b43_pcmcia_resume NULL -#endif /* CONFIG_PM */ - -static int b43_pcmcia_probe(struct pcmcia_device *dev) -{ - struct ssb_bus *ssb; - int err = -ENOMEM; - int res = 0; - - ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); - if (!ssb) - goto out_error; - - err = -ENODEV; - - dev->config_flags |= CONF_ENABLE_IRQ; - - dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 | - WIN_USE_WAIT; - dev->resource[2]->start = 0; - dev->resource[2]->end = SSB_CORE_SIZE; - res = pcmcia_request_window(dev, dev->resource[2], 250); - if (res != 0) - goto err_kfree_ssb; - - res = pcmcia_map_mem_page(dev, dev->resource[2], 0); - if (res != 0) - goto err_disable; - - if (!dev->irq) - goto err_disable; - - res = pcmcia_enable_device(dev); - if (res != 0) - goto err_disable; - - err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start); - if (err) - goto err_disable; - dev->priv = ssb; - - return 0; - -err_disable: - pcmcia_disable_device(dev); -err_kfree_ssb: - kfree(ssb); -out_error: - printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n", - res, err); - return err; -} - -static void b43_pcmcia_remove(struct pcmcia_device *dev) -{ - struct ssb_bus *ssb = dev->priv; - - ssb_bus_unregister(ssb); - pcmcia_disable_device(dev); - kfree(ssb); - dev->priv = NULL; -} - -static struct pcmcia_driver b43_pcmcia_driver = { - .owner = THIS_MODULE, - .name = "b43-pcmcia", - .id_table = b43_pcmcia_tbl, - .probe = b43_pcmcia_probe, - .remove = b43_pcmcia_remove, - .suspend = b43_pcmcia_suspend, - .resume = b43_pcmcia_resume, -}; - -/* - * These are not module init/exit functions! - * The module_pcmcia_driver() helper cannot be used here. - */ -int b43_pcmcia_init(void) -{ - return pcmcia_register_driver(&b43_pcmcia_driver); -} - -void b43_pcmcia_exit(void) -{ - pcmcia_unregister_driver(&b43_pcmcia_driver); -} diff --git a/drivers/net/wireless/b43/pcmcia.h b/drivers/net/wireless/b43/pcmcia.h deleted file mode 100644 index 85f120a67cbe..000000000000 --- a/drivers/net/wireless/b43/pcmcia.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef B43_PCMCIA_H_ -#define B43_PCMCIA_H_ - -#ifdef CONFIG_B43_PCMCIA - -int b43_pcmcia_init(void); -void b43_pcmcia_exit(void); - -#else /* CONFIG_B43_PCMCIA */ - -static inline int b43_pcmcia_init(void) -{ - return 0; -} -static inline void b43_pcmcia_exit(void) -{ -} - -#endif /* CONFIG_B43_PCMCIA */ -#endif /* B43_PCMCIA_H_ */ diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig index fe3dc126b149..ab42b1fea03c 100644 --- a/drivers/net/wireless/brcm80211/Kconfig +++ b/drivers/net/wireless/brcm80211/Kconfig @@ -82,5 +82,6 @@ config BRCM_TRACING config BRCMDBG bool "Broadcom driver debug functions" depends on BRCMSMAC || BRCMFMAC + select WANT_DEV_COREDUMP ---help--- Selecting this enables additional code for debug purposes. diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c index 8e0e91c4a0b1..288c84e7c56b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c @@ -272,10 +272,11 @@ brcmf_proto_bcdc_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, } static int -brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, - struct sk_buff *pktbuf) +brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, + struct sk_buff *pktbuf, struct brcmf_if **ifp) { struct brcmf_proto_bcdc_header *h; + struct brcmf_if *tmp_if; brcmf_dbg(BCDC, "Enter\n"); @@ -289,30 +290,21 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, trace_brcmf_bcdchdr(pktbuf->data); h = (struct brcmf_proto_bcdc_header *)(pktbuf->data); - *ifidx = BCDC_GET_IF_IDX(h); - if (*ifidx >= BRCMF_MAX_IFS) { - brcmf_err("rx data ifnum out of range (%d)\n", *ifidx); + tmp_if = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h)); + if (!tmp_if) { + brcmf_dbg(INFO, "no matching ifp found\n"); return -EBADE; } - /* The ifidx is the idx to map to matching netdev/ifp. When receiving - * events this is easy because it contains the bssidx which maps - * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. - * bssidx 1 is used for p2p0 and no data can be received or - * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 - */ - if (*ifidx) - (*ifidx)++; - if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) != BCDC_PROTO_VER) { brcmf_err("%s: non-BCDC packet received, flags 0x%x\n", - brcmf_ifname(drvr, *ifidx), h->flags); + brcmf_ifname(drvr, tmp_if->ifidx), h->flags); return -EBADE; } if (h->flags & BCDC_FLAG_SUM_GOOD) { brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n", - brcmf_ifname(drvr, *ifidx), h->flags); + brcmf_ifname(drvr, tmp_if->ifidx), h->flags); pktbuf->ip_summed = CHECKSUM_UNNECESSARY; } @@ -320,12 +312,14 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, skb_pull(pktbuf, BCDC_HEADER_LEN); if (do_fws) - brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf); + brcmf_fws_hdrpull(tmp_if, h->data_offset << 2, pktbuf); else skb_pull(pktbuf, h->data_offset << 2); if (pktbuf->len == 0) return -ENODATA; + + *ifp = tmp_if; return 0; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c index 0445163991b7..4e33f96b3dd1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c @@ -149,7 +149,7 @@ static s32 brcmf_btcoex_params_read(struct brcmf_if *ifp, u32 addr, u32 *data) static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci, bool trump_sco) { - struct brcmf_if *ifp = btci->cfg->pub->iflist[0]; + struct brcmf_if *ifp = brcmf_get_ifp(btci->cfg->pub, 0); if (trump_sco && !btci->saved_regs_part2) { /* this should reduce eSCO agressive @@ -468,7 +468,7 @@ int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif, { struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy); struct brcmf_btcoex_info *btci = cfg->btcoex; - struct brcmf_if *ifp = cfg->pub->iflist[0]; + struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); switch (mode) { case BRCMF_BTCOEX_DISABLED: diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/brcm80211/brcmfmac/bus.h index 89e6a4dc105e..230cad788ace 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/bus.h @@ -65,6 +65,8 @@ struct brcmf_bus_dcmd { * @rxctl: receive a control response message from dongle. * @gettxq: obtain a reference of bus transmit queue (optional). * @wowl_config: specify if dongle is configured for wowl when going to suspend + * @get_ramsize: obtain size of device memory. + * @get_memdump: obtain device memory dump in provided buffer. * * This structure provides an abstract interface towards the * bus specific driver. For control messages to common driver @@ -79,6 +81,8 @@ struct brcmf_bus_ops { int (*rxctl)(struct device *dev, unsigned char *msg, uint len); struct pktq * (*gettxq)(struct device *dev); void (*wowl_config)(struct device *dev, bool enabled); + size_t (*get_ramsize)(struct device *dev); + int (*get_memdump)(struct device *dev, void *data, size_t len); }; @@ -185,6 +189,23 @@ void brcmf_bus_wowl_config(struct brcmf_bus *bus, bool enabled) bus->ops->wowl_config(bus->dev, enabled); } +static inline size_t brcmf_bus_get_ramsize(struct brcmf_bus *bus) +{ + if (!bus->ops->get_ramsize) + return 0; + + return bus->ops->get_ramsize(bus->dev); +} + +static inline +int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len) +{ + if (!bus->ops->get_memdump) + return -EOPNOTSUPP; + + return bus->ops->get_memdump(bus->dev, data, len); +} + /* * interface functions from common layer */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index a293275c1b0b..deb5f78dcacc 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -236,89 +236,6 @@ static int brcmf_roamoff; module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR); MODULE_PARM_DESC(roamoff, "do not use internal roaming engine"); -/* Quarter dBm units to mW - * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 - * Table is offset so the last entry is largest mW value that fits in - * a u16. - */ - -#define QDBM_OFFSET 153 /* Offset for first entry */ -#define QDBM_TABLE_LEN 40 /* Table size */ - -/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. - * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 - */ -#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ - -/* Largest mW value that will round down to the last table entry, - * QDBM_OFFSET + QDBM_TABLE_LEN-1. - * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + - * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. - */ -#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ - -static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { -/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ -/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, -/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, -/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, -/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, -/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 -}; - -static u16 brcmf_qdbm_to_mw(u8 qdbm) -{ - uint factor = 1; - int idx = qdbm - QDBM_OFFSET; - - if (idx >= QDBM_TABLE_LEN) - /* clamp to max u16 mW value */ - return 0xFFFF; - - /* scale the qdBm index up to the range of the table 0-40 - * where an offset of 40 qdBm equals a factor of 10 mW. - */ - while (idx < 0) { - idx += 40; - factor *= 10; - } - - /* return the mW value scaled down to the correct factor of 10, - * adding in factor/2 to get proper rounding. - */ - return (nqdBm_to_mW_map[idx] + factor / 2) / factor; -} - -static u8 brcmf_mw_to_qdbm(u16 mw) -{ - u8 qdbm; - int offset; - uint mw_uint = mw; - uint boundary; - - /* handle boundary case */ - if (mw_uint <= 1) - return 0; - - offset = QDBM_OFFSET; - - /* move mw into the range of the table */ - while (mw_uint < QDBM_TABLE_LOW_BOUND) { - mw_uint *= 10; - offset -= 40; - } - - for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) { - boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] - - nqdBm_to_mW_map[qdbm]) / 2; - if (mw_uint < boundary) - break; - } - - qdbm += (u8) offset; - - return qdbm; -} static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, struct cfg80211_chan_def *ch) @@ -860,6 +777,37 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, s32 err = 0; brcmf_dbg(TRACE, "Enter, idx=%d, type=%d\n", ifp->bssidx, type); + + /* WAR: There are a number of p2p interface related problems which + * need to be handled initially (before doing the validate). + * wpa_supplicant tends to do iface changes on p2p device/client/go + * which are not always possible/allowed. However we need to return + * OK otherwise the wpa_supplicant wont start. The situation differs + * on configuration and setup (p2pon=1 module param). The first check + * is to see if the request is a change to station for p2p iface. + */ + if ((type == NL80211_IFTYPE_STATION) && + ((vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) || + (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) || + (vif->wdev.iftype == NL80211_IFTYPE_P2P_DEVICE))) { + brcmf_dbg(TRACE, "Ignoring cmd for p2p if\n"); + /* Now depending on whether module param p2pon=1 was used the + * response needs to be either 0 or EOPNOTSUPP. The reason is + * that if p2pon=1 is used, but a newer supplicant is used then + * we should return an error, as this combination wont work. + * In other situations 0 is returned and supplicant will start + * normally. It will give a trace in cfg80211, but it is the + * only way to get it working. Unfortunately this will result + * in situation where we wont support new supplicant in + * combination with module param p2pon=1, but that is the way + * it is. If the user tries this then unloading of driver might + * fail/lock. + */ + if (cfg->p2p.p2pdev_dynamically) + return -EOPNOTSUPP; + else + return 0; + } err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type); if (err) { brcmf_err("iface validation failed: err=%d\n", err); @@ -875,18 +823,6 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, infra = 0; break; case NL80211_IFTYPE_STATION: - /* Ignore change for p2p IF. Unclear why supplicant does this */ - if ((vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) || - (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) { - brcmf_dbg(TRACE, "Ignoring cmd for p2p if\n"); - /* WAR: It is unexpected to get a change of VIF for P2P - * IF, but it happens. The request can not be handled - * but returning EPERM causes a crash. Returning 0 - * without setting ieee80211_ptr->iftype causes trace - * (WARN_ON) but it works with wpa_supplicant - */ - return 0; - } infra = 1; break; case NL80211_IFTYPE_AP: @@ -904,7 +840,6 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_p2p_ifchange(cfg, BRCMF_FIL_P2P_IF_GO); } if (!err) { - set_bit(BRCMF_VIF_STATUS_AP_CREATING, &vif->sme_state); brcmf_dbg(INFO, "IF Type = AP\n"); } } else { @@ -2017,16 +1952,14 @@ static s32 brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, enum nl80211_tx_power_setting type, s32 mbm) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct net_device *ndev = cfg_to_ndev(cfg); struct brcmf_if *ifp = netdev_priv(ndev); - u16 txpwrmw; - s32 err = 0; - s32 disable = 0; - s32 dbm = MBM_TO_DBM(mbm); + s32 err; + s32 disable; + u32 qdbm = 127; - brcmf_dbg(TRACE, "Enter\n"); + brcmf_dbg(TRACE, "Enter %d %d\n", type, mbm); if (!check_vif_up(ifp->vif)) return -EIO; @@ -2035,12 +1968,20 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, break; case NL80211_TX_POWER_LIMITED: case NL80211_TX_POWER_FIXED: - if (dbm < 0) { + if (mbm < 0) { brcmf_err("TX_POWER_FIXED - dbm is negative\n"); err = -EINVAL; goto done; } + qdbm = MBM_TO_DBM(4 * mbm); + if (qdbm > 127) + qdbm = 127; + qdbm |= WL_TXPWR_OVERRIDE; break; + default: + brcmf_err("Unsupported type %d\n", type); + err = -EINVAL; + goto done; } /* Make sure radio is off or on as far as software is concerned */ disable = WL_RADIO_SW_DISABLE << 16; @@ -2048,52 +1989,44 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, if (err) brcmf_err("WLC_SET_RADIO error (%d)\n", err); - if (dbm > 0xffff) - txpwrmw = 0xffff; - else - txpwrmw = (u16) dbm; - err = brcmf_fil_iovar_int_set(ifp, "qtxpower", - (s32)brcmf_mw_to_qdbm(txpwrmw)); + err = brcmf_fil_iovar_int_set(ifp, "qtxpower", qdbm); if (err) brcmf_err("qtxpower error (%d)\n", err); - cfg->conf->tx_power = dbm; done: - brcmf_dbg(TRACE, "Exit\n"); + brcmf_dbg(TRACE, "Exit %d (qdbm)\n", qdbm & ~WL_TXPWR_OVERRIDE); return err; } -static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, - struct wireless_dev *wdev, - s32 *dbm) +static s32 +brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, + s32 *dbm) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); - s32 txpwrdbm; - u8 result; - s32 err = 0; + struct net_device *ndev = cfg_to_ndev(cfg); + struct brcmf_if *ifp = netdev_priv(ndev); + s32 qdbm = 0; + s32 err; brcmf_dbg(TRACE, "Enter\n"); if (!check_vif_up(ifp->vif)) return -EIO; - err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &txpwrdbm); + err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &qdbm); if (err) { brcmf_err("error (%d)\n", err); goto done; } - - result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE); - *dbm = (s32) brcmf_qdbm_to_mw(result); + *dbm = (qdbm & ~WL_TXPWR_OVERRIDE) / 4; done: - brcmf_dbg(TRACE, "Exit\n"); + brcmf_dbg(TRACE, "Exit (0x%x %d)\n", qdbm, *dbm); return err; } static s32 brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, - u8 key_idx, bool unicast, bool multicast) + u8 key_idx, bool unicast, bool multicast) { struct brcmf_if *ifp = netdev_priv(ndev); u32 index; @@ -2498,6 +2431,9 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, struct brcmf_sta_info_le sta_info_le; u32 sta_flags; u32 is_tdls_peer; + s32 total_rssi; + s32 count_rssi; + u32 i; brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac); if (!check_vif_up(ifp->vif)) @@ -2544,13 +2480,13 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts); if (sinfo->tx_packets) { sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); - sinfo->txrate.legacy = le32_to_cpu(sta_info_le.tx_rate); - sinfo->txrate.legacy /= 100; + sinfo->txrate.legacy = + le32_to_cpu(sta_info_le.tx_rate) / 100; } if (sinfo->rx_packets) { sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE); - sinfo->rxrate.legacy = le32_to_cpu(sta_info_le.rx_rate); - sinfo->rxrate.legacy /= 100; + sinfo->rxrate.legacy = + le32_to_cpu(sta_info_le.rx_rate) / 100; } if (le16_to_cpu(sta_info_le.ver) >= 4) { sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES); @@ -2558,12 +2494,61 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES); sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes); } + total_rssi = 0; + count_rssi = 0; + for (i = 0; i < BRCMF_ANT_MAX; i++) { + if (sta_info_le.rssi[i]) { + sinfo->chain_signal_avg[count_rssi] = + sta_info_le.rssi[i]; + sinfo->chain_signal[count_rssi] = + sta_info_le.rssi[i]; + total_rssi += sta_info_le.rssi[i]; + count_rssi++; + } + } + if (count_rssi) { + sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL); + sinfo->chains = count_rssi; + + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); + total_rssi /= count_rssi; + sinfo->signal = total_rssi; + } } done: brcmf_dbg(TRACE, "Exit\n"); return err; } +static int +brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev, + int idx, u8 *mac, struct station_info *sinfo) +{ + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_if *ifp = netdev_priv(ndev); + s32 err; + + brcmf_dbg(TRACE, "Enter, idx %d\n", idx); + + if (idx == 0) { + cfg->assoclist.count = cpu_to_le32(BRCMF_MAX_ASSOCLIST); + err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_ASSOCLIST, + &cfg->assoclist, + sizeof(cfg->assoclist)); + if (err) { + brcmf_err("BRCMF_C_GET_ASSOCLIST unsupported, err=%d\n", + err); + cfg->assoclist.count = 0; + return -EOPNOTSUPP; + } + } + if (idx < le32_to_cpu(cfg->assoclist.count)) { + memcpy(mac, cfg->assoclist.mac[idx], ETH_ALEN); + return brcmf_cfg80211_get_station(wiphy, ndev, mac, sinfo); + } + return -ENOENT; +} + static s32 brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, bool enabled, s32 timeout) @@ -4265,8 +4250,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, brcmf_dbg(TRACE, "GO mode configuration complete\n"); } - clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); + brcmf_net_setcarrier(ifp, true); exit: if ((err) && (!mbss)) { @@ -4330,8 +4315,8 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) } brcmf_set_mpc(ifp, 1); brcmf_configure_arp_offload(ifp, true); - set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); + brcmf_net_setcarrier(ifp, false); return err; } @@ -4663,6 +4648,7 @@ static struct cfg80211_ops wl_cfg80211_ops = { .join_ibss = brcmf_cfg80211_join_ibss, .leave_ibss = brcmf_cfg80211_leave_ibss, .get_station = brcmf_cfg80211_get_station, + .dump_station = brcmf_cfg80211_dump_station, .set_tx_power = brcmf_cfg80211_set_tx_power, .get_tx_power = brcmf_cfg80211_get_tx_power, .add_key = brcmf_cfg80211_add_key, @@ -4747,7 +4733,8 @@ void brcmf_cfg80211_free_netdev(struct net_device *ndev) ifp = netdev_priv(ndev); vif = ifp->vif; - brcmf_free_vif(vif); + if (vif) + brcmf_free_vif(vif); free_netdev(ndev); } @@ -4983,7 +4970,7 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg, brcmf_dbg(CONN, "AP mode link down\n"); complete(&cfg->vif_disabled); if (ifp->vif->mbss) - brcmf_remove_interface(ifp->drvr, ifp->bssidx); + brcmf_remove_interface(ifp); return 0; } @@ -5039,6 +5026,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, &ifp->vif->sme_state); } else brcmf_bss_connect_done(cfg, ndev, e, true); + brcmf_net_setcarrier(ifp, true); } else if (brcmf_is_linkdown(e)) { brcmf_dbg(CONN, "Linkdown\n"); if (!brcmf_is_ibssmode(ifp->vif)) { @@ -5048,6 +5036,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, brcmf_init_prof(ndev_to_prof(ndev)); if (ndev != cfg_to_ndev(cfg)) complete(&cfg->vif_disabled); + brcmf_net_setcarrier(ifp, false); } else if (brcmf_is_nonetwork(cfg, e)) { if (brcmf_is_ibssmode(ifp->vif)) clear_bit(BRCMF_VIF_STATUS_CONNECTING, @@ -6211,9 +6200,10 @@ static void brcmf_free_wiphy(struct wiphy *wiphy) } struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, - struct device *busdev) + struct device *busdev, + bool p2pdev_forced) { - struct net_device *ndev = drvr->iflist[0]->ndev; + struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev; struct brcmf_cfg80211_info *cfg; struct wiphy *wiphy; struct brcmf_cfg80211_vif *vif; @@ -6302,8 +6292,19 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, else *cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; } + /* p2p might require that "if-events" get processed by fweh. So + * activate the already registered event handlers now and activate + * the rest when initialization has completed. drvr->config needs to + * be assigned before activating events. + */ + drvr->config = cfg; + err = brcmf_fweh_activate_events(ifp); + if (err) { + brcmf_err("FWEH activation failed (%d)\n", err); + goto wiphy_unreg_out; + } - err = brcmf_p2p_attach(cfg); + err = brcmf_p2p_attach(cfg, p2pdev_forced); if (err) { brcmf_err("P2P initilisation failed (%d)\n", err); goto wiphy_unreg_out; @@ -6324,6 +6325,13 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, brcmf_notify_tdls_peer_event); } + /* (re-) activate FWEH event handling */ + err = brcmf_fweh_activate_events(ifp); + if (err) { + brcmf_err("FWEH activation failed (%d)\n", err); + goto wiphy_unreg_out; + } + return cfg; wiphy_unreg_out: @@ -6331,6 +6339,7 @@ wiphy_unreg_out: priv_out: wl_deinit_priv(cfg); brcmf_free_vif(vif); + ifp->vif = NULL; wiphy_out: brcmf_free_wiphy(wiphy); return NULL; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h index d9e6d01b2b69..6a878c8f883f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h @@ -143,7 +143,6 @@ struct brcmf_cfg80211_profile { * @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress. * @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully. * @BRCMF_VIF_STATUS_DISCONNECTING: disconnect/disable in progress. - * @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation. * @BRCMF_VIF_STATUS_AP_CREATED: AP operation started. */ enum brcmf_vif_status { @@ -151,7 +150,6 @@ enum brcmf_vif_status { BRCMF_VIF_STATUS_CONNECTING, BRCMF_VIF_STATUS_CONNECTED, BRCMF_VIF_STATUS_DISCONNECTING, - BRCMF_VIF_STATUS_AP_CREATING, BRCMF_VIF_STATUS_AP_CREATED }; @@ -407,6 +405,7 @@ struct brcmf_cfg80211_info { struct brcmu_d11inf d11inf; bool wowl_enabled; u32 pre_wowl_pmmode; + struct brcmf_assoclist_le assoclist; }; /** @@ -469,7 +468,8 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg) } struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, - struct device *busdev); + struct device *busdev, + bool p2pdev_forced); void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg); s32 brcmf_cfg80211_up(struct net_device *ndev); s32 brcmf_cfg80211_down(struct net_device *ndev); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c index 288f8314f208..f04833db2fd0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c @@ -101,6 +101,9 @@ /* ARM Cortex M3 core, ID 0x82a */ #define BCM4329_CORE_ARM_BASE 0x18002000 +/* Max possibly supported memory size (limited by IO mapped memory) */ +#define BRCMF_CHIP_MAX_MEMSIZE (4 * 1024 * 1024) + #define CORE_SB(base, field) \ (base + SBCONFIGOFF + offsetof(struct sbconfig, field)) #define SBCOREREV(sbidh) \ @@ -205,6 +208,7 @@ struct sbsocramregs { }; #define SOCRAMREGOFFS(_f) offsetof(struct sbsocramregs, _f) +#define SYSMEMREGOFFS(_f) offsetof(struct sbsocramregs, _f) #define ARMCR4_CAP (0x04) #define ARMCR4_BANKIDX (0x40) @@ -513,6 +517,9 @@ static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) case BCMA_CORE_ARM_CR4: cpu_found = true; break; + case BCMA_CORE_ARM_CA7: + cpu_found = true; + break; default: break; } @@ -611,6 +618,29 @@ static void brcmf_chip_socram_ramsize(struct brcmf_core_priv *sr, u32 *ramsize, } } +/** Return the SYS MEM size */ +static u32 brcmf_chip_sysmem_ramsize(struct brcmf_core_priv *sysmem) +{ + u32 memsize = 0; + u32 coreinfo; + u32 idx; + u32 nb; + u32 banksize; + + if (!brcmf_chip_iscoreup(&sysmem->pub)) + brcmf_chip_resetcore(&sysmem->pub, 0, 0, 0); + + coreinfo = brcmf_chip_core_read32(sysmem, SYSMEMREGOFFS(coreinfo)); + nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; + + for (idx = 0; idx < nb; idx++) { + brcmf_chip_socram_banksize(sysmem, idx, &banksize); + memsize += banksize; + } + + return memsize; +} + /** Return the TCM-RAM size of the ARMCR4 core. */ static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4) { @@ -644,6 +674,7 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) return 0x198000; case BRCM_CC_4335_CHIP_ID: case BRCM_CC_4339_CHIP_ID: + case BRCM_CC_4350_CHIP_ID: case BRCM_CC_4354_CHIP_ID: case BRCM_CC_4356_CHIP_ID: case BRCM_CC_43567_CHIP_ID: @@ -651,7 +682,11 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) case BRCM_CC_43570_CHIP_ID: case BRCM_CC_4358_CHIP_ID: case BRCM_CC_43602_CHIP_ID: + case BRCM_CC_4371_CHIP_ID: return 0x180000; + case BRCM_CC_4365_CHIP_ID: + case BRCM_CC_4366_CHIP_ID: + return 0x200000; default: brcmf_err("unknown chip: %s\n", ci->pub.name); break; @@ -674,10 +709,28 @@ static int brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) return -EINVAL; } } else { - mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_INTERNAL_MEM); - mem_core = container_of(mem, struct brcmf_core_priv, pub); - brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize, - &ci->pub.srsize); + mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_SYS_MEM); + if (mem) { + mem_core = container_of(mem, struct brcmf_core_priv, + pub); + ci->pub.ramsize = brcmf_chip_sysmem_ramsize(mem_core); + ci->pub.rambase = brcmf_chip_tcm_rambase(ci); + if (!ci->pub.rambase) { + brcmf_err("RAM base not provided with ARM CA7 core\n"); + return -EINVAL; + } + } else { + mem = brcmf_chip_get_core(&ci->pub, + BCMA_CORE_INTERNAL_MEM); + if (!mem) { + brcmf_err("No memory cores found\n"); + return -ENOMEM; + } + mem_core = container_of(mem, struct brcmf_core_priv, + pub); + brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize, + &ci->pub.srsize); + } } brcmf_dbg(INFO, "RAM: base=0x%x size=%d (0x%x) sr=%d (0x%x)\n", ci->pub.rambase, ci->pub.ramsize, ci->pub.ramsize, @@ -687,6 +740,12 @@ static int brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) brcmf_err("RAM size is undetermined\n"); return -ENOMEM; } + + if (ci->pub.ramsize > BRCMF_CHIP_MAX_MEMSIZE) { + brcmf_err("RAM size is incorrect\n"); + return -ENOMEM; + } + return 0; } @@ -899,13 +958,22 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) /* assure chip is passive for core access */ brcmf_chip_set_passive(&ci->pub); + + /* Call bus specific reset function now. Cores have been determined + * but further access may require a chip specific reset at this point. + */ + if (ci->ops->reset) { + ci->ops->reset(ci->ctx, &ci->pub); + brcmf_chip_set_passive(&ci->pub); + } + return brcmf_chip_get_raminfo(ci); } static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id) { struct brcmf_core *core; - struct brcmf_core_priv *cr4; + struct brcmf_core_priv *cpu; u32 val; @@ -918,10 +986,11 @@ static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id) brcmf_chip_coredisable(core, 0, 0); break; case BCMA_CORE_ARM_CR4: - cr4 = container_of(core, struct brcmf_core_priv, pub); + case BCMA_CORE_ARM_CA7: + cpu = container_of(core, struct brcmf_core_priv, pub); /* clear all IOCTL bits except HALT bit */ - val = chip->ops->read32(chip->ctx, cr4->wrapbase + BCMA_IOCTL); + val = chip->ops->read32(chip->ctx, cpu->wrapbase + BCMA_IOCTL); val &= ARMCR4_BCMA_IOCTL_CPUHALT; brcmf_chip_resetcore(core, val, ARMCR4_BCMA_IOCTL_CPUHALT, ARMCR4_BCMA_IOCTL_CPUHALT); @@ -1143,6 +1212,33 @@ static bool brcmf_chip_cr4_set_active(struct brcmf_chip_priv *chip, u32 rstvec) return true; } +static inline void +brcmf_chip_ca7_set_passive(struct brcmf_chip_priv *chip) +{ + struct brcmf_core *core; + + brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CA7); + + core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211); + brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET | + D11_BCMA_IOCTL_PHYCLOCKEN, + D11_BCMA_IOCTL_PHYCLOCKEN, + D11_BCMA_IOCTL_PHYCLOCKEN); +} + +static bool brcmf_chip_ca7_set_active(struct brcmf_chip_priv *chip, u32 rstvec) +{ + struct brcmf_core *core; + + chip->ops->activate(chip->ctx, &chip->pub, rstvec); + + /* restore ARM */ + core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CA7); + brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0); + + return true; +} + void brcmf_chip_set_passive(struct brcmf_chip *pub) { struct brcmf_chip_priv *chip; @@ -1156,8 +1252,16 @@ void brcmf_chip_set_passive(struct brcmf_chip *pub) brcmf_chip_cr4_set_passive(chip); return; } - - brcmf_chip_cm3_set_passive(chip); + arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7); + if (arm) { + brcmf_chip_ca7_set_passive(chip); + return; + } + arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3); + if (arm) { + brcmf_chip_cm3_set_passive(chip); + return; + } } bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec) @@ -1171,8 +1275,14 @@ bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec) arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4); if (arm) return brcmf_chip_cr4_set_active(chip, rstvec); + arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7); + if (arm) + return brcmf_chip_ca7_set_active(chip, rstvec); + arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3); + if (arm) + return brcmf_chip_cm3_set_active(chip); - return brcmf_chip_cm3_set_active(chip); + return false; } bool brcmf_chip_sr_capable(struct brcmf_chip *pub) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/brcm80211/brcmfmac/chip.h index 60dcb38fc77a..f6b5feea23d2 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h @@ -73,6 +73,7 @@ struct brcmf_buscore_ops { u32 (*read32)(void *ctx, u32 addr); void (*write32)(void *ctx, u32 addr, u32 value); int (*prepare)(void *ctx); + int (*reset)(void *ctx, struct brcmf_chip *chip); int (*setup)(void *ctx, struct brcmf_chip *chip); void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec); }; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/common.h b/drivers/net/wireless/brcm80211/brcmfmac/common.h index 0d39d80cee28..21c7488b4732 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/common.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/common.h @@ -17,4 +17,7 @@ extern const u8 ALLFFMAC[ETH_ALEN]; +/* Sets dongle media info (drv_version, mac address). */ +int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); + #endif /* BRCMFMAC_COMMON_H */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index fe9d3fbf5fe2..b5ab98ee1445 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -33,6 +33,7 @@ #include "feature.h" #include "proto.h" #include "pcie.h" +#include "common.h" MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); @@ -53,6 +54,8 @@ MODULE_LICENSE("Dual BSD/GPL"); #define BRCMF_RXREORDER_EXPIDX_VALID 0x08 #define BRCMF_RXREORDER_NEW_HOLE 0x10 +#define BRCMF_BSSIDX_INVALID -1 + /* Error bits */ int brcmf_msg_level; module_param_named(debug, brcmf_msg_level, int, S_IRUSR | S_IWUSR); @@ -60,10 +63,8 @@ MODULE_PARM_DESC(debug, "level of debug output"); /* P2P0 enable */ static int brcmf_p2p_enable; -#ifdef CONFIG_BRCMDBG module_param_named(p2pon, brcmf_p2p_enable, int, 0); -MODULE_PARM_DESC(p2pon, "enable p2p management functionality"); -#endif +MODULE_PARM_DESC(p2pon, "enable legacy p2p management functionality"); char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx) { @@ -83,6 +84,24 @@ char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx) return "<if_none>"; } +struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx) +{ + struct brcmf_if *ifp; + s32 bssidx; + + if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { + brcmf_err("ifidx %d out of range\n", ifidx); + return NULL; + } + + ifp = NULL; + bssidx = drvr->if2bss[ifidx]; + if (bssidx >= 0) + ifp = drvr->iflist[bssidx]; + + return ifp; +} + static void _brcmf_set_multicast_list(struct work_struct *work) { struct brcmf_if *ifp; @@ -520,17 +539,15 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb) struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_pub *drvr = bus_if->drvr; struct brcmf_skb_reorder_data *rd; - u8 ifidx; int ret; brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb); /* process and remove protocol-specific header */ - ret = brcmf_proto_hdrpull(drvr, true, &ifidx, skb); - ifp = drvr->iflist[ifidx]; + ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp); if (ret || !ifp || !ifp->ndev) { - if ((ret != -ENODATA) && ifp) + if (ret != -ENODATA && ifp) ifp->stats.rx_errors++; brcmu_pkt_buf_free_skb(skb); return; @@ -543,17 +560,11 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb) brcmf_netif_rx(ifp, skb); } -void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, - bool success) +void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success) { - struct brcmf_if *ifp; struct ethhdr *eh; u16 type; - ifp = drvr->iflist[ifidx]; - if (!ifp) - goto done; - eh = (struct ethhdr *)(txp->data); type = ntohs(eh->h_proto); @@ -565,7 +576,7 @@ void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, if (!success) ifp->stats.tx_errors++; -done: + brcmu_pkt_buf_free_skb(txp); } @@ -573,17 +584,17 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) { struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_pub *drvr = bus_if->drvr; - u8 ifidx; + struct brcmf_if *ifp; /* await txstatus signal for firmware if active */ if (brcmf_fws_fc_active(drvr->fws)) { if (!success) brcmf_fws_bustxfail(drvr->fws, txp); } else { - if (brcmf_proto_hdrpull(drvr, false, &ifidx, txp)) + if (brcmf_proto_hdrpull(drvr, false, txp, &ifp)) brcmu_pkt_buf_free_skb(txp); else - brcmf_txfinalize(drvr, txp, ifidx, success); + brcmf_txfinalize(ifp, txp, success); } } @@ -624,8 +635,7 @@ static int brcmf_netdev_stop(struct net_device *ndev) brcmf_cfg80211_down(ndev); - /* Set state and stop OS transmissions */ - netif_stop_queue(ndev); + brcmf_net_setcarrier(ifp, false); return 0; } @@ -659,8 +669,8 @@ static int brcmf_netdev_open(struct net_device *ndev) return -EIO; } - /* Allow transmit calls */ - netif_start_queue(ndev); + /* Clear, carrier, set when connected or AP mode. */ + netif_carrier_off(ndev); return 0; } @@ -708,8 +718,6 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked) } brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); - - ndev->destructor = brcmf_cfg80211_free_netdev; return 0; fail: @@ -719,6 +727,32 @@ fail: return -EBADE; } +static void brcmf_net_detach(struct net_device *ndev) +{ + if (ndev->reg_state == NETREG_REGISTERED) + unregister_netdev(ndev); + else + brcmf_cfg80211_free_netdev(ndev); +} + +void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on) +{ + struct net_device *ndev; + + brcmf_dbg(TRACE, "Enter, idx=%d carrier=%d\n", ifp->bssidx, on); + + ndev = ifp->ndev; + brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_DISCONNECTED, !on); + if (on) { + if (!netif_carrier_ok(ndev)) + netif_carrier_on(ndev); + + } else { + if (netif_carrier_ok(ndev)) + netif_carrier_off(ndev); + } +} + static int brcmf_net_p2p_open(struct net_device *ndev) { brcmf_dbg(TRACE, "Enter\n"); @@ -778,7 +812,7 @@ fail: } struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, - char *name, u8 *mac_addr) + bool is_p2pdev, char *name, u8 *mac_addr) { struct brcmf_if *ifp; struct net_device *ndev; @@ -795,8 +829,7 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, ifp->ndev->name); if (ifidx) { netif_stop_queue(ifp->ndev); - unregister_netdev(ifp->ndev); - free_netdev(ifp->ndev); + brcmf_net_detach(ifp->ndev); drvr->iflist[bssidx] = NULL; } else { brcmf_err("ignore IF event\n"); @@ -804,7 +837,7 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, } } - if (!brcmf_p2p_enable && bssidx == 1) { + if (!brcmf_p2p_enable && is_p2pdev) { /* this is P2P_DEVICE interface */ brcmf_dbg(INFO, "allocate non-netdev interface\n"); ifp = kzalloc(sizeof(*ifp), GFP_KERNEL); @@ -813,13 +846,17 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, } else { brcmf_dbg(INFO, "allocate netdev interface\n"); /* Allocate netdev, including space for private structure */ - ndev = alloc_netdev(sizeof(*ifp), name, NET_NAME_UNKNOWN, - ether_setup); + ndev = alloc_netdev(sizeof(*ifp), is_p2pdev ? "p2p%d" : name, + NET_NAME_UNKNOWN, ether_setup); if (!ndev) return ERR_PTR(-ENOMEM); + ndev->destructor = brcmf_cfg80211_free_netdev; ifp = netdev_priv(ndev); ifp->ndev = ndev; + /* store mapping ifidx to bssidx */ + if (drvr->if2bss[ifidx] == BRCMF_BSSIDX_INVALID) + drvr->if2bss[ifidx] = bssidx; } ifp->drvr = drvr; @@ -850,6 +887,8 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) return; } brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx); + if (drvr->if2bss[ifp->ifidx] == bssidx) + drvr->if2bss[ifp->ifidx] = BRCMF_BSSIDX_INVALID; if (ifp->ndev) { if (bssidx == 0) { if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { @@ -865,17 +904,28 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) cancel_work_sync(&ifp->setmacaddr_work); cancel_work_sync(&ifp->multicast_work); } - /* unregister will take care of freeing it */ - unregister_netdev(ifp->ndev); + brcmf_net_detach(ifp->ndev); + } else { + /* Only p2p device interfaces which get dynamically created + * end up here. In this case the p2p module should be informed + * about the removal of the interface within the firmware. If + * not then p2p commands towards the firmware will cause some + * serious troublesome side effects. The p2p module will clean + * up the ifp if needed. + */ + brcmf_p2p_ifp_removed(ifp); + kfree(ifp); } } -void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx) +void brcmf_remove_interface(struct brcmf_if *ifp) { - if (drvr->iflist[bssidx]) { - brcmf_fws_del_interface(drvr->iflist[bssidx]); - brcmf_del_if(drvr, bssidx); - } + if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bssidx] != ifp)) + return; + brcmf_dbg(TRACE, "Enter, bssidx=%d, ifidx=%d\n", ifp->bssidx, + ifp->ifidx); + brcmf_fws_del_interface(ifp); + brcmf_del_if(ifp->drvr, ifp->bssidx); } int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr) @@ -906,6 +956,7 @@ int brcmf_attach(struct device *dev) { struct brcmf_pub *drvr = NULL; int ret = 0; + int i; brcmf_dbg(TRACE, "Enter\n"); @@ -914,6 +965,9 @@ int brcmf_attach(struct device *dev) if (!drvr) return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(drvr->if2bss); i++) + drvr->if2bss[i] = BRCMF_BSSIDX_INVALID; + mutex_init(&drvr->proto_block); /* Link to bus module */ @@ -921,8 +975,8 @@ int brcmf_attach(struct device *dev) drvr->bus_if = dev_get_drvdata(dev); drvr->bus_if->drvr = drvr; - /* create device debugfs folder */ - brcmf_debugfs_attach(drvr); + /* attach debug facilities */ + brcmf_debug_attach(drvr); /* Attach and link in the protocol */ ret = brcmf_proto_attach(drvr); @@ -981,16 +1035,11 @@ int brcmf_bus_start(struct device *dev) brcmf_dbg(TRACE, "\n"); /* add primary networking interface */ - ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL); + ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d", NULL); if (IS_ERR(ifp)) return PTR_ERR(ifp); - if (brcmf_p2p_enable) - p2p_ifp = brcmf_add_if(drvr, 1, 0, "p2p%d", NULL); - else - p2p_ifp = NULL; - if (IS_ERR(p2p_ifp)) - p2p_ifp = NULL; + p2p_ifp = NULL; /* signal bus ready */ brcmf_bus_change_state(bus_if, BRCMF_BUS_UP); @@ -1017,39 +1066,37 @@ int brcmf_bus_start(struct device *dev) brcmf_fws_add_interface(ifp); - drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev); + drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev, + brcmf_p2p_enable); if (drvr->config == NULL) { ret = -ENOMEM; goto fail; } - ret = brcmf_fweh_activate_events(ifp); - if (ret < 0) - goto fail; - ret = brcmf_net_attach(ifp, false); + + if ((!ret) && (brcmf_p2p_enable)) { + p2p_ifp = drvr->iflist[1]; + if (p2p_ifp) + ret = brcmf_net_p2p_attach(p2p_ifp); + } fail: if (ret < 0) { brcmf_err("failed: %d\n", ret); - brcmf_cfg80211_detach(drvr->config); + if (drvr->config) { + brcmf_cfg80211_detach(drvr->config); + drvr->config = NULL; + } if (drvr->fws) { brcmf_fws_del_interface(ifp); brcmf_fws_deinit(drvr); } - if (drvr->iflist[0]) { - free_netdev(ifp->ndev); - drvr->iflist[0] = NULL; - } - if (p2p_ifp) { - free_netdev(p2p_ifp->ndev); - drvr->iflist[1] = NULL; - } + if (ifp) + brcmf_net_detach(ifp->ndev); + if (p2p_ifp) + brcmf_net_detach(p2p_ifp->ndev); return ret; } - if ((brcmf_p2p_enable) && (p2p_ifp)) - if (brcmf_net_p2p_attach(p2p_ifp) < 0) - brcmf_p2p_enable = 0; - return 0; } @@ -1105,7 +1152,7 @@ void brcmf_detach(struct device *dev) /* make sure primary interface removed last */ for (i = BRCMF_MAX_IFS-1; i > -1; i--) - brcmf_remove_interface(drvr, i); + brcmf_remove_interface(drvr->iflist[i]); brcmf_cfg80211_detach(drvr->config); @@ -1115,7 +1162,7 @@ void brcmf_detach(struct device *dev) brcmf_proto_detach(drvr); - brcmf_debugfs_detach(drvr); + brcmf_debug_detach(drvr); bus_if->drvr = NULL; kfree(drvr); } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h index 746304121cdb..2f9101b2ad34 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h @@ -122,6 +122,7 @@ struct brcmf_pub { struct mac_address addresses[BRCMF_MAX_IFS]; struct brcmf_if *iflist[BRCMF_MAX_IFS]; + s32 if2bss[BRCMF_MAX_IFS]; struct mutex proto_block; unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; @@ -153,10 +154,13 @@ struct brcmf_fws_mac_descriptor; * netif stopped due to firmware signalling flow control. * @BRCMF_NETIF_STOP_REASON_FLOW: * netif stopped due to flowring full. + * @BRCMF_NETIF_STOP_REASON_DISCONNECTED: + * netif stopped due to not being connected (STA mode). */ enum brcmf_netif_stop_reason { - BRCMF_NETIF_STOP_REASON_FWS_FC = 1, - BRCMF_NETIF_STOP_REASON_FLOW = 2 + BRCMF_NETIF_STOP_REASON_FWS_FC = BIT(0), + BRCMF_NETIF_STOP_REASON_FLOW = BIT(1), + BRCMF_NETIF_STOP_REASON_DISCONNECTED = BIT(2) }; /** @@ -202,19 +206,16 @@ int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp); /* Return pointer to interface name */ char *brcmf_ifname(struct brcmf_pub *drvr, int idx); - +struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx); int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, - char *name, u8 *mac_addr); -void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx); + bool is_p2pdev, char *name, u8 *mac_addr); +void brcmf_remove_interface(struct brcmf_if *ifp); int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr); void brcmf_txflowblock_if(struct brcmf_if *ifp, enum brcmf_netif_stop_reason reason, bool state); -void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, - bool success); +void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); - -/* Sets dongle media info (drv_version, mac address). */ -int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); +void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); #endif /* BRCMFMAC_CORE_H */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/debug.c b/drivers/net/wireless/brcm80211/brcmfmac/debug.c index 2d6d00553858..1299dccc78b4 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/debug.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.c @@ -16,15 +16,45 @@ #include <linux/debugfs.h> #include <linux/netdevice.h> #include <linux/module.h> +#include <linux/devcoredump.h> #include <brcmu_wifi.h> #include <brcmu_utils.h> #include "core.h" #include "bus.h" +#include "fweh.h" #include "debug.h" static struct dentry *root_folder; +static int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data, + size_t len) +{ + void *dump; + size_t ramsize; + + ramsize = brcmf_bus_get_ramsize(bus); + if (ramsize) { + dump = vzalloc(len + ramsize); + if (!dump) + return -ENOMEM; + memcpy(dump, data, len); + brcmf_bus_get_memdump(bus, dump + len, ramsize); + dev_coredumpv(bus->dev, dump, len + ramsize, GFP_KERNEL); + } + return 0; +} + +static int brcmf_debug_psm_watchdog_notify(struct brcmf_if *ifp, + const struct brcmf_event_msg *evtmsg, + void *data) +{ + brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx); + + return brcmf_debug_create_memdump(ifp->drvr->bus_if, data, + evtmsg->datalen); +} + void brcmf_debugfs_init(void) { root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL); @@ -41,7 +71,7 @@ void brcmf_debugfs_exit(void) root_folder = NULL; } -int brcmf_debugfs_attach(struct brcmf_pub *drvr) +int brcmf_debug_attach(struct brcmf_pub *drvr) { struct device *dev = drvr->bus_if->dev; @@ -49,12 +79,18 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr) return -ENODEV; drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); + if (IS_ERR(drvr->dbgfs_dir)) + return PTR_ERR(drvr->dbgfs_dir); - return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); + + return brcmf_fweh_register(drvr, BRCMF_E_PSM_WATCHDOG, + brcmf_debug_psm_watchdog_notify); } -void brcmf_debugfs_detach(struct brcmf_pub *drvr) +void brcmf_debug_detach(struct brcmf_pub *drvr) { + brcmf_fweh_unregister(drvr, BRCMF_E_PSM_WATCHDOG); + if (!IS_ERR_OR_NULL(drvr->dbgfs_dir)) debugfs_remove_recursive(drvr->dbgfs_dir); } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/brcm80211/brcmfmac/debug.h index eb0b8c47479d..d0d9676f7f9d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/debug.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.h @@ -37,6 +37,7 @@ #define BRCMF_SDIO_VAL 0x00020000 #define BRCMF_MSGBUF_VAL 0x00040000 #define BRCMF_PCIE_VAL 0x00080000 +#define BRCMF_FWCON_VAL 0x00100000 /* set default print format */ #undef pr_fmt @@ -78,6 +79,7 @@ do { \ #define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL) #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) #else /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */ @@ -90,6 +92,7 @@ do { \ #define BRCMF_GLOM_ON() 0 #define BRCMF_EVENT_ON() 0 #define BRCMF_FIL_ON() 0 +#define BRCMF_FWCON_ON() 0 #endif /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */ @@ -106,8 +109,8 @@ struct brcmf_pub; #ifdef DEBUG void brcmf_debugfs_init(void); void brcmf_debugfs_exit(void); -int brcmf_debugfs_attach(struct brcmf_pub *drvr); -void brcmf_debugfs_detach(struct brcmf_pub *drvr); +int brcmf_debug_attach(struct brcmf_pub *drvr); +void brcmf_debug_detach(struct brcmf_pub *drvr); struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, int (*read_fn)(struct seq_file *seq, void *data)); @@ -118,11 +121,11 @@ static inline void brcmf_debugfs_init(void) static inline void brcmf_debugfs_exit(void) { } -static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr) +static inline int brcmf_debug_attach(struct brcmf_pub *drvr) { return 0; } -static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) +static inline void brcmf_debug_detach(struct brcmf_pub *drvr) { } static inline diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/brcm80211/brcmfmac/feature.c index 1e94e94e01dc..44bb30636690 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c @@ -15,6 +15,7 @@ */ #include <linux/netdevice.h> +#include <linux/module.h> #include <brcm_hw_ids.h> #include "core.h" @@ -23,6 +24,12 @@ #include "fwil.h" #include "feature.h" + +/* Module param feature_disable (global for all devices) */ +static int brcmf_feature_disable; +module_param_named(feature_disable, brcmf_feature_disable, int, 0); +MODULE_PARM_DESC(feature_disable, "Disable features"); + /* * expand feature list to array of feature strings. */ @@ -121,7 +128,7 @@ static void brcmf_feat_iovar_int_set(struct brcmf_if *ifp, void brcmf_feat_attach(struct brcmf_pub *drvr) { - struct brcmf_if *ifp = drvr->iflist[0]; + struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan"); brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn"); @@ -131,6 +138,12 @@ void brcmf_feat_attach(struct brcmf_pub *drvr) brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0); brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p"); + if (brcmf_feature_disable) { + brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n", + ifp->drvr->feat_flags, brcmf_feature_disable); + ifp->drvr->feat_flags &= ~brcmf_feature_disable; + } + /* set chip related quirks */ switch (drvr->bus_if->chip) { case BRCM_CC_43236_CHIP_ID: diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c index 971920f77b68..4248f3c80e78 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c @@ -29,7 +29,7 @@ #define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */ char brcmf_firmware_path[BRCMF_FW_PATH_LEN]; -module_param_string(firmware_path, brcmf_firmware_path, +module_param_string(alternative_fw_path, brcmf_firmware_path, BRCMF_FW_PATH_LEN, 0440); enum nvram_parser_state { diff --git a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c index 8d1ab4ab5be8..2ca783fa50cf 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c @@ -221,7 +221,7 @@ static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid, bus_if = dev_get_drvdata(flow->dev); drvr = bus_if->drvr; - ifp = drvr->iflist[ifidx]; + ifp = brcmf_get_ifp(drvr, ifidx); brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW, blocked); spin_unlock_irqrestore(&flow->block_lock, flags); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/flowring.h b/drivers/net/wireless/brcm80211/brcmfmac/flowring.h index 5551861a44bc..95fd1c9675d1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.h @@ -34,7 +34,7 @@ enum ring_status { }; struct brcmf_flowring_ring { - u8 hash_id; + u16 hash_id; bool blocked; enum ring_status status; struct sk_buff_head skblist; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index ec62492ffa69..3878b6f6cfce 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c @@ -179,25 +179,28 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, { struct brcmf_if_event *ifevent = data; struct brcmf_if *ifp; + bool is_p2pdev; int err = 0; brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n", ifevent->action, ifevent->ifidx, ifevent->bssidx, ifevent->flags, ifevent->role); - /* The P2P Device interface event must not be ignored - * contrary to what firmware tells us. The only way to - * distinguish the P2P Device is by looking at the ifidx - * and bssidx received. + /* The P2P Device interface event must not be ignored contrary to what + * firmware tells us. Older firmware uses p2p noif, with sta role. + * This should be accepted when p2pdev_setup is ongoing. TDLS setup will + * use the same ifevent and should be ignored. */ - if (!(ifevent->ifidx == 0 && ifevent->bssidx == 1) && - (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) { + is_p2pdev = ((ifevent->flags & BRCMF_E_IF_FLAG_NOIF) && + (ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT || + ((ifevent->role == BRCMF_E_IF_ROLE_STA) && + (drvr->fweh.p2pdev_setup_ongoing)))); + if (!is_p2pdev && (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) { brcmf_dbg(EVENT, "event can be ignored\n"); return; } if (ifevent->ifidx >= BRCMF_MAX_IFS) { - brcmf_err("invalid interface index: %u\n", - ifevent->ifidx); + brcmf_err("invalid interface index: %u\n", ifevent->ifidx); return; } @@ -207,10 +210,11 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname, emsg->addr); ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx, - emsg->ifname, emsg->addr); + is_p2pdev, emsg->ifname, emsg->addr); if (IS_ERR(ifp)) return; - brcmf_fws_add_interface(ifp); + if (!is_p2pdev) + brcmf_fws_add_interface(ifp); if (!drvr->fweh.evt_handler[BRCMF_E_IF]) if (brcmf_net_attach(ifp, false) < 0) return; @@ -222,7 +226,7 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data); if (ifp && ifevent->action == BRCMF_E_IF_DEL) - brcmf_remove_interface(drvr, ifevent->bssidx); + brcmf_remove_interface(ifp); } /** @@ -297,8 +301,7 @@ static void brcmf_fweh_event_worker(struct work_struct *work) goto event_free; } - if ((event->code == BRCMF_E_TDLS_PEER_EVENT) && - (emsg.bsscfgidx == 1)) + if (event->code == BRCMF_E_TDLS_PEER_EVENT) ifp = drvr->iflist[0]; else ifp = drvr->iflist[emsg.bsscfgidx]; @@ -315,6 +318,17 @@ event_free: } /** + * brcmf_fweh_p2pdev_setup() - P2P device setup ongoing (or not). + * + * @ifp: ifp on which setup is taking place or finished. + * @ongoing: p2p device setup in progress (or not). + */ +void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing) +{ + ifp->drvr->fweh.p2pdev_setup_ongoing = ongoing; +} + +/** * brcmf_fweh_attach() - initialize firmware event handling. * * @drvr: driver information object. @@ -335,7 +349,7 @@ void brcmf_fweh_attach(struct brcmf_pub *drvr) void brcmf_fweh_detach(struct brcmf_pub *drvr) { struct brcmf_fweh_info *fweh = &drvr->fweh; - struct brcmf_if *ifp = drvr->iflist[0]; + struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); s8 eventmask[BRCMF_EVENTING_MASK_LEN]; if (ifp) { diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h index 1326898d608e..d9a942842382 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h @@ -230,12 +230,14 @@ typedef int (*brcmf_fweh_handler_t)(struct brcmf_if *ifp, /** * struct brcmf_fweh_info - firmware event handling information. * + * @p2pdev_setup_ongoing: P2P device creation in progress. * @event_work: event worker. * @evt_q_lock: lock for event queue protection. * @event_q: event queue. * @evt_handler: registered event handlers. */ struct brcmf_fweh_info { + bool p2pdev_setup_ongoing; struct work_struct event_work; spinlock_t evt_q_lock; struct list_head event_q; @@ -255,6 +257,7 @@ void brcmf_fweh_unregister(struct brcmf_pub *drvr, int brcmf_fweh_activate_events(struct brcmf_if *ifp); void brcmf_fweh_process_event(struct brcmf_pub *drvr, struct brcmf_event *event_packet); +void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing); static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, struct sk_buff *skb) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h index 5434dcf64f7d..b20fc0f82a48 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h @@ -72,6 +72,7 @@ #define BRCMF_C_GET_BSS_INFO 136 #define BRCMF_C_GET_BANDLIST 140 #define BRCMF_C_SET_SCB_TIMEOUT 158 +#define BRCMF_C_GET_ASSOCLIST 159 #define BRCMF_C_GET_PHYLIST 180 #define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 #define BRCMF_C_SET_SCAN_UNASSOC_TIME 187 diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h index 297911f38fa0..daa427b46712 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h @@ -119,6 +119,8 @@ #define BRCMF_COUNTRY_BUF_SZ 4 #define BRCMF_ANT_MAX 4 +#define BRCMF_MAX_ASSOCLIST 128 + /* join preference types for join_pref iovar */ enum brcmf_join_pref_types { BRCMF_JOIN_PREF_RSSI = 1, @@ -621,4 +623,15 @@ struct brcmf_rev_info_le { __le32 nvramrev; }; +/** + * struct brcmf_assoclist_le - request assoc list. + * + * @count: indicates number of stations. + * @mac: MAC addresses of stations. + */ +struct brcmf_assoclist_le { + __le32 count; + u8 mac[BRCMF_MAX_ASSOCLIST][ETH_ALEN]; +}; + #endif /* FWIL_TYPES_H_ */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 5017eaa4af45..086cac3f86d6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -972,7 +972,7 @@ static void brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq, u8 if_id) { - struct brcmf_if *ifp = fws->drvr->iflist[!if_id ? 0 : if_id + 1]; + struct brcmf_if *ifp = brcmf_get_ifp(fws->drvr, if_id); if (WARN_ON(!ifp)) return; @@ -1398,7 +1398,7 @@ done: } static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, - struct sk_buff *skb, u8 ifidx, + struct sk_buff *skb, u32 genbit, u16 seq) { struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; @@ -1448,7 +1448,7 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, struct sk_buff *skb; struct brcmf_skbuff_cb *skcb; struct brcmf_fws_mac_descriptor *entry = NULL; - u8 ifidx; + struct brcmf_if *ifp; brcmf_dbg(DATA, "flags %d\n", flags); @@ -1497,15 +1497,16 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, } brcmf_fws_macdesc_return_req_credit(skb); - if (brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb)) { + ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp); + if (ret) { brcmu_pkt_buf_free_skb(skb); return -EINVAL; } if (!remove_from_hanger) - ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifidx, + ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit, seq); if (remove_from_hanger || ret) - brcmf_txfinalize(fws->drvr, skb, ifidx, true); + brcmf_txfinalize(ifp, skb, true); return 0; } @@ -1615,11 +1616,10 @@ static int brcmf_fws_notify_bcmc_credit_support(struct brcmf_if *ifp, return 0; } -int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, - struct sk_buff *skb) +void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb) { struct brcmf_skb_reorder_data *rd; - struct brcmf_fws_info *fws = drvr->fws; + struct brcmf_fws_info *fws = ifp->drvr->fws; u8 *signal_data; s16 data_len; u8 type; @@ -1629,20 +1629,20 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, s32 err; brcmf_dbg(HDRS, "enter: ifidx %d, skblen %u, sig %d\n", - ifidx, skb->len, signal_len); + ifp->ifidx, skb->len, siglen); - WARN_ON(signal_len > skb->len); + WARN_ON(siglen > skb->len); - if (!signal_len) - return 0; + if (!siglen) + return; /* if flow control disabled, skip to packet data and leave */ if ((!fws) || (!fws->fw_signals)) { - skb_pull(skb, signal_len); - return 0; + skb_pull(skb, siglen); + return; } fws->stats.header_pulls++; - data_len = signal_len; + data_len = siglen; signal_data = skb->data; status = BRCMF_FWS_RET_OK_NOSCHEDULE; @@ -1730,14 +1730,12 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, /* signalling processing result does * not affect the actual ethernet packet. */ - skb_pull(skb, signal_len); + skb_pull(skb, siglen); /* this may be a signal-only packet */ if (skb->len == 0) fws->stats.header_only_pkt++; - - return 0; } static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, @@ -1848,7 +1846,7 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, entry->transit_count--; if (entry->suppressed) entry->suppr_transit_count--; - brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); + (void)brcmf_proto_hdrpull(fws->drvr, false, skb, NULL); goto rollback; } @@ -1904,7 +1902,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) if (fws->avoid_queueing) { rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb); if (rc < 0) - brcmf_txfinalize(drvr, skb, ifp->ifidx, false); + brcmf_txfinalize(ifp, skb, false); return rc; } @@ -1928,7 +1926,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) brcmf_fws_schedule_deq(fws); } else { brcmf_err("drop skb: no hanger slot\n"); - brcmf_txfinalize(drvr, skb, ifp->ifidx, false); + brcmf_txfinalize(ifp, skb, false); rc = -ENOMEM; } brcmf_fws_unlock(fws); @@ -2008,8 +2006,9 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) ret = brcmf_proto_txdata(drvr, ifidx, 0, skb); brcmf_fws_lock(fws); if (ret < 0) - brcmf_txfinalize(drvr, skb, ifidx, - false); + brcmf_txfinalize(brcmf_get_ifp(drvr, + ifidx), + skb, false); if (fws->bus_flow_blocked) break; } @@ -2117,6 +2116,7 @@ static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data) int brcmf_fws_init(struct brcmf_pub *drvr) { struct brcmf_fws_info *fws; + struct brcmf_if *ifp; u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS; int rc; u32 mode; @@ -2176,21 +2176,22 @@ int brcmf_fws_init(struct brcmf_pub *drvr) * continue. Set mode back to none indicating not enabled. */ fws->fw_signals = true; - if (brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv)) { + ifp = brcmf_get_ifp(drvr, 0); + if (brcmf_fil_iovar_int_set(ifp, "tlv", tlv)) { brcmf_err("failed to set bdcv2 tlv signaling\n"); fws->fcmode = BRCMF_FWS_FCMODE_NONE; fws->fw_signals = false; } - if (brcmf_fil_iovar_int_set(drvr->iflist[0], "ampdu_hostreorder", 1)) + if (brcmf_fil_iovar_int_set(ifp, "ampdu_hostreorder", 1)) brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n"); /* Enable seq number reuse, if supported */ - if (brcmf_fil_iovar_int_get(drvr->iflist[0], "wlfc_mode", &mode) == 0) { + if (brcmf_fil_iovar_int_get(ifp, "wlfc_mode", &mode) == 0) { if (BRCMF_FWS_MODE_GET_REUSESEQ(mode)) { mode = 0; BRCMF_FWS_MODE_SET_REUSESEQ(mode, 1); - if (brcmf_fil_iovar_int_set(drvr->iflist[0], + if (brcmf_fil_iovar_int_set(ifp, "wlfc_mode", mode) == 0) { BRCMF_FWS_MODE_SET_REUSESEQ(fws->mode, 1); } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h index 9fc860910bd8..a36bac17eafd 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h @@ -21,8 +21,7 @@ int brcmf_fws_init(struct brcmf_pub *drvr); void brcmf_fws_deinit(struct brcmf_pub *drvr); bool brcmf_fws_fc_active(struct brcmf_fws_info *fws); -int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, - struct sk_buff *skb); +void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb); int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb); void brcmf_fws_reset_interface(struct brcmf_if *ifp); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c index 7b2136c9badb..44e618f9d890 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c @@ -522,7 +522,7 @@ static int brcmf_msgbuf_set_dcmd(struct brcmf_pub *drvr, int ifidx, static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws, - u8 *ifidx, struct sk_buff *skb) + struct sk_buff *skb, struct brcmf_if **ifp) { return -ENODEV; } @@ -873,7 +873,8 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf) commonring = msgbuf->flowrings[flowid]; atomic_dec(&commonring->outstanding_tx); - brcmf_txfinalize(msgbuf->drvr, skb, tx_status->msg.ifidx, true); + brcmf_txfinalize(brcmf_get_ifp(msgbuf->drvr, tx_status->msg.ifidx), + skb, true); } @@ -1081,15 +1082,7 @@ brcmf_msgbuf_rx_skb(struct brcmf_msgbuf *msgbuf, struct sk_buff *skb, { struct brcmf_if *ifp; - /* The ifidx is the idx to map to matching netdev/ifp. When receiving - * events this is easy because it contains the bssidx which maps - * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. - * bssidx 1 is used for p2p0 and no data can be received or - * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 - */ - if (ifidx) - (ifidx)++; - ifp = msgbuf->drvr->iflist[ifidx]; + ifp = brcmf_get_ifp(msgbuf->drvr, ifidx); if (!ifp || !ifp->ndev) { brcmf_err("Received pkt for invalid ifidx %d\n", ifidx); brcmu_pkt_buf_free_skb(skb); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index a9ba775a24c1..d224b3dd72ed 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c @@ -2084,11 +2084,13 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); brcmf_cfg80211_arm_vif_event(p2p->cfg, p2p_vif); + brcmf_fweh_p2pdev_setup(pri_ifp, true); /* Initialize P2P Discovery in the firmware */ err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); if (err < 0) { brcmf_err("set p2p_disc error\n"); + brcmf_fweh_p2pdev_setup(pri_ifp, false); brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); goto fail; } @@ -2097,6 +2099,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, err = brcmf_cfg80211_wait_vif_event_timeout(p2p->cfg, BRCMF_E_IF_ADD, msecs_to_jiffies(1500)); brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); + brcmf_fweh_p2pdev_setup(pri_ifp, false); if (!err) { brcmf_err("timeout occurred\n"); err = -EIO; @@ -2131,20 +2134,6 @@ fail: } /** - * brcmf_p2p_delete_p2pdev() - delete P2P_DEVICE virtual interface. - * - * @vif: virtual interface object to delete. - */ -static void brcmf_p2p_delete_p2pdev(struct brcmf_p2p_info *p2p, - struct brcmf_cfg80211_vif *vif) -{ - cfg80211_unregister_wdev(&vif->wdev); - p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; - brcmf_remove_interface(vif->ifp->drvr, vif->ifp->bssidx); - brcmf_free_vif(vif); -} - -/** * brcmf_p2p_add_vif() - create a new P2P virtual interface. * * @wiphy: wiphy device of new interface. @@ -2255,6 +2244,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) brcmf_dbg(TRACE, "delete P2P vif\n"); vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); + brcmf_cfg80211_arm_vif_event(cfg, vif); switch (vif->wdev.iftype) { case NL80211_IFTYPE_P2P_CLIENT: if (test_bit(BRCMF_VIF_STATUS_DISCONNECTING, &vif->sme_state)) @@ -2267,10 +2257,10 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) break; case NL80211_IFTYPE_P2P_DEVICE: + if (!p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif) + return 0; brcmf_p2p_cancel_remain_on_channel(vif->ifp); brcmf_p2p_deinit_discovery(p2p); - brcmf_p2p_delete_p2pdev(p2p, vif); - return 0; default: return -ENOTSUPP; } @@ -2282,10 +2272,11 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) wait_for_completion_timeout(&cfg->vif_disabled, msecs_to_jiffies(500)); - brcmf_vif_clear_mgmt_ies(vif); - - brcmf_cfg80211_arm_vif_event(cfg, vif); - err = brcmf_p2p_release_p2p_if(vif); + err = 0; + if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE) { + brcmf_vif_clear_mgmt_ies(vif); + err = brcmf_p2p_release_p2p_if(vif); + } if (!err) { /* wait for firmware event */ err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_DEL, @@ -2295,12 +2286,31 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) else err = 0; } + if (err) + brcmf_remove_interface(vif->ifp); + brcmf_cfg80211_arm_vif_event(cfg, NULL); - p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL; + if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE) + p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL; return err; } +void brcmf_p2p_ifp_removed(struct brcmf_if *ifp) +{ + struct brcmf_cfg80211_info *cfg; + struct brcmf_cfg80211_vif *vif; + + brcmf_dbg(INFO, "P2P: device interface removed\n"); + vif = ifp->vif; + cfg = wdev_to_cfg(&vif->wdev); + cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; + rtnl_lock(); + cfg80211_unregister_wdev(&vif->wdev); + rtnl_unlock(); + brcmf_free_vif(vif); +} + int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); @@ -2324,87 +2334,49 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev) struct brcmf_cfg80211_vif *vif; vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); - mutex_lock(&cfg->usr_sync); - (void)brcmf_p2p_deinit_discovery(p2p); - brcmf_abort_scanning(cfg); - clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); - mutex_unlock(&cfg->usr_sync); + /* This call can be result of the unregister_wdev call. In that case + * we dont want to do anything anymore. Just return. The config vif + * will have been cleared at this point. + */ + if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif == vif) { + mutex_lock(&cfg->usr_sync); + /* Set the discovery state to SCAN */ + (void)brcmf_p2p_set_discover_state(vif->ifp, + WL_P2P_DISC_ST_SCAN, 0, 0); + brcmf_abort_scanning(cfg); + clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); + mutex_unlock(&cfg->usr_sync); + } } /** * brcmf_p2p_attach() - attach for P2P. * * @cfg: driver private data for cfg80211 interface. + * @p2pdev_forced: create p2p device interface at attach. */ -s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg) +s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced) { - struct brcmf_if *pri_ifp; - struct brcmf_if *p2p_ifp; - struct brcmf_cfg80211_vif *p2p_vif; struct brcmf_p2p_info *p2p; - struct brcmf_pub *drvr; - s32 bssidx; + struct brcmf_if *pri_ifp; s32 err = 0; + void *err_ptr; p2p = &cfg->p2p; p2p->cfg = cfg; - drvr = cfg->pub; - - pri_ifp = drvr->iflist[0]; - p2p_ifp = drvr->iflist[1]; - + pri_ifp = brcmf_get_ifp(cfg->pub, 0); p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif; - if (p2p_ifp) { - p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE, - false); - if (IS_ERR(p2p_vif)) { - brcmf_err("could not create discovery vif\n"); - err = -ENOMEM; - goto exit; - } - - p2p_vif->ifp = p2p_ifp; - p2p_ifp->vif = p2p_vif; - p2p_vif->wdev.netdev = p2p_ifp->ndev; - p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev; - SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy)); - - p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; - - brcmf_p2p_generate_bss_mac(p2p, NULL); - memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); - brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); - - /* Initialize P2P Discovery in the firmware */ - err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); - if (err < 0) { - brcmf_err("set p2p_disc error\n"); - brcmf_free_vif(p2p_vif); - goto exit; - } - /* obtain bsscfg index for P2P discovery */ - err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); - if (err < 0) { - brcmf_err("retrieving discover bsscfg index failed\n"); - brcmf_free_vif(p2p_vif); - goto exit; - } - /* Verify that firmware uses same bssidx as driver !! */ - if (p2p_ifp->bssidx != bssidx) { - brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n", - bssidx, p2p_ifp->bssidx); - brcmf_free_vif(p2p_vif); - goto exit; + if (p2pdev_forced) { + err_ptr = brcmf_p2p_create_p2pdev(p2p, NULL, NULL); + if (IS_ERR(err_ptr)) { + brcmf_err("P2P device creation failed.\n"); + err = PTR_ERR(err_ptr); } - - init_completion(&p2p->send_af_done); - INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler); - init_completion(&p2p->afx_hdl.act_frm_scan); - init_completion(&p2p->wait_next_af); + } else { + p2p->p2pdev_dynamically = true; } -exit: return err; } @@ -2421,10 +2393,7 @@ void brcmf_p2p_detach(struct brcmf_p2p_info *p2p) if (vif != NULL) { brcmf_p2p_cancel_remain_on_channel(vif->ifp); brcmf_p2p_deinit_discovery(p2p); - /* remove discovery interface */ - rtnl_lock(); - brcmf_p2p_delete_p2pdev(p2p, vif); - rtnl_unlock(); + brcmf_remove_interface(vif->ifp); } /* just set it all to zero */ memset(p2p, 0, sizeof(*p2p)); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h index 872f382d9e49..5d49059021a9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h @@ -124,6 +124,7 @@ struct afx_hdl { * @wait_next_af: thread synchronizing struct. * @gon_req_action: about to send go negotiation requets frame. * @block_gon_req_tx: drop tx go negotiation requets frame. + * @p2pdev_dynamically: is p2p device if created by module param or supplicant. */ struct brcmf_p2p_info { struct brcmf_cfg80211_info *cfg; @@ -144,9 +145,10 @@ struct brcmf_p2p_info { struct completion wait_next_af; bool gon_req_action; bool block_gon_req_tx; + bool p2pdev_dynamically; }; -s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg); +s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced); void brcmf_p2p_detach(struct brcmf_p2p_info *p2p); struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, unsigned char name_assign_type, @@ -155,6 +157,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev); int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg, enum brcmf_fil_p2p_if_types if_type); +void brcmf_p2p_ifp_removed(struct brcmf_if *ifp); int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev); void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev); int brcmf_p2p_scan_prep(struct wiphy *wiphy, diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c index 3a98c4306d1d..83d804221715 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c @@ -47,12 +47,20 @@ enum brcmf_pcie_state { #define BRCMF_PCIE_43602_FW_NAME "brcm/brcmfmac43602-pcie.bin" #define BRCMF_PCIE_43602_NVRAM_NAME "brcm/brcmfmac43602-pcie.txt" +#define BRCMF_PCIE_4350_FW_NAME "brcm/brcmfmac4350-pcie.bin" +#define BRCMF_PCIE_4350_NVRAM_NAME "brcm/brcmfmac4350-pcie.txt" #define BRCMF_PCIE_4356_FW_NAME "brcm/brcmfmac4356-pcie.bin" #define BRCMF_PCIE_4356_NVRAM_NAME "brcm/brcmfmac4356-pcie.txt" #define BRCMF_PCIE_43570_FW_NAME "brcm/brcmfmac43570-pcie.bin" #define BRCMF_PCIE_43570_NVRAM_NAME "brcm/brcmfmac43570-pcie.txt" #define BRCMF_PCIE_4358_FW_NAME "brcm/brcmfmac4358-pcie.bin" #define BRCMF_PCIE_4358_NVRAM_NAME "brcm/brcmfmac4358-pcie.txt" +#define BRCMF_PCIE_4365_FW_NAME "brcm/brcmfmac4365b-pcie.bin" +#define BRCMF_PCIE_4365_NVRAM_NAME "brcm/brcmfmac4365b-pcie.txt" +#define BRCMF_PCIE_4366_FW_NAME "brcm/brcmfmac4366b-pcie.bin" +#define BRCMF_PCIE_4366_NVRAM_NAME "brcm/brcmfmac4366b-pcie.txt" +#define BRCMF_PCIE_4371_FW_NAME "brcm/brcmfmac4371-pcie.bin" +#define BRCMF_PCIE_4371_NVRAM_NAME "brcm/brcmfmac4371-pcie.txt" #define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */ @@ -74,6 +82,8 @@ enum brcmf_pcie_state { #define BRCMF_PCIE_REG_INTMASK 0x94 #define BRCMF_PCIE_REG_SBMBX 0x98 +#define BRCMF_PCIE_REG_LINK_STATUS_CTRL 0xBC + #define BRCMF_PCIE_PCIE2REG_INTMASK 0x24 #define BRCMF_PCIE_PCIE2REG_MAILBOXINT 0x48 #define BRCMF_PCIE_PCIE2REG_MAILBOXMASK 0x4C @@ -192,12 +202,20 @@ enum brcmf_pcie_state { MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME); MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4350_FW_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4350_NVRAM_NAME); MODULE_FIRMWARE(BRCMF_PCIE_4356_FW_NAME); MODULE_FIRMWARE(BRCMF_PCIE_4356_NVRAM_NAME); MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME); MODULE_FIRMWARE(BRCMF_PCIE_43570_NVRAM_NAME); MODULE_FIRMWARE(BRCMF_PCIE_4358_FW_NAME); MODULE_FIRMWARE(BRCMF_PCIE_4358_NVRAM_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4365_FW_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4365_NVRAM_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4366_FW_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4366_NVRAM_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4371_FW_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4371_NVRAM_NAME); struct brcmf_pcie_console { @@ -434,6 +452,47 @@ brcmf_pcie_copy_mem_todev(struct brcmf_pciedev_info *devinfo, u32 mem_offset, } +static void +brcmf_pcie_copy_dev_tomem(struct brcmf_pciedev_info *devinfo, u32 mem_offset, + void *dstaddr, u32 len) +{ + void __iomem *address = devinfo->tcm + mem_offset; + __le32 *dst32; + __le16 *dst16; + u8 *dst8; + + if (((ulong)address & 4) || ((ulong)dstaddr & 4) || (len & 4)) { + if (((ulong)address & 2) || ((ulong)dstaddr & 2) || (len & 2)) { + dst8 = (u8 *)dstaddr; + while (len) { + *dst8 = ioread8(address); + address++; + dst8++; + len--; + } + } else { + len = len / 2; + dst16 = (__le16 *)dstaddr; + while (len) { + *dst16 = cpu_to_le16(ioread16(address)); + address += 2; + dst16++; + len--; + } + } + } else { + len = len / 4; + dst32 = (__le32 *)dstaddr; + while (len) { + *dst32 = cpu_to_le32(ioread32(address)); + address += 4; + dst32++; + len--; + } + } +} + + #define WRITECC32(devinfo, reg, value) brcmf_pcie_write_reg32(devinfo, \ CHIPCREGOFFS(reg), value) @@ -466,6 +525,7 @@ brcmf_pcie_select_core(struct brcmf_pciedev_info *devinfo, u16 coreid) static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo) { + struct brcmf_core *core; u16 cfg_offset[] = { BRCMF_PCIE_CFGREG_STATUS_CMD, BRCMF_PCIE_CFGREG_PM_CSR, BRCMF_PCIE_CFGREG_MSI_CAP, @@ -484,32 +544,38 @@ static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo) if (!devinfo->ci) return; + /* Disable ASPM */ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); - brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, - BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL); - lsc = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA); + pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL, + &lsc); val = lsc & (~BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB); - brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, val); + pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL, + val); + /* Watchdog reset */ brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON); WRITECC32(devinfo, watchdog, 4); msleep(100); + /* Restore ASPM */ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); - brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, - BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL); - brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, lsc); - - brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); - for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) { - brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, - cfg_offset[i]); - val = brcmf_pcie_read_reg32(devinfo, - BRCMF_PCIE_PCIE2REG_CONFIGDATA); - brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n", - cfg_offset[i], val); - brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, - val); + pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL, + lsc); + + core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2); + if (core->rev <= 13) { + for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) { + brcmf_pcie_write_reg32(devinfo, + BRCMF_PCIE_PCIE2REG_CONFIGADDR, + cfg_offset[i]); + val = brcmf_pcie_read_reg32(devinfo, + BRCMF_PCIE_PCIE2REG_CONFIGDATA); + brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n", + cfg_offset[i], val); + brcmf_pcie_write_reg32(devinfo, + BRCMF_PCIE_PCIE2REG_CONFIGDATA, + val); + } } } @@ -519,8 +585,6 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo) u32 config; brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); - if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0) - brcmf_pcie_reset_device(devinfo); /* BAR1 window may not be sized properly */ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0); @@ -644,7 +708,7 @@ static void brcmf_pcie_bus_console_init(struct brcmf_pciedev_info *devinfo) addr = console->base_addr + BRCMF_CONSOLE_BUFSIZE_OFFSET; console->bufsize = brcmf_pcie_read_tcm32(devinfo, addr); - brcmf_dbg(PCIE, "Console: base %x, buf %x, size %d\n", + brcmf_dbg(FWCON, "Console: base %x, buf %x, size %d\n", console->base_addr, console->buf_addr, console->bufsize); } @@ -656,6 +720,9 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo) u8 ch; u32 newidx; + if (!BRCMF_FWCON_ON()) + return; + console = &devinfo->shared.console; addr = console->base_addr + BRCMF_CONSOLE_WRITEIDX_OFFSET; newidx = brcmf_pcie_read_tcm32(devinfo, addr); @@ -677,7 +744,7 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo) } if (ch == '\n') { console->log_str[console->log_idx] = 0; - brcmf_dbg(PCIE, "CONSOLE: %s", console->log_str); + pr_debug("CONSOLE: %s", console->log_str); console->log_idx = 0; } } @@ -1330,12 +1397,36 @@ static void brcmf_pcie_wowl_config(struct device *dev, bool enabled) } +static size_t brcmf_pcie_get_ramsize(struct device *dev) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie; + struct brcmf_pciedev_info *devinfo = buspub->devinfo; + + return devinfo->ci->ramsize - devinfo->ci->srsize; +} + + +static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie; + struct brcmf_pciedev_info *devinfo = buspub->devinfo; + + brcmf_dbg(PCIE, "dump at 0x%08X: len=%zu\n", devinfo->ci->rambase, len); + brcmf_pcie_copy_dev_tomem(devinfo, devinfo->ci->rambase, data, len); + return 0; +} + + static struct brcmf_bus_ops brcmf_pcie_bus_ops = { .txdata = brcmf_pcie_tx, .stop = brcmf_pcie_down, .txctl = brcmf_pcie_tx_ctlpkt, .rxctl = brcmf_pcie_rx_ctlpkt, .wowl_config = brcmf_pcie_wowl_config, + .get_ramsize = brcmf_pcie_get_ramsize, + .get_memdump = brcmf_pcie_get_memdump, }; @@ -1408,6 +1499,10 @@ static int brcmf_pcie_get_fwnames(struct brcmf_pciedev_info *devinfo) fw_name = BRCMF_PCIE_43602_FW_NAME; nvram_name = BRCMF_PCIE_43602_NVRAM_NAME; break; + case BRCM_CC_4350_CHIP_ID: + fw_name = BRCMF_PCIE_4350_FW_NAME; + nvram_name = BRCMF_PCIE_4350_NVRAM_NAME; + break; case BRCM_CC_4356_CHIP_ID: fw_name = BRCMF_PCIE_4356_FW_NAME; nvram_name = BRCMF_PCIE_4356_NVRAM_NAME; @@ -1422,6 +1517,18 @@ static int brcmf_pcie_get_fwnames(struct brcmf_pciedev_info *devinfo) fw_name = BRCMF_PCIE_4358_FW_NAME; nvram_name = BRCMF_PCIE_4358_NVRAM_NAME; break; + case BRCM_CC_4365_CHIP_ID: + fw_name = BRCMF_PCIE_4365_FW_NAME; + nvram_name = BRCMF_PCIE_4365_NVRAM_NAME; + break; + case BRCM_CC_4366_CHIP_ID: + fw_name = BRCMF_PCIE_4366_FW_NAME; + nvram_name = BRCMF_PCIE_4366_NVRAM_NAME; + break; + case BRCM_CC_4371_CHIP_ID: + fw_name = BRCMF_PCIE_4371_FW_NAME; + nvram_name = BRCMF_PCIE_4371_NVRAM_NAME; + break; default: brcmf_err("Unsupported chip 0x%04x\n", devinfo->ci->chip); return -ENODEV; @@ -1633,6 +1740,23 @@ static int brcmf_pcie_buscoreprep(void *ctx) } +static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip) +{ + struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx; + u32 val; + + devinfo->ci = chip; + brcmf_pcie_reset_device(devinfo); + + val = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT); + if (val != 0xffffffff) + brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, + val); + + return 0; +} + + static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip, u32 rstvec) { @@ -1644,6 +1768,7 @@ static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip, static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = { .prepare = brcmf_pcie_buscoreprep, + .reset = brcmf_pcie_buscore_reset, .activate = brcmf_pcie_buscore_activate, .read32 = brcmf_pcie_buscore_read32, .write32 = brcmf_pcie_buscore_write32, @@ -1811,7 +1936,6 @@ brcmf_pcie_remove(struct pci_dev *pdev) brcmf_pcie_intr_disable(devinfo); brcmf_detach(&pdev->dev); - brcmf_pcie_reset_device(devinfo); kfree(bus->bus_priv.pcie); kfree(bus->msgbuf->flowrings); @@ -1929,6 +2053,7 @@ cleanup: PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 } static struct pci_device_id brcmf_pcie_devid_table[] = { + BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID), @@ -1937,6 +2062,13 @@ static struct pci_device_id brcmf_pcie_devid_table[] = { BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID), { /* end: all zeroes */ } }; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/brcm80211/brcmfmac/proto.h index 971172ff686c..d55119d36755 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/proto.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.h @@ -24,8 +24,8 @@ enum proto_addr_mode { struct brcmf_proto { - int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, - struct sk_buff *skb); + int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, + struct sk_buff *skb, struct brcmf_if **ifp); int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, uint len); int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, @@ -46,9 +46,19 @@ int brcmf_proto_attach(struct brcmf_pub *drvr); void brcmf_proto_detach(struct brcmf_pub *drvr); static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, - u8 *ifidx, struct sk_buff *skb) + struct sk_buff *skb, + struct brcmf_if **ifp) { - return drvr->proto->hdrpull(drvr, do_fws, ifidx, skb); + struct brcmf_if *tmp = NULL; + + /* assure protocol is always called with + * non-null initialized pointer. + */ + if (ifp) + *ifp = NULL; + else + ifp = &tmp; + return drvr->proto->hdrpull(drvr, do_fws, skb, ifp); } static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, uint len) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c index f990e3d0e696..7e74ac3ad815 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c @@ -15,6 +15,7 @@ */ #include <linux/types.h> +#include <linux/atomic.h> #include <linux/kernel.h> #include <linux/kthread.h> #include <linux/printk.h> @@ -123,6 +124,7 @@ struct rte_console { #define BRCMF_FIRSTREAD (1 << 6) +#define BRCMF_CONSOLE 10 /* watchdog interval to poll console */ /* SBSDIO_DEVICE_CTL */ @@ -3204,6 +3206,8 @@ static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) if (IS_ERR_OR_NULL(dentry)) return; + bus->console_interval = BRCMF_CONSOLE; + brcmf_debugfs_add_entry(drvr, "forensics", brcmf_sdio_forensic_read); brcmf_debugfs_add_entry(drvr, "counters", brcmf_debugfs_sdio_count_read); @@ -3535,6 +3539,51 @@ done: return err; } +static size_t brcmf_sdio_bus_get_ramsize(struct device *dev) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct brcmf_sdio *bus = sdiodev->bus; + + return bus->ci->ramsize - bus->ci->srsize; +} + +static int brcmf_sdio_bus_get_memdump(struct device *dev, void *data, + size_t mem_size) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct brcmf_sdio *bus = sdiodev->bus; + int err; + int address; + int offset; + int len; + + brcmf_dbg(INFO, "dump at 0x%08x: size=%zu\n", bus->ci->rambase, + mem_size); + + address = bus->ci->rambase; + offset = err = 0; + sdio_claim_host(sdiodev->func[1]); + while (offset < mem_size) { + len = ((offset + MEMBLOCK) < mem_size) ? MEMBLOCK : + mem_size - offset; + err = brcmf_sdiod_ramrw(sdiodev, false, address, data, len); + if (err) { + brcmf_err("error %d on reading %d membytes at 0x%08x\n", + err, len, address); + goto done; + } + data += len; + offset += len; + address += len; + } + +done: + sdio_release_host(sdiodev->func[1]); + return err; +} + void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus) { if (!bus->dpc_triggered) { @@ -3613,7 +3662,7 @@ static void brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) } #ifdef DEBUG /* Poll for console output periodically */ - if (bus->sdiodev->state == BRCMF_SDIOD_DATA && + if (bus->sdiodev->state == BRCMF_SDIOD_DATA && BRCMF_FWCON_ON() && bus->console_interval != 0) { bus->console.count += BRCMF_WD_POLL_MS; if (bus->console.count >= bus->console_interval) { @@ -3983,7 +4032,9 @@ static struct brcmf_bus_ops brcmf_sdio_bus_ops = { .txctl = brcmf_sdio_bus_txctl, .rxctl = brcmf_sdio_bus_rxctl, .gettxq = brcmf_sdio_bus_gettxq, - .wowl_config = brcmf_sdio_wowl_config + .wowl_config = brcmf_sdio_wowl_config, + .get_ramsize = brcmf_sdio_bus_get_ramsize, + .get_memdump = brcmf_sdio_bus_get_memdump, }; static void brcmf_sdio_firmware_callback(struct device *dev, diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index daba86d881bc..689e64d004bc 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -144,6 +144,7 @@ struct brcmf_usbdev_info { struct usb_device *usbdev; struct device *dev; + struct mutex dev_init_lock; int ctl_in_pipe, ctl_out_pipe; struct urb *ctl_urb; /* URB for control endpoint */ @@ -1204,6 +1205,8 @@ static void brcmf_usb_probe_phase2(struct device *dev, int ret; brcmf_dbg(USB, "Start fw downloading\n"); + + devinfo = bus->bus_priv.usb->devinfo; ret = check_file(fw->data); if (ret < 0) { brcmf_err("invalid firmware\n"); @@ -1211,7 +1214,6 @@ static void brcmf_usb_probe_phase2(struct device *dev, goto error; } - devinfo = bus->bus_priv.usb->devinfo; devinfo->image = fw->data; devinfo->image_len = fw->size; @@ -1224,9 +1226,11 @@ static void brcmf_usb_probe_phase2(struct device *dev, if (ret) goto error; + mutex_unlock(&devinfo->dev_init_lock); return; error: brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), ret); + mutex_unlock(&devinfo->dev_init_lock); device_release_driver(dev); } @@ -1264,6 +1268,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) if (ret) goto fail; /* we are done */ + mutex_unlock(&devinfo->dev_init_lock); return 0; } bus->chip = bus_pub->devid; @@ -1317,6 +1322,12 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) devinfo->usbdev = usb; devinfo->dev = &usb->dev; + /* Take an init lock, to protect for disconnect while still loading. + * Necessary because of the asynchronous firmware load construction + */ + mutex_init(&devinfo->dev_init_lock); + mutex_lock(&devinfo->dev_init_lock); + usb_set_intfdata(intf, devinfo); /* Check that the device supports only one configuration */ @@ -1391,6 +1402,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) return 0; fail: + mutex_unlock(&devinfo->dev_init_lock); kfree(devinfo); usb_set_intfdata(intf, NULL); return ret; @@ -1403,8 +1415,19 @@ brcmf_usb_disconnect(struct usb_interface *intf) brcmf_dbg(USB, "Enter\n"); devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf); - brcmf_usb_disconnect_cb(devinfo); - kfree(devinfo); + + if (devinfo) { + mutex_lock(&devinfo->dev_init_lock); + /* Make sure that devinfo still exists. Firmware probe routines + * may have released the device and cleared the intfdata. + */ + if (!usb_get_intfdata(intf)) + goto done; + + brcmf_usb_disconnect_cb(devinfo); + kfree(devinfo); + } +done: brcmf_dbg(USB, "Exit\n"); } diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index d2c5747e3ac9..bec2dc1ca2e4 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -820,7 +820,7 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct brcms_info *wl = hw->priv; struct scb *scb = &wl->wlc->pri_scb; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 9728be0e704b..218cbc8bf3a7 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -4585,7 +4585,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, wlc_hw->machwcap_backup = wlc_hw->machwcap; /* init tx fifo size */ - WARN_ON((wlc_hw->corerev - XMTFIFOTBL_STARTREV) < 0 || + WARN_ON(wlc_hw->corerev < XMTFIFOTBL_STARTREV || (wlc_hw->corerev - XMTFIFOTBL_STARTREV) > ARRAY_SIZE(xmtfifo_sz)); wlc_hw->xmtfifo_sz = diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h index 7a6daa37dc6b..aa06ea231db3 100644 --- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h @@ -39,6 +39,7 @@ #define BRCM_CC_4339_CHIP_ID 0x4339 #define BRCM_CC_43430_CHIP_ID 43430 #define BRCM_CC_4345_CHIP_ID 0x4345 +#define BRCM_CC_4350_CHIP_ID 0x4350 #define BRCM_CC_4354_CHIP_ID 0x4354 #define BRCM_CC_4356_CHIP_ID 0x4356 #define BRCM_CC_43566_CHIP_ID 43566 @@ -47,6 +48,9 @@ #define BRCM_CC_43570_CHIP_ID 43570 #define BRCM_CC_4358_CHIP_ID 0x4358 #define BRCM_CC_43602_CHIP_ID 43602 +#define BRCM_CC_4365_CHIP_ID 0x4365 +#define BRCM_CC_4366_CHIP_ID 0x4366 +#define BRCM_CC_4371_CHIP_ID 0x4371 /* USB Device IDs */ #define BRCM_USB_43143_DEVICE_ID 0xbd1e @@ -56,6 +60,7 @@ #define BRCM_USB_BCMFW_DEVICE_ID 0x0bdc /* PCIE Device IDs */ +#define BRCM_PCIE_4350_DEVICE_ID 0x43a3 #define BRCM_PCIE_4354_DEVICE_ID 0x43df #define BRCM_PCIE_4356_DEVICE_ID 0x43ec #define BRCM_PCIE_43567_DEVICE_ID 0x43d3 @@ -65,6 +70,14 @@ #define BRCM_PCIE_43602_2G_DEVICE_ID 0x43bb #define BRCM_PCIE_43602_5G_DEVICE_ID 0x43bc #define BRCM_PCIE_43602_RAW_DEVICE_ID 43602 +#define BRCM_PCIE_4365_DEVICE_ID 0x43ca +#define BRCM_PCIE_4365_2G_DEVICE_ID 0x43cb +#define BRCM_PCIE_4365_5G_DEVICE_ID 0x43cc +#define BRCM_PCIE_4366_DEVICE_ID 0x43c3 +#define BRCM_PCIE_4366_2G_DEVICE_ID 0x43c4 +#define BRCM_PCIE_4366_5G_DEVICE_ID 0x43c5 +#define BRCM_PCIE_4371_DEVICE_ID 0x440d + /* brcmsmac IDs */ #define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ diff --git a/drivers/net/wireless/cw1200/sta.c b/drivers/net/wireless/cw1200/sta.c index b86500b4418f..95a7fdb3cc1c 100644 --- a/drivers/net/wireless/cw1200/sta.c +++ b/drivers/net/wireless/cw1200/sta.c @@ -2137,7 +2137,7 @@ int cw1200_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { /* Aggregation is implemented fully in firmware, * including block ack negotiation. Do not allow diff --git a/drivers/net/wireless/cw1200/sta.h b/drivers/net/wireless/cw1200/sta.h index b7e386b7662b..bebb3379017f 100644 --- a/drivers/net/wireless/cw1200/sta.h +++ b/drivers/net/wireless/cw1200/sta.h @@ -111,7 +111,7 @@ int cw1200_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size); + u8 buf_size, bool amsdu); void cw1200_suspend_resume(struct cw1200_common *priv, struct wsm_suspend_resume *arg); diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 39f3e6f5cbcd..ed0adaf1eec4 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -10470,7 +10470,6 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev, vers, date); strlcpy(info->bus_info, pci_name(p->pci_dev), sizeof(info->bus_info)); - info->eedump_len = IPW_EEPROM_IMAGE_SIZE; } static u32 ipw_ethtool_get_link(struct net_device *dev) diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index a6877dd6ba73..cef7f7d79cd9 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c @@ -1091,8 +1091,6 @@ static const char *get_info_element_string(u16 id) MFIE_STRING(TIM); MFIE_STRING(IBSS_PARAMS); MFIE_STRING(COUNTRY); - MFIE_STRING(HP_PARAMS); - MFIE_STRING(HP_TABLE); MFIE_STRING(REQUEST); MFIE_STRING(CHALLENGE); MFIE_STRING(PWR_CONSTRAINT); diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 44fa422f255e..6656215a13a9 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -5984,7 +5984,7 @@ int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 * ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct il_priv *il = hw->priv; int ret = -EINVAL; diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h index 3a57f71b8ed5..8ab8706f9422 100644 --- a/drivers/net/wireless/iwlegacy/4965.h +++ b/drivers/net/wireless/iwlegacy/4965.h @@ -184,7 +184,7 @@ void il4965_mac_update_tkip_key(struct ieee80211_hw *hw, int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 * ssn, - u8 buf_size); + u8 buf_size, bool amsdu); int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index aba095761ac6..6e949df399d6 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -142,6 +142,7 @@ config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE config IWLWIFI_DEVICE_TRACING bool "iwlwifi device access tracing" depends on EVENT_TRACING + default y help Say Y here to trace all commands, including TX frames and IO accesses, sent to the device. If you say yes, iwlwifi will diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 453f7c315ab5..b3ad34e8bf5a 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -731,7 +731,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); int ret = -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 3fb327d5a911..1a73c7a1da77 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -72,12 +72,10 @@ #define IWL7260_UCODE_API_MAX 17 /* Oldest version we won't warn about */ -#define IWL7260_UCODE_API_OK 12 -#define IWL3165_UCODE_API_OK 13 +#define IWL7260_UCODE_API_OK 13 /* Lowest firmware API version supported */ -#define IWL7260_UCODE_API_MIN 12 -#define IWL3165_UCODE_API_MIN 13 +#define IWL7260_UCODE_API_MIN 13 /* NVM versions */ #define IWL7260_NVM_VERSION 0x0a1d @@ -113,7 +111,7 @@ static const struct iwl_base_params iwl7000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_7000, - .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_queues = 31, .pll_cfg_val = 0, .shadow_ram_support = true, .led_compensation = 57, @@ -269,11 +267,6 @@ const struct iwl_cfg iwl3165_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 3165", .fw_name_pre = IWL7265D_FW_PRE, IWL_DEVICE_7000, - /* sparse doens't like the re-assignment but it is safe */ -#ifndef __CHECKER__ - .ucode_api_ok = IWL3165_UCODE_API_OK, - .ucode_api_min = IWL3165_UCODE_API_MIN, -#endif .ht_params = &iwl7000_ht_params, .nvm_ver = IWL3165_NVM_VERSION, .nvm_calib_ver = IWL3165_TX_POWER_VERSION, diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c index 197abe43ddc5..0116e5a4c393 100644 --- a/drivers/net/wireless/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/iwlwifi/iwl-8000.c @@ -72,10 +72,10 @@ #define IWL8000_UCODE_API_MAX 17 /* Oldest version we won't warn about */ -#define IWL8000_UCODE_API_OK 12 +#define IWL8000_UCODE_API_OK 13 /* Lowest firmware API version supported */ -#define IWL8000_UCODE_API_MIN 12 +#define IWL8000_UCODE_API_MIN 13 /* NVM versions */ #define IWL8000_NVM_VERSION 0x0a1d @@ -107,7 +107,7 @@ static const struct iwl_base_params iwl8000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000, - .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_queues = 31, .pll_cfg_val = 0, .shadow_ram_support = true, .led_compensation = 57, diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 939fa229c038..910970858f98 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h @@ -223,13 +223,13 @@ struct iwl_tt_tx_backoff { * @support_tx_backoff: Support tx-backoff? */ struct iwl_tt_params { - s32 ct_kill_entry; - s32 ct_kill_exit; + u32 ct_kill_entry; + u32 ct_kill_exit; u32 ct_kill_duration; - s32 dynamic_smps_entry; - s32 dynamic_smps_exit; - s32 tx_protection_entry; - s32 tx_protection_exit; + u32 dynamic_smps_entry; + u32 dynamic_smps_exit; + u32 tx_protection_entry; + u32 tx_protection_exit; struct iwl_tt_tx_backoff tx_backoff[TT_TX_BACKOFF_SIZE]; bool support_ct_kill; bool support_dynamic_smps; diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index a86aa5bcee7d..463cadfbfccb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -450,7 +450,7 @@ static int iwl_set_ucode_api_flags(struct iwl_drv *drv, const u8 *data, u32 api_flags = le32_to_cpu(ucode_api->api_flags); int i; - if (api_index >= IWL_API_MAX_BITS / 32) { + if (api_index >= DIV_ROUND_UP(NUM_IWL_UCODE_TLV_API, 32)) { IWL_ERR(drv, "api_index larger than supported by driver\n"); /* don't return an error so we can load FW that has more bits */ return 0; @@ -472,7 +472,7 @@ static int iwl_set_ucode_capabilities(struct iwl_drv *drv, const u8 *data, u32 api_flags = le32_to_cpu(ucode_capa->api_capa); int i; - if (api_index >= IWL_CAPABILITIES_MAX_BITS / 32) { + if (api_index >= DIV_ROUND_UP(NUM_IWL_UCODE_TLV_CAPA, 32)) { IWL_ERR(drv, "api_index larger than supported by driver\n"); /* don't return an error so we can load FW that has more bits */ return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h index af5b3201492c..9dbe19cbb4dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h @@ -86,6 +86,8 @@ * Structured as &struct iwl_fw_error_dump_trigger_desc. * @IWL_FW_ERROR_DUMP_RB: the content of an RB structured as * &struct iwl_fw_error_dump_rb + * @IWL_FW_ERROR_PAGING: UMAC's image memory segments which were + * paged to the DRAM. */ enum iwl_fw_error_dump_type { /* 0 is deprecated */ @@ -100,6 +102,7 @@ enum iwl_fw_error_dump_type { IWL_FW_ERROR_DUMP_MEM = 9, IWL_FW_ERROR_DUMP_ERROR_INFO = 10, IWL_FW_ERROR_DUMP_RB = 11, + IWL_FW_ERROR_DUMP_PAGING = 12, IWL_FW_ERROR_DUMP_MAX, }; @@ -240,6 +243,19 @@ struct iwl_fw_error_dump_rb { }; /** + * struct iwl_fw_error_dump_paging - content of the UMAC's image page + * block on DRAM + * @index: the index of the page block + * @reserved: + * @data: the content of the page block + */ +struct iwl_fw_error_dump_paging { + __le32 index; + __le32 reserved; + u8 data[]; +}; + +/** * iwl_fw_error_next_data - advance fw error dump data pointer * @data: previous data block * Returns: next data block diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 84653e3d02ba..08303db0000f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h @@ -247,36 +247,31 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t; * @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time * longer than the passive one, which is essential for fragmented scan. * @IWL_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source. - * IWL_UCODE_TLV_API_HDC_PHASE_0: ucode supports finer configuration of LTR - * @IWL_UCODE_TLV_API_TX_POWER_DEV: new API for tx power. * @IWL_UCODE_TLV_API_WIDE_CMD_HDR: ucode supports wide command header - * @IWL_UCODE_TLV_API_SCD_CFG: This firmware can configure the scheduler - * through the dedicated host command. - * @IWL_UCODE_TLV_API_SINGLE_SCAN_EBS: EBS is supported for single scans too. - * @IWL_UCODE_TLV_API_ASYNC_DTM: Async temperature notifications are supported. * @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params - * @IWL_UCODE_TLV_API_STATS_V10: uCode supports/uses statistics API version 10 * @IWL_UCODE_TLV_API_NEW_VERSION: new versioning format * @IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY: scan APIs use 8-level priority * instead of 3. * @IWL_UCODE_TLV_API_TX_POWER_CHAIN: TX power API has larger command size * (command version 3) that supports per-chain limits + * + * @NUM_IWL_UCODE_TLV_API: number of bits used */ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_BT_COEX_SPLIT = (__force iwl_ucode_tlv_api_t)3, 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_HDC_PHASE_0 = (__force iwl_ucode_tlv_api_t)10, - IWL_UCODE_TLV_API_TX_POWER_DEV = (__force iwl_ucode_tlv_api_t)11, IWL_UCODE_TLV_API_WIDE_CMD_HDR = (__force iwl_ucode_tlv_api_t)14, - IWL_UCODE_TLV_API_SCD_CFG = (__force iwl_ucode_tlv_api_t)15, - IWL_UCODE_TLV_API_SINGLE_SCAN_EBS = (__force iwl_ucode_tlv_api_t)16, - IWL_UCODE_TLV_API_ASYNC_DTM = (__force iwl_ucode_tlv_api_t)17, IWL_UCODE_TLV_API_LQ_SS_PARAMS = (__force iwl_ucode_tlv_api_t)18, - IWL_UCODE_TLV_API_STATS_V10 = (__force iwl_ucode_tlv_api_t)19, IWL_UCODE_TLV_API_NEW_VERSION = (__force iwl_ucode_tlv_api_t)20, IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY = (__force iwl_ucode_tlv_api_t)24, IWL_UCODE_TLV_API_TX_POWER_CHAIN = (__force iwl_ucode_tlv_api_t)27, + + NUM_IWL_UCODE_TLV_API +#ifdef __CHECKER__ + /* sparse says it cannot increment the previous enum member */ + = 128 +#endif }; typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; @@ -311,6 +306,10 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; * is supported. * @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC * @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan + * @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement + * @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts + * + * @NUM_IWL_UCODE_TLV_CAPA: number of bits used */ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = (__force iwl_ucode_tlv_capa_t)0, @@ -333,6 +332,14 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29, IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30, IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31, + 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, + + NUM_IWL_UCODE_TLV_CAPA +#ifdef __CHECKER__ + /* sparse says it cannot increment the previous enum member */ + = 128 +#endif }; /* The default calibrate table size if not specified by firmware file */ @@ -343,9 +350,6 @@ enum iwl_ucode_tlv_capa { /* The default max probe length if not specified by the firmware file */ #define IWL_DEFAULT_MAX_PROBE_LENGTH 200 -#define IWL_API_MAX_BITS 64 -#define IWL_CAPABILITIES_MAX_BITS 64 - /* * For 16.0 uCode and above, there is no differentiation between sections, * just an offset to the HW address. diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index 45e732150d28..84ec0cefb62a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h @@ -105,8 +105,8 @@ struct iwl_ucode_capabilities { u32 n_scan_channels; u32 standard_phy_calibration_size; u32 flags; - unsigned long _api[BITS_TO_LONGS(IWL_API_MAX_BITS)]; - unsigned long _capa[BITS_TO_LONGS(IWL_CAPABILITIES_MAX_BITS)]; + unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)]; + unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)]; }; static inline bool diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 27c66e477833..0bd9d4aad0c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c @@ -36,6 +36,29 @@ #include "iwl-prph.h" #include "iwl-fh.h" +void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) +{ + trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val); + iwl_trans_write8(trans, ofs, val); +} +IWL_EXPORT_SYMBOL(iwl_write8); + +void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val) +{ + trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val); + iwl_trans_write32(trans, ofs, val); +} +IWL_EXPORT_SYMBOL(iwl_write32); + +u32 iwl_read32(struct iwl_trans *trans, u32 ofs) +{ + u32 val = iwl_trans_read32(trans, ofs); + + trace_iwlwifi_dev_ioread32(trans->dev, ofs, val); + return val; +} +IWL_EXPORT_SYMBOL(iwl_read32); + #define IWL_POLL_INTERVAL 10 /* microseconds */ int iwl_poll_bit(struct iwl_trans *trans, u32 addr, diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 705d12c079e8..501d0560c061 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -32,24 +32,9 @@ #include "iwl-devtrace.h" #include "iwl-trans.h" -static inline void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) -{ - trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val); - iwl_trans_write8(trans, ofs, val); -} - -static inline void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val) -{ - trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val); - iwl_trans_write32(trans, ofs, val); -} - -static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs) -{ - u32 val = iwl_trans_read32(trans, ofs); - trace_iwlwifi_dev_ioread32(trans->dev, ofs, val); - return val; -} +void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val); +void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val); +u32 iwl_read32(struct iwl_trans *trans, u32 ofs); static inline void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) { diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 3b8e85e51002..d82984912e04 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c @@ -580,13 +580,15 @@ static void iwl_set_hw_address_family_8000(struct device *dev, IWL_ERR_DEV(dev, "mac address is not found\n"); } +#define IWL_4165_DEVICE_ID 0x5501 + struct iwl_nvm_data * iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_hw, const __le16 *nvm_sw, const __le16 *nvm_calib, const __le16 *regulatory, const __le16 *mac_override, const __le16 *phy_sku, u8 tx_chains, u8 rx_chains, bool lar_fw_supported, - u32 mac_addr0, u32 mac_addr1) + u32 mac_addr0, u32 mac_addr1, u32 hw_id) { struct iwl_nvm_data *data; u32 sku; @@ -625,6 +627,17 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, (sku & NVM_SKU_CAP_11AC_ENABLE); data->sku_cap_mimo_disabled = sku & NVM_SKU_CAP_MIMO_DISABLE; + /* + * OTP 0x52 bug work around + * define antenna 1x1 according to MIMO disabled + */ + if (hw_id == IWL_4165_DEVICE_ID && data->sku_cap_mimo_disabled) { + data->valid_tx_ant = ANT_B; + data->valid_rx_ant = ANT_B; + tx_chains = ANT_B; + rx_chains = ANT_B; + } + data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw); if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h index 822ba52e0e5a..9f44d8188c5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h @@ -79,7 +79,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_calib, const __le16 *regulatory, const __le16 *mac_override, const __le16 *phy_sku, u8 tx_chains, u8 rx_chains, bool lar_fw_supported, - u32 mac_addr0, u32 mac_addr1); + u32 mac_addr0, u32 mac_addr1, u32 hw_id); /** * iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index b47fe9d6b97a..2a58d6833224 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h @@ -7,6 +7,7 @@ * * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2015 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) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2015 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,7 +110,8 @@ struct iwl_cfg; * interact with it. The driver layer typically calls the start and stop * handlers, the transport layer calls the others. * - * All the handlers MUST be implemented + * All the handlers MUST be implemented, except @rx_rss which can be left + * out *iff* the opmode will never run on hardware with multi-queue capability. * * @start: start the op_mode. The transport layer is already allocated. * May sleep @@ -116,6 +119,10 @@ struct iwl_cfg; * May sleep * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the * HCMD this Rx responds to. Can't sleep. + * @rx_rss: data queue RX notification to the op_mode, for (data) notifications + * received on the RSS queue(s). The queue parameter indicates which of the + * RSS queues received this frame; it will always be non-zero. + * This method must not sleep. * @queue_full: notifies that a HW queue is full. * Must be atomic and called with BH disabled. * @queue_not_full: notifies that a HW queue is not full any more. @@ -146,6 +153,8 @@ struct iwl_op_mode_ops { void (*stop)(struct iwl_op_mode *op_mode); void (*rx)(struct iwl_op_mode *op_mode, struct napi_struct *napi, struct iwl_rx_cmd_buffer *rxb); + void (*rx_rss)(struct iwl_op_mode *op_mode, struct napi_struct *napi, + struct iwl_rx_cmd_buffer *rxb, unsigned int queue); void (*queue_full)(struct iwl_op_mode *op_mode, int queue); void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue); bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state); @@ -186,6 +195,14 @@ static inline void iwl_op_mode_rx(struct iwl_op_mode *op_mode, return op_mode->ops->rx(op_mode, napi, rxb); } +static inline void iwl_op_mode_rx_rss(struct iwl_op_mode *op_mode, + struct napi_struct *napi, + struct iwl_rx_cmd_buffer *rxb, + unsigned int queue) +{ + op_mode->ops->rx_rss(op_mode, napi, rxb, queue); +} + static inline void iwl_op_mode_queue_full(struct iwl_op_mode *op_mode, int queue) { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 9f8bcefc04c5..71610968c365 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -87,6 +87,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, trans->cfg = cfg; trans->ops = ops; trans->dev_cmd_headroom = dev_cmd_headroom; + trans->num_rx_queues = 1; snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name), "iwl_cmd_pool:%s", dev_name(trans->dev)); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index c829c505e141..6f76525088f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -386,6 +386,7 @@ static inline void iwl_free_rxb(struct iwl_rx_cmd_buffer *r) #define IWL_MAX_HW_QUEUES 32 #define IWL_MAX_TID_COUNT 8 #define IWL_FRAME_LIMIT 64 +#define IWL_MAX_RX_HW_QUEUES 16 /** * enum iwl_wowlan_status - WoWLAN image/device status @@ -408,6 +409,7 @@ enum iwl_d3_status { * @STATUS_TRANS_GOING_IDLE: shutting down the trans, only special commands * are sent * @STATUS_TRANS_IDLE: the trans is idle - general commands are not to be sent + * @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation */ enum iwl_trans_status { STATUS_SYNC_HCMD_ACTIVE, @@ -418,6 +420,7 @@ enum iwl_trans_status { STATUS_FW_ERROR, STATUS_TRANS_GOING_IDLE, STATUS_TRANS_IDLE, + STATUS_TRANS_DEAD, }; /** @@ -654,6 +657,8 @@ enum iwl_d0i3_mode { * @hw_id_str: a string with info about HW ID. Set during transport allocation. * @pm_support: set to true in start_hw if link pm is supported * @ltr_enabled: set to true if the LTR is enabled + * @num_rx_queues: number of RX queues allocated by the transport; + * the transport must set this before calling iwl_drv_start() * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only. * The user should use iwl_trans_{alloc,free}_tx_cmd. * @dev_cmd_headroom: room needed for the transport's private use before the @@ -693,6 +698,8 @@ struct iwl_trans { bool pm_support; bool ltr_enabled; + u8 num_rx_queues; + /* The following fields are internal only */ struct kmem_cache *dev_cmd_pool; size_t dev_cmd_headroom; diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index b8ee3121fbd2..5c21231e195d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h @@ -71,6 +71,9 @@ #define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC) #define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC) #define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC) +#define IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT (2 * 1024) /* defined in TU */ +#define IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT (40 * 1024) /* defined in TU */ +#define IWL_MVM_P2P_LOWLATENCY_PS_ENABLE 0 #define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC) #define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC) #define IWL_MVM_UAPSD_QUEUES (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\ @@ -101,7 +104,7 @@ #define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0 #define IWL_MVM_QUOTA_THRESHOLD 4 #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 -#define IWL_MVM_RS_DISABLE_P2P_MIMO 0 +#define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1 #define IWL_MVM_TOF_IS_RESPONDER 0 #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/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 576187611e61..85ae902df7c0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -1165,6 +1165,9 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); int ret; + /* make sure the d0i3 exit work is not pending */ + flush_work(&mvm->d0i3_exit_work); + ret = iwl_trans_suspend(mvm->trans); if (ret) return ret; diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index 383a3162046c..7904b41a04c6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c @@ -511,7 +511,8 @@ static ssize_t iwl_dbgfs_tof_enable_write(struct ieee80211_vif *vif, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = mvmvif->mvm; - int value, ret = -EINVAL; + u32 value; + int ret = -EINVAL; char *data; mutex_lock(&mvm->mutex); @@ -599,7 +600,8 @@ static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = mvmvif->mvm; - int value, ret = 0; + u32 value; + int ret = 0; char *data; mutex_lock(&mvm->mutex); @@ -713,11 +715,30 @@ static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif, goto out; } - data = iwl_dbgfs_is_match("ctrl_ch_position=", buf); + data = iwl_dbgfs_is_match("center_freq=", buf); if (data) { + struct iwl_tof_responder_config_cmd *cmd = + &mvm->tof_data.responder_cfg; + ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.ctrl_ch_position = value; + if (ret == 0 && value) { + enum ieee80211_band band = (cmd->channel_num <= 14) ? + IEEE80211_BAND_2GHZ : + IEEE80211_BAND_5GHZ; + struct ieee80211_channel chn = { + .band = band, + .center_freq = ieee80211_channel_to_frequency( + cmd->channel_num, band), + }; + struct cfg80211_chan_def chandef = { + .chan = &chn, + .center_freq1 = + ieee80211_channel_to_frequency(value, + band), + }; + + cmd->ctrl_ch_position = iwl_mvm_get_ctrl_pos(&chandef); + } goto out; } @@ -822,7 +843,8 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = mvmvif->mvm; - int value, ret = 0; + u32 value; + int ret = 0; char *data; mutex_lock(&mvm->mutex); @@ -892,6 +914,7 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif, goto out; } memcpy(mvm->tof_data.range_req.macaddr_template, mac, ETH_ALEN); + goto out; } data = iwl_dbgfs_is_match("macaddr_mask=", buf); @@ -903,21 +926,22 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif, goto out; } memcpy(mvm->tof_data.range_req.macaddr_mask, mac, ETH_ALEN); + goto out; } data = iwl_dbgfs_is_match("ap=", buf); if (data) { - struct iwl_tof_range_req_ap_entry ap; + struct iwl_tof_range_req_ap_entry ap = {}; int size = sizeof(struct iwl_tof_range_req_ap_entry); u16 burst_period; u8 *mac = ap.bssid; unsigned int i; - if (sscanf(data, "%u %hhd %hhx %hhx" + if (sscanf(data, "%u %hhd %hhd %hhd" "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx" - "%hhx %hhx %hx" - "%hhx %hhx %x" - "%hhx %hhx %hhx %hhx", + "%hhd %hhd %hd" + "%hhd %hhd %d" + "%hhx %hhd %hhd %hhd", &i, &ap.channel_num, &ap.bandwidth, &ap.ctrl_ch_position, mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5, @@ -944,12 +968,12 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif, data = iwl_dbgfs_is_match("send_range_request=", buf); if (data) { ret = kstrtou32(data, 10, &value); - if (ret == 0 && value) { + if (ret == 0 && value) ret = iwl_mvm_tof_range_request_cmd(mvm, vif); - goto out; - } + goto out; } + ret = -EINVAL; out: mutex_unlock(&mvm->mutex); return ret ?: count; @@ -994,16 +1018,18 @@ static ssize_t iwl_dbgfs_tof_range_request_read(struct file *file, struct iwl_tof_range_req_ap_entry *ap = &cmd->ap[i]; pos += scnprintf(buf + pos, bufsz - pos, - "ap %.2d: channel_num=%hhx bw=%hhx" - " control=%hhx bssid=%pM type=%hhx" - " num_of_bursts=%hhx burst_period=%hx ftm=%hhx" - " retries=%hhx tsf_delta=%x location_req=%hhx " - " asap=%hhx enable=%hhx rssi=%hhx\n", + "ap %.2d: channel_num=%hhd bw=%hhd" + " control=%hhd bssid=%pM type=%hhd" + " num_of_bursts=%hhd burst_period=%hd ftm=%hhd" + " retries=%hhd tsf_delta=%d" + " tsf_delta_direction=%hhd location_req=0x%hhx " + " asap=%hhd enable=%hhd rssi=%hhd\n", i, ap->channel_num, ap->bandwidth, ap->ctrl_ch_position, ap->bssid, ap->measure_type, ap->num_of_bursts, ap->burst_period, ap->samples_per_burst, ap->retries_per_sample, ap->tsf_delta, + ap->tsf_delta_direction, ap->location_req, ap->asap_mode, ap->enable_dyn_ack, ap->rssi); } @@ -1019,7 +1045,8 @@ static ssize_t iwl_dbgfs_tof_range_req_ext_write(struct ieee80211_vif *vif, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = mvmvif->mvm; - int value, ret = 0; + u32 value; + int ret = 0; char *data; mutex_lock(&mvm->mutex); @@ -1071,12 +1098,12 @@ static ssize_t iwl_dbgfs_tof_range_req_ext_write(struct ieee80211_vif *vif, data = iwl_dbgfs_is_match("send_range_req_ext=", buf); if (data) { ret = kstrtou32(data, 10, &value); - if (ret == 0 && value) { + if (ret == 0 && value) ret = iwl_mvm_tof_range_request_ext_cmd(mvm, vif); - goto out; - } + goto out; } + ret = -EINVAL; out: mutex_unlock(&mvm->mutex); return ret ?: count; @@ -1099,18 +1126,18 @@ static ssize_t iwl_dbgfs_tof_range_req_ext_read(struct file *file, mutex_lock(&mvm->mutex); pos += scnprintf(buf + pos, bufsz - pos, - "tsf_timer_offset_msec = %hx\n", + "tsf_timer_offset_msec = %hd\n", cmd->tsf_timer_offset_msec); - pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %hhx\n", + pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %hhd\n", cmd->min_delta_ftm); pos += scnprintf(buf + pos, bufsz - pos, - "ftm_format_and_bw20M = %hhx\n", + "ftm_format_and_bw20M = %hhd\n", cmd->ftm_format_and_bw20M); pos += scnprintf(buf + pos, bufsz - pos, - "ftm_format_and_bw40M = %hhx\n", + "ftm_format_and_bw40M = %hhd\n", cmd->ftm_format_and_bw40M); pos += scnprintf(buf + pos, bufsz - pos, - "ftm_format_and_bw80M = %hhx\n", + "ftm_format_and_bw80M = %hhd\n", cmd->ftm_format_and_bw80M); mutex_unlock(&mvm->mutex); @@ -1123,8 +1150,8 @@ static ssize_t iwl_dbgfs_tof_range_abort_write(struct ieee80211_vif *vif, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = mvmvif->mvm; - int value, ret = 0; - int abort_id; + u32 value; + int abort_id, ret = 0; char *data; mutex_lock(&mvm->mutex); @@ -1205,11 +1232,11 @@ static ssize_t iwl_dbgfs_tof_range_response_read(struct file *file, struct iwl_tof_range_rsp_ap_entry_ntfy *ap = &cmd->ap[i]; pos += scnprintf(buf + pos, bufsz - pos, - "ap %.2d: bssid=%pM status=%hhx bw=%hhx" - " rtt=%x rtt_var=%x rtt_spread=%x" - " rssi=%hhx rssi_spread=%hhx" - " range=%x range_var=%x" - " time_stamp=%x\n", + "ap %.2d: bssid=%pM status=%hhd bw=%hhd" + " rtt=%d rtt_var=%d rtt_spread=%d" + " rssi=%hhd rssi_spread=%hhd" + " range=%d range_var=%d" + " time_stamp=%d\n", i, ap->bssid, ap->measure_status, ap->measure_bw, ap->rtt, ap->rtt_variance, ap->rtt_spread, @@ -1250,11 +1277,10 @@ static ssize_t iwl_dbgfs_low_latency_read(struct file *file, { struct ieee80211_vif *vif = file->private_data; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - char buf[3]; + char buf[2]; buf[0] = mvmvif->low_latency ? '1' : '0'; buf[1] = '\n'; - buf[2] = '\0'; return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf)); } diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 7d69a556bcc8..05928fb4021d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -85,7 +85,7 @@ static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf, IWL_ERR(mvm, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk); mutex_lock(&mvm->mutex); - ret = iwl_mvm_flush_tx_path(mvm, scd_q_msk, true) ? : count; + ret = iwl_mvm_flush_tx_path(mvm, scd_q_msk, 0) ? : count; mutex_unlock(&mvm->mutex); return ret; @@ -1214,118 +1214,6 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf, return ret; } - -#define MAX_NUM_ND_MATCHSETS 10 - -static ssize_t iwl_dbgfs_netdetect_write(struct iwl_mvm *mvm, char *buf, - size_t count, loff_t *ppos) -{ - const char *seps = ",\n"; - char *buf_ptr = buf; - char *value_str = NULL; - int ret, i; - - /* TODO: don't free if write is being called several times in one go */ - if (mvm->nd_config) { - kfree(mvm->nd_config->match_sets); - kfree(mvm->nd_config); - mvm->nd_config = NULL; - } - - mvm->nd_config = kzalloc(sizeof(*mvm->nd_config) + - (11 * sizeof(struct ieee80211_channel *)), - GFP_KERNEL); - if (!mvm->nd_config) { - ret = -ENOMEM; - goto out_free; - } - - mvm->nd_config->n_channels = 11; - mvm->nd_config->scan_width = NL80211_BSS_CHAN_WIDTH_20; - mvm->nd_config->interval = 5; - mvm->nd_config->min_rssi_thold = -80; - for (i = 0; i < mvm->nd_config->n_channels; i++) - mvm->nd_config->channels[i] = &mvm->nvm_data->channels[i]; - - mvm->nd_config->match_sets = - kcalloc(MAX_NUM_ND_MATCHSETS, - sizeof(*mvm->nd_config->match_sets), - GFP_KERNEL); - if (!mvm->nd_config->match_sets) { - ret = -ENOMEM; - goto out_free; - } - - while ((value_str = strsep(&buf_ptr, seps)) && - strlen(value_str)) { - struct cfg80211_match_set *set; - - if (mvm->nd_config->n_match_sets >= MAX_NUM_ND_MATCHSETS) { - ret = -EINVAL; - goto out_free; - } - - set = &mvm->nd_config->match_sets[mvm->nd_config->n_match_sets]; - set->ssid.ssid_len = strlen(value_str); - - if (set->ssid.ssid_len > IEEE80211_MAX_SSID_LEN) { - ret = -EINVAL; - goto out_free; - } - - memcpy(set->ssid.ssid, value_str, set->ssid.ssid_len); - - mvm->nd_config->n_match_sets++; - } - - ret = count; - - if (mvm->nd_config->n_match_sets) - goto out; - -out_free: - if (mvm->nd_config) - kfree(mvm->nd_config->match_sets); - kfree(mvm->nd_config); - mvm->nd_config = NULL; -out: - return ret; -} - -static ssize_t -iwl_dbgfs_netdetect_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_mvm *mvm = file->private_data; - size_t bufsz, ret; - char *buf; - int i, n_match_sets, pos = 0; - - n_match_sets = mvm->nd_config ? mvm->nd_config->n_match_sets : 0; - - bufsz = n_match_sets * (IEEE80211_MAX_SSID_LEN + 1) + 1; - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - for (i = 0; i < n_match_sets; i++) { - if (pos + - mvm->nd_config->match_sets[i].ssid.ssid_len + 2 > bufsz) { - ret = -EIO; - goto out; - } - - memcpy(buf + pos, mvm->nd_config->match_sets[i].ssid.ssid, - mvm->nd_config->match_sets[i].ssid.ssid_len); - pos += mvm->nd_config->match_sets[i].ssid.ssid_len; - buf[pos++] = '\n'; - } - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -out: - kfree(buf); - return ret; -} #endif #define PRINT_MVM_REF(ref) do { \ @@ -1473,11 +1361,25 @@ out: return count; } +static ssize_t +iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf, + size_t count, loff_t *ppos) +{ + int ret; + + mutex_lock(&mvm->mutex); + ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL); + mutex_unlock(&mvm->mutex); + + return ret ?: count; +} + MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64); /* Device wide debugfs entries */ MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16); MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8); +MVM_DEBUGFS_WRITE_FILE_OPS(send_echo_cmd, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64); MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64); MVM_DEBUGFS_READ_FILE_OPS(nic_temp); @@ -1503,7 +1405,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); #ifdef CONFIG_PM_SLEEP MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8); -MVM_DEBUGFS_READ_WRITE_FILE_OPS(netdetect, 384); #endif int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) @@ -1538,6 +1439,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR); MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR); MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR); + MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR); if (!debugfs_create_bool("enable_scan_iteration_notif", S_IRUSR | S_IWUSR, mvm->debugfs_dir, @@ -1572,7 +1474,6 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) if (!debugfs_create_u32("last_netdetect_scans", S_IRUSR, mvm->debugfs_dir, &mvm->last_netdetect_scans)) goto err; - MVM_DEBUGFS_ADD_FILE(netdetect, mvm->debugfs_dir, S_IRUSR | S_IWUSR); #endif if (!debugfs_create_u8("low_latency_agg_frame_limit", S_IRUSR | S_IWUSR, @@ -1594,6 +1495,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) if (!debugfs_create_blob("nvm_prod", S_IRUSR, mvm->debugfs_dir, &mvm->nvm_prod_blob)) goto err; + if (!debugfs_create_blob("nvm_phy_sku", S_IRUSR, + mvm->debugfs_dir, &mvm->nvm_phy_sku_blob)) + goto err; /* * Create a symlink with mac80211. It will be removed when mac80211 diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index 7005fa4be74a..c8f3e2536cbb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h @@ -192,16 +192,10 @@ 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 - * receiver and transmitter. '0' - does not allow. This flag should be - * always set to '1' unless one need to disable actual power down for debug - * purposes. - * @DEVICE_POWER_FLAGS_CAM_MSK: '1' CAM (Continuous Active Mode) is set, meaning - * that power management is disabled. '0' Power management is enabled, one - * of power schemes is applied. + * receiver and transmitter. '0' - does not allow. */ enum iwl_device_power_flags { DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), - DEVICE_POWER_FLAGS_CAM_MSK = BIT(13), }; /** diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h new file mode 100644 index 000000000000..9b7e49d4620f --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h @@ -0,0 +1,238 @@ +/****************************************************************************** + * + * 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) 2012 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2015 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called COPYING. + * + * Contact Information: + * Intel Linux Wireless <ilw@linux.intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2015 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 __fw_api_rx_h__ +#define __fw_api_rx_h__ + +#define IWL_RX_INFO_PHY_CNT 8 +#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1 +#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff +#define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00 +#define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000 +#define IWL_RX_INFO_ENERGY_ANT_A_POS 0 +#define IWL_RX_INFO_ENERGY_ANT_B_POS 8 +#define IWL_RX_INFO_ENERGY_ANT_C_POS 16 + +/** + * struct iwl_rx_phy_info - phy info + * (REPLY_RX_PHY_CMD = 0xc0) + * @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: + * @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 + * @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 + * calculation + * @mac_active_msk: what MACs were active when the frame was received + * + * Before each Rx, the device sends this data. It contains PHY information + * about the reception of the packet. + */ +struct iwl_rx_phy_info { + u8 non_cfg_phy_cnt; + u8 cfg_phy_cnt; + u8 stat_id; + u8 reserved1; + __le32 system_timestamp; + __le64 timestamp; + __le32 beacon_time_stamp; + __le16 phy_flags; + __le16 channel; + __le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT]; + __le32 rate_n_flags; + __le32 byte_count; + __le16 mac_active_msk; + __le16 frame_time; +} __packed; + +/* + * TCP offload Rx assist info + * + * bits 0:3 - reserved + * bits 4:7 - MIC CRC length + * bits 8:12 - MAC header length + * bit 13 - Padding indication + * bit 14 - A-AMSDU indication + * bit 15 - Offload enabled + */ +enum iwl_csum_rx_assist_info { + CSUM_RXA_RESERVED_MASK = 0x000f, + CSUM_RXA_MICSIZE_MASK = 0x00f0, + CSUM_RXA_HEADERLEN_MASK = 0x1f00, + CSUM_RXA_PADD = BIT(13), + CSUM_RXA_AMSDU = BIT(14), + CSUM_RXA_ENA = BIT(15) +}; + +/** + * struct iwl_rx_mpdu_res_start - phy info + * @assist: see CSUM_RX_ASSIST_ above + */ +struct iwl_rx_mpdu_res_start { + __le16 byte_count; + __le16 assist; +} __packed; /* _RX_MPDU_RES_START_API_S_VER_2 */ + +/** + * 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_SHORT_PREAMBLE: true if packet's preamble was short + * @RX_RES_PHY_FLAGS_NARROW_BAND: + * @RX_RES_PHY_FLAGS_ANTENNA: antenna on which the packet was received + * @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 + * @RX_RES_PHY_FLAGS_OFDM_VHT: The frame was a VHT frame + */ +enum iwl_rx_phy_flags { + RX_RES_PHY_FLAGS_BAND_24 = BIT(0), + RX_RES_PHY_FLAGS_MOD_CCK = BIT(1), + RX_RES_PHY_FLAGS_SHORT_PREAMBLE = BIT(2), + RX_RES_PHY_FLAGS_NARROW_BAND = BIT(3), + RX_RES_PHY_FLAGS_ANTENNA = (0x7 << 4), + RX_RES_PHY_FLAGS_ANTENNA_POS = 4, + RX_RES_PHY_FLAGS_AGG = BIT(7), + RX_RES_PHY_FLAGS_OFDM_HT = BIT(8), + RX_RES_PHY_FLAGS_OFDM_GF = BIT(9), + RX_RES_PHY_FLAGS_OFDM_VHT = BIT(10), +}; + +/** + * 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_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. + * @RX_MPDU_RES_STATUS_TTAK_OK: TTAK is fine + * @RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR: valid for alg = CCM_CMAC or + * alg = CCM only. Checks replay attack for 11w frames. Relevant only if + * %RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME is set. + * @RX_MPDU_RES_STATUS_SEC_NO_ENC: this frame is not encrypted + * @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_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_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: + */ +enum iwl_mvm_rx_status { + RX_MPDU_RES_STATUS_CRC_OK = BIT(0), + RX_MPDU_RES_STATUS_OVERRUN_OK = BIT(1), + RX_MPDU_RES_STATUS_SRC_STA_FOUND = BIT(2), + RX_MPDU_RES_STATUS_KEY_VALID = BIT(3), + RX_MPDU_RES_STATUS_KEY_PARAM_OK = BIT(4), + RX_MPDU_RES_STATUS_ICV_OK = BIT(5), + RX_MPDU_RES_STATUS_MIC_OK = BIT(6), + RX_MPDU_RES_STATUS_TTAK_OK = BIT(7), + RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR = BIT(7), + RX_MPDU_RES_STATUS_SEC_NO_ENC = (0 << 8), + RX_MPDU_RES_STATUS_SEC_WEP_ENC = (1 << 8), + RX_MPDU_RES_STATUS_SEC_CCM_ENC = (2 << 8), + RX_MPDU_RES_STATUS_SEC_TKIP_ENC = (3 << 8), + RX_MPDU_RES_STATUS_SEC_EXT_ENC = (4 << 8), + RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC = (6 << 8), + 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_MPDU_RES_STATUS_STA_ID_MSK = (0x1f000000), + RX_MPDU_RES_STATUS_RRF_KILL = BIT(29), + RX_MPDU_RES_STATUS_FILTERING_MSK = (0xc00000), + RX_MPDU_RES_STATUS2_FILTERING_MSK = (0xc0000000), +}; + +#endif /* __fw_api_rx_h__ */ diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 660cc1c93e19..3a657e4b60ac 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h @@ -101,6 +101,7 @@ struct iwl_ssid_ie { #define IWL_FULL_SCAN_MULTIPLIER 5 #define IWL_FAST_SCHED_SCAN_ITERATIONS 3 +#define IWL_MAX_SCHED_SCAN_PLANS 2 enum scan_framework_client { SCAN_CLIENT_SCHED_SCAN = BIT(0), @@ -359,7 +360,7 @@ struct iwl_scan_req_lmac { /* SCAN_REQ_PERIODIC_PARAMS_API_S */ __le32 iter_num; __le32 delay; - struct iwl_scan_schedule_lmac schedule[2]; + struct iwl_scan_schedule_lmac schedule[IWL_MAX_SCHED_SCAN_PLANS]; struct iwl_scan_channel_opt channel_opt[2]; u8 data[]; } __packed; @@ -582,7 +583,7 @@ struct iwl_scan_umac_schedule { */ struct iwl_scan_req_umac_tail { /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */ - struct iwl_scan_umac_schedule schedule[2]; + struct iwl_scan_umac_schedule schedule[IWL_MAX_SCHED_SCAN_PLANS]; __le16 delay; __le16 reserved; /* SCAN_PROBE_PARAMS_API_S_VER_1 */ diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h index 709e28d8b1b0..0c321f63ee42 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h @@ -219,32 +219,6 @@ struct mvm_statistics_bt_activity { __le32 lo_priority_rx_denied_cnt; } __packed; /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */ -struct mvm_statistics_general_v5 { - __le32 radio_temperature; - __le32 radio_voltage; - 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; - __s8 beacon_filter_average_energy; - __s8 beacon_filter_reason; - __s8 beacon_filter_current_energy; - __s8 beacon_filter_reserved; - __le32 beacon_filter_delta_time; - struct mvm_statistics_bt_activity bt_activity; -} __packed; /* STATISTICS_GENERAL_API_S_VER_5 */ - struct mvm_statistics_general_v8 { __le32 radio_temperature; __le32 radio_voltage; @@ -263,10 +237,10 @@ struct mvm_statistics_general_v8 { __le32 num_of_sos_states; __le32 beacon_filtered; __le32 missed_beacons; - __s8 beacon_filter_average_energy; - __s8 beacon_filter_reason; - __s8 beacon_filter_current_energy; - __s8 beacon_filter_reserved; + 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; @@ -293,13 +267,6 @@ struct mvm_statistics_rx { * STATISTICS_CMD (0x9c), below. */ -struct iwl_notif_statistics_v8 { - __le32 flag; - struct mvm_statistics_rx rx; - struct mvm_statistics_tx tx; - struct mvm_statistics_general_v5 general; -} __packed; /* STATISTICS_NTFY_API_S_VER_8 */ - struct iwl_notif_statistics_v10 { __le32 flag; struct mvm_statistics_rx rx; diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 4af7513adda2..181590fbd3b3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h @@ -67,6 +67,7 @@ #define __fw_api_h__ #include "fw-api-rs.h" +#include "fw-api-rx.h" #include "fw-api-tx.h" #include "fw-api-sta.h" #include "fw-api-mac.h" @@ -100,6 +101,7 @@ enum iwl_mvm_tx_fifo { enum { MVM_ALIVE = 0x1, REPLY_ERROR = 0x2, + ECHO_CMD = 0x3, INIT_COMPLETE_NOTIF = 0x4, @@ -266,6 +268,16 @@ enum { REPLY_MAX = 0xff, }; +enum iwl_phy_ops_subcmd_ids { + CMD_DTS_MEASUREMENT_TRIGGER_WIDE = 0x0, + DTS_MEASUREMENT_NOTIF_WIDE = 0xFF, +}; + +/* command groups */ +enum { + PHY_OPS_GROUP = 0x4, +}; + /** * struct iwl_cmd_response - generic response struct for most commands * @status: status of the command asked, changes for each one @@ -1070,190 +1082,6 @@ struct iwl_hs20_roc_res { __le32 status; } __packed; /* HOT_SPOT_RSP_API_S_VER_1 */ -#define IWL_RX_INFO_PHY_CNT 8 -#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1 -#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff -#define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00 -#define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000 -#define IWL_RX_INFO_ENERGY_ANT_A_POS 0 -#define IWL_RX_INFO_ENERGY_ANT_B_POS 8 -#define IWL_RX_INFO_ENERGY_ANT_C_POS 16 - -#define IWL_RX_INFO_AGC_IDX 1 -#define IWL_RX_INFO_RSSI_AB_IDX 2 -#define IWL_OFDM_AGC_A_MSK 0x0000007f -#define IWL_OFDM_AGC_A_POS 0 -#define IWL_OFDM_AGC_B_MSK 0x00003f80 -#define IWL_OFDM_AGC_B_POS 7 -#define IWL_OFDM_AGC_CODE_MSK 0x3fe00000 -#define IWL_OFDM_AGC_CODE_POS 20 -#define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff -#define IWL_OFDM_RSSI_A_POS 0 -#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00 -#define IWL_OFDM_RSSI_ALLBAND_A_POS 8 -#define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000 -#define IWL_OFDM_RSSI_B_POS 16 -#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000 -#define IWL_OFDM_RSSI_ALLBAND_B_POS 24 - -/** - * struct iwl_rx_phy_info - phy info - * (REPLY_RX_PHY_CMD = 0xc0) - * @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: - * @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 - * @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 - * calculation - * @mac_active_msk: what MACs were active when the frame was received - * - * Before each Rx, the device sends this data. It contains PHY information - * about the reception of the packet. - */ -struct iwl_rx_phy_info { - u8 non_cfg_phy_cnt; - u8 cfg_phy_cnt; - u8 stat_id; - u8 reserved1; - __le32 system_timestamp; - __le64 timestamp; - __le32 beacon_time_stamp; - __le16 phy_flags; - __le16 channel; - __le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT]; - __le32 rate_n_flags; - __le32 byte_count; - __le16 mac_active_msk; - __le16 frame_time; -} __packed; - -/* - * TCP offload Rx assist info - * - * bits 0:3 - reserved - * bits 4:7 - MIC CRC length - * bits 8:12 - MAC header length - * bit 13 - Padding indication - * bit 14 - A-AMSDU indication - * bit 15 - Offload enabled - */ -enum iwl_csum_rx_assist_info { - CSUM_RXA_RESERVED_MASK = 0x000f, - CSUM_RXA_MICSIZE_MASK = 0x00f0, - CSUM_RXA_HEADERLEN_MASK = 0x1f00, - CSUM_RXA_PADD = BIT(13), - CSUM_RXA_AMSDU = BIT(14), - CSUM_RXA_ENA = BIT(15) -}; - -/** - * struct iwl_rx_mpdu_res_start - phy info - * @assist: see CSUM_RX_ASSIST_ above - */ -struct iwl_rx_mpdu_res_start { - __le16 byte_count; - __le16 assist; -} __packed; /* _RX_MPDU_RES_START_API_S_VER_2 */ - -/** - * 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_SHORT_PREAMBLE: true if packet's preamble was short - * @RX_RES_PHY_FLAGS_NARROW_BAND: - * @RX_RES_PHY_FLAGS_ANTENNA: antenna on which the packet was received - * @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 - * @RX_RES_PHY_FLAGS_OFDM_VHT: The frame was a VHT frame - */ -enum iwl_rx_phy_flags { - RX_RES_PHY_FLAGS_BAND_24 = BIT(0), - RX_RES_PHY_FLAGS_MOD_CCK = BIT(1), - RX_RES_PHY_FLAGS_SHORT_PREAMBLE = BIT(2), - RX_RES_PHY_FLAGS_NARROW_BAND = BIT(3), - RX_RES_PHY_FLAGS_ANTENNA = (0x7 << 4), - RX_RES_PHY_FLAGS_ANTENNA_POS = 4, - RX_RES_PHY_FLAGS_AGG = BIT(7), - RX_RES_PHY_FLAGS_OFDM_HT = BIT(8), - RX_RES_PHY_FLAGS_OFDM_GF = BIT(9), - RX_RES_PHY_FLAGS_OFDM_VHT = BIT(10), -}; - -/** - * 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_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. - * @RX_MPDU_RES_STATUS_TTAK_OK: TTAK is fine - * @RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR: valid for alg = CCM_CMAC or - * alg = CCM only. Checks replay attack for 11w frames. Relevant only if - * %RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME is set. - * @RX_MPDU_RES_STATUS_SEC_NO_ENC: this frame is not encrypted - * @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_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_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: - */ -enum iwl_mvm_rx_status { - RX_MPDU_RES_STATUS_CRC_OK = BIT(0), - RX_MPDU_RES_STATUS_OVERRUN_OK = BIT(1), - RX_MPDU_RES_STATUS_SRC_STA_FOUND = BIT(2), - RX_MPDU_RES_STATUS_KEY_VALID = BIT(3), - RX_MPDU_RES_STATUS_KEY_PARAM_OK = BIT(4), - RX_MPDU_RES_STATUS_ICV_OK = BIT(5), - RX_MPDU_RES_STATUS_MIC_OK = BIT(6), - RX_MPDU_RES_STATUS_TTAK_OK = BIT(7), - RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR = BIT(7), - RX_MPDU_RES_STATUS_SEC_NO_ENC = (0 << 8), - RX_MPDU_RES_STATUS_SEC_WEP_ENC = (1 << 8), - RX_MPDU_RES_STATUS_SEC_CCM_ENC = (2 << 8), - RX_MPDU_RES_STATUS_SEC_TKIP_ENC = (3 << 8), - RX_MPDU_RES_STATUS_SEC_EXT_ENC = (4 << 8), - RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC = (6 << 8), - 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_MPDU_RES_STATUS_STA_ID_MSK = (0x1f000000), - RX_MPDU_RES_STATUS_RRF_KILL = BIT(29), - RX_MPDU_RES_STATUS_FILTERING_MSK = (0xc00000), - RX_MPDU_RES_STATUS2_FILTERING_MSK = (0xc0000000), -}; - /** * struct iwl_radio_version_notif - information on the radio version * ( RADIO_VERSION_NOTIFICATION = 0x68 ) @@ -1696,6 +1524,69 @@ struct iwl_dts_measurement_cmd { } __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_CMD_S */ /** +* enum iwl_dts_control_measurement_mode - DTS measurement type +* @DTS_AUTOMATIC: Automatic mode (full SW control). Provide temperature read +* back (latest value. Not waiting for new value). Use automatic +* SW DTS configuration. +* @DTS_REQUEST_READ: Request DTS read. Configure DTS with manual settings, +* trigger DTS reading and provide read back temperature read +* when available. +* @DTS_OVER_WRITE: over-write the DTS temperatures in the SW until next read +* @DTS_DIRECT_WITHOUT_MEASURE: DTS returns its latest temperature result, +* without measurement trigger. +*/ +enum iwl_dts_control_measurement_mode { + DTS_AUTOMATIC = 0, + DTS_REQUEST_READ = 1, + DTS_OVER_WRITE = 2, + DTS_DIRECT_WITHOUT_MEASURE = 3, +}; + +/** +* enum iwl_dts_used - DTS to use or used for measurement in the DTS request +* @DTS_USE_TOP: Top +* @DTS_USE_CHAIN_A: chain A +* @DTS_USE_CHAIN_B: chain B +* @DTS_USE_CHAIN_C: chain C +* @XTAL_TEMPERATURE - read temperature from xtal +*/ +enum iwl_dts_used { + DTS_USE_TOP = 0, + DTS_USE_CHAIN_A = 1, + DTS_USE_CHAIN_B = 2, + DTS_USE_CHAIN_C = 3, + XTAL_TEMPERATURE = 4, +}; + +/** +* enum iwl_dts_bit_mode - bit-mode to use in DTS request read mode +* @DTS_BIT6_MODE: bit 6 mode +* @DTS_BIT8_MODE: bit 8 mode +*/ +enum iwl_dts_bit_mode { + DTS_BIT6_MODE = 0, + DTS_BIT8_MODE = 1, +}; + +/** + * iwl_ext_dts_measurement_cmd - request extended DTS temperature 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 + * @avg_factor: average factor to DTS in request DTS read mode + * @bit_mode: value defines the DTS bit mode to use. See &enum iwl_dts_bit_mode + * @step_duration: step duration for the DTS + */ +struct iwl_ext_dts_measurement_cmd { + __le32 control_mode; + __le32 temperature; + __le32 sensor; + __le32 avg_factor; + __le32 bit_mode; + __le32 step_duration; +} __packed; /* XVT_FW_DTS_CONTROL_MEASUREMENT_REQUEST_API_S */ + +/** * iwl_dts_measurement_notif - notification received with the measurements * * @temp: the measured temperature diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 5c7f7cc9ffcc..d906fa13ba97 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c @@ -616,12 +616,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, * will be empty. */ - for (i = 0; i < IWL_MAX_HW_QUEUES; i++) { - if (i < mvm->first_agg_queue && i != IWL_MVM_CMD_QUEUE) - mvm->queue_to_mac80211[i] = i; - else - mvm->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE; - } + memset(&mvm->queue_info, 0, sizeof(mvm->queue_info)); + mvm->queue_info[IWL_MVM_CMD_QUEUE].hw_queue_refcount = 1; for (i = 0; i < IEEE80211_MAX_QUEUES; i++) atomic_set(&mvm->mac80211_queue_stop_count[i], 0); @@ -940,19 +936,6 @@ int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id) return ret; } -static int iwl_mvm_config_ltr_v1(struct iwl_mvm *mvm) -{ - struct iwl_ltr_config_cmd_v1 cmd_v1 = { - .flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE), - }; - - if (!mvm->trans->ltr_enabled) - return 0; - - return iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, - sizeof(cmd_v1), &cmd_v1); -} - static int iwl_mvm_config_ltr(struct iwl_mvm *mvm) { struct iwl_ltr_config_cmd cmd = { @@ -962,9 +945,6 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm) if (!mvm->trans->ltr_enabled) return 0; - if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_HDC_PHASE_0)) - return iwl_mvm_config_ltr_v1(mvm); - return iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, sizeof(cmd), &cmd); } diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 3424315dd876..ad7ad720d2e7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c @@ -7,6 +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 * * 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) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2015 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -484,16 +486,18 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) switch (vif->type) { case NL80211_IFTYPE_P2P_DEVICE: iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, - IWL_MVM_TX_FIFO_VO, wdg_timeout); + IWL_MVM_OFFCHANNEL_QUEUE, + IWL_MVM_TX_FIFO_VO, 0, wdg_timeout); break; case NL80211_IFTYPE_AP: - iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, - IWL_MVM_TX_FIFO_MCAST, wdg_timeout); + iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, vif->cab_queue, + IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout); /* fall through */ default: for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac], - iwl_mvm_ac_to_tx_fifo[ac], + vif->hw_queue[ac], + iwl_mvm_ac_to_tx_fifo[ac], 0, wdg_timeout); break; } @@ -509,14 +513,19 @@ void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif) switch (vif->type) { case NL80211_IFTYPE_P2P_DEVICE: - iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, 0); + iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, + IWL_MVM_OFFCHANNEL_QUEUE, IWL_MAX_TID_COUNT, + 0); break; case NL80211_IFTYPE_AP: - iwl_mvm_disable_txq(mvm, vif->cab_queue, 0); + iwl_mvm_disable_txq(mvm, vif->cab_queue, vif->cab_queue, + IWL_MAX_TID_COUNT, 0); /* fall through */ default: for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) - iwl_mvm_disable_txq(mvm, vif->hw_queue[ac], 0); + iwl_mvm_disable_txq(mvm, vif->hw_queue[ac], + vif->hw_queue[ac], + IWL_MAX_TID_COUNT, 0); } } @@ -834,6 +843,9 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval); ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid); + if (vif->probe_req_reg && vif->bss_conf.assoc && vif->p2p) + cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); + return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); } @@ -1128,6 +1140,7 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm, struct ieee80211_vif *vif, u32 action) { + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mac_ctx_cmd cmd = {}; WARN_ON(vif->type != NL80211_IFTYPE_AP || vif->p2p); @@ -1137,10 +1150,16 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm, /* * pass probe requests and beacons from other APs (needed - * for ht protection) + * for ht protection); when there're no any associated station + * don't ask FW to pass beacons to prevent unnecessary wake-ups. */ - cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST | - MAC_FILTER_IN_BEACON); + cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); + if (mvmvif->ap_assoc_sta_count) { + cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON); + IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n"); + } else { + IWL_DEBUG_HC(mvm, "No need to receive beacons\n"); + } /* Fill the data specific for ap mode */ iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap, diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 7c2944a72470..1fb684693040 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -572,6 +572,14 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) /* we create the 802.11 header and zero length SSID IE. */ hw->wiphy->max_sched_scan_ie_len = SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2; + hw->wiphy->max_sched_scan_plans = IWL_MAX_SCHED_SCAN_PLANS; + hw->wiphy->max_sched_scan_plan_interval = U16_MAX; + + /* + * the firmware uses u8 for num of iterations, but 0xff is saved for + * infinite loop, so the maximum number of iterations is actually 254. + */ + hw->wiphy->max_sched_scan_plan_iterations = 254; hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | NL80211_FEATURE_LOW_PRIORITY_SCAN | @@ -820,7 +828,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size) + u16 *ssn, u8 buf_size, bool amsdu) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); int ret; @@ -1129,6 +1137,12 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) lockdep_assert_held(&mvm->mutex); + /* there's no point in fw dump if the bus is dead */ + if (test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) { + IWL_ERR(mvm, "Skip fw error dump since bus is dead\n"); + return; + } + if (mvm->fw_dump_trig && mvm->fw_dump_trig->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY) monitor_dump_only = true; @@ -1192,6 +1206,13 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) if (sram2_len) file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len; + /* Make room for fw's virtual image pages, if it exists */ + if (mvm->fw->img[mvm->cur_ucode].paging_mem_size) + file_len += mvm->num_of_paging_blk * + (sizeof(*dump_data) + + sizeof(struct iwl_fw_error_dump_paging) + + PAGING_BLOCK_SIZE); + /* If we only want a monitor dump, reset the file length */ if (monitor_dump_only) { file_len = sizeof(*dump_file) + sizeof(*dump_data) + @@ -1302,6 +1323,26 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) dump_mem->data, IWL8260_ICCM_LEN); } + /* Dump fw's virtual image */ + if (mvm->fw->img[mvm->cur_ucode].paging_mem_size) { + u32 i; + + for (i = 1; i < mvm->num_of_paging_blk + 1; i++) { + struct iwl_fw_error_dump_paging *paging; + struct page *pages = + mvm->fw_paging_db[i].fw_paging_block; + + dump_data = iwl_fw_error_next_data(dump_data); + dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING); + dump_data->len = cpu_to_le32(sizeof(*paging) + + PAGING_BLOCK_SIZE); + paging = (void *)dump_data->data; + paging->index = cpu_to_le32(i); + memcpy(paging->data, page_address(pages), + PAGING_BLOCK_SIZE); + } + } + dump_trans_data: fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans, mvm->fw_dump_trig); @@ -1577,20 +1618,6 @@ static struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm) return NULL; } -static int iwl_mvm_set_tx_power_old(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, s8 tx_power) -{ - /* FW is in charge of regulatory enforcement */ - struct iwl_reduce_tx_power_cmd reduce_txpwr_cmd = { - .mac_context_id = iwl_mvm_vif_from_mac80211(vif)->id, - .pwr_restriction = cpu_to_le16(tx_power), - }; - - return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, - sizeof(reduce_txpwr_cmd), - &reduce_txpwr_cmd); -} - static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, s16 tx_power) { @@ -1602,9 +1629,6 @@ static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, }; int len = sizeof(cmd); - if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_TX_POWER_DEV)) - return iwl_mvm_set_tx_power_old(mvm, vif, tx_power); - if (tx_power == IWL_DEFAULT_MAX_TX_POWER) cmd.v2.pwr_restriction = cpu_to_le16(IWL_DEV_MAX_TX_POWER); @@ -1771,7 +1795,7 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, * Flush them here. */ mutex_lock(&mvm->mutex); - iwl_mvm_flush_tx_path(mvm, tfd_msk, true); + iwl_mvm_flush_tx_path(mvm, tfd_msk, 0); mutex_unlock(&mvm->mutex); /* @@ -1972,6 +1996,27 @@ out: *total_flags = 0; } +static void iwl_mvm_config_iface_filter(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + unsigned int filter_flags, + unsigned int changed_flags) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + + /* We support only filter for probe requests */ + if (!(changed_flags & FIF_PROBE_REQ)) + return; + + /* Supported only for p2p client interfaces */ + if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc || + !vif->p2p) + return; + + mutex_lock(&mvm->mutex); + iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); + mutex_unlock(&mvm->mutex); +} + #ifdef CONFIG_IWLWIFI_BCAST_FILTERING struct iwl_bcast_iter_data { struct iwl_mvm *mvm; @@ -2319,6 +2364,8 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, if (vif->type == NL80211_IFTYPE_AP) iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif); + mvmvif->ap_assoc_sta_count = 0; + /* Add the mac context */ ret = iwl_mvm_mac_ctxt_add(mvm, vif); if (ret) @@ -2614,6 +2661,7 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); /* @@ -2628,6 +2676,12 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id])) rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], ERR_PTR(-ENOENT)); + + if (mvm_sta->vif->type == NL80211_IFTYPE_AP) { + mvmvif->ap_assoc_sta_count--; + iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); + } + mutex_unlock(&mvm->mutex); } @@ -3906,7 +3960,7 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, } if (drop) { - if (iwl_mvm_flush_tx_path(mvm, msk, true)) + if (iwl_mvm_flush_tx_path(mvm, msk, 0)) IWL_ERR(mvm, "flush request fail\n"); mutex_unlock(&mvm->mutex); } else { @@ -4143,6 +4197,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { .config = iwl_mvm_mac_config, .prepare_multicast = iwl_mvm_prepare_multicast, .configure_filter = iwl_mvm_configure_filter, + .config_iface_filter = iwl_mvm_config_iface_filter, .bss_info_changed = iwl_mvm_bss_info_changed, .hw_scan = iwl_mvm_mac_hw_scan, .cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan, diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index c754051a4cea..c6327cd1d071 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -82,7 +82,6 @@ #include "constants.h" #include "tof.h" -#define IWL_INVALID_MAC80211_QUEUE 0xff #define IWL_MVM_MAX_ADDRESSES 5 /* RSSI offset for WkP */ #define IWL_RSSI_OFFSET 50 @@ -323,11 +322,11 @@ enum iwl_bt_force_ant_mode { struct iwl_mvm_vif_bf_data { bool bf_enabled; bool ba_enabled; - s8 ave_beacon_signal; - s8 last_cqm_event; - s8 bt_coex_min_thold; - s8 bt_coex_max_thold; - s8 last_bt_coex_event; + int ave_beacon_signal; + int last_cqm_event; + int bt_coex_min_thold; + int bt_coex_max_thold; + int last_bt_coex_event; }; /** @@ -338,6 +337,8 @@ struct iwl_mvm_vif_bf_data { * @bssid: BSSID for this (client) interface * @associated: indicates that we're currently associated, used only for * managing the firmware state in iwl_mvm_bss_info_changed_station() + * @ap_assoc_sta_count: count of stations associated to us - valid only + * if VIF type is AP * @uploaded: indicates the MAC context has been added to the device * @ap_ibss_active: indicates that AP/IBSS is configured and that the interface * should get quota etc. @@ -367,6 +368,7 @@ struct iwl_mvm_vif { u8 bssid[ETH_ALEN]; bool associated; + u8 ap_assoc_sta_count; bool uploaded; bool ap_ibss_active; @@ -602,7 +604,14 @@ struct iwl_mvm { u64 on_time_scan; } radio_stats, accu_radio_stats; - u8 queue_to_mac80211[IWL_MAX_HW_QUEUES]; + struct { + /* Map to HW queue */ + u32 hw_queue_to_mac80211; + u8 hw_queue_refcount; + bool setup_reserved; + u16 tid_bitmap; /* Bitmap of the TIDs mapped to this queue */ + } queue_info[IWL_MAX_HW_QUEUES]; + spinlock_t queue_info_lock; /* For syncing queue mgmt operations */ atomic_t mac80211_queue_stop_count[IEEE80211_MAX_QUEUES]; const char *nvm_file_name; @@ -679,6 +688,7 @@ struct iwl_mvm { struct debugfs_blob_wrapper nvm_sw_blob; struct debugfs_blob_wrapper nvm_calib_blob; struct debugfs_blob_wrapper nvm_prod_blob; + struct debugfs_blob_wrapper nvm_phy_sku_blob; struct iwl_mvm_frame_stats drv_rx_stats; spinlock_t drv_stats_lock; @@ -912,6 +922,12 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm) IWL_UCODE_TLV_CAPA_D0I3_SUPPORT); } +static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm) +{ + return fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_DQA_SUPPORT); +} + static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm) { bool nvm_lar = mvm->nvm_data->lar_enabled; @@ -939,11 +955,6 @@ static inline bool iwl_mvm_is_wifi_mcc_supported(struct iwl_mvm *mvm) IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC); } -static inline bool iwl_mvm_is_scd_cfg_supported(struct iwl_mvm *mvm) -{ - return fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_SCD_CFG); -} - static inline bool iwl_mvm_bt_is_plcr_supported(struct iwl_mvm *mvm) { return fw_has_capa(&mvm->fw->ucode_capa, @@ -964,6 +975,12 @@ static inline bool iwl_mvm_is_csum_supported(struct iwl_mvm *mvm) IWL_UCODE_TLV_CAPA_CSUM_SUPPORT); } +static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm) +{ + /* firmware flag isn't defined yet */ + return false; +} + extern const u8 iwl_mvm_ac_to_tx_fifo[]; struct iwl_rate_info { @@ -1019,7 +1036,7 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status); #else 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, bool sync); +int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, 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, @@ -1136,7 +1153,6 @@ void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif); unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm, struct ieee80211_vif *exclude_vif); - /* Bindings */ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); @@ -1349,14 +1365,20 @@ 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, u16 ssn, - const struct iwl_trans_txq_scd_cfg *cfg, +void 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); -void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, u8 flags); +/* + * Disable a TXQ. + * Note that in non-DQA mode the %mac80211_queue and %tid params are ignored. + */ +void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, + u8 tid, u8 flags); +int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 minq, u8 maxq); static inline -void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, - u8 fifo, unsigned int wdg_timeout) +void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, + u8 fifo, u16 ssn, unsigned int wdg_timeout) { struct iwl_trans_txq_scd_cfg cfg = { .fifo = fifo, @@ -1365,13 +1387,13 @@ void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, .frame_limit = IWL_FRAME_LIMIT, }; - iwl_mvm_enable_txq(mvm, queue, 0, &cfg, wdg_timeout); + iwl_mvm_enable_txq(mvm, queue, mac80211_queue, ssn, &cfg, wdg_timeout); } static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue, - int fifo, int sta_id, int tid, - int frame_limit, u16 ssn, - unsigned int wdg_timeout) + int mac80211_queue, int fifo, + int sta_id, int tid, int frame_limit, + u16 ssn, unsigned int wdg_timeout) { struct iwl_trans_txq_scd_cfg cfg = { .fifo = fifo, @@ -1381,7 +1403,7 @@ static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue, .aggregate = true, }; - iwl_mvm_enable_txq(mvm, queue, ssn, &cfg, wdg_timeout); + iwl_mvm_enable_txq(mvm, queue, mac80211_queue, ssn, &cfg, wdg_timeout); } /* Thermal management and CT-kill */ diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 328187da7541..2ee0f6fe56a1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c @@ -316,7 +316,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib, regulatory, mac_override, phy_sku, mvm->fw->valid_tx_ant, mvm->fw->valid_rx_ant, - lar_enabled, mac_addr0, mac_addr1); + lar_enabled, mac_addr0, mac_addr1, + mvm->trans->hw_id); } #define MAX_NVM_FILE_LEN 16384 @@ -482,6 +483,7 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) ret = -ENOMEM; break; } + kfree(mvm->nvm_sections[section_id].data); mvm->nvm_sections[section_id].data = temp; mvm->nvm_sections[section_id].length = section_size; @@ -563,6 +565,10 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic) mvm->nvm_prod_blob.data = temp; mvm->nvm_prod_blob.size = ret; break; + case NVM_SECTION_TYPE_PHY_SKU: + mvm->nvm_phy_sku_blob.data = temp; + mvm->nvm_phy_sku_blob.size = ret; + break; default: if (section == mvm->cfg->nvm_hw_section_num) { mvm->nvm_hw_blob.data = temp; diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index f0cb092f980e..13c97f665ba8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -89,6 +89,7 @@ MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_LICENSE("GPL"); static const struct iwl_op_mode_ops iwl_mvm_ops; +static const struct iwl_op_mode_ops iwl_mvm_ops_mq; struct iwl_mvm_mod_params iwlmvm_mod_params = { .power_scheme = IWL_POWER_SCHEME_BPS, @@ -222,7 +223,6 @@ struct iwl_rx_handlers { * called from a worker with mvm->mutex held. */ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { - RX_HANDLER(REPLY_RX_PHY_CMD, iwl_mvm_rx_rx_phy_cmd, false), RX_HANDLER(TX_CMD, iwl_mvm_rx_tx_cmd, false), RX_HANDLER(BA_NOTIF, iwl_mvm_rx_ba_notif, false), @@ -257,6 +257,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { RX_HANDLER(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION, iwl_mvm_power_uapsd_misbehaving_ap_notif, false), RX_HANDLER(DTS_MEASUREMENT_NOTIFICATION, iwl_mvm_temp_notif, true), + RX_HANDLER_GRP(PHY_OPS_GROUP, DTS_MEASUREMENT_NOTIF_WIDE, + iwl_mvm_temp_notif, true), RX_HANDLER(TDLS_CHANNEL_SWITCH_NOTIFICATION, iwl_mvm_rx_tdls_notif, true), @@ -271,6 +273,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { static const char *const iwl_mvm_cmd_strings[REPLY_MAX + 1] = { CMD(MVM_ALIVE), CMD(REPLY_ERROR), + CMD(ECHO_CMD), CMD(INIT_COMPLETE_NOTIF), CMD(PHY_CONTEXT_CMD), CMD(MGMT_MCAST_KEY), @@ -422,7 +425,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size; op_mode = hw->priv; - op_mode->ops = &iwl_mvm_ops; mvm = IWL_OP_MODE_GET_MVM(op_mode); mvm->dev = trans->dev; @@ -431,6 +433,15 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, mvm->fw = fw; mvm->hw = hw; + if (iwl_mvm_has_new_rx_api(mvm)) { + op_mode->ops = &iwl_mvm_ops_mq; + } else { + op_mode->ops = &iwl_mvm_ops; + + if (WARN_ON(trans->num_rx_queues > 1)) + goto out_free; + } + mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0; mvm->aux_queue = 15; @@ -451,6 +462,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, INIT_LIST_HEAD(&mvm->aux_roc_te_list); INIT_LIST_HEAD(&mvm->async_handlers_list); spin_lock_init(&mvm->time_event_lock); + spin_lock_init(&mvm->queue_info_lock); INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk); INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk); @@ -618,6 +630,7 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) kfree(mvm->d3_resume_sram); if (mvm->nd_config) { kfree(mvm->nd_config->match_sets); + kfree(mvm->nd_config->scan_plans); kfree(mvm->nd_config); mvm->nd_config = NULL; } @@ -717,18 +730,11 @@ static inline void iwl_mvm_rx_check_trigger(struct iwl_mvm *mvm, } } -static void iwl_mvm_rx_dispatch(struct iwl_op_mode *op_mode, - struct napi_struct *napi, - struct iwl_rx_cmd_buffer *rxb) +static void iwl_mvm_rx_common(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb, + struct iwl_rx_packet *pkt) { - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); - u8 i; - - if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD)) { - iwl_mvm_rx_rx_mpdu(mvm, napi, rxb); - return; - } + int i; iwl_mvm_rx_check_trigger(mvm, pkt); @@ -768,40 +774,84 @@ static void iwl_mvm_rx_dispatch(struct iwl_op_mode *op_mode, } } +static void iwl_mvm_rx(struct iwl_op_mode *op_mode, + struct napi_struct *napi, + struct iwl_rx_cmd_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); + + if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD)) + iwl_mvm_rx_rx_mpdu(mvm, napi, rxb); + else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD) + iwl_mvm_rx_rx_phy_cmd(mvm, rxb); + else + iwl_mvm_rx_common(mvm, rxb, pkt); +} + +static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode, + struct napi_struct *napi, + struct iwl_rx_cmd_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); + + if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD)) + iwl_mvm_rx_rx_mpdu(mvm, napi, rxb); + else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD) + iwl_mvm_rx_rx_phy_cmd(mvm, rxb); + else + iwl_mvm_rx_common(mvm, rxb, pkt); +} + static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) { struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); - int mq = mvm->queue_to_mac80211[queue]; + unsigned long mq; + int q; - if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE)) - return; + spin_lock_bh(&mvm->queue_info_lock); + mq = mvm->queue_info[queue].hw_queue_to_mac80211; + spin_unlock_bh(&mvm->queue_info_lock); - if (atomic_inc_return(&mvm->mac80211_queue_stop_count[mq]) > 1) { - IWL_DEBUG_TX_QUEUES(mvm, - "queue %d (mac80211 %d) already stopped\n", - queue, mq); + if (WARN_ON_ONCE(!mq)) return; - } - ieee80211_stop_queue(mvm->hw, mq); + for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) { + if (atomic_inc_return(&mvm->mac80211_queue_stop_count[q]) > 1) { + IWL_DEBUG_TX_QUEUES(mvm, + "queue %d (mac80211 %d) already stopped\n", + queue, q); + continue; + } + + ieee80211_stop_queue(mvm->hw, q); + } } static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) { struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); - int mq = mvm->queue_to_mac80211[queue]; + unsigned long mq; + int q; - if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE)) - return; + spin_lock_bh(&mvm->queue_info_lock); + mq = mvm->queue_info[queue].hw_queue_to_mac80211; + spin_unlock_bh(&mvm->queue_info_lock); - if (atomic_dec_return(&mvm->mac80211_queue_stop_count[mq]) > 0) { - IWL_DEBUG_TX_QUEUES(mvm, - "queue %d (mac80211 %d) still stopped\n", - queue, mq); + if (WARN_ON_ONCE(!mq)) return; - } - ieee80211_wake_queue(mvm->hw, mq); + for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) { + if (atomic_dec_return(&mvm->mac80211_queue_stop_count[q]) > 0) { + IWL_DEBUG_TX_QUEUES(mvm, + "queue %d (mac80211 %d) still stopped\n", + queue, q); + continue; + } + + ieee80211_wake_queue(mvm->hw, q); + } } void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state) @@ -1146,12 +1196,17 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) /* make sure we have no running tx while configuring the seqno */ synchronize_net(); - iwl_mvm_set_wowlan_data(mvm, &wowlan_config_cmd, &d0i3_iter_data); - ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, flags, - sizeof(wowlan_config_cmd), - &wowlan_config_cmd); - if (ret) - return ret; + /* configure wowlan configuration only if needed */ + if (mvm->d0i3_ap_sta_id != IWL_MVM_STATION_COUNT) { + iwl_mvm_set_wowlan_data(mvm, &wowlan_config_cmd, + &d0i3_iter_data); + + ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, flags, + sizeof(wowlan_config_cmd), + &wowlan_config_cmd); + if (ret) + return ret; + } return iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, flags | CMD_MAKE_TRANS_IDLE, @@ -1258,7 +1313,7 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) }; struct iwl_wowlan_status *status; int ret; - u32 handled_reasons, wakeup_reasons; + u32 handled_reasons, wakeup_reasons = 0; __le16 *qos_seq = NULL; mutex_lock(&mvm->mutex); @@ -1290,6 +1345,9 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) out: iwl_mvm_d0i3_enable_tx(mvm, qos_seq); + IWL_DEBUG_INFO(mvm, "d0i3 exit completed (wakeup reasons: 0x%x)\n", + wakeup_reasons); + /* qos_seq might point inside resp_pkt, so free it only now */ if (get_status_cmd.resp_pkt) iwl_free_resp(&get_status_cmd); @@ -1339,17 +1397,38 @@ int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode) return _iwl_mvm_exit_d0i3(mvm); } +#define IWL_MVM_COMMON_OPS \ + /* these could be differentiated */ \ + .queue_full = iwl_mvm_stop_sw_queue, \ + .queue_not_full = iwl_mvm_wake_sw_queue, \ + .hw_rf_kill = iwl_mvm_set_hw_rfkill_state, \ + .free_skb = iwl_mvm_free_skb, \ + .nic_error = iwl_mvm_nic_error, \ + .cmd_queue_full = iwl_mvm_cmd_queue_full, \ + .nic_config = iwl_mvm_nic_config, \ + .enter_d0i3 = iwl_mvm_enter_d0i3, \ + .exit_d0i3 = iwl_mvm_exit_d0i3, \ + /* as we only register one, these MUST be common! */ \ + .start = iwl_op_mode_mvm_start, \ + .stop = iwl_op_mode_mvm_stop + static const struct iwl_op_mode_ops iwl_mvm_ops = { - .start = iwl_op_mode_mvm_start, - .stop = iwl_op_mode_mvm_stop, - .rx = iwl_mvm_rx_dispatch, - .queue_full = iwl_mvm_stop_sw_queue, - .queue_not_full = iwl_mvm_wake_sw_queue, - .hw_rf_kill = iwl_mvm_set_hw_rfkill_state, - .free_skb = iwl_mvm_free_skb, - .nic_error = iwl_mvm_nic_error, - .cmd_queue_full = iwl_mvm_cmd_queue_full, - .nic_config = iwl_mvm_nic_config, - .enter_d0i3 = iwl_mvm_enter_d0i3, - .exit_d0i3 = iwl_mvm_exit_d0i3, + IWL_MVM_COMMON_OPS, + .rx = iwl_mvm_rx, +}; + +static void iwl_mvm_rx_mq_rss(struct iwl_op_mode *op_mode, + struct napi_struct *napi, + struct iwl_rx_cmd_buffer *rxb, + unsigned int queue) +{ + struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); + + iwl_mvm_rx_rx_mpdu(mvm, napi, rxb); +} + +static const struct iwl_op_mode_ops iwl_mvm_ops_mq = { + IWL_MVM_COMMON_OPS, + .rx = iwl_mvm_rx_mq, + .rx_rss = iwl_mvm_rx_mq_rss, }; diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 4645877882a6..bed9696ee410 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -7,6 +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 * * 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) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2015 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -306,13 +308,51 @@ static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif) return radar_detect; } +static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct iwl_mac_power_cmd *cmd, + bool host_awake) +{ + int dtimper = vif->bss_conf.dtim_period ?: 1; + int skip; + + /* disable, in case we're supposed to override */ + cmd->skip_dtim_periods = 0; + cmd->flags &= ~cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); + + if (iwl_mvm_power_is_radar(vif)) + return; + + if (dtimper >= 10) + return; + + /* TODO: check that multicast wake lock is off */ + + if (host_awake) { + if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_LP) + return; + skip = 2; + } else { + int dtimper_tu = dtimper * vif->bss_conf.beacon_int; + + if (WARN_ON(!dtimper_tu)) + return; + /* configure skip over dtim up to 306TU - 314 msec */ + skip = max_t(u8, 1, 306 / dtimper_tu); + } + + /* the firmware really expects "look at every X DTIMs", so add 1 */ + cmd->skip_dtim_periods = 1 + skip; + cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); +} + static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct iwl_mac_power_cmd *cmd) + struct iwl_mac_power_cmd *cmd, + bool host_awake) { int dtimper, bi; int keep_alive; - bool radar_detect = false; struct iwl_mvm_vif *mvmvif __maybe_unused = iwl_mvm_vif_from_mac80211(vif); @@ -337,8 +377,13 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); - if (!vif->bss_conf.ps || !mvmvif->pm_enabled || - (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p)) + if (!vif->bss_conf.ps || !mvmvif->pm_enabled) + return; + + if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p && + (!fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS) || + !IWL_MVM_P2P_LOWLATENCY_PS_ENABLE)) return; cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); @@ -350,27 +395,25 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD; } - /* Check if radar detection is required on current channel */ - radar_detect = iwl_mvm_power_is_radar(vif); + iwl_mvm_power_config_skip_dtim(mvm, vif, cmd, host_awake); - /* Check skip over DTIM conditions */ - if (!radar_detect && (dtimper < 10) && - (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP || - mvm->cur_ucode == IWL_UCODE_WOWLAN)) { - cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); - cmd->skip_dtim_periods = 3; - } - - if (mvm->cur_ucode != IWL_UCODE_WOWLAN) { + if (!host_awake) { cmd->rx_data_timeout = - cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT); + cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); cmd->tx_data_timeout = - cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT); + cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); + } else if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p && + fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS)) { + cmd->tx_data_timeout = + cpu_to_le32(IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT); + cmd->rx_data_timeout = + cpu_to_le32(IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT); } else { cmd->rx_data_timeout = - cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); + cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT); cmd->tx_data_timeout = - cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); + cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT); } if (iwl_mvm_power_allow_uapsd(mvm, vif)) @@ -427,7 +470,8 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm, { struct iwl_mac_power_cmd cmd = {}; - iwl_mvm_power_build_cmd(mvm, vif, &cmd); + iwl_mvm_power_build_cmd(mvm, vif, &cmd, + mvm->cur_ucode != IWL_UCODE_WOWLAN); iwl_mvm_power_log(mvm, &cmd); #ifdef CONFIG_IWLWIFI_DEBUGFS memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd)); @@ -440,14 +484,14 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm, int iwl_mvm_power_update_device(struct iwl_mvm *mvm) { struct iwl_device_power_cmd cmd = { - .flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK), + .flags = 0, }; if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) mvm->ps_disabled = true; - if (mvm->ps_disabled) - cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK); + if (!mvm->ps_disabled) + cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK); #ifdef CONFIG_IWLWIFI_DEBUGFS if ((mvm->cur_ucode == IWL_UCODE_WOWLAN) ? mvm->disable_power_off_d3 : @@ -963,25 +1007,8 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, if (!vif->bss_conf.assoc) return 0; - iwl_mvm_power_build_cmd(mvm, vif, &cmd); - if (enable) { - /* configure skip over dtim up to 306TU - 314 msec */ - int dtimper = vif->bss_conf.dtim_period ?: 1; - int dtimper_tu = dtimper * vif->bss_conf.beacon_int; - bool radar_detect = iwl_mvm_power_is_radar(vif); + iwl_mvm_power_build_cmd(mvm, vif, &cmd, !enable); - if (WARN_ON(!dtimper_tu)) - return 0; - - /* Check skip over DTIM conditions */ - /* TODO: check that multicast wake lock is off */ - if (!radar_detect && (dtimper < 10)) { - cmd.skip_dtim_periods = 306 / dtimper_tu; - if (cmd.skip_dtim_periods) - cmd.flags |= cpu_to_le16( - POWER_FLAGS_SKIP_OVER_DTIM_MSK); - } - } iwl_mvm_power_log(mvm, &cmd); #ifdef CONFIG_IWLWIFI_DEBUGFS memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd)); diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 5ae9c8aa868f..d1ad10391b47 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -177,9 +177,6 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, mvmsta = iwl_mvm_sta_from_mac80211(sta); mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif); - if (IWL_MVM_RS_DISABLE_P2P_MIMO && - iwl_mvm_vif_low_latency(mvmvif) && mvmsta->vif->p2p) - return false; if (mvm->nvm_data->sku_cap_mimo_disabled) return false; @@ -524,14 +521,56 @@ static const char *rs_pretty_lq_type(enum iwl_table_type type) return lq_types[type]; } +static char *rs_pretty_rate(const struct rs_rate *rate) +{ + static char buf[40]; + static const char * const legacy_rates[] = { + [IWL_RATE_1M_INDEX] = "1M", + [IWL_RATE_2M_INDEX] = "2M", + [IWL_RATE_5M_INDEX] = "5.5M", + [IWL_RATE_11M_INDEX] = "11M", + [IWL_RATE_6M_INDEX] = "6M", + [IWL_RATE_9M_INDEX] = "9M", + [IWL_RATE_12M_INDEX] = "12M", + [IWL_RATE_18M_INDEX] = "18M", + [IWL_RATE_24M_INDEX] = "24M", + [IWL_RATE_36M_INDEX] = "36M", + [IWL_RATE_48M_INDEX] = "48M", + [IWL_RATE_54M_INDEX] = "54M", + }; + static const char *const ht_vht_rates[] = { + [IWL_RATE_MCS_0_INDEX] = "MCS0", + [IWL_RATE_MCS_1_INDEX] = "MCS1", + [IWL_RATE_MCS_2_INDEX] = "MCS2", + [IWL_RATE_MCS_3_INDEX] = "MCS3", + [IWL_RATE_MCS_4_INDEX] = "MCS4", + [IWL_RATE_MCS_5_INDEX] = "MCS5", + [IWL_RATE_MCS_6_INDEX] = "MCS6", + [IWL_RATE_MCS_7_INDEX] = "MCS7", + [IWL_RATE_MCS_8_INDEX] = "MCS8", + [IWL_RATE_MCS_9_INDEX] = "MCS9", + }; + const char *rate_str; + + if (is_type_legacy(rate->type)) + rate_str = legacy_rates[rate->index]; + else if (is_type_ht(rate->type) || is_type_vht(rate->type)) + rate_str = ht_vht_rates[rate->index]; + else + rate_str = "BAD_RATE"; + + sprintf(buf, "(%s|%s|%s)", rs_pretty_lq_type(rate->type), + rs_pretty_ant(rate->ant), rate_str); + return buf; +} + static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate, const char *prefix) { IWL_DEBUG_RATE(mvm, - "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d STBC: %d\n", - prefix, rs_pretty_lq_type(rate->type), - rate->index, rs_pretty_ant(rate->ant), - rate->bw, rate->sgi, rate->ldpc, rate->stbc); + "%s: %s BW: %d SGI: %d LDPC: %d STBC: %d\n", + prefix, rs_pretty_rate(rate), rate->bw, + rate->sgi, rate->ldpc, rate->stbc); } static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) @@ -562,8 +601,8 @@ static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) } static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm, - struct iwl_lq_sta *lq_data, u8 tid, - struct ieee80211_sta *sta) + struct iwl_lq_sta *lq_data, u8 tid, + struct ieee80211_sta *sta) { int ret = -EAGAIN; @@ -1485,7 +1524,7 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm, u32 target_tpt; int rate_idx; - if (success_ratio > IWL_MVM_RS_SR_NO_DECREASE) { + if (success_ratio >= RS_PERCENT(IWL_MVM_RS_SR_NO_DECREASE)) { target_tpt = 100 * expected_current_tpt; IWL_DEBUG_RATE(mvm, "SR %d high. Find rate exceeding EXPECTED_CURRENT %d\n", @@ -1493,7 +1532,7 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm, } else { target_tpt = lq_sta->last_tpt; IWL_DEBUG_RATE(mvm, - "SR %d not thag good. Find rate exceeding ACTUAL_TPT %d\n", + "SR %d not that good. Find rate exceeding ACTUAL_TPT %d\n", success_ratio, target_tpt); } @@ -1622,6 +1661,51 @@ static void rs_update_rate_tbl(struct iwl_mvm *mvm, iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); } +static bool rs_tweak_rate_tbl(struct iwl_mvm *mvm, + struct ieee80211_sta *sta, + struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl, + enum rs_action scale_action) +{ + if (sta->bandwidth != IEEE80211_STA_RX_BW_80) + return false; + + if (!is_vht_siso(&tbl->rate)) + return false; + + if ((tbl->rate.bw == RATE_MCS_CHAN_WIDTH_80) && + (tbl->rate.index == IWL_RATE_MCS_0_INDEX) && + (scale_action == RS_ACTION_DOWNSCALE)) { + tbl->rate.bw = RATE_MCS_CHAN_WIDTH_20; + tbl->rate.index = IWL_RATE_MCS_4_INDEX; + IWL_DEBUG_RATE(mvm, "Switch 80Mhz SISO MCS0 -> 20Mhz MCS4\n"); + goto tweaked; + } + + /* Go back to 80Mhz MCS1 only if we've established that 20Mhz MCS5 is + * sustainable, i.e. we're past the test window. We can't go back + * if MCS5 is just tested as this will happen always after switching + * to 20Mhz MCS4 because the rate stats are cleared. + */ + if ((tbl->rate.bw == RATE_MCS_CHAN_WIDTH_20) && + (((tbl->rate.index == IWL_RATE_MCS_5_INDEX) && + (scale_action == RS_ACTION_STAY)) || + ((tbl->rate.index > IWL_RATE_MCS_5_INDEX) && + (scale_action == RS_ACTION_UPSCALE)))) { + tbl->rate.bw = RATE_MCS_CHAN_WIDTH_80; + tbl->rate.index = IWL_RATE_MCS_1_INDEX; + IWL_DEBUG_RATE(mvm, "Switch 20Mhz SISO MCS5 -> 80Mhz MCS1\n"); + goto tweaked; + } + + return false; + +tweaked: + rs_set_expected_tpt_table(lq_sta, tbl); + rs_rate_scale_clear_tbl_windows(mvm, tbl); + return true; +} + static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, struct iwl_lq_sta *lq_sta, struct ieee80211_sta *sta, @@ -2174,9 +2258,9 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, if ((fail_count < IWL_MVM_RS_RATE_MIN_FAILURE_TH) && (window->success_counter < IWL_MVM_RS_RATE_MIN_SUCCESS_TH)) { IWL_DEBUG_RATE(mvm, - "(%s: %d): Test Window: succ %d total %d\n", - rs_pretty_lq_type(rate->type), - index, window->success_counter, window->counter); + "%s: Test Window: succ %d total %d\n", + rs_pretty_rate(rate), + window->success_counter, window->counter); /* Can't calculate this yet; not enough history */ window->average_tpt = IWL_INVALID_VALUE; @@ -2253,8 +2337,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, high_tpt = tbl->win[high].average_tpt; IWL_DEBUG_RATE(mvm, - "(%s: %d): cur_tpt %d SR %d low %d high %d low_tpt %d high_tpt %d\n", - rs_pretty_lq_type(rate->type), index, current_tpt, sr, + "%s: cur_tpt %d SR %d low %d high %d low_tpt %d high_tpt %d\n", + rs_pretty_rate(rate), current_tpt, sr, low, high, low_tpt, high_tpt); scale_action = rs_get_rate_action(mvm, tbl, sr, low, high, @@ -2305,6 +2389,8 @@ lq_update: /* Replace uCode's rate table for the destination station. */ if (update_lq) { tbl->rate.index = index; + if (IWL_MVM_RS_80_20_FAR_RANGE_TWEAK) + rs_tweak_rate_tbl(mvm, sta, lq_sta, tbl, scale_action); rs_update_rate_tbl(mvm, sta, lq_sta, tbl); } @@ -2542,7 +2628,6 @@ static struct rs_rate *rs_get_optimal_rate(struct iwl_mvm *mvm, } } - rs_dump_rate(mvm, rate, "OPTIMAL RATE"); return rate; } @@ -2983,9 +3068,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, else rs_vht_init(mvm, sta, lq_sta, vht_cap); - if (IWL_MVM_RS_DISABLE_P2P_MIMO && sta_priv->vif->p2p) - lq_sta->active_mimo2_rate = 0; - lq_sta->max_legacy_rate_idx = rs_get_max_rate_from_mask(lq_sta->active_legacy_rate); lq_sta->max_siso_rate_idx = diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index c37c10a423ce..5b58f5320e8d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c @@ -202,7 +202,6 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm, return -1; stats->flag |= RX_FLAG_DECRYPTED; - IWL_DEBUG_WEP(mvm, "hw decrypted CCMP successfully\n"); *crypt_len = IEEE80211_CCMP_HDR_LEN; return 0; @@ -299,13 +298,6 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, return; } - if ((unlikely(phy_info->cfg_phy_cnt > 20))) { - IWL_DEBUG_DROP(mvm, "dsp size out of range [0,20]: %d\n", - phy_info->cfg_phy_cnt); - kfree_skb(skb); - return; - } - /* * Keep packets with CRC errors (and with overrun) for monitor mode * (otherwise the firmware discards them) but mark them as bad. @@ -354,8 +346,8 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, /* This is fine since we don't support multiple AP interfaces */ sta = ieee80211_find_sta_by_ifaddr(mvm->hw, hdr->addr2, NULL); if (sta) { - struct iwl_mvm_sta *mvmsta; - mvmsta = iwl_mvm_sta_from_mac80211(sta); + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + rs_update_last_rssi(mvm, &mvmsta->lq_sta, rx_status); if (iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_RSSI) && @@ -459,7 +451,7 @@ static void iwl_mvm_update_rx_statistics(struct iwl_mvm *mvm, struct iwl_mvm_stat_data { struct iwl_mvm *mvm; __le32 mac_id; - __s8 beacon_filter_average_energy; + u8 beacon_filter_average_energy; struct mvm_statistics_general_v8 *general; }; @@ -577,56 +569,33 @@ 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) { - size_t v8_len = sizeof(struct iwl_notif_statistics_v8); - size_t v10_len = sizeof(struct iwl_notif_statistics_v10); + struct iwl_notif_statistics_v10 *stats = (void *)&pkt->data; struct iwl_mvm_stat_data data = { .mvm = mvm, }; u32 temperature; - if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STATS_V10)) { - struct iwl_notif_statistics_v10 *stats = (void *)&pkt->data; - - if (iwl_rx_packet_payload_len(pkt) != v10_len) - goto invalid; + if (iwl_rx_packet_payload_len(pkt) != sizeof(*stats)) + goto invalid; - temperature = le32_to_cpu(stats->general.radio_temperature); - data.mac_id = stats->rx.general.mac_id; - data.beacon_filter_average_energy = - stats->general.beacon_filter_average_energy; + temperature = le32_to_cpu(stats->general.radio_temperature); + data.mac_id = stats->rx.general.mac_id; + data.beacon_filter_average_energy = + stats->general.beacon_filter_average_energy; - iwl_mvm_update_rx_statistics(mvm, &stats->rx); + iwl_mvm_update_rx_statistics(mvm, &stats->rx); - mvm->radio_stats.rx_time = le64_to_cpu(stats->general.rx_time); - mvm->radio_stats.tx_time = le64_to_cpu(stats->general.tx_time); - mvm->radio_stats.on_time_rf = - le64_to_cpu(stats->general.on_time_rf); - mvm->radio_stats.on_time_scan = - le64_to_cpu(stats->general.on_time_scan); + mvm->radio_stats.rx_time = le64_to_cpu(stats->general.rx_time); + mvm->radio_stats.tx_time = le64_to_cpu(stats->general.tx_time); + mvm->radio_stats.on_time_rf = + le64_to_cpu(stats->general.on_time_rf); + mvm->radio_stats.on_time_scan = + le64_to_cpu(stats->general.on_time_scan); - data.general = &stats->general; - } else { - struct iwl_notif_statistics_v8 *stats = (void *)&pkt->data; - - if (iwl_rx_packet_payload_len(pkt) != v8_len) - goto invalid; - - temperature = le32_to_cpu(stats->general.radio_temperature); - data.mac_id = stats->rx.general.mac_id; - data.beacon_filter_average_energy = - stats->general.beacon_filter_average_energy; - - iwl_mvm_update_rx_statistics(mvm, &stats->rx); - } + data.general = &stats->general; iwl_mvm_rx_stats_check_trigger(mvm, pkt); - /* Only handle rx statistics temperature changes if async temp - * notifications are not supported - */ - if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_ASYNC_DTM)) - iwl_mvm_tt_temp_changed(mvm, temperature); - ieee80211_iterate_active_interfaces(mvm->hw, IEEE80211_IFACE_ITER_NORMAL, iwl_mvm_stat_iterator, diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 56559d4d34ad..d6e0c1b5c20c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -131,7 +131,6 @@ struct iwl_mvm_scan_params { int n_ssids; struct cfg80211_ssid *ssids; struct ieee80211_channel **channels; - u16 interval; /* interval between scans (in secs) */ u32 flags; u8 *mac_addr; u8 *mac_addr_mask; @@ -140,7 +139,8 @@ struct iwl_mvm_scan_params { int n_match_sets; struct iwl_scan_probe_req preq; struct cfg80211_match_set *match_sets; - u8 iterations[2]; + int n_scan_plans; + struct cfg80211_sched_scan_plan *scan_plans; }; static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm) @@ -474,7 +474,7 @@ iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, int ret; if (WARN_ON(req->n_match_sets > IWL_SCAN_MAX_PROFILES)) - return -EIO; + return -EIO; if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SHORT_BL) blacklist_len = IWL_SCAN_SHORT_BLACKLIST_LEN; @@ -737,8 +737,7 @@ static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids, } static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - int n_iterations) + struct ieee80211_vif *vif) { const struct iwl_ucode_capabilities *capa = &mvm->fw->ucode_capa; @@ -750,16 +749,9 @@ static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm, */ return ((capa->flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT) && mvm->last_ebs_successful && - (n_iterations > 1 || - fw_has_api(capa, IWL_UCODE_TLV_API_SINGLE_SCAN_EBS)) && vif->type != NL80211_IFTYPE_P2P_DEVICE); } -static int iwl_mvm_scan_total_iterations(struct iwl_mvm_scan_params *params) -{ - return params->iterations[0] + params->iterations[1]; -} - static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, struct iwl_mvm_scan_params *params) { @@ -798,12 +790,15 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) * mvm->fw->ucode_capa.n_scan_channels); u32 ssid_bitmap = 0; - int n_iterations = iwl_mvm_scan_total_iterations(params); + int i; lockdep_assert_held(&mvm->mutex); memset(cmd, 0, ksize(cmd)); + if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS)) + return -EINVAL; + iwl_mvm_scan_lmac_dwell(mvm, cmd, params); cmd->rx_chain_select = iwl_mvm_scan_rx_chain(mvm); @@ -823,14 +818,26 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, /* this API uses bits 1-20 instead of 0-19 */ ssid_bitmap <<= 1; - cmd->schedule[0].delay = cpu_to_le16(params->interval); - cmd->schedule[0].iterations = params->iterations[0]; - cmd->schedule[0].full_scan_mul = 1; - cmd->schedule[1].delay = cpu_to_le16(params->interval); - cmd->schedule[1].iterations = params->iterations[1]; - cmd->schedule[1].full_scan_mul = 1; + for (i = 0; i < params->n_scan_plans; i++) { + struct cfg80211_sched_scan_plan *scan_plan = + ¶ms->scan_plans[i]; + + cmd->schedule[i].delay = + cpu_to_le16(scan_plan->interval); + cmd->schedule[i].iterations = scan_plan->iterations; + cmd->schedule[i].full_scan_mul = 1; + } + + /* + * If the number of iterations of the last scan plan is set to + * zero, it should run infinitely. However, this is not always the case. + * For example, when regular scan is requested the driver sets one scan + * plan with one iteration. + */ + if (!cmd->schedule[i - 1].iterations) + cmd->schedule[i - 1].iterations = 0xff; - if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) { + if (iwl_mvm_scan_use_ebs(mvm, vif)) { cmd->channel_opt[0].flags = cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | @@ -894,7 +901,6 @@ static __le32 iwl_mvm_scan_config_rates(struct iwl_mvm *mvm) int iwl_mvm_config_scan(struct iwl_mvm *mvm) { - struct iwl_scan_config *scan_config; struct ieee80211_supported_band *band; int num_channels = @@ -970,6 +976,12 @@ static int iwl_mvm_scan_uid_by_status(struct iwl_mvm *mvm, int status) return -ENOENT; } +static inline bool iwl_mvm_is_regular_scan(struct iwl_mvm_scan_params *params) +{ + return params->n_scan_plans == 1 && + params->scan_plans[0].iterations == 1; +} + static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, struct iwl_scan_req_umac *cmd, struct iwl_mvm_scan_params *params) @@ -982,7 +994,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, cmd->scan_priority = iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6); - if (iwl_mvm_scan_total_iterations(params) == 1) + if (iwl_mvm_is_regular_scan(params)) cmd->ooc_priority = iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6); else @@ -1029,7 +1041,7 @@ static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm, else flags |= IWL_UMAC_SCAN_GEN_FLAGS_MATCH; - if (iwl_mvm_scan_total_iterations(params) > 1) + if (!iwl_mvm_is_regular_scan(params)) flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC; #ifdef CONFIG_IWLWIFI_DEBUGFS @@ -1047,12 +1059,14 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data + sizeof(struct iwl_scan_channel_cfg_umac) * mvm->fw->ucode_capa.n_scan_channels; - int uid; + int uid, i; u32 ssid_bitmap = 0; - int n_iterations = iwl_mvm_scan_total_iterations(params); lockdep_assert_held(&mvm->mutex); + if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS)) + return -EINVAL; + uid = iwl_mvm_scan_uid_by_status(mvm, 0); if (uid < 0) return uid; @@ -1069,7 +1083,7 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (type == IWL_MVM_SCAN_SCHED) cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE); - if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) + if (iwl_mvm_scan_use_ebs(mvm, vif)) cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD; @@ -1081,12 +1095,23 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, iwl_mvm_umac_scan_cfg_channels(mvm, params->channels, params->n_channels, ssid_bitmap, cmd); - /* With UMAC we use only one schedule for now, so use the sum - * of the iterations (with a a maximum of 255). + for (i = 0; i < params->n_scan_plans; i++) { + struct cfg80211_sched_scan_plan *scan_plan = + ¶ms->scan_plans[i]; + + sec_part->schedule[i].iter_count = scan_plan->iterations; + sec_part->schedule[i].interval = + cpu_to_le16(scan_plan->interval); + } + + /* + * If the number of iterations of the last scan plan is set to + * zero, it should run infinitely. However, this is not always the case. + * For example, when regular scan is requested the driver sets one scan + * plan with one iteration. */ - sec_part->schedule[0].iter_count = - (n_iterations > 255) ? 255 : n_iterations; - sec_part->schedule[0].interval = cpu_to_le16(params->interval); + if (!sec_part->schedule[i - 1].iter_count) + sec_part->schedule[i - 1].iter_count = 0xff; sec_part->delay = cpu_to_le16(params->delay); sec_part->preq = params->preq; @@ -1152,6 +1177,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, }; struct iwl_mvm_scan_params params = {}; int ret; + struct cfg80211_sched_scan_plan scan_plan = { .iterations = 1 }; lockdep_assert_held(&mvm->mutex); @@ -1164,8 +1190,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (ret) return ret; - iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN); - /* we should have failed registration if scan_cmd was NULL */ if (WARN_ON(!mvm->scan_cmd)) return -ENOMEM; @@ -1177,7 +1201,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, params.flags = req->flags; params.n_channels = req->n_channels; params.delay = 0; - params.interval = 0; params.ssids = req->ssids; params.channels = req->channels; params.mac_addr = req->mac_addr; @@ -1187,8 +1210,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, params.n_match_sets = 0; params.match_sets = NULL; - params.iterations[0] = 1; - params.iterations[1] = 0; + params.scan_plans = &scan_plan; + params.n_scan_plans = 1; params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); @@ -1207,21 +1230,20 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return ret; ret = iwl_mvm_send_cmd(mvm, &hcmd); - if (!ret) { - IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n"); - mvm->scan_status |= IWL_MVM_SCAN_REGULAR; - } else { + if (ret) { /* If the scan failed, it usually means that the FW was unable * to allocate the time events. Warn on it, but maybe we * should try to send the command again with different params. */ IWL_ERR(mvm, "Scan failed! ret %d\n", ret); + return ret; } - if (ret) - iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); + IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n"); + mvm->scan_status |= IWL_MVM_SCAN_REGULAR; + iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN); - return ret; + return 0; } int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, @@ -1267,20 +1289,14 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, params.pass_all = iwl_mvm_scan_pass_all(mvm, req); params.n_match_sets = req->n_match_sets; params.match_sets = req->match_sets; + if (!req->n_scan_plans) + return -EINVAL; - params.iterations[0] = 0; - params.iterations[1] = 0xff; + params.n_scan_plans = req->n_scan_plans; + params.scan_plans = req->scan_plans; params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); - if (req->interval > U16_MAX) { - IWL_DEBUG_SCAN(mvm, - "interval value is > 16-bits, set to max possible\n"); - params.interval = U16_MAX; - } else { - params.interval = req->interval / MSEC_PER_SEC; - } - /* In theory, LMAC scans can handle a 32-bit delay, but since * waiting for over 18 hours to start the scan is a bit silly * and to keep it aligned with UMAC scans (which only support diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index df216cd0c98f..300a249486e4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -234,7 +234,9 @@ static int iwl_mvm_tdls_sta_init(struct iwl_mvm *mvm, /* Found a place for all queues - enable them */ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { iwl_mvm_enable_ac_txq(mvm, mvmsta->hw_queue[ac], - iwl_mvm_ac_to_tx_fifo[ac], wdg_timeout); + mvmsta->hw_queue[ac], + iwl_mvm_ac_to_tx_fifo[ac], 0, + wdg_timeout); mvmsta->tfd_queue_msk |= BIT(mvmsta->hw_queue[ac]); } @@ -253,7 +255,7 @@ static void iwl_mvm_tdls_sta_deinit(struct iwl_mvm *mvm, /* disable the TDLS STA-specific queues */ sta_msk = mvmsta->tfd_queue_msk; for_each_set_bit(i, &sta_msk, sizeof(sta_msk) * BITS_PER_BYTE) - iwl_mvm_disable_txq(mvm, i, 0); + iwl_mvm_disable_txq(mvm, i, i, IWL_MAX_TID_COUNT, 0); } int iwl_mvm_add_sta(struct iwl_mvm *mvm, @@ -275,6 +277,11 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, if (sta_id == IWL_MVM_STATION_COUNT) return -ENOSPC; + if (vif->type == NL80211_IFTYPE_AP) { + mvmvif->ap_assoc_sta_count++; + iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); + } + spin_lock_init(&mvm_sta->lock); mvm_sta->sta_id = sta_id; @@ -287,7 +294,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, /* HW restart, don't assume the memory has been zeroed */ atomic_set(&mvm->pending_frames[sta_id], 0); - mvm_sta->tid_disable_agg = 0; + mvm_sta->tid_disable_agg = 0xffff; /* No aggs at first */ mvm_sta->tfd_queue_msk = 0; /* allocate new queues for a TDLS station */ @@ -467,7 +474,8 @@ void iwl_mvm_sta_drained_wk(struct work_struct *wk) unsigned long i, msk = mvm->tfd_drained[sta_id]; for_each_set_bit(i, &msk, sizeof(msk) * BITS_PER_BYTE) - iwl_mvm_disable_txq(mvm, i, 0); + iwl_mvm_disable_txq(mvm, i, i, + IWL_MAX_TID_COUNT, 0); mvm->tfd_drained[sta_id] = 0; IWL_DEBUG_TDLS(mvm, "Drained sta %d, with queues %ld\n", @@ -494,7 +502,7 @@ 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, true); + ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, 0); if (ret) return ret; ret = iwl_trans_wait_tx_queue_empty(mvm->trans, @@ -646,8 +654,8 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) lockdep_assert_held(&mvm->mutex); /* Map Aux queue to fifo - needs to happen before adding Aux station */ - iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, - IWL_MVM_TX_FIFO_MCAST, wdg_timeout); + iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, mvm->aux_queue, + IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout); /* Allocate aux station and assign to it the aux queue */ ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue), @@ -918,6 +926,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; int txq_id; + int ret; if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) return -EINVAL; @@ -930,17 +939,6 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, lockdep_assert_held(&mvm->mutex); - for (txq_id = mvm->first_agg_queue; - txq_id <= mvm->last_agg_queue; txq_id++) - if (mvm->queue_to_mac80211[txq_id] == - IWL_INVALID_MAC80211_QUEUE) - break; - - if (txq_id > mvm->last_agg_queue) { - IWL_ERR(mvm, "Failed to allocate agg queue\n"); - return -EIO; - } - spin_lock_bh(&mvmsta->lock); /* possible race condition - we entered D0i3 while starting agg */ @@ -950,8 +948,18 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return -EIO; } - /* the new tx queue is still connected to the same mac80211 queue */ - mvm->queue_to_mac80211[txq_id] = vif->hw_queue[tid_to_mac80211_ac[tid]]; + spin_lock_bh(&mvm->queue_info_lock); + + txq_id = iwl_mvm_find_free_queue(mvm, mvm->first_agg_queue, + mvm->last_agg_queue); + if (txq_id < 0) { + ret = txq_id; + spin_unlock_bh(&mvm->queue_info_lock); + IWL_ERR(mvm, "Failed to allocate agg queue\n"); + goto release_locks; + } + mvm->queue_info[txq_id].setup_reserved = true; + spin_unlock_bh(&mvm->queue_info_lock); tid_data = &mvmsta->tid_data[tid]; tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); @@ -970,9 +978,12 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, tid_data->state = IWL_EMPTYING_HW_QUEUE_ADDBA; } + ret = 0; + +release_locks: spin_unlock_bh(&mvmsta->lock); - return 0; + return ret; } int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, @@ -1000,13 +1011,19 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]]; - iwl_mvm_enable_agg_txq(mvm, queue, fifo, mvmsta->sta_id, tid, - buf_size, ssn, wdg_timeout); + iwl_mvm_enable_agg_txq(mvm, queue, + vif->hw_queue[tid_to_mac80211_ac[tid]], fifo, + mvmsta->sta_id, tid, buf_size, ssn, wdg_timeout); ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true); if (ret) return -EIO; + /* No need to mark as reserved */ + spin_lock_bh(&mvm->queue_info_lock); + mvm->queue_info[queue].setup_reserved = false; + spin_unlock_bh(&mvm->queue_info_lock); + /* * Even though in theory the peer could have different * aggregation reorder buffer sizes for different sessions, @@ -1051,6 +1068,11 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, mvmsta->agg_tids &= ~BIT(tid); + /* No need to mark as reserved anymore */ + spin_lock_bh(&mvm->queue_info_lock); + mvm->queue_info[txq_id].setup_reserved = false; + spin_unlock_bh(&mvm->queue_info_lock); + switch (tid_data->state) { case IWL_AGG_ON: tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); @@ -1068,14 +1090,15 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, tid_data->ssn = 0xffff; tid_data->state = IWL_AGG_OFF; - mvm->queue_to_mac80211[txq_id] = IWL_INVALID_MAC80211_QUEUE; spin_unlock_bh(&mvmsta->lock); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false); - iwl_mvm_disable_txq(mvm, txq_id, 0); + iwl_mvm_disable_txq(mvm, txq_id, + vif->hw_queue[tid_to_mac80211_ac[tid]], tid, + 0); return 0; case IWL_AGG_STARTING: case IWL_EMPTYING_HW_QUEUE_ADDBA: @@ -1086,7 +1109,6 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, /* No barriers since we are under mutex */ lockdep_assert_held(&mvm->mutex); - mvm->queue_to_mac80211[txq_id] = IWL_INVALID_MAC80211_QUEUE; ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); tid_data->state = IWL_AGG_OFF; @@ -1127,9 +1149,14 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, mvmsta->agg_tids &= ~BIT(tid); spin_unlock_bh(&mvmsta->lock); + /* No need to mark as reserved */ + spin_lock_bh(&mvm->queue_info_lock); + mvm->queue_info[txq_id].setup_reserved = false; + spin_unlock_bh(&mvm->queue_info_lock); + if (old_state >= IWL_AGG_ON) { iwl_mvm_drain_sta(mvm, mvmsta, true); - if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), 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_queue_empty(mvm->trans, mvmsta->tfd_queue_msk); @@ -1137,12 +1164,11 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false); - iwl_mvm_disable_txq(mvm, tid_data->txq_id, 0); + iwl_mvm_disable_txq(mvm, tid_data->txq_id, + vif->hw_queue[tid_to_mac80211_ac[tid]], tid, + 0); } - mvm->queue_to_mac80211[tid_data->txq_id] = - IWL_INVALID_MAC80211_QUEUE; - return 0; } diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index dbd7d544575d..7530eb23035d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c @@ -129,7 +129,7 @@ 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, false); + 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/iwlwifi/mvm/tof.c b/drivers/net/wireless/iwlwifi/mvm/tof.c index 380972f8fb82..4007f1d421dd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tof.c +++ b/drivers/net/wireless/iwlwifi/mvm/tof.c @@ -178,12 +178,14 @@ int iwl_mvm_tof_responder_cmd(struct iwl_mvm *mvm, if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT)) return -EINVAL; - if (vif->p2p || vif->type != NL80211_IFTYPE_AP) { + if (vif->p2p || vif->type != NL80211_IFTYPE_AP || + !mvmvif->ap_ibss_active) { IWL_ERR(mvm, "Cannot start responder, not in AP mode\n"); return -EIO; } cmd->sta_id = mvmvif->bcast_sta.sta_id; + memcpy(cmd->bssid, vif->addr, ETH_ALEN); return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_CMD, IWL_ALWAYS_LONG_GROUP, 0), 0, sizeof(*cmd), cmd); diff --git a/drivers/net/wireless/iwlwifi/mvm/tof.h b/drivers/net/wireless/iwlwifi/mvm/tof.h index 50ae8adaaa6e..9beebc33cb8d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tof.h +++ b/drivers/net/wireless/iwlwifi/mvm/tof.h @@ -60,7 +60,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ -#ifndef __tof +#ifndef __tof_h__ #define __tof_h__ #include "fw-api-tof.h" diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index fe7145c2c98a..cadfc0460597 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c @@ -176,17 +176,34 @@ static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm) struct iwl_dts_measurement_cmd cmd = { .flags = cpu_to_le32(DTS_TRIGGER_CMD_FLAGS_TEMP), }; + struct iwl_ext_dts_measurement_cmd extcmd = { + .control_mode = cpu_to_le32(DTS_AUTOMATIC), + }; + u32 cmdid; + + if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_WIDE_CMD_HDR)) + cmdid = iwl_cmd_id(CMD_DTS_MEASUREMENT_TRIGGER_WIDE, + PHY_OPS_GROUP, 0); + else + cmdid = CMD_DTS_MEASUREMENT_TRIGGER; - return iwl_mvm_send_cmd_pdu(mvm, CMD_DTS_MEASUREMENT_TRIGGER, 0, - sizeof(cmd), &cmd); + if (!fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE)) + return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(cmd), &cmd); + + return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(extcmd), &extcmd); } int iwl_mvm_get_temp(struct iwl_mvm *mvm) { struct iwl_notification_wait wait_temp_notif; - static const u16 temp_notif[] = { DTS_MEASUREMENT_NOTIFICATION }; + static u16 temp_notif[] = { WIDE_ID(PHY_OPS_GROUP, + DTS_MEASUREMENT_NOTIF_WIDE) }; int ret, temp; + if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_WIDE_CMD_HDR)) + temp_notif[0] = DTS_MEASUREMENT_NOTIFICATION; + lockdep_assert_held(&mvm->mutex); iwl_init_notification_wait(&mvm->notif_wait, &wait_temp_notif, diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 6df5aada4f16..c652a66be803 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -560,15 +560,10 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm, IWL_DEBUG_TX_QUEUES(mvm, "Can continue DELBA flow ssn = next_recl = %d\n", tid_data->next_reclaimed); - iwl_mvm_disable_txq(mvm, tid_data->txq_id, CMD_ASYNC); + iwl_mvm_disable_txq(mvm, tid_data->txq_id, + vif->hw_queue[tid_to_mac80211_ac[tid]], tid, + CMD_ASYNC); tid_data->state = IWL_AGG_OFF; - /* - * we can't hold the mutex - but since we are after a sequence - * point (call to iwl_mvm_disable_txq(), so we don't even need - * a memory barrier. - */ - mvm->queue_to_mac80211[tid_data->txq_id] = - IWL_INVALID_MAC80211_QUEUE; ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; @@ -1104,7 +1099,7 @@ out: * 2) flush the Tx path * 3) wait for the transport queues to be empty */ -int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync) +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 = { @@ -1112,8 +1107,6 @@ int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync) .flush_ctl = cpu_to_le16(DUMP_TX_FIFO_FLUSH), }; - u32 flags = sync ? 0 : CMD_ASYNC; - ret = iwl_mvm_send_cmd_pdu(mvm, TXPATH_FLUSH, flags, sizeof(flush_cmd), &flush_cmd); if (ret) diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index a7d434256423..ad0f16909e2e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c @@ -7,6 +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 * * 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 @@ -657,45 +658,143 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) if (mvm->support_umac_log) iwl_mvm_dump_umac_error_log(mvm); } -void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, - const struct iwl_trans_txq_scd_cfg *cfg, + +int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 minq, u8 maxq) +{ + int i; + + lockdep_assert_held(&mvm->queue_info_lock); + + for (i = minq; i <= maxq; i++) + if (mvm->queue_info[i].hw_queue_refcount == 0 && + !mvm->queue_info[i].setup_reserved) + return i; + + return -ENOSPC; +} + +void 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, - .enable = 1, - .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 enable_queue = true; - if (!iwl_mvm_is_scd_cfg_supported(mvm)) { - iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, cfg, - wdg_timeout); + spin_lock_bh(&mvm->queue_info_lock); + + /* Make sure this TID isn't already enabled */ + if (mvm->queue_info[queue].tid_bitmap & BIT(cfg->tid)) { + spin_unlock_bh(&mvm->queue_info_lock); + IWL_ERR(mvm, "Trying to enable TXQ with existing TID %d\n", + cfg->tid); return; } - iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, NULL, wdg_timeout); - 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); + /* Update mappings and refcounts */ + mvm->queue_info[queue].hw_queue_to_mac80211 |= BIT(mac80211_queue); + mvm->queue_info[queue].hw_queue_refcount++; + if (mvm->queue_info[queue].hw_queue_refcount > 1) + enable_queue = false; + mvm->queue_info[queue].tid_bitmap |= BIT(cfg->tid); + + IWL_DEBUG_TX_QUEUES(mvm, + "Enabling TXQ #%d refcount=%d (mac80211 map:0x%x)\n", + queue, mvm->queue_info[queue].hw_queue_refcount, + mvm->queue_info[queue].hw_queue_to_mac80211); + + spin_unlock_bh(&mvm->queue_info_lock); + + /* Send the enabling command if we need to */ + if (enable_queue) { + struct iwl_scd_txq_cfg_cmd cmd = { + .scd_queue = queue, + .enable = 1, + .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(cmd), + &cmd), + "Failed to configure queue %d on FIFO %d\n", queue, + cfg->fifo); + } } -void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, u8 flags) +void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, + u8 tid, u8 flags) { struct iwl_scd_txq_cfg_cmd cmd = { .scd_queue = queue, .enable = 0, }; + bool remove_mac_queue = true; int ret; - if (!iwl_mvm_is_scd_cfg_supported(mvm)) { - iwl_trans_txq_disable(mvm->trans, queue, true); + spin_lock_bh(&mvm->queue_info_lock); + + if (WARN_ON(mvm->queue_info[queue].hw_queue_refcount == 0)) { + spin_unlock_bh(&mvm->queue_info_lock); + return; + } + + mvm->queue_info[queue].tid_bitmap &= ~BIT(tid); + + /* + * If there is another TID with the same AC - don't remove the MAC queue + * from the mapping + */ + if (tid < IWL_MAX_TID_COUNT) { + unsigned long tid_bitmap = + mvm->queue_info[queue].tid_bitmap; + int ac = tid_to_mac80211_ac[tid]; + int i; + + for_each_set_bit(i, &tid_bitmap, IWL_MAX_TID_COUNT) { + if (tid_to_mac80211_ac[i] == ac) + remove_mac_queue = false; + } + } + + if (remove_mac_queue) + mvm->queue_info[queue].hw_queue_to_mac80211 &= + ~BIT(mac80211_queue); + mvm->queue_info[queue].hw_queue_refcount--; + + cmd.enable = mvm->queue_info[queue].hw_queue_refcount ? 1 : 0; + + IWL_DEBUG_TX_QUEUES(mvm, + "Disabling TXQ #%d refcount=%d (mac80211 map:0x%x)\n", + queue, + mvm->queue_info[queue].hw_queue_refcount, + mvm->queue_info[queue].hw_queue_to_mac80211); + + /* If the queue is still enabled - nothing left to do in this func */ + if (cmd.enable) { + spin_unlock_bh(&mvm->queue_info_lock); return; } + /* Make sure queue info is correct even though we overwrite it */ + WARN(mvm->queue_info[queue].hw_queue_refcount || + mvm->queue_info[queue].tid_bitmap || + mvm->queue_info[queue].hw_queue_to_mac80211, + "TXQ #%d info out-of-sync - refcount=%d, mac map=0x%x, tid=0x%x\n", + queue, mvm->queue_info[queue].hw_queue_refcount, + mvm->queue_info[queue].hw_queue_to_mac80211, + mvm->queue_info[queue].tid_bitmap); + + /* If we are here - the queue is freed and we can zero out these vals */ + mvm->queue_info[queue].hw_queue_refcount = 0; + mvm->queue_info[queue].tid_bitmap = 0; + mvm->queue_info[queue].hw_queue_to_mac80211 = 0; + + spin_unlock_bh(&mvm->queue_info_lock); + iwl_trans_txq_disable(mvm->trans, queue, false); ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, flags, sizeof(cmd), &cmd); diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 6ba7d300b08f..90283453073c 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -592,10 +592,8 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) do { ret = iwl_pcie_set_hw_ready(trans); - if (ret >= 0) { - ret = 0; - goto out; - } + if (ret >= 0) + return 0; usleep_range(200, 1000); t += 200; @@ -605,10 +603,6 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) IWL_ERR(trans, "Couldn't prepare the card\n"); -out: - iwl_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, - CSR_RESET_LINK_PWR_MGMT_DISABLED); - return ret; } diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 520bef80747f..ee46f4647fbc 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1819,7 +1819,7 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { switch (action) { case IEEE80211_AMPDU_TX_START: @@ -2190,9 +2190,8 @@ static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb, struct genl_info *info) { if (info) - genl_notify(&hwsim_genl_family, mcast_skb, - genl_info_net(info), info->snd_portid, - HWSIM_MCGRP_CONFIG, info->nlhdr, GFP_KERNEL); + genl_notify(&hwsim_genl_family, mcast_skb, info, + HWSIM_MCGRP_CONFIG, GFP_KERNEL); else genlmsg_multicast(&hwsim_genl_family, mcast_skb, 0, HWSIM_MCGRP_CONFIG, GFP_KERNEL); diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c index 169384b48b27..f715eee39851 100644 --- a/drivers/net/wireless/mediatek/mt7601u/main.c +++ b/drivers/net/wireless/mediatek/mt7601u/main.c @@ -335,7 +335,8 @@ static int mt7601u_set_rts_threshold(struct ieee80211_hw *hw, u32 value) static int mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size) + struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, + bool amsdu) { struct mt7601u_dev *dev = hw->priv; struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv; diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index f7c717253a66..aa498e0d2204 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -173,7 +173,6 @@ 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; - struct timeval tv; int headroom = adapter->iface_type == MWIFIEX_USB ? 0 : INTF_HEADER_LEN; skb_src = skb_peek(&pra_list->skb_head); @@ -202,9 +201,9 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT; skb_aggr->priority = skb_src->priority; + skb_aggr->tstamp = skb_src->tstamp; - do_gettimeofday(&tv); - skb_aggr->tstamp = timeval_to_ktime(tv); + skb_aggr->tstamp = ktime_get_real(); do { /* Check if AMSDU can accommodate this MSDU */ @@ -258,8 +257,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, } if (adapter->iface_type == MWIFIEX_USB) { - adapter->data_sent = true; - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, + ret = adapter->if_ops.host_to_card(adapter, priv->usb_port, skb_aggr, NULL); } else { if (skb_src) @@ -299,16 +297,12 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); break; case -1: - if (adapter->iface_type != MWIFIEX_PCIE) - adapter->data_sent = false; mwifiex_dbg(adapter, ERROR, "%s: host_to_card failed: %#x\n", __func__, ret); adapter->dbg.num_tx_host_to_card_failure++; mwifiex_write_data_complete(adapter, skb_aggr, 1, ret); return 0; case -EINPROGRESS: - if (adapter->iface_type != MWIFIEX_PCIE) - adapter->data_sent = false; break; case 0: mwifiex_write_data_complete(adapter, skb_aggr, 1, ret); diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index 2906cd543532..b3970a8c9e48 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -615,10 +615,10 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, ((end_win > start_win) && ((seq_num > end_win) || (seq_num < start_win)))) { end_win = seq_num; - if (((seq_num - win_size) + 1) >= 0) + if (((end_win - win_size) + 1) >= 0) start_win = (end_win - win_size) + 1; else - start_win = (MAX_TID_VALUE - (win_size - seq_num)) + 1; + start_win = (MAX_TID_VALUE - (win_size - end_win)) + 1; mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); } diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig index 317d99189556..279167ddd293 100644 --- a/drivers/net/wireless/mwifiex/Kconfig +++ b/drivers/net/wireless/mwifiex/Kconfig @@ -33,12 +33,12 @@ config MWIFIEX_PCIE mwifiex_pcie. config MWIFIEX_USB - tristate "Marvell WiFi-Ex Driver for USB8766/8797/8897/8997" + tristate "Marvell WiFi-Ex Driver for USB8766/8797/8997" depends on MWIFIEX && USB select FW_LOADER ---help--- This adds support for wireless adapters based on Marvell - 8797/8897/8997 chipset with USB interface. + 8797/8997 chipset with USB interface. If you choose to build it as a module, it will be called mwifiex_usb. diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index ff63cb5632eb..4073116e6e9f 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1821,6 +1821,10 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) return -1; } + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); + return 0; } @@ -1925,6 +1929,10 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon)) return -1; + if (!netif_carrier_ok(priv->netdev)) + netif_carrier_on(priv->netdev); + mwifiex_wake_up_net_dev_queue(priv->netdev, priv->adapter); + memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg)); kfree(bss_cfg); return 0; @@ -1994,8 +2002,10 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) CFG80211_BSS_FTYPE_UNKNOWN, bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, 0, ie_buf, ie_len, 0, GFP_KERNEL); - cfg80211_put_bss(priv->wdev.wiphy, bss); - memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); + if (bss) { + cfg80211_put_bss(priv->wdev.wiphy, bss); + ether_addr_copy(priv->cfg_bssid, bss_info.bssid); + } return 0; } @@ -2372,7 +2382,7 @@ mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) * CFG802.11 operation handler for scan request. * * This function issues a scan request to the firmware based upon - * the user specified scan configuration. On successfull completion, + * the user specified scan configuration. On successful completion, * it also informs the results. */ static int @@ -2859,14 +2869,14 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: - adapter->curr_iface_comb.sta_intf++; + adapter->curr_iface_comb.sta_intf--; break; case NL80211_IFTYPE_AP: - adapter->curr_iface_comb.uap_intf++; + adapter->curr_iface_comb.uap_intf--; break; case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_GO: - adapter->curr_iface_comb.p2p_intf++; + adapter->curr_iface_comb.p2p_intf--; break; default: mwifiex_dbg(adapter, ERROR, diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c index 5a0636d43a1b..9824d8dd2b44 100644 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ b/drivers/net/wireless/mwifiex/debugfs.c @@ -731,7 +731,7 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf, (struct mwifiex_private *) file->private_data; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *) addr; - int pos = 0, ret = 0, i; + int pos, ret, i; u8 value[MAX_EEPROM_DATA]; if (!buf) @@ -739,7 +739,7 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf, if (saved_offset == -1) { /* No command has been given */ - pos += snprintf(buf, PAGE_SIZE, "0"); + pos = snprintf(buf, PAGE_SIZE, "0"); goto done; } @@ -748,17 +748,17 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf, (u16) saved_bytes, value); if (ret) { ret = -EINVAL; - goto done; + goto out_free; } - pos += snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes); + pos = snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes); for (i = 0; i < saved_bytes; i++) - pos += snprintf(buf + strlen(buf), PAGE_SIZE, "%d ", value[i]); - - ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); + pos += scnprintf(buf + pos, PAGE_SIZE - pos, "%d ", value[i]); done: + ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); +out_free: free_page(addr); return ret; } @@ -856,6 +856,56 @@ mwifiex_hscfg_read(struct file *file, char __user *ubuf, return ret; } +static ssize_t +mwifiex_timeshare_coex_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct mwifiex_private *priv = file->private_data; + char buf[3]; + bool timeshare_coex; + int ret; + unsigned int len; + + if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15) + return -EOPNOTSUPP; + + ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX, + HostCmd_ACT_GEN_GET, 0, ×hare_coex, true); + if (ret) + return ret; + + len = sprintf(buf, "%d\n", timeshare_coex); + return simple_read_from_buffer(ubuf, count, ppos, buf, len); +} + +static ssize_t +mwifiex_timeshare_coex_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + bool timeshare_coex; + struct mwifiex_private *priv = file->private_data; + char kbuf[16]; + int ret; + + if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15) + return -EOPNOTSUPP; + + memset(kbuf, 0, sizeof(kbuf)); + + if (copy_from_user(&kbuf, ubuf, min_t(size_t, sizeof(kbuf) - 1, count))) + return -EFAULT; + + if (strtobool(kbuf, ×hare_coex)) + return -EINVAL; + + ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX, + HostCmd_ACT_GEN_SET, 0, ×hare_coex, true); + if (ret) + return ret; + else + return count; +} + #define MWIFIEX_DFS_ADD_FILE(name) do { \ if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir, \ priv, &mwifiex_dfs_##name##_fops)) \ @@ -892,6 +942,7 @@ MWIFIEX_DFS_FILE_OPS(memrw); MWIFIEX_DFS_FILE_OPS(hscfg); MWIFIEX_DFS_FILE_OPS(histogram); MWIFIEX_DFS_FILE_OPS(debug_mask); +MWIFIEX_DFS_FILE_OPS(timeshare_coex); /* * This function creates the debug FS directory structure and the files. @@ -918,6 +969,7 @@ mwifiex_dev_debugfs_init(struct mwifiex_private *priv) MWIFIEX_DFS_ADD_FILE(hscfg); MWIFIEX_DFS_ADD_FILE(histogram); MWIFIEX_DFS_ADD_FILE(debug_mask); + MWIFIEX_DFS_ADD_FILE(timeshare_coex); } /* diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 3ec2ac82e394..1e1e81a0a8d4 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -101,9 +101,13 @@ enum KEY_TYPE_ID { #define FIRMWARE_READY_SDIO 0xfedc #define FIRMWARE_READY_PCIE 0xfedcba00 +#define MWIFIEX_COEX_MODE_TIMESHARE 0x01 +#define MWIFIEX_COEX_MODE_SPATIAL 0x82 + enum mwifiex_usb_ep { MWIFIEX_USB_EP_CMD_EVENT = 1, MWIFIEX_USB_EP_DATA = 2, + MWIFIEX_USB_EP_DATA_CH2 = 3, }; enum MWIFIEX_802_11_PRIVACY_FILTER { @@ -162,6 +166,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_CHANRPT_11H_BASIC (PROPRIETARY_TLV_BASE_ID + 91) #define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93) #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) +#define TLV_TYPE_ROBUST_COEX (PROPRIETARY_TLV_BASE_ID + 96) #define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104) #define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 105) #define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) @@ -173,6 +178,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154) #define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 156) #define TLV_TYPE_MULTI_CHAN_INFO (PROPRIETARY_TLV_BASE_ID + 183) +#define TLV_TYPE_MC_GROUP_INFO (PROPRIETARY_TLV_BASE_ID + 184) #define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194) #define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197) #define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199) @@ -352,6 +358,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HostCmd_CMD_AMSDU_AGGR_CTRL 0x00df #define HostCmd_CMD_TXPWR_CFG 0x00d1 #define HostCmd_CMD_TX_RATE_CFG 0x00d6 +#define HostCmd_CMD_ROBUST_COEX 0x00e0 #define HostCmd_CMD_802_11_PS_MODE_ENH 0x00e4 #define HostCmd_CMD_802_11_HS_CFG_ENH 0x00e5 #define HostCmd_CMD_P2P_MODE_CFG 0x00eb @@ -1875,6 +1882,11 @@ struct mwifiex_ie_types_btcoex_aggr_win_size { u8 reserved; } __packed; +struct mwifiex_ie_types_robust_coex { + struct mwifiex_ie_types_header header; + __le32 mode; +} __packed; + struct host_cmd_ds_version_ext { u8 version_str_sel; char version_str[128]; @@ -1984,6 +1996,22 @@ struct mwifiex_ie_types_multi_chan_info { u8 tlv_buffer[0]; } __packed; +struct mwifiex_ie_types_mc_group_info { + struct mwifiex_ie_types_header header; + u8 chan_group_id; + u8 chan_buf_weight; + u8 band_config; + u8 chan_num; + u32 chan_time; + u32 reserved; + union { + u8 sdio_func_num; + u8 usb_ep_num; + } hid_num; + u8 intf_num; + u8 bss_type_numlist[0]; +} __packed; + struct meas_rpt_map { u8 rssi:3; u8 unmeasured:1; @@ -2060,6 +2088,11 @@ struct host_cmd_ds_multi_chan_policy { __le16 policy; } __packed; +struct host_cmd_ds_robust_coex { + __le16 action; + __le16 reserved; +} __packed; + struct host_cmd_ds_command { __le16 command; __le16 size; @@ -2129,6 +2162,7 @@ struct host_cmd_ds_command { struct host_cmd_ds_chan_rpt_req chan_rpt_req; struct host_cmd_sdio_sp_rx_aggr_cfg sdio_rx_aggr_cfg; struct host_cmd_ds_multi_chan_policy mc_policy; + struct host_cmd_ds_robust_coex coex; } params; } __packed; diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 5d3ae63baea4..de74a7773fb6 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -78,6 +78,7 @@ int mwifiex_init_priv(struct mwifiex_private *priv) priv->media_connected = false; eth_broadcast_addr(priv->curr_addr); priv->port_open = false; + priv->usb_port = MWIFIEX_USB_EP_DATA; priv->pkt_tx_ctrl = 0; priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; priv->data_rate = 0; /* Initially indicate the rate as auto */ diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 278dc94eaecb..969ca1e1f3e9 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -294,9 +294,15 @@ process_start: /* We have tried to wakeup the card already */ if (adapter->pm_wakeup_fw_try) break; - if (adapter->ps_state != PS_STATE_AWAKE || - adapter->tx_lock_flag) + if (adapter->ps_state != PS_STATE_AWAKE) break; + if (adapter->tx_lock_flag) { + if (adapter->iface_type == MWIFIEX_USB) { + if (!adapter->usb_mc_setup) + break; + } else + break; + } if ((!adapter->scan_chan_gap_enabled && adapter->scan_processing) || adapter->data_sent || @@ -345,11 +351,18 @@ process_start: */ if ((adapter->ps_state == PS_STATE_SLEEP) || (adapter->ps_state == PS_STATE_PRE_SLEEP) || - (adapter->ps_state == PS_STATE_SLEEP_CFM) || - adapter->tx_lock_flag){ + (adapter->ps_state == PS_STATE_SLEEP_CFM)) { continue; } + if (adapter->tx_lock_flag) { + if (adapter->iface_type == MWIFIEX_USB) { + if (!adapter->usb_mc_setup) + continue; + } else + continue; + } + if (!adapter->cmd_sent && !adapter->curr_cmd && mwifiex_is_send_cmd_allowed (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) { @@ -359,6 +372,13 @@ process_start: } } + /** If USB Multi channel setup ongoing, + * wait for ready to tx data. + */ + if (adapter->iface_type == MWIFIEX_USB && + adapter->usb_mc_setup) + continue; + if ((adapter->scan_chan_gap_enabled || !adapter->scan_processing) && !adapter->data_sent && @@ -928,6 +948,32 @@ mwifiex_tx_timeout(struct net_device *dev) } } +void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter) +{ + struct usb_card_rec *card = adapter->card; + struct mwifiex_private *priv; + u16 tx_buf_size; + int i, ret; + + card->mc_resync_flag = true; + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { + if (atomic_read(&card->port[i].tx_data_urb_pending)) { + mwifiex_dbg(adapter, WARN, "pending data urb in sys\n"); + return; + } + } + + card->mc_resync_flag = false; + tx_buf_size = 0xffff; + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, + HostCmd_ACT_GEN_SET, 0, &tx_buf_size, false); + if (ret) + mwifiex_dbg(adapter, ERROR, + "send reconfig tx buf size cmd err\n"); +} +EXPORT_SYMBOL_GPL(mwifiex_multi_chan_resync); + void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter) { void *p; @@ -963,8 +1009,10 @@ void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter) cardp = (struct usb_card_rec *)adapter->card; p += sprintf(p, "tx_cmd_urb_pending = %d\n", atomic_read(&cardp->tx_cmd_urb_pending)); - p += sprintf(p, "tx_data_urb_pending = %d\n", - atomic_read(&cardp->tx_data_urb_pending)); + p += sprintf(p, "tx_data_urb_pending_port_0 = %d\n", + atomic_read(&cardp->port[0].tx_data_urb_pending)); + p += sprintf(p, "tx_data_urb_pending_port_1 = %d\n", + atomic_read(&cardp->port[1].tx_data_urb_pending)); p += sprintf(p, "rx_cmd_urb_pending = %d\n", atomic_read(&cardp->rx_cmd_urb_pending)); p += sprintf(p, "rx_data_urb_pending = %d\n", @@ -1151,6 +1199,7 @@ static const struct net_device_ops mwifiex_netdev_ops = { .ndo_stop = mwifiex_close, .ndo_start_xmit = mwifiex_hard_start_xmit, .ndo_set_mac_address = mwifiex_set_mac_address, + .ndo_validate_addr = eth_validate_addr, .ndo_tx_timeout = mwifiex_tx_timeout, .ndo_get_stats = mwifiex_get_stats, .ndo_set_rx_mode = mwifiex_set_multicast_list, @@ -1447,6 +1496,26 @@ exit_sem_err: } EXPORT_SYMBOL_GPL(mwifiex_remove_card); +void _mwifiex_dbg(const struct mwifiex_adapter *adapter, int mask, + const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + if (!adapter->dev || !(adapter->debug_mask & mask)) + return; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + dev_info(adapter->dev, "%pV", &vaf); + + va_end(args); +} +EXPORT_SYMBOL_GPL(_mwifiex_dbg); + /* * This function initializes the module. * diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 6b9512140e7a..3959f1c97f4e 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -48,6 +48,9 @@ extern const char driver_version[]; +struct mwifiex_adapter; +struct mwifiex_private; + enum { MWIFIEX_ASYNC_CMD, MWIFIEX_SYNC_CMD @@ -180,12 +183,11 @@ enum MWIFIEX_DEBUG_LEVEL { MWIFIEX_DBG_FATAL | \ MWIFIEX_DBG_ERROR) -#define mwifiex_dbg(adapter, dbg_mask, fmt, args...) \ -do { \ - if ((adapter)->debug_mask & MWIFIEX_DBG_##dbg_mask) \ - if ((adapter)->dev) \ - dev_info((adapter)->dev, fmt, ## args); \ -} while (0) +__printf(3, 4) +void _mwifiex_dbg(const struct mwifiex_adapter *adapter, int mask, + const char *fmt, ...); +#define mwifiex_dbg(adapter, mask, fmt, ...) \ + _mwifiex_dbg(adapter, MWIFIEX_DBG_##mask, fmt, ##__VA_ARGS__) #define DEBUG_DUMP_DATA_MAX_LEN 128 #define mwifiex_dbg_dump(adapter, dbg_mask, str, buf, len) \ @@ -506,9 +508,6 @@ enum mwifiex_iface_work_flags { MWIFIEX_IFACE_WORK_CARD_RESET, }; -struct mwifiex_adapter; -struct mwifiex_private; - struct mwifiex_private { struct mwifiex_adapter *adapter; u8 bss_type; @@ -520,6 +519,7 @@ struct mwifiex_private { u8 curr_addr[ETH_ALEN]; u8 media_connected; u8 port_open; + u8 usb_port; u32 num_tx_timeout; /* track consecutive timeout */ u8 tx_timeout_cnt; @@ -816,6 +816,8 @@ struct mwifiex_if_ops { void (*iface_work)(struct work_struct *work); void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter); void (*deaggr_pkt)(struct mwifiex_adapter *, struct sk_buff *); + void (*multi_port_resync)(struct mwifiex_adapter *); + bool (*is_port_ready)(struct mwifiex_private *); }; struct mwifiex_adapter { @@ -861,6 +863,8 @@ struct mwifiex_adapter { u8 more_task_flag; u16 tx_buf_size; u16 curr_tx_buf_size; + /* sdio single port rx aggregation capability */ + bool host_disable_sdio_rx_aggr; bool sdio_rx_aggr_enable; u16 sdio_rx_block_size; u32 ioport; @@ -988,6 +992,8 @@ struct mwifiex_adapter { u8 coex_rx_win_size; bool drcs_enabled; u8 active_scan_triggered; + bool usb_mc_status; + bool usb_mc_setup; }; void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter); @@ -1561,6 +1567,7 @@ void mwifiex_process_tx_pause_event(struct mwifiex_private *priv, struct sk_buff *event); void mwifiex_process_multi_chan_event(struct mwifiex_private *priv, struct sk_buff *event_skb); +void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter); #ifdef CONFIG_DEBUG_FS void mwifiex_debugfs_init(void); diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 408b68460716..21192b6f9c64 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c @@ -1815,7 +1815,6 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, if (!card->evt_buf_list[rdptr]) { skb_push(skb, INTF_HEADER_LEN); skb_put(skb, MAX_EVENT_SIZE - skb->len); - memset(skb->data, 0, MAX_EVENT_SIZE); if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE, PCI_DMA_FROMDEVICE)) diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 5847863a2d6b..c20017ced566 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1839,14 +1839,18 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info, bssid, timestamp, cap_info_bitmap, beacon_period, ie_buf, ie_len, rssi, GFP_KERNEL); - bss_priv = (struct mwifiex_bss_priv *)bss->priv; - bss_priv->band = band; - bss_priv->fw_tsf = fw_tsf; - if (priv->media_connected && - !memcmp(bssid, priv->curr_bss_params.bss_descriptor - .mac_address, ETH_ALEN)) - mwifiex_update_curr_bss_params(priv, bss); - cfg80211_put_bss(priv->wdev.wiphy, bss); + if (bss) { + bss_priv = (struct mwifiex_bss_priv *)bss->priv; + bss_priv->band = band; + bss_priv->fw_tsf = fw_tsf; + if (priv->media_connected && + !memcmp(bssid, priv->curr_bss_params. + bss_descriptor.mac_address, + ETH_ALEN)) + mwifiex_update_curr_bss_params(priv, + bss); + cfg80211_put_bss(priv->wdev.wiphy, bss); + } if ((chan->flags & IEEE80211_CHAN_RADAR) || (chan->flags & IEEE80211_CHAN_NO_IR)) { @@ -1889,7 +1893,7 @@ mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv) u8 id = 0; struct mwifiex_user_scan_cfg *user_scan_cfg; - if (adapter->active_scan_triggered) { + if (adapter->active_scan_triggered || !priv->scan_request) { adapter->active_scan_triggered = false; return 0; } diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 5d05c6fe6429..78a8474e1a3d 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -1606,8 +1606,9 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) (rx_len + MWIFIEX_SDIO_BLOCK_SIZE - 1) / MWIFIEX_SDIO_BLOCK_SIZE; if (rx_len <= INTF_HEADER_LEN || - (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) > - card->mpa_rx.buf_size) { + (card->mpa_rx.enabled && + ((rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) > + card->mpa_rx.buf_size))) { mwifiex_dbg(adapter, ERROR, "invalid rx_len=%d\n", rx_len); @@ -1925,6 +1926,8 @@ error: if (ret) { kfree(card->mpa_tx.buf); kfree(card->mpa_rx.buf); + card->mpa_tx.buf_size = 0; + card->mpa_rx.buf_size = 0; } return ret; @@ -2055,16 +2058,26 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) ret = mwifiex_alloc_sdio_mpa_buffers(adapter, card->mp_tx_agg_buf_size, card->mp_rx_agg_buf_size); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "failed to alloc sdio mp-a buffers\n"); - kfree(card->mp_regs); - return -1; + + /* Allocate 32k MPA Tx/Rx buffers if 64k memory allocation fails */ + if (ret && (card->mp_tx_agg_buf_size == MWIFIEX_MP_AGGR_BUF_SIZE_MAX || + card->mp_rx_agg_buf_size == MWIFIEX_MP_AGGR_BUF_SIZE_MAX)) { + /* Disable rx single port aggregation */ + adapter->host_disable_sdio_rx_aggr = true; + + ret = mwifiex_alloc_sdio_mpa_buffers + (adapter, MWIFIEX_MP_AGGR_BUF_SIZE_32K, + MWIFIEX_MP_AGGR_BUF_SIZE_32K); + if (ret) { + /* Disable multi port aggregation */ + card->mpa_tx.enabled = 0; + card->mpa_rx.enabled = 0; + } } adapter->auto_tdls = card->can_auto_tdls; adapter->ext_scan = card->can_ext_scan; - return ret; + return 0; } /* diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index a49a80dd773e..e486867a4c67 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -1531,6 +1531,33 @@ mwifiex_cmd_set_mc_policy(struct mwifiex_private *priv, return 0; } +static int mwifiex_cmd_robust_coex(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, bool *is_timeshare) +{ + struct host_cmd_ds_robust_coex *coex = &cmd->params.coex; + struct mwifiex_ie_types_robust_coex *coex_tlv; + + cmd->command = cpu_to_le16(HostCmd_CMD_ROBUST_COEX); + cmd->size = cpu_to_le16(sizeof(*coex) + sizeof(*coex_tlv) + S_DS_GEN); + + coex->action = cpu_to_le16(cmd_action); + coex_tlv = (struct mwifiex_ie_types_robust_coex *) + ((u8 *)coex + sizeof(*coex)); + coex_tlv->header.type = cpu_to_le16(TLV_TYPE_ROBUST_COEX); + coex_tlv->header.len = cpu_to_le16(sizeof(coex_tlv->mode)); + + if (coex->action == HostCmd_ACT_GEN_GET) + return 0; + + if (*is_timeshare) + coex_tlv->mode = cpu_to_le32(MWIFIEX_COEX_MODE_TIMESHARE); + else + coex_tlv->mode = cpu_to_le32(MWIFIEX_COEX_MODE_SPATIAL); + + return 0; +} + static int mwifiex_cmd_coalesce_cfg(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, @@ -2040,6 +2067,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, ret = mwifiex_cmd_set_mc_policy(priv, cmd_ptr, cmd_action, data_buf); break; + case HostCmd_CMD_ROBUST_COEX: + ret = mwifiex_cmd_robust_coex(priv, cmd_ptr, cmd_action, + data_buf); + break; default: mwifiex_dbg(priv->adapter, ERROR, "PREP_CMD: unknown cmd- %#x\n", cmd_no); @@ -2125,7 +2156,8 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) /** Set SDIO Single Port RX Aggr Info */ if (priv->adapter->iface_type == MWIFIEX_SDIO && - ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info)) { + ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info) && + !priv->adapter->host_disable_sdio_rx_aggr) { sdio_sp_rx_aggr_enable = true; ret = mwifiex_send_cmd(priv, HostCmd_CMD_SDIO_SP_RX_AGGR_CFG, diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 87b69d8ad120..9ac7aa2431b4 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -1007,6 +1007,28 @@ static int mwifiex_ret_sdio_rx_aggr_cfg(struct mwifiex_private *priv, return 0; } +static int mwifiex_ret_robust_coex(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + bool *is_timeshare) +{ + struct host_cmd_ds_robust_coex *coex = &resp->params.coex; + struct mwifiex_ie_types_robust_coex *coex_tlv; + u16 action = le16_to_cpu(coex->action); + u32 mode; + + coex_tlv = (struct mwifiex_ie_types_robust_coex + *)((u8 *)coex + sizeof(struct host_cmd_ds_robust_coex)); + if (action == HostCmd_ACT_GEN_GET) { + mode = le32_to_cpu(coex_tlv->mode); + if (mode == MWIFIEX_COEX_MODE_TIMESHARE) + *is_timeshare = true; + else + *is_timeshare = false; + } + + return 0; +} + /* * This function handles the command responses. * @@ -1128,6 +1150,17 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, ret = mwifiex_ret_11n_addba_resp(priv, resp); break; case HostCmd_CMD_RECONFIGURE_TX_BUFF: + if (0xffff == (u16)le16_to_cpu(resp->params.tx_buf.buff_size)) { + if (adapter->iface_type == MWIFIEX_USB && + adapter->usb_mc_setup) { + if (adapter->if_ops.multi_port_resync) + adapter->if_ops. + multi_port_resync(adapter); + adapter->usb_mc_setup = false; + adapter->tx_lock_flag = false; + } + break; + } adapter->tx_buf_size = (u16) le16_to_cpu(resp->params. tx_buf.buff_size); adapter->tx_buf_size = (adapter->tx_buf_size @@ -1202,6 +1235,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, break; case HostCmd_CMD_TDLS_CONFIG: break; + case HostCmd_CMD_ROBUST_COEX: + ret = mwifiex_ret_robust_coex(priv, resp, data_buf); + break; default: mwifiex_dbg(adapter, ERROR, "CMD_RESP: unknown cmd response %#x\n", diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 3d18c585e543..ff3ee9dfbbd5 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -313,24 +313,78 @@ void mwifiex_process_multi_chan_event(struct mwifiex_private *priv, struct sk_buff *event_skb) { struct mwifiex_ie_types_multi_chan_info *chan_info; - u16 status; + struct mwifiex_ie_types_mc_group_info *grp_info; + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_ie_types_header *tlv; + u16 tlv_buf_left, tlv_type, tlv_len; + int intf_num, bss_type, bss_num, i; + struct mwifiex_private *intf_priv; + tlv_buf_left = event_skb->len - sizeof(u32); chan_info = (void *)event_skb->data + sizeof(u32); - if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO) { - mwifiex_dbg(priv->adapter, ERROR, + if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO || + tlv_buf_left < sizeof(struct mwifiex_ie_types_multi_chan_info)) { + mwifiex_dbg(adapter, ERROR, "unknown TLV in chan_info event\n"); return; } - status = le16_to_cpu(chan_info->status); + adapter->usb_mc_status = le16_to_cpu(chan_info->status); + mwifiex_dbg(adapter, EVENT, "multi chan operation %s\n", + adapter->usb_mc_status ? "started" : "over"); - if (status) { - mwifiex_dbg(priv->adapter, EVENT, - "multi-channel operation started\n"); - } else { - mwifiex_dbg(priv->adapter, EVENT, - "multi-channel operation over\n"); + tlv_buf_left -= sizeof(struct mwifiex_ie_types_multi_chan_info); + tlv = (struct mwifiex_ie_types_header *)chan_info->tlv_buffer; + + while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) { + tlv_type = le16_to_cpu(tlv->type); + tlv_len = le16_to_cpu(tlv->len); + if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) > + tlv_buf_left) { + mwifiex_dbg(adapter, ERROR, "wrong tlv: tlvLen=%d,\t" + "tlvBufLeft=%d\n", tlv_len, tlv_buf_left); + break; + } + if (tlv_type != TLV_TYPE_MC_GROUP_INFO) { + mwifiex_dbg(adapter, ERROR, "wrong tlv type: 0x%x\n", + tlv_type); + break; + } + + grp_info = (struct mwifiex_ie_types_mc_group_info *)tlv; + intf_num = grp_info->intf_num; + for (i = 0; i < intf_num; i++) { + bss_type = grp_info->bss_type_numlist[i] >> 4; + bss_num = grp_info->bss_type_numlist[i] & BSS_NUM_MASK; + intf_priv = mwifiex_get_priv_by_id(adapter, bss_num, + bss_type); + if (!intf_priv) { + mwifiex_dbg(adapter, ERROR, + "Invalid bss_type bss_num\t" + "in multi channel event\n"); + continue; + } + if (adapter->iface_type == MWIFIEX_USB) { + u8 ep; + + ep = grp_info->hid_num.usb_ep_num; + if (ep == MWIFIEX_USB_EP_DATA || + ep == MWIFIEX_USB_EP_DATA_CH2) + intf_priv->usb_port = ep; + } + } + + tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) + + tlv_len; + tlv = (void *)((u8 *)tlv + tlv_len + + sizeof(struct mwifiex_ie_types_header)); + } + + if (adapter->iface_type == MWIFIEX_USB) { + adapter->tx_lock_flag = true; + adapter->usb_mc_setup = true; + mwifiex_multi_chan_resync(adapter); } } @@ -562,7 +616,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) adapter->tx_lock_flag = false; if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { if (mwifiex_check_last_packet_indication(priv)) { - if (adapter->data_sent) { + if (adapter->data_sent || + (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv))) { adapter->ps_state = PS_STATE_AWAKE; adapter->pm_wakeup_card_req = false; adapter->pm_wakeup_fw_try = false; diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index 355ac5904fac..f6683ea6bd5d 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c @@ -153,6 +153,10 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) if (adapter->data_sent) return -1; + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) + return -1; + skb = dev_alloc_skb(data_len); if (!skb) return -1; @@ -174,7 +178,7 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) local_tx_pd->bss_type = priv->bss_type; if (adapter->iface_type == MWIFIEX_USB) { - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, + ret = adapter->if_ops.host_to_card(adapter, priv->usb_port, skb, NULL); } else { skb_push(skb, INTF_HEADER_LEN); @@ -191,7 +195,6 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) adapter->dbg.num_tx_host_to_card_failure++; break; case -1: - adapter->data_sent = false; dev_kfree_skb_any(skb); mwifiex_dbg(adapter, ERROR, "%s: host_to_card failed: ret=%d\n", diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c index b3e163de9899..9275f9c3f869 100644 --- a/drivers/net/wireless/mwifiex/tdls.c +++ b/drivers/net/wireless/mwifiex/tdls.c @@ -204,6 +204,12 @@ mwifiex_tdls_add_ht_oper(struct mwifiex_private *priv, const u8 *mac, return -1; } + if (!(le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info))) { + mwifiex_dbg(priv->adapter, WARN, + "TDLS peer doesn't support ht capabilities\n"); + return 0; + } + pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_operation) + 2); *pos++ = WLAN_EID_HT_OPERATION; *pos++ = sizeof(struct ieee80211_ht_operation); @@ -252,6 +258,12 @@ static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv, return -1; } + if (!(le32_to_cpu(sta_ptr->tdls_cap.vhtcap.vht_cap_info))) { + mwifiex_dbg(adapter, WARN, + "TDLS peer doesn't support vht capabilities\n"); + return 0; + } + if (!mwifiex_is_bss_in_11ac_mode(priv)) { if (sta_ptr->tdls_cap.extcap.ext_capab[7] & WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) { diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 8b1e5b5d47fe..bf6182b646a5 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -115,9 +115,8 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) local_tx_pd = (struct txpd *)(head_ptr + hroom); if (adapter->iface_type == MWIFIEX_USB) { - adapter->data_sent = true; ret = adapter->if_ops.host_to_card(adapter, - MWIFIEX_USB_EP_DATA, + priv->usb_port, skb, NULL); } else { ret = adapter->if_ops.host_to_card(adapter, @@ -130,7 +129,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, switch (ret) { case -ENOSR: - mwifiex_dbg(adapter, ERROR, "data: -ENOSR is returned\n"); + mwifiex_dbg(adapter, DATA, "data: -ENOSR is returned\n"); break; case -EBUSY: if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && @@ -142,8 +141,6 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); break; case -1: - if (adapter->iface_type != MWIFIEX_PCIE) - adapter->data_sent = false; mwifiex_dbg(adapter, ERROR, "mwifiex_write_data_async failed: 0x%X\n", ret); @@ -151,8 +148,6 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, mwifiex_write_data_complete(adapter, skb, 0, ret); break; case -EINPROGRESS: - if (adapter->iface_type != MWIFIEX_PCIE) - adapter->data_sent = false; break; case 0: mwifiex_write_data_complete(adapter, skb, 0, ret); @@ -193,9 +188,8 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter, } if (adapter->iface_type == MWIFIEX_USB) { - adapter->data_sent = true; ret = adapter->if_ops.host_to_card(adapter, - MWIFIEX_USB_EP_DATA, + priv->usb_port, skb, NULL); } else { ret = adapter->if_ops.host_to_card(adapter, @@ -222,16 +216,12 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter, mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); break; case -1: - if (adapter->iface_type != MWIFIEX_PCIE) - adapter->data_sent = false; mwifiex_dbg(adapter, ERROR, "mwifiex_write_data_async failed: 0x%X\n", ret); adapter->dbg.num_tx_host_to_card_failure++; mwifiex_write_data_complete(adapter, skb, 0, ret); break; case -EINPROGRESS: - if (adapter->iface_type != MWIFIEX_PCIE) - adapter->data_sent = false; break; case 0: mwifiex_write_data_complete(adapter, skb, 0, ret); @@ -306,9 +296,6 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, if (!priv) goto done; - if (adapter->iface_type == MWIFIEX_USB) - adapter->data_sent = false; - mwifiex_set_trans_start(priv->netdev); if (!status) { priv->stats.tx_packets++; diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index 4d5a6e3b6361..759a6ada5b0f 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c @@ -846,22 +846,6 @@ int mwifiex_config_start_uap(struct mwifiex_private *priv, { enum state_11d_t state_11d; - if (mwifiex_del_mgmt_ies(priv)) - mwifiex_dbg(priv->adapter, ERROR, - "Failed to delete mgmt IEs!\n"); - - if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, - HostCmd_ACT_GEN_SET, 0, NULL, true)) { - mwifiex_dbg(priv->adapter, ERROR, "Failed to stop the BSS\n"); - return -1; - } - - if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET, - HostCmd_ACT_GEN_SET, 0, NULL, true)) { - mwifiex_dbg(priv->adapter, ERROR, "Failed to reset BSS\n"); - return -1; - } - if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, HostCmd_ACT_GEN_SET, UAP_BSS_PARAMS_I, bss_cfg, false)) { diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index 46c972a650a4..86ff54296f39 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c @@ -179,19 +179,12 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) case EVENT_UAP_BSS_IDLE: priv->media_connected = false; priv->port_open = false; - if (netif_carrier_ok(priv->netdev)) - netif_carrier_off(priv->netdev); - mwifiex_stop_net_dev_queue(priv->netdev, adapter); - mwifiex_clean_txrx(priv); mwifiex_del_all_sta_list(priv); break; case EVENT_UAP_BSS_ACTIVE: priv->media_connected = true; priv->port_open = true; - if (!netif_carrier_ok(priv->netdev)) - netif_carrier_on(priv->netdev); - mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); break; case EVENT_UAP_BSS_START: mwifiex_dbg(adapter, EVENT, @@ -269,7 +262,9 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) adapter->tx_lock_flag = false; if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { if (mwifiex_check_last_packet_indication(priv)) { - if (adapter->data_sent) { + if (adapter->data_sent || + (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv))) { adapter->ps_state = PS_STATE_AWAKE; adapter->pm_wakeup_card_req = false; adapter->pm_wakeup_fw_try = false; diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index 87667418af5f..74d5d7238633 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c @@ -31,7 +31,8 @@ */ static bool mwifiex_uap_del_tx_pkts_in_ralist(struct mwifiex_private *priv, - struct list_head *ra_list_head) + struct list_head *ra_list_head, + int tid) { struct mwifiex_ra_list_tbl *ra_list; struct sk_buff *skb, *tmp; @@ -49,7 +50,10 @@ mwifiex_uap_del_tx_pkts_in_ralist(struct mwifiex_private *priv, __skb_unlink(skb, &ra_list->skb_head); mwifiex_write_data_complete(adapter, skb, 0, -1); - atomic_dec(&priv->wmm.tx_pkts_queued); + if (ra_list->tx_paused) + priv->wmm.pkts_paused[tid]--; + else + atomic_dec(&priv->wmm.tx_pkts_queued); pkt_deleted = true; } if ((atomic_read(&adapter->pending_bridged_pkts) <= @@ -77,7 +81,7 @@ static void mwifiex_uap_cleanup_tx_queues(struct mwifiex_private *priv) if (priv->del_list_idx == MAX_NUM_TID) priv->del_list_idx = 0; ra_list = &priv->wmm.tid_tbl_ptr[priv->del_list_idx].ra_list; - if (mwifiex_uap_del_tx_pkts_in_ralist(priv, ra_list)) { + if (mwifiex_uap_del_tx_pkts_in_ralist(priv, ra_list, i)) { priv->del_list_idx++; break; } diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 5e789b2e06ea..e43aff932360 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c @@ -42,11 +42,6 @@ static struct usb_device_id mwifiex_usb_table[] = { {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8801_PID_2, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff)}, - /* 8897 */ - {USB_DEVICE(USB8XXX_VID, USB8897_PID_1)}, - {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8897_PID_2, - USB_CLASS_VENDOR_SPEC, - USB_SUBCLASS_VENDOR_SPEC, 0xff)}, /* 8997 */ {USB_DEVICE(USB8XXX_VID, USB8997_PID_1)}, {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8997_PID_2, @@ -264,6 +259,8 @@ static void mwifiex_usb_tx_complete(struct urb *urb) struct urb_context *context = (struct urb_context *)(urb->context); struct mwifiex_adapter *adapter = context->adapter; struct usb_card_rec *card = adapter->card; + struct usb_tx_data_port *port; + int i; mwifiex_dbg(adapter, INFO, "%s: status: %d\n", __func__, urb->status); @@ -276,11 +273,22 @@ static void mwifiex_usb_tx_complete(struct urb *urb) } else { mwifiex_dbg(adapter, DATA, "%s: DATA\n", __func__); - atomic_dec(&card->tx_data_urb_pending); + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { + port = &card->port[i]; + if (context->ep == port->tx_data_ep) { + atomic_dec(&port->tx_data_urb_pending); + port->block_status = false; + break; + } + } + adapter->data_sent = false; mwifiex_write_data_complete(adapter, context->skb, 0, urb->status ? -1 : 0); } + if (card->mc_resync_flag) + mwifiex_multi_chan_resync(adapter); + mwifiex_queue_main_work(adapter); return; @@ -327,7 +335,8 @@ static int mwifiex_usb_submit_rx_urb(struct urb_context *ctx, int size) static void mwifiex_usb_free(struct usb_card_rec *card) { - int i; + struct usb_tx_data_port *port; + int i, j; if (atomic_read(&card->rx_cmd_urb_pending) && card->rx_cmd.urb) usb_kill_urb(card->rx_cmd.urb); @@ -345,9 +354,12 @@ static void mwifiex_usb_free(struct usb_card_rec *card) card->rx_data_list[i].urb = NULL; } - for (i = 0; i < MWIFIEX_TX_DATA_URB; i++) { - usb_free_urb(card->tx_data_list[i].urb); - card->tx_data_list[i].urb = NULL; + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { + port = &card->port[i]; + for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) { + usb_free_urb(port->tx_data_list[j].urb); + port->tx_data_list[j].urb = NULL; + } } usb_free_urb(card->tx_cmd.urb); @@ -386,14 +398,12 @@ static int mwifiex_usb_probe(struct usb_interface *intf, case USB8766_PID_1: case USB8797_PID_1: case USB8801_PID_1: - case USB8897_PID_1: case USB8997_PID_1: card->usb_boot_state = USB8XXX_FW_DNLD; break; case USB8766_PID_2: case USB8797_PID_2: case USB8801_PID_2: - case USB8897_PID_2: case USB8997_PID_2: card->usb_boot_state = USB8XXX_FW_READY; break; @@ -437,8 +447,18 @@ static int mwifiex_usb_probe(struct usb_interface *intf, pr_debug("info: bulk OUT: max pkt size: %d, addr: %d\n", le16_to_cpu(epd->wMaxPacketSize), epd->bEndpointAddress); - card->tx_data_ep = usb_endpoint_num(epd); - atomic_set(&card->tx_data_urb_pending, 0); + card->port[0].tx_data_ep = usb_endpoint_num(epd); + atomic_set(&card->port[0].tx_data_urb_pending, 0); + } + if (usb_endpoint_dir_out(epd) && + usb_endpoint_num(epd) == MWIFIEX_USB_EP_DATA_CH2 && + usb_endpoint_xfer_bulk(epd)) { + pr_debug("info: bulk OUT chan2:\t" + "max pkt size: %d, addr: %d\n", + le16_to_cpu(epd->wMaxPacketSize), + epd->bEndpointAddress); + card->port[1].tx_data_ep = usb_endpoint_num(epd); + atomic_set(&card->port[1].tx_data_urb_pending, 0); } if (usb_endpoint_dir_out(epd) && usb_endpoint_num(epd) == MWIFIEX_USB_EP_CMD_EVENT && @@ -480,7 +500,8 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message) { struct usb_card_rec *card = usb_get_intfdata(intf); struct mwifiex_adapter *adapter; - int i; + struct usb_tx_data_port *port; + int i, j; if (!card || !card->adapter) { pr_err("%s: card or card->adapter is NULL\n", __func__); @@ -511,9 +532,13 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message) if (card->rx_data_list[i].urb) usb_kill_urb(card->rx_data_list[i].urb); - for (i = 0; i < MWIFIEX_TX_DATA_URB; i++) - if (card->tx_data_list[i].urb) - usb_kill_urb(card->tx_data_list[i].urb); + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { + port = &card->port[i]; + for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) { + if (port->tx_data_list[j].urb) + usb_kill_urb(port->tx_data_list[j].urb); + } + } if (card->tx_cmd.urb) usb_kill_urb(card->tx_cmd.urb); @@ -625,7 +650,8 @@ static struct usb_driver mwifiex_usb_driver = { static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter) { struct usb_card_rec *card = (struct usb_card_rec *)adapter->card; - int i; + struct usb_tx_data_port *port; + int i, j; card->tx_cmd.adapter = adapter; card->tx_cmd.ep = card->tx_cmd_ep; @@ -637,17 +663,25 @@ static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter) return -ENOMEM; } - card->tx_data_ix = 0; - - for (i = 0; i < MWIFIEX_TX_DATA_URB; i++) { - card->tx_data_list[i].adapter = adapter; - card->tx_data_list[i].ep = card->tx_data_ep; - - card->tx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL); - if (!card->tx_data_list[i].urb) { - mwifiex_dbg(adapter, ERROR, - "tx_data_list[] urb allocation failed\n"); - 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) { + mwifiex_dbg(adapter, ERROR, + "urb allocation failed\n"); + return -ENOMEM; + } } } @@ -736,15 +770,89 @@ static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *pbuf, return ret; } +static void mwifiex_usb_port_resync(struct mwifiex_adapter *adapter) +{ + struct usb_card_rec *card = adapter->card; + u8 active_port = MWIFIEX_USB_EP_DATA; + struct mwifiex_private *priv = NULL; + int i; + + if (adapter->usb_mc_status) { + for (i = 0; i < adapter->priv_num; i++) { + priv = adapter->priv[i]; + if (!priv) + continue; + if ((priv->bss_role == MWIFIEX_BSS_ROLE_UAP && + !priv->bss_started) || + (priv->bss_role == MWIFIEX_BSS_ROLE_STA && + !priv->media_connected)) + priv->usb_port = MWIFIEX_USB_EP_DATA; + } + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) + card->port[i].block_status = false; + } else { + for (i = 0; i < adapter->priv_num; i++) { + priv = adapter->priv[i]; + if (!priv) + continue; + if ((priv->bss_role == MWIFIEX_BSS_ROLE_UAP && + priv->bss_started) || + (priv->bss_role == MWIFIEX_BSS_ROLE_STA && + priv->media_connected)) { + active_port = priv->usb_port; + break; + } + } + for (i = 0; i < adapter->priv_num; i++) { + priv = adapter->priv[i]; + if (priv) + priv->usb_port = active_port; + } + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { + if (active_port == card->port[i].tx_data_ep) + card->port[i].block_status = false; + else + card->port[i].block_status = true; + } + } +} + +static bool mwifiex_usb_is_port_ready(struct mwifiex_private *priv) +{ + struct usb_card_rec *card = priv->adapter->card; + int idx; + + for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) { + if (priv->usb_port == card->port[idx].tx_data_ep) + return !card->port[idx].block_status; + } + + return false; +} + +static inline u8 mwifiex_usb_data_sent(struct mwifiex_adapter *adapter) +{ + struct usb_card_rec *card = adapter->card; + int i; + + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) + if (!card->port[i].block_status) + return false; + + return true; +} + /* 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, struct mwifiex_tx_param *tx_param) { struct usb_card_rec *card = adapter->card; - struct urb_context *context; + struct urb_context *context = NULL; + struct usb_tx_data_port *port = NULL; u8 *data = (u8 *)skb->data; struct urb *tx_urb; + int idx, ret; if (adapter->is_suspended) { mwifiex_dbg(adapter, ERROR, @@ -757,19 +865,31 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, return -1; } - if (ep == card->tx_data_ep && - atomic_read(&card->tx_data_urb_pending) >= MWIFIEX_TX_DATA_URB) { - return -EBUSY; - } - mwifiex_dbg(adapter, INFO, "%s: ep=%d\n", __func__, ep); if (ep == card->tx_cmd_ep) { context = &card->tx_cmd; } else { - if (card->tx_data_ix >= MWIFIEX_TX_DATA_URB) - card->tx_data_ix = 0; - context = &card->tx_data_list[card->tx_data_ix++]; + for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) { + if (ep == card->port[idx].tx_data_ep) { + port = &card->port[idx]; + if (atomic_read(&port->tx_data_urb_pending) + >= MWIFIEX_TX_DATA_URB) { + port->block_status = true; + ret = -EBUSY; + goto done; + } + 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; @@ -786,7 +906,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, if (ep == card->tx_cmd_ep) atomic_inc(&card->tx_cmd_urb_pending); else - atomic_inc(&card->tx_data_urb_pending); + atomic_inc(&port->tx_data_urb_pending); if (usb_submit_urb(tx_urb, GFP_ATOMIC)) { mwifiex_dbg(adapter, ERROR, @@ -794,22 +914,32 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, if (ep == card->tx_cmd_ep) { atomic_dec(&card->tx_cmd_urb_pending); } else { - atomic_dec(&card->tx_data_urb_pending); - if (card->tx_data_ix) - card->tx_data_ix--; + atomic_dec(&port->tx_data_urb_pending); + port->block_status = false; + if (port->tx_data_ix) + port->tx_data_ix--; else - card->tx_data_ix = MWIFIEX_TX_DATA_URB; + port->tx_data_ix = MWIFIEX_TX_DATA_URB; } return -1; } else { - if (ep == card->tx_data_ep && - atomic_read(&card->tx_data_urb_pending) == - MWIFIEX_TX_DATA_URB) - return -ENOSR; + if (ep != card->tx_cmd_ep && + atomic_read(&port->tx_data_urb_pending) == + MWIFIEX_TX_DATA_URB) { + port->block_status = true; + ret = -ENOSR; + goto done; + } } return -EINPROGRESS; + +done: + if (ep != card->tx_cmd_ep) + adapter->data_sent = mwifiex_usb_data_sent(adapter); + + return ret; } /* This function register usb device and initialize parameter. */ @@ -827,12 +957,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) strcpy(adapter->fw_name, USB8997_DEFAULT_FW_NAME); adapter->ext_scan = true; break; - case USB8897_PID_1: - case USB8897_PID_2: - adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; - strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME); - adapter->ext_scan = true; - break; case USB8766_PID_1: case USB8766_PID_2: adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; @@ -853,6 +977,9 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) break; } + adapter->usb_mc_status = false; + adapter->usb_mc_setup = false; + return 0; } @@ -1082,6 +1209,8 @@ static struct mwifiex_if_ops usb_ops = { .event_complete = mwifiex_usb_cmd_event_complete, .host_to_card = mwifiex_usb_host_to_card, .submit_rem_rx_urbs = mwifiex_usb_submit_rem_rx_urbs, + .multi_port_resync = mwifiex_usb_port_resync, + .is_port_ready = mwifiex_usb_is_port_ready, }; /* This function initializes the USB driver module. @@ -1135,5 +1264,4 @@ MODULE_LICENSE("GPL v2"); MODULE_FIRMWARE(USB8766_DEFAULT_FW_NAME); MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME); MODULE_FIRMWARE(USB8801_DEFAULT_FW_NAME); -MODULE_FIRMWARE(USB8897_DEFAULT_FW_NAME); MODULE_FIRMWARE(USB8997_DEFAULT_FW_NAME); diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h index f0051f8c8981..b4e9246bbcdc 100644 --- a/drivers/net/wireless/mwifiex/usb.h +++ b/drivers/net/wireless/mwifiex/usb.h @@ -28,11 +28,9 @@ #define USB8766_PID_2 0x2042 #define USB8797_PID_1 0x2043 #define USB8797_PID_2 0x2044 -#define USB8897_PID_1 0x2045 -#define USB8897_PID_2 0x2046 #define USB8801_PID_1 0x2049 #define USB8801_PID_2 0x204a -#define USB8997_PID_1 0x204d +#define USB8997_PID_1 0x2052 #define USB8997_PID_2 0x204e @@ -40,6 +38,7 @@ #define USB8XXX_FW_READY 2 #define USB8XXX_FW_MAX_RETRY 3 +#define MWIFIEX_TX_DATA_PORT 2 #define MWIFIEX_TX_DATA_URB 6 #define MWIFIEX_RX_DATA_URB 6 #define MWIFIEX_USB_TIMEOUT 100 @@ -47,7 +46,6 @@ #define USB8766_DEFAULT_FW_NAME "mrvl/usb8766_uapsta.bin" #define USB8797_DEFAULT_FW_NAME "mrvl/usb8797_uapsta.bin" #define USB8801_DEFAULT_FW_NAME "mrvl/usb8801_uapsta.bin" -#define USB8897_DEFAULT_FW_NAME "mrvl/usb8897_uapsta.bin" #define USB8997_DEFAULT_FW_NAME "mrvl/usb8997_uapsta.bin" #define FW_DNLD_TX_BUF_SIZE 620 @@ -64,6 +62,14 @@ struct urb_context { u8 ep; }; +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]; +}; + struct usb_card_rec { struct mwifiex_adapter *adapter; struct usb_device *udev; @@ -75,14 +81,12 @@ struct usb_card_rec { u8 usb_boot_state; u8 rx_data_ep; atomic_t rx_data_urb_pending; - u8 tx_data_ep; u8 tx_cmd_ep; - atomic_t tx_data_urb_pending; atomic_t tx_cmd_urb_pending; int bulk_out_maxpktsize; struct urb_context tx_cmd; - int tx_data_ix; - struct urb_context tx_data_list[MWIFIEX_TX_DATA_URB]; + u8 mc_resync_flag; + struct usb_tx_data_port port[MWIFIEX_TX_DATA_PORT]; }; struct fw_header { diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 173d3663c2e0..acccd6734e3b 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -117,22 +117,15 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, const u8 *ra) */ static u8 mwifiex_get_random_ba_threshold(void) { - u32 sec, usec; - struct timeval ba_tstamp; - u8 ba_threshold; - + u64 ns; /* setup ba_packet_threshold here random number between * [BA_SETUP_PACKET_OFFSET, * BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1] */ + ns = ktime_get_ns(); + ns += (ns >> 32) + (ns >> 16); - do_gettimeofday(&ba_tstamp); - sec = (ba_tstamp.tv_sec & 0xFFFF) + (ba_tstamp.tv_sec >> 16); - usec = (ba_tstamp.tv_usec & 0xFFFF) + (ba_tstamp.tv_usec >> 16); - ba_threshold = (((sec << 16) + usec) % BA_SETUP_MAX_PACKET_THRESHOLD) - + BA_SETUP_PACKET_OFFSET; - - return ba_threshold; + return ((u8)ns % BA_SETUP_MAX_PACKET_THRESHOLD) + BA_SETUP_PACKET_OFFSET; } /* @@ -160,7 +153,6 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra) ra_list->tdls_link = false; ra_list->ba_status = BA_SETUP_NONE; ra_list->amsdu_in_ampdu = false; - ra_list->tx_paused = false; if (!mwifiex_queuing_ra_based(priv)) { if (mwifiex_is_tdls_link_setup (mwifiex_get_tdls_link_status(priv, ra))) { @@ -173,6 +165,8 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra) } else { spin_lock_irqsave(&priv->sta_list_spinlock, flags); node = mwifiex_get_sta_entry(priv, ra); + if (node) + ra_list->tx_paused = node->tx_pause; ra_list->is_11n_enabled = mwifiex_is_sta_11n_enabled(priv, node); if (ra_list->is_11n_enabled) @@ -451,7 +445,21 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) int mwifiex_bypass_txlist_empty(struct mwifiex_adapter *adapter) { - return atomic_read(&adapter->bypass_tx_pending) ? false : true; + struct mwifiex_private *priv; + int i; + + for (i = 0; i < adapter->priv_num; i++) { + priv = adapter->priv[i]; + if (!priv) + continue; + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) + continue; + if (!skb_queue_empty(&priv->bypass_txq)) + return false; + } + + return true; } /* @@ -465,9 +473,14 @@ mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) for (i = 0; i < adapter->priv_num; ++i) { priv = adapter->priv[i]; - if (priv && !priv->port_open) + if (!priv) + continue; + if (!priv->port_open) continue; - if (priv && atomic_read(&priv->wmm.tx_pkts_queued)) + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) + continue; + if (atomic_read(&priv->wmm.tx_pkts_queued)) return false; } @@ -671,7 +684,7 @@ void mwifiex_update_ralist_tx_pause_in_tdls_cs(struct mwifiex_private *priv, if (!memcmp(ra_list->ra, mac, ETH_ALEN)) continue; - if (ra_list && ra_list->tx_paused != tx_pause) { + if (ra_list->tx_paused != tx_pause) { pkt_cnt += ra_list->total_pkt_count; ra_list->tx_paused = tx_pause; if (tx_pause) @@ -737,7 +750,11 @@ mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv, const u8 *ra_addr) if (!ra_list) continue; mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list); - atomic_sub(ra_list->total_pkt_count, &priv->wmm.tx_pkts_queued); + if (ra_list->tx_paused) + priv->wmm.pkts_paused[i] -= ra_list->total_pkt_count; + else + atomic_sub(ra_list->total_pkt_count, + &priv->wmm.tx_pkts_queued); list_del(&ra_list->list); kfree(ra_list); } @@ -1086,6 +1103,10 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0)) continue; + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv_tmp)) + continue; + /* iterate over the WMM queues of the BSS */ hqp = &priv_tmp->wmm.highest_queued_prio; for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) { @@ -1321,8 +1342,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); if (adapter->iface_type == MWIFIEX_USB) { - adapter->data_sent = true; - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, + ret = adapter->if_ops.host_to_card(adapter, priv->usb_port, skb, NULL); } else { tx_param.next_pkt_len = @@ -1351,15 +1371,11 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, ra_list_flags); break; case -1: - if (adapter->iface_type != MWIFIEX_PCIE) - adapter->data_sent = false; mwifiex_dbg(adapter, ERROR, "host_to_card failed: %#x\n", ret); adapter->dbg.num_tx_host_to_card_failure++; mwifiex_write_data_complete(adapter, skb, 0, ret); break; case -EINPROGRESS: - if (adapter->iface_type != MWIFIEX_PCIE) - adapter->data_sent = false; break; case 0: mwifiex_write_data_complete(adapter, skb, 0, ret); @@ -1467,6 +1483,13 @@ void mwifiex_process_bypass_tx(struct mwifiex_adapter *adapter) for (i = 0; i < adapter->priv_num; ++i) { priv = adapter->priv[i]; + if (!priv) + continue; + + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) + continue; + if (skb_queue_empty(&priv->bypass_txq)) continue; diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 9420fc61c2e6..30e3aaae32e2 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -5423,7 +5423,7 @@ static int mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { int i, rc = 0; diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c index a9e94b6db5b7..0f6ea316e38e 100644 --- a/drivers/net/wireless/orinoco/cfg.c +++ b/drivers/net/wireless/orinoco/cfg.c @@ -220,7 +220,7 @@ static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed) if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { /* Set fragmentation */ if (priv->has_mwo) { - if (wiphy->frag_threshold < 0) + if (wiphy->frag_threshold == -1) frag_value = 0; else { printk(KERN_WARNING "%s: Fixed fragmentation " @@ -230,7 +230,7 @@ static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed) frag_value = 1; } } else { - if (wiphy->frag_threshold < 0) + if (wiphy->frag_threshold == -1) frag_value = 2346; else if ((wiphy->frag_threshold < 257) || (wiphy->frag_threshold > 2347)) @@ -252,7 +252,7 @@ static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed) * the upper limit. */ - if (wiphy->rts_threshold < 0) + if (wiphy->rts_threshold == -1) rts_value = 2347; else if (wiphy->rts_threshold > 2347) err = -EINVAL; diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index 26a57d773d30..f2cd513d54b2 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c @@ -1576,6 +1576,7 @@ static int ezusb_probe(struct usb_interface *interface, ezusb_hard_reset, NULL); if (!priv) { err("Couldn't allocate orinocodev"); + retval = -ENOMEM; goto exit; } diff --git a/drivers/net/wireless/realtek/Makefile b/drivers/net/wireless/realtek/Makefile new file mode 100644 index 000000000000..9c78deb5eea9 --- /dev/null +++ b/drivers/net/wireless/realtek/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for the Linux Wireless network device drivers for Realtek units +# + +obj-$(CONFIG_RTL8180) += rtl818x/ +obj-$(CONFIG_RTL8187) += rtl818x/ +obj-$(CONFIG_RTLWIFI) += rtlwifi/ +obj-$(CONFIG_RTL8XXXU) += rtl8xxxu/ + diff --git a/drivers/net/wireless/rtl818x/Kconfig b/drivers/net/wireless/realtek/rtl818x/Kconfig index 1ce1d55f0010..1ce1d55f0010 100644 --- a/drivers/net/wireless/rtl818x/Kconfig +++ b/drivers/net/wireless/realtek/rtl818x/Kconfig diff --git a/drivers/net/wireless/rtl818x/Makefile b/drivers/net/wireless/realtek/rtl818x/Makefile index 997569076923..997569076923 100644 --- a/drivers/net/wireless/rtl818x/Makefile +++ b/drivers/net/wireless/realtek/rtl818x/Makefile diff --git a/drivers/net/wireless/rtl818x/rtl8180/Makefile b/drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile index 21005bd8b43c..2966681efaef 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/Makefile +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile @@ -2,4 +2,4 @@ rtl818x_pci-objs := dev.o rtl8225.o sa2400.o max2820.o grf5101.o rtl8225se.o obj-$(CONFIG_RTL8180) += rtl818x_pci.o -ccflags-y += -Idrivers/net/wireless/rtl818x +ccflags-y += -Idrivers/net/wireless/realtek/rtl818x diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c index a43a16fde59d..a43a16fde59d 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c diff --git a/drivers/net/wireless/rtl818x/rtl8180/grf5101.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.c index b1bfee738937..b1bfee738937 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/grf5101.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.c diff --git a/drivers/net/wireless/rtl818x/rtl8180/grf5101.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.h index 4d80a2785123..4d80a2785123 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/grf5101.h +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.h diff --git a/drivers/net/wireless/rtl818x/rtl8180/max2820.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.c index eebf23976524..eebf23976524 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/max2820.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.c diff --git a/drivers/net/wireless/rtl818x/rtl8180/max2820.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.h index 8e982b72b690..8e982b72b690 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/max2820.h +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.h diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8180.h index e8243a44d6b6..e8243a44d6b6 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8180.h diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.c index 9bda5bc78eda..9bda5bc78eda 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.c diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.h index 310013a2d726..310013a2d726 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.h +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.h diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c index fde89866fa8d..fde89866fa8d 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.h index 229400264088..229400264088 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.h +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.h diff --git a/drivers/net/wireless/rtl818x/rtl8180/sa2400.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.c index 959b049827de..959b049827de 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/sa2400.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.c diff --git a/drivers/net/wireless/rtl818x/rtl8180/sa2400.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.h index fb0093f35148..fb0093f35148 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/sa2400.h +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.h diff --git a/drivers/net/wireless/rtl818x/rtl8187/Makefile b/drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile index 7b6299268ecf..ff074912a095 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/Makefile +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile @@ -2,4 +2,4 @@ rtl8187-objs := dev.o rtl8225.o leds.o rfkill.o obj-$(CONFIG_RTL8187) += rtl8187.o -ccflags-y += -Idrivers/net/wireless/rtl818x +ccflags-y += -Idrivers/net/wireless/realtek/rtl818x diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c index b7f72f9c7988..b7f72f9c7988 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/leds.c index c2d5b495c179..c2d5b495c179 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/leds.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/leds.c diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.h b/drivers/net/wireless/realtek/rtl818x/rtl8187/leds.h index d743c96d4a20..d743c96d4a20 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/leds.h +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/leds.h diff --git a/drivers/net/wireless/rtl818x/rtl8187/rfkill.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.c index 34116719974a..34116719974a 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/rfkill.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.c diff --git a/drivers/net/wireless/rtl818x/rtl8187/rfkill.h b/drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.h index e12575e96d11..e12575e96d11 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/rfkill.h +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.h diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8187.h index a6ad79f61bf9..a6ad79f61bf9 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8187.h diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c index 5ecf18ed67b8..5ecf18ed67b8 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.h b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.h index 141afb09a5b4..141afb09a5b4 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.h +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.h diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/realtek/rtl818x/rtl818x.h index 7abef95d278b..7abef95d278b 100644 --- a/drivers/net/wireless/rtl818x/rtl818x.h +++ b/drivers/net/wireless/realtek/rtl818x/rtl818x.h diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Kconfig b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig new file mode 100644 index 000000000000..dd4d626aecbc --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig @@ -0,0 +1,34 @@ +# +# RTL8XXXU Wireless LAN device configuration +# +config RTL8XXXU + tristate "RTL8723AU/RTL8188[CR]U/RTL819[12]CU (mac80211) support" + depends on MAC80211 && USB + ---help--- + This is an alternative driver for various Realtek RTL8XXX + parts written to utilize the Linux mac80211 stack. + The driver is known to work with a number of RTL8723AU, + RL8188CU, RTL8188RU, RTL8191CU, and RTL8192CU devices + + This driver is under development and has a limited feature + set. In particular it does not yet support 40MHz channels + and power management. However it should have a smaller + memory footprint than the vendor drivers and benetifs + from the in kernel mac80211 stack. + + It can coexist with drivers from drivers/staging/rtl8723au, + drivers/staging/rtl8192u, and drivers/net/wireless/rtlwifi, + but you will need to control which module you wish to load. + + To compile this driver as a module, choose M here: the module will + be called r8xxxu. If unsure, say N. + +config RTL8XXXU_UNTESTED + bool "Include support for untested Realtek 8xxx USB devices (EXPERIMENTAL)" + depends on RTL8XXXU + ---help--- + This option enables detection of Realtek 8723/8188/8191/8192 WiFi + USB devices which have not been tested directly by the driver + author or reported to be working by third parties. + + Please report your results! diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Makefile b/drivers/net/wireless/realtek/rtl8xxxu/Makefile new file mode 100644 index 000000000000..5dea3bb93069 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8xxxu/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_RTL8XXXU) += rtl8xxxu.o diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c new file mode 100644 index 000000000000..6aed923a709a --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -0,0 +1,5993 @@ +/* + * RTL8XXXU mac80211 USB driver + * + * Copyright (c) 2014 - 2015 Jes Sorensen <Jes.Sorensen@redhat.com> + * + * Portions, notably calibration code: + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + * + * This driver was written as a replacement for the vendor provided + * rtl8723au driver. As the Realtek 8xxx chips are very similar in + * their programming interface, I have started adding support for + * additional 8xxx chips like the 8192cu, 8188cus, etc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/spinlock.h> +#include <linux/list.h> +#include <linux/usb.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/wireless.h> +#include <linux/firmware.h> +#include <linux/moduleparam.h> +#include <net/mac80211.h> +#include "rtl8xxxu.h" +#include "rtl8xxxu_regs.h" + +#define DRIVER_NAME "rtl8xxxu" + +static int rtl8xxxu_debug; +static bool rtl8xxxu_ht40_2g; + +MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@redhat.com>"); +MODULE_DESCRIPTION("RTL8XXXu USB mac80211 Wireless LAN Driver"); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE("rtlwifi/rtl8723aufw_A.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8723aufw_B.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8723aufw_B_NoBT.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw_A.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw_B.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw_TMSC.bin"); + +module_param_named(debug, rtl8xxxu_debug, int, 0600); +MODULE_PARM_DESC(debug, "Set debug mask"); +module_param_named(ht40_2g, rtl8xxxu_ht40_2g, bool, 0600); +MODULE_PARM_DESC(ht40_2g, "Enable HT40 support on the 2.4GHz band"); + +#define USB_VENDOR_ID_REALTEK 0x0bda +/* Minimum IEEE80211_MAX_FRAME_LEN */ +#define RTL_RX_BUFFER_SIZE IEEE80211_MAX_FRAME_LEN +#define RTL8XXXU_RX_URBS 32 +#define RTL8XXXU_RX_URB_PENDING_WATER 8 +#define RTL8XXXU_TX_URBS 64 +#define RTL8XXXU_TX_URB_LOW_WATER 25 +#define RTL8XXXU_TX_URB_HIGH_WATER 32 + +static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_priv *priv, + struct rtl8xxxu_rx_urb *rx_urb); + +static struct ieee80211_rate rtl8xxxu_rates[] = { + { .bitrate = 10, .hw_value = DESC_RATE_1M, .flags = 0 }, + { .bitrate = 20, .hw_value = DESC_RATE_2M, .flags = 0 }, + { .bitrate = 55, .hw_value = DESC_RATE_5_5M, .flags = 0 }, + { .bitrate = 110, .hw_value = DESC_RATE_11M, .flags = 0 }, + { .bitrate = 60, .hw_value = DESC_RATE_6M, .flags = 0 }, + { .bitrate = 90, .hw_value = DESC_RATE_9M, .flags = 0 }, + { .bitrate = 120, .hw_value = DESC_RATE_12M, .flags = 0 }, + { .bitrate = 180, .hw_value = DESC_RATE_18M, .flags = 0 }, + { .bitrate = 240, .hw_value = DESC_RATE_24M, .flags = 0 }, + { .bitrate = 360, .hw_value = DESC_RATE_36M, .flags = 0 }, + { .bitrate = 480, .hw_value = DESC_RATE_48M, .flags = 0 }, + { .bitrate = 540, .hw_value = DESC_RATE_54M, .flags = 0 }, +}; + +static struct ieee80211_channel rtl8xxxu_channels_2g[] = { + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2412, + .hw_value = 1, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2417, + .hw_value = 2, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2422, + .hw_value = 3, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2427, + .hw_value = 4, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2432, + .hw_value = 5, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2437, + .hw_value = 6, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2442, + .hw_value = 7, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2447, + .hw_value = 8, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2452, + .hw_value = 9, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2457, + .hw_value = 10, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2462, + .hw_value = 11, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2467, + .hw_value = 12, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2472, + .hw_value = 13, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2484, + .hw_value = 14, .max_power = 30 } +}; + +static struct ieee80211_supported_band rtl8xxxu_supported_band = { + .channels = rtl8xxxu_channels_2g, + .n_channels = ARRAY_SIZE(rtl8xxxu_channels_2g), + .bitrates = rtl8xxxu_rates, + .n_bitrates = ARRAY_SIZE(rtl8xxxu_rates), +}; + +static struct rtl8xxxu_reg8val rtl8723a_mac_init_table[] = { + {0x420, 0x80}, {0x423, 0x00}, {0x430, 0x00}, {0x431, 0x00}, + {0x432, 0x00}, {0x433, 0x01}, {0x434, 0x04}, {0x435, 0x05}, + {0x436, 0x06}, {0x437, 0x07}, {0x438, 0x00}, {0x439, 0x00}, + {0x43a, 0x00}, {0x43b, 0x01}, {0x43c, 0x04}, {0x43d, 0x05}, + {0x43e, 0x06}, {0x43f, 0x07}, {0x440, 0x5d}, {0x441, 0x01}, + {0x442, 0x00}, {0x444, 0x15}, {0x445, 0xf0}, {0x446, 0x0f}, + {0x447, 0x00}, {0x458, 0x41}, {0x459, 0xa8}, {0x45a, 0x72}, + {0x45b, 0xb9}, {0x460, 0x66}, {0x461, 0x66}, {0x462, 0x08}, + {0x463, 0x03}, {0x4c8, 0xff}, {0x4c9, 0x08}, {0x4cc, 0xff}, + {0x4cd, 0xff}, {0x4ce, 0x01}, {0x500, 0x26}, {0x501, 0xa2}, + {0x502, 0x2f}, {0x503, 0x00}, {0x504, 0x28}, {0x505, 0xa3}, + {0x506, 0x5e}, {0x507, 0x00}, {0x508, 0x2b}, {0x509, 0xa4}, + {0x50a, 0x5e}, {0x50b, 0x00}, {0x50c, 0x4f}, {0x50d, 0xa4}, + {0x50e, 0x00}, {0x50f, 0x00}, {0x512, 0x1c}, {0x514, 0x0a}, + {0x515, 0x10}, {0x516, 0x0a}, {0x517, 0x10}, {0x51a, 0x16}, + {0x524, 0x0f}, {0x525, 0x4f}, {0x546, 0x40}, {0x547, 0x00}, + {0x550, 0x10}, {0x551, 0x10}, {0x559, 0x02}, {0x55a, 0x02}, + {0x55d, 0xff}, {0x605, 0x30}, {0x608, 0x0e}, {0x609, 0x2a}, + {0x652, 0x20}, {0x63c, 0x0a}, {0x63d, 0x0a}, {0x63e, 0x0e}, + {0x63f, 0x0e}, {0x66e, 0x05}, {0x700, 0x21}, {0x701, 0x43}, + {0x702, 0x65}, {0x703, 0x87}, {0x708, 0x21}, {0x709, 0x43}, + {0x70a, 0x65}, {0x70b, 0x87}, {0xffff, 0xff}, +}; + +static struct rtl8xxxu_reg32val rtl8723a_phy_1t_init_table[] = { + {0x800, 0x80040000}, {0x804, 0x00000003}, + {0x808, 0x0000fc00}, {0x80c, 0x0000000a}, + {0x810, 0x10001331}, {0x814, 0x020c3d10}, + {0x818, 0x02200385}, {0x81c, 0x00000000}, + {0x820, 0x01000100}, {0x824, 0x00390004}, + {0x828, 0x00000000}, {0x82c, 0x00000000}, + {0x830, 0x00000000}, {0x834, 0x00000000}, + {0x838, 0x00000000}, {0x83c, 0x00000000}, + {0x840, 0x00010000}, {0x844, 0x00000000}, + {0x848, 0x00000000}, {0x84c, 0x00000000}, + {0x850, 0x00000000}, {0x854, 0x00000000}, + {0x858, 0x569a569a}, {0x85c, 0x001b25a4}, + {0x860, 0x66f60110}, {0x864, 0x061f0130}, + {0x868, 0x00000000}, {0x86c, 0x32323200}, + {0x870, 0x07000760}, {0x874, 0x22004000}, + {0x878, 0x00000808}, {0x87c, 0x00000000}, + {0x880, 0xc0083070}, {0x884, 0x000004d5}, + {0x888, 0x00000000}, {0x88c, 0xccc000c0}, + {0x890, 0x00000800}, {0x894, 0xfffffffe}, + {0x898, 0x40302010}, {0x89c, 0x00706050}, + {0x900, 0x00000000}, {0x904, 0x00000023}, + {0x908, 0x00000000}, {0x90c, 0x81121111}, + {0xa00, 0x00d047c8}, {0xa04, 0x80ff000c}, + {0xa08, 0x8c838300}, {0xa0c, 0x2e68120f}, + {0xa10, 0x9500bb78}, {0xa14, 0x11144028}, + {0xa18, 0x00881117}, {0xa1c, 0x89140f00}, + {0xa20, 0x1a1b0000}, {0xa24, 0x090e1317}, + {0xa28, 0x00000204}, {0xa2c, 0x00d30000}, + {0xa70, 0x101fbf00}, {0xa74, 0x00000007}, + {0xa78, 0x00000900}, + {0xc00, 0x48071d40}, {0xc04, 0x03a05611}, + {0xc08, 0x000000e4}, {0xc0c, 0x6c6c6c6c}, + {0xc10, 0x08800000}, {0xc14, 0x40000100}, + {0xc18, 0x08800000}, {0xc1c, 0x40000100}, + {0xc20, 0x00000000}, {0xc24, 0x00000000}, + {0xc28, 0x00000000}, {0xc2c, 0x00000000}, + {0xc30, 0x69e9ac44}, {0xc34, 0x469652af}, + {0xc38, 0x49795994}, {0xc3c, 0x0a97971c}, + {0xc40, 0x1f7c403f}, {0xc44, 0x000100b7}, + {0xc48, 0xec020107}, {0xc4c, 0x007f037f}, + {0xc50, 0x69543420}, {0xc54, 0x43bc0094}, + {0xc58, 0x69543420}, {0xc5c, 0x433c0094}, + {0xc60, 0x00000000}, {0xc64, 0x7112848b}, + {0xc68, 0x47c00bff}, {0xc6c, 0x00000036}, + {0xc70, 0x2c7f000d}, {0xc74, 0x018610db}, + {0xc78, 0x0000001f}, {0xc7c, 0x00b91612}, + {0xc80, 0x40000100}, {0xc84, 0x20f60000}, + {0xc88, 0x40000100}, {0xc8c, 0x20200000}, + {0xc90, 0x00121820}, {0xc94, 0x00000000}, + {0xc98, 0x00121820}, {0xc9c, 0x00007f7f}, + {0xca0, 0x00000000}, {0xca4, 0x00000080}, + {0xca8, 0x00000000}, {0xcac, 0x00000000}, + {0xcb0, 0x00000000}, {0xcb4, 0x00000000}, + {0xcb8, 0x00000000}, {0xcbc, 0x28000000}, + {0xcc0, 0x00000000}, {0xcc4, 0x00000000}, + {0xcc8, 0x00000000}, {0xccc, 0x00000000}, + {0xcd0, 0x00000000}, {0xcd4, 0x00000000}, + {0xcd8, 0x64b22427}, {0xcdc, 0x00766932}, + {0xce0, 0x00222222}, {0xce4, 0x00000000}, + {0xce8, 0x37644302}, {0xcec, 0x2f97d40c}, + {0xd00, 0x00080740}, {0xd04, 0x00020401}, + {0xd08, 0x0000907f}, {0xd0c, 0x20010201}, + {0xd10, 0xa0633333}, {0xd14, 0x3333bc43}, + {0xd18, 0x7a8f5b6b}, {0xd2c, 0xcc979975}, + {0xd30, 0x00000000}, {0xd34, 0x80608000}, + {0xd38, 0x00000000}, {0xd3c, 0x00027293}, + {0xd40, 0x00000000}, {0xd44, 0x00000000}, + {0xd48, 0x00000000}, {0xd4c, 0x00000000}, + {0xd50, 0x6437140a}, {0xd54, 0x00000000}, + {0xd58, 0x00000000}, {0xd5c, 0x30032064}, + {0xd60, 0x4653de68}, {0xd64, 0x04518a3c}, + {0xd68, 0x00002101}, {0xd6c, 0x2a201c16}, + {0xd70, 0x1812362e}, {0xd74, 0x322c2220}, + {0xd78, 0x000e3c24}, {0xe00, 0x2a2a2a2a}, + {0xe04, 0x2a2a2a2a}, {0xe08, 0x03902a2a}, + {0xe10, 0x2a2a2a2a}, {0xe14, 0x2a2a2a2a}, + {0xe18, 0x2a2a2a2a}, {0xe1c, 0x2a2a2a2a}, + {0xe28, 0x00000000}, {0xe30, 0x1000dc1f}, + {0xe34, 0x10008c1f}, {0xe38, 0x02140102}, + {0xe3c, 0x681604c2}, {0xe40, 0x01007c00}, + {0xe44, 0x01004800}, {0xe48, 0xfb000000}, + {0xe4c, 0x000028d1}, {0xe50, 0x1000dc1f}, + {0xe54, 0x10008c1f}, {0xe58, 0x02140102}, + {0xe5c, 0x28160d05}, {0xe60, 0x00000008}, + {0xe68, 0x001b25a4}, {0xe6c, 0x631b25a0}, + {0xe70, 0x631b25a0}, {0xe74, 0x081b25a0}, + {0xe78, 0x081b25a0}, {0xe7c, 0x081b25a0}, + {0xe80, 0x081b25a0}, {0xe84, 0x631b25a0}, + {0xe88, 0x081b25a0}, {0xe8c, 0x631b25a0}, + {0xed0, 0x631b25a0}, {0xed4, 0x631b25a0}, + {0xed8, 0x631b25a0}, {0xedc, 0x001b25a0}, + {0xee0, 0x001b25a0}, {0xeec, 0x6b1b25a0}, + {0xf14, 0x00000003}, {0xf4c, 0x00000000}, + {0xf00, 0x00000300}, + {0xffff, 0xffffffff}, +}; + +static struct rtl8xxxu_reg32val rtl8192cu_phy_2t_init_table[] = { + {0x024, 0x0011800f}, {0x028, 0x00ffdb83}, + {0x800, 0x80040002}, {0x804, 0x00000003}, + {0x808, 0x0000fc00}, {0x80c, 0x0000000a}, + {0x810, 0x10000330}, {0x814, 0x020c3d10}, + {0x818, 0x02200385}, {0x81c, 0x00000000}, + {0x820, 0x01000100}, {0x824, 0x00390004}, + {0x828, 0x01000100}, {0x82c, 0x00390004}, + {0x830, 0x27272727}, {0x834, 0x27272727}, + {0x838, 0x27272727}, {0x83c, 0x27272727}, + {0x840, 0x00010000}, {0x844, 0x00010000}, + {0x848, 0x27272727}, {0x84c, 0x27272727}, + {0x850, 0x00000000}, {0x854, 0x00000000}, + {0x858, 0x569a569a}, {0x85c, 0x0c1b25a4}, + {0x860, 0x66e60230}, {0x864, 0x061f0130}, + {0x868, 0x27272727}, {0x86c, 0x2b2b2b27}, + {0x870, 0x07000700}, {0x874, 0x22184000}, + {0x878, 0x08080808}, {0x87c, 0x00000000}, + {0x880, 0xc0083070}, {0x884, 0x000004d5}, + {0x888, 0x00000000}, {0x88c, 0xcc0000c0}, + {0x890, 0x00000800}, {0x894, 0xfffffffe}, + {0x898, 0x40302010}, {0x89c, 0x00706050}, + {0x900, 0x00000000}, {0x904, 0x00000023}, + {0x908, 0x00000000}, {0x90c, 0x81121313}, + {0xa00, 0x00d047c8}, {0xa04, 0x80ff000c}, + {0xa08, 0x8c838300}, {0xa0c, 0x2e68120f}, + {0xa10, 0x9500bb78}, {0xa14, 0x11144028}, + {0xa18, 0x00881117}, {0xa1c, 0x89140f00}, + {0xa20, 0x1a1b0000}, {0xa24, 0x090e1317}, + {0xa28, 0x00000204}, {0xa2c, 0x00d30000}, + {0xa70, 0x101fbf00}, {0xa74, 0x00000007}, + {0xc00, 0x48071d40}, {0xc04, 0x03a05633}, + {0xc08, 0x000000e4}, {0xc0c, 0x6c6c6c6c}, + {0xc10, 0x08800000}, {0xc14, 0x40000100}, + {0xc18, 0x08800000}, {0xc1c, 0x40000100}, + {0xc20, 0x00000000}, {0xc24, 0x00000000}, + {0xc28, 0x00000000}, {0xc2c, 0x00000000}, + {0xc30, 0x69e9ac44}, {0xc34, 0x469652cf}, + {0xc38, 0x49795994}, {0xc3c, 0x0a97971c}, + {0xc40, 0x1f7c403f}, {0xc44, 0x000100b7}, + {0xc48, 0xec020107}, {0xc4c, 0x007f037f}, + {0xc50, 0x69543420}, {0xc54, 0x43bc0094}, + {0xc58, 0x69543420}, {0xc5c, 0x433c0094}, + {0xc60, 0x00000000}, {0xc64, 0x5116848b}, + {0xc68, 0x47c00bff}, {0xc6c, 0x00000036}, + {0xc70, 0x2c7f000d}, {0xc74, 0x2186115b}, + {0xc78, 0x0000001f}, {0xc7c, 0x00b99612}, + {0xc80, 0x40000100}, {0xc84, 0x20f60000}, + {0xc88, 0x40000100}, {0xc8c, 0xa0e40000}, + {0xc90, 0x00121820}, {0xc94, 0x00000000}, + {0xc98, 0x00121820}, {0xc9c, 0x00007f7f}, + {0xca0, 0x00000000}, {0xca4, 0x00000080}, + {0xca8, 0x00000000}, {0xcac, 0x00000000}, + {0xcb0, 0x00000000}, {0xcb4, 0x00000000}, + {0xcb8, 0x00000000}, {0xcbc, 0x28000000}, + {0xcc0, 0x00000000}, {0xcc4, 0x00000000}, + {0xcc8, 0x00000000}, {0xccc, 0x00000000}, + {0xcd0, 0x00000000}, {0xcd4, 0x00000000}, + {0xcd8, 0x64b22427}, {0xcdc, 0x00766932}, + {0xce0, 0x00222222}, {0xce4, 0x00000000}, + {0xce8, 0x37644302}, {0xcec, 0x2f97d40c}, + {0xd00, 0x00080740}, {0xd04, 0x00020403}, + {0xd08, 0x0000907f}, {0xd0c, 0x20010201}, + {0xd10, 0xa0633333}, {0xd14, 0x3333bc43}, + {0xd18, 0x7a8f5b6b}, {0xd2c, 0xcc979975}, + {0xd30, 0x00000000}, {0xd34, 0x80608000}, + {0xd38, 0x00000000}, {0xd3c, 0x00027293}, + {0xd40, 0x00000000}, {0xd44, 0x00000000}, + {0xd48, 0x00000000}, {0xd4c, 0x00000000}, + {0xd50, 0x6437140a}, {0xd54, 0x00000000}, + {0xd58, 0x00000000}, {0xd5c, 0x30032064}, + {0xd60, 0x4653de68}, {0xd64, 0x04518a3c}, + {0xd68, 0x00002101}, {0xd6c, 0x2a201c16}, + {0xd70, 0x1812362e}, {0xd74, 0x322c2220}, + {0xd78, 0x000e3c24}, {0xe00, 0x2a2a2a2a}, + {0xe04, 0x2a2a2a2a}, {0xe08, 0x03902a2a}, + {0xe10, 0x2a2a2a2a}, {0xe14, 0x2a2a2a2a}, + {0xe18, 0x2a2a2a2a}, {0xe1c, 0x2a2a2a2a}, + {0xe28, 0x00000000}, {0xe30, 0x1000dc1f}, + {0xe34, 0x10008c1f}, {0xe38, 0x02140102}, + {0xe3c, 0x681604c2}, {0xe40, 0x01007c00}, + {0xe44, 0x01004800}, {0xe48, 0xfb000000}, + {0xe4c, 0x000028d1}, {0xe50, 0x1000dc1f}, + {0xe54, 0x10008c1f}, {0xe58, 0x02140102}, + {0xe5c, 0x28160d05}, {0xe60, 0x00000010}, + {0xe68, 0x001b25a4}, {0xe6c, 0x63db25a4}, + {0xe70, 0x63db25a4}, {0xe74, 0x0c1b25a4}, + {0xe78, 0x0c1b25a4}, {0xe7c, 0x0c1b25a4}, + {0xe80, 0x0c1b25a4}, {0xe84, 0x63db25a4}, + {0xe88, 0x0c1b25a4}, {0xe8c, 0x63db25a4}, + {0xed0, 0x63db25a4}, {0xed4, 0x63db25a4}, + {0xed8, 0x63db25a4}, {0xedc, 0x001b25a4}, + {0xee0, 0x001b25a4}, {0xeec, 0x6fdb25a4}, + {0xf14, 0x00000003}, {0xf4c, 0x00000000}, + {0xf00, 0x00000300}, + {0xffff, 0xffffffff}, +}; + +static struct rtl8xxxu_reg32val rtl8188ru_phy_1t_highpa_table[] = { + {0x024, 0x0011800f}, {0x028, 0x00ffdb83}, + {0x040, 0x000c0004}, {0x800, 0x80040000}, + {0x804, 0x00000001}, {0x808, 0x0000fc00}, + {0x80c, 0x0000000a}, {0x810, 0x10005388}, + {0x814, 0x020c3d10}, {0x818, 0x02200385}, + {0x81c, 0x00000000}, {0x820, 0x01000100}, + {0x824, 0x00390204}, {0x828, 0x00000000}, + {0x82c, 0x00000000}, {0x830, 0x00000000}, + {0x834, 0x00000000}, {0x838, 0x00000000}, + {0x83c, 0x00000000}, {0x840, 0x00010000}, + {0x844, 0x00000000}, {0x848, 0x00000000}, + {0x84c, 0x00000000}, {0x850, 0x00000000}, + {0x854, 0x00000000}, {0x858, 0x569a569a}, + {0x85c, 0x001b25a4}, {0x860, 0x66e60230}, + {0x864, 0x061f0130}, {0x868, 0x00000000}, + {0x86c, 0x20202000}, {0x870, 0x03000300}, + {0x874, 0x22004000}, {0x878, 0x00000808}, + {0x87c, 0x00ffc3f1}, {0x880, 0xc0083070}, + {0x884, 0x000004d5}, {0x888, 0x00000000}, + {0x88c, 0xccc000c0}, {0x890, 0x00000800}, + {0x894, 0xfffffffe}, {0x898, 0x40302010}, + {0x89c, 0x00706050}, {0x900, 0x00000000}, + {0x904, 0x00000023}, {0x908, 0x00000000}, + {0x90c, 0x81121111}, {0xa00, 0x00d047c8}, + {0xa04, 0x80ff000c}, {0xa08, 0x8c838300}, + {0xa0c, 0x2e68120f}, {0xa10, 0x9500bb78}, + {0xa14, 0x11144028}, {0xa18, 0x00881117}, + {0xa1c, 0x89140f00}, {0xa20, 0x15160000}, + {0xa24, 0x070b0f12}, {0xa28, 0x00000104}, + {0xa2c, 0x00d30000}, {0xa70, 0x101fbf00}, + {0xa74, 0x00000007}, {0xc00, 0x48071d40}, + {0xc04, 0x03a05611}, {0xc08, 0x000000e4}, + {0xc0c, 0x6c6c6c6c}, {0xc10, 0x08800000}, + {0xc14, 0x40000100}, {0xc18, 0x08800000}, + {0xc1c, 0x40000100}, {0xc20, 0x00000000}, + {0xc24, 0x00000000}, {0xc28, 0x00000000}, + {0xc2c, 0x00000000}, {0xc30, 0x69e9ac44}, + {0xc34, 0x469652cf}, {0xc38, 0x49795994}, + {0xc3c, 0x0a97971c}, {0xc40, 0x1f7c403f}, + {0xc44, 0x000100b7}, {0xc48, 0xec020107}, + {0xc4c, 0x007f037f}, {0xc50, 0x6954342e}, + {0xc54, 0x43bc0094}, {0xc58, 0x6954342f}, + {0xc5c, 0x433c0094}, {0xc60, 0x00000000}, + {0xc64, 0x5116848b}, {0xc68, 0x47c00bff}, + {0xc6c, 0x00000036}, {0xc70, 0x2c46000d}, + {0xc74, 0x018610db}, {0xc78, 0x0000001f}, + {0xc7c, 0x00b91612}, {0xc80, 0x24000090}, + {0xc84, 0x20f60000}, {0xc88, 0x24000090}, + {0xc8c, 0x20200000}, {0xc90, 0x00121820}, + {0xc94, 0x00000000}, {0xc98, 0x00121820}, + {0xc9c, 0x00007f7f}, {0xca0, 0x00000000}, + {0xca4, 0x00000080}, {0xca8, 0x00000000}, + {0xcac, 0x00000000}, {0xcb0, 0x00000000}, + {0xcb4, 0x00000000}, {0xcb8, 0x00000000}, + {0xcbc, 0x28000000}, {0xcc0, 0x00000000}, + {0xcc4, 0x00000000}, {0xcc8, 0x00000000}, + {0xccc, 0x00000000}, {0xcd0, 0x00000000}, + {0xcd4, 0x00000000}, {0xcd8, 0x64b22427}, + {0xcdc, 0x00766932}, {0xce0, 0x00222222}, + {0xce4, 0x00000000}, {0xce8, 0x37644302}, + {0xcec, 0x2f97d40c}, {0xd00, 0x00080740}, + {0xd04, 0x00020401}, {0xd08, 0x0000907f}, + {0xd0c, 0x20010201}, {0xd10, 0xa0633333}, + {0xd14, 0x3333bc43}, {0xd18, 0x7a8f5b6b}, + {0xd2c, 0xcc979975}, {0xd30, 0x00000000}, + {0xd34, 0x80608000}, {0xd38, 0x00000000}, + {0xd3c, 0x00027293}, {0xd40, 0x00000000}, + {0xd44, 0x00000000}, {0xd48, 0x00000000}, + {0xd4c, 0x00000000}, {0xd50, 0x6437140a}, + {0xd54, 0x00000000}, {0xd58, 0x00000000}, + {0xd5c, 0x30032064}, {0xd60, 0x4653de68}, + {0xd64, 0x04518a3c}, {0xd68, 0x00002101}, + {0xd6c, 0x2a201c16}, {0xd70, 0x1812362e}, + {0xd74, 0x322c2220}, {0xd78, 0x000e3c24}, + {0xe00, 0x24242424}, {0xe04, 0x24242424}, + {0xe08, 0x03902024}, {0xe10, 0x24242424}, + {0xe14, 0x24242424}, {0xe18, 0x24242424}, + {0xe1c, 0x24242424}, {0xe28, 0x00000000}, + {0xe30, 0x1000dc1f}, {0xe34, 0x10008c1f}, + {0xe38, 0x02140102}, {0xe3c, 0x681604c2}, + {0xe40, 0x01007c00}, {0xe44, 0x01004800}, + {0xe48, 0xfb000000}, {0xe4c, 0x000028d1}, + {0xe50, 0x1000dc1f}, {0xe54, 0x10008c1f}, + {0xe58, 0x02140102}, {0xe5c, 0x28160d05}, + {0xe60, 0x00000008}, {0xe68, 0x001b25a4}, + {0xe6c, 0x631b25a0}, {0xe70, 0x631b25a0}, + {0xe74, 0x081b25a0}, {0xe78, 0x081b25a0}, + {0xe7c, 0x081b25a0}, {0xe80, 0x081b25a0}, + {0xe84, 0x631b25a0}, {0xe88, 0x081b25a0}, + {0xe8c, 0x631b25a0}, {0xed0, 0x631b25a0}, + {0xed4, 0x631b25a0}, {0xed8, 0x631b25a0}, + {0xedc, 0x001b25a0}, {0xee0, 0x001b25a0}, + {0xeec, 0x6b1b25a0}, {0xee8, 0x31555448}, + {0xf14, 0x00000003}, {0xf4c, 0x00000000}, + {0xf00, 0x00000300}, + {0xffff, 0xffffffff}, +}; + +static struct rtl8xxxu_reg32val rtl8xxx_agc_standard_table[] = { + {0xc78, 0x7b000001}, {0xc78, 0x7b010001}, + {0xc78, 0x7b020001}, {0xc78, 0x7b030001}, + {0xc78, 0x7b040001}, {0xc78, 0x7b050001}, + {0xc78, 0x7a060001}, {0xc78, 0x79070001}, + {0xc78, 0x78080001}, {0xc78, 0x77090001}, + {0xc78, 0x760a0001}, {0xc78, 0x750b0001}, + {0xc78, 0x740c0001}, {0xc78, 0x730d0001}, + {0xc78, 0x720e0001}, {0xc78, 0x710f0001}, + {0xc78, 0x70100001}, {0xc78, 0x6f110001}, + {0xc78, 0x6e120001}, {0xc78, 0x6d130001}, + {0xc78, 0x6c140001}, {0xc78, 0x6b150001}, + {0xc78, 0x6a160001}, {0xc78, 0x69170001}, + {0xc78, 0x68180001}, {0xc78, 0x67190001}, + {0xc78, 0x661a0001}, {0xc78, 0x651b0001}, + {0xc78, 0x641c0001}, {0xc78, 0x631d0001}, + {0xc78, 0x621e0001}, {0xc78, 0x611f0001}, + {0xc78, 0x60200001}, {0xc78, 0x49210001}, + {0xc78, 0x48220001}, {0xc78, 0x47230001}, + {0xc78, 0x46240001}, {0xc78, 0x45250001}, + {0xc78, 0x44260001}, {0xc78, 0x43270001}, + {0xc78, 0x42280001}, {0xc78, 0x41290001}, + {0xc78, 0x402a0001}, {0xc78, 0x262b0001}, + {0xc78, 0x252c0001}, {0xc78, 0x242d0001}, + {0xc78, 0x232e0001}, {0xc78, 0x222f0001}, + {0xc78, 0x21300001}, {0xc78, 0x20310001}, + {0xc78, 0x06320001}, {0xc78, 0x05330001}, + {0xc78, 0x04340001}, {0xc78, 0x03350001}, + {0xc78, 0x02360001}, {0xc78, 0x01370001}, + {0xc78, 0x00380001}, {0xc78, 0x00390001}, + {0xc78, 0x003a0001}, {0xc78, 0x003b0001}, + {0xc78, 0x003c0001}, {0xc78, 0x003d0001}, + {0xc78, 0x003e0001}, {0xc78, 0x003f0001}, + {0xc78, 0x7b400001}, {0xc78, 0x7b410001}, + {0xc78, 0x7b420001}, {0xc78, 0x7b430001}, + {0xc78, 0x7b440001}, {0xc78, 0x7b450001}, + {0xc78, 0x7a460001}, {0xc78, 0x79470001}, + {0xc78, 0x78480001}, {0xc78, 0x77490001}, + {0xc78, 0x764a0001}, {0xc78, 0x754b0001}, + {0xc78, 0x744c0001}, {0xc78, 0x734d0001}, + {0xc78, 0x724e0001}, {0xc78, 0x714f0001}, + {0xc78, 0x70500001}, {0xc78, 0x6f510001}, + {0xc78, 0x6e520001}, {0xc78, 0x6d530001}, + {0xc78, 0x6c540001}, {0xc78, 0x6b550001}, + {0xc78, 0x6a560001}, {0xc78, 0x69570001}, + {0xc78, 0x68580001}, {0xc78, 0x67590001}, + {0xc78, 0x665a0001}, {0xc78, 0x655b0001}, + {0xc78, 0x645c0001}, {0xc78, 0x635d0001}, + {0xc78, 0x625e0001}, {0xc78, 0x615f0001}, + {0xc78, 0x60600001}, {0xc78, 0x49610001}, + {0xc78, 0x48620001}, {0xc78, 0x47630001}, + {0xc78, 0x46640001}, {0xc78, 0x45650001}, + {0xc78, 0x44660001}, {0xc78, 0x43670001}, + {0xc78, 0x42680001}, {0xc78, 0x41690001}, + {0xc78, 0x406a0001}, {0xc78, 0x266b0001}, + {0xc78, 0x256c0001}, {0xc78, 0x246d0001}, + {0xc78, 0x236e0001}, {0xc78, 0x226f0001}, + {0xc78, 0x21700001}, {0xc78, 0x20710001}, + {0xc78, 0x06720001}, {0xc78, 0x05730001}, + {0xc78, 0x04740001}, {0xc78, 0x03750001}, + {0xc78, 0x02760001}, {0xc78, 0x01770001}, + {0xc78, 0x00780001}, {0xc78, 0x00790001}, + {0xc78, 0x007a0001}, {0xc78, 0x007b0001}, + {0xc78, 0x007c0001}, {0xc78, 0x007d0001}, + {0xc78, 0x007e0001}, {0xc78, 0x007f0001}, + {0xc78, 0x3800001e}, {0xc78, 0x3801001e}, + {0xc78, 0x3802001e}, {0xc78, 0x3803001e}, + {0xc78, 0x3804001e}, {0xc78, 0x3805001e}, + {0xc78, 0x3806001e}, {0xc78, 0x3807001e}, + {0xc78, 0x3808001e}, {0xc78, 0x3c09001e}, + {0xc78, 0x3e0a001e}, {0xc78, 0x400b001e}, + {0xc78, 0x440c001e}, {0xc78, 0x480d001e}, + {0xc78, 0x4c0e001e}, {0xc78, 0x500f001e}, + {0xc78, 0x5210001e}, {0xc78, 0x5611001e}, + {0xc78, 0x5a12001e}, {0xc78, 0x5e13001e}, + {0xc78, 0x6014001e}, {0xc78, 0x6015001e}, + {0xc78, 0x6016001e}, {0xc78, 0x6217001e}, + {0xc78, 0x6218001e}, {0xc78, 0x6219001e}, + {0xc78, 0x621a001e}, {0xc78, 0x621b001e}, + {0xc78, 0x621c001e}, {0xc78, 0x621d001e}, + {0xc78, 0x621e001e}, {0xc78, 0x621f001e}, + {0xffff, 0xffffffff} +}; + +static struct rtl8xxxu_reg32val rtl8xxx_agc_highpa_table[] = { + {0xc78, 0x7b000001}, {0xc78, 0x7b010001}, + {0xc78, 0x7b020001}, {0xc78, 0x7b030001}, + {0xc78, 0x7b040001}, {0xc78, 0x7b050001}, + {0xc78, 0x7b060001}, {0xc78, 0x7b070001}, + {0xc78, 0x7b080001}, {0xc78, 0x7a090001}, + {0xc78, 0x790a0001}, {0xc78, 0x780b0001}, + {0xc78, 0x770c0001}, {0xc78, 0x760d0001}, + {0xc78, 0x750e0001}, {0xc78, 0x740f0001}, + {0xc78, 0x73100001}, {0xc78, 0x72110001}, + {0xc78, 0x71120001}, {0xc78, 0x70130001}, + {0xc78, 0x6f140001}, {0xc78, 0x6e150001}, + {0xc78, 0x6d160001}, {0xc78, 0x6c170001}, + {0xc78, 0x6b180001}, {0xc78, 0x6a190001}, + {0xc78, 0x691a0001}, {0xc78, 0x681b0001}, + {0xc78, 0x671c0001}, {0xc78, 0x661d0001}, + {0xc78, 0x651e0001}, {0xc78, 0x641f0001}, + {0xc78, 0x63200001}, {0xc78, 0x62210001}, + {0xc78, 0x61220001}, {0xc78, 0x60230001}, + {0xc78, 0x46240001}, {0xc78, 0x45250001}, + {0xc78, 0x44260001}, {0xc78, 0x43270001}, + {0xc78, 0x42280001}, {0xc78, 0x41290001}, + {0xc78, 0x402a0001}, {0xc78, 0x262b0001}, + {0xc78, 0x252c0001}, {0xc78, 0x242d0001}, + {0xc78, 0x232e0001}, {0xc78, 0x222f0001}, + {0xc78, 0x21300001}, {0xc78, 0x20310001}, + {0xc78, 0x06320001}, {0xc78, 0x05330001}, + {0xc78, 0x04340001}, {0xc78, 0x03350001}, + {0xc78, 0x02360001}, {0xc78, 0x01370001}, + {0xc78, 0x00380001}, {0xc78, 0x00390001}, + {0xc78, 0x003a0001}, {0xc78, 0x003b0001}, + {0xc78, 0x003c0001}, {0xc78, 0x003d0001}, + {0xc78, 0x003e0001}, {0xc78, 0x003f0001}, + {0xc78, 0x7b400001}, {0xc78, 0x7b410001}, + {0xc78, 0x7b420001}, {0xc78, 0x7b430001}, + {0xc78, 0x7b440001}, {0xc78, 0x7b450001}, + {0xc78, 0x7b460001}, {0xc78, 0x7b470001}, + {0xc78, 0x7b480001}, {0xc78, 0x7a490001}, + {0xc78, 0x794a0001}, {0xc78, 0x784b0001}, + {0xc78, 0x774c0001}, {0xc78, 0x764d0001}, + {0xc78, 0x754e0001}, {0xc78, 0x744f0001}, + {0xc78, 0x73500001}, {0xc78, 0x72510001}, + {0xc78, 0x71520001}, {0xc78, 0x70530001}, + {0xc78, 0x6f540001}, {0xc78, 0x6e550001}, + {0xc78, 0x6d560001}, {0xc78, 0x6c570001}, + {0xc78, 0x6b580001}, {0xc78, 0x6a590001}, + {0xc78, 0x695a0001}, {0xc78, 0x685b0001}, + {0xc78, 0x675c0001}, {0xc78, 0x665d0001}, + {0xc78, 0x655e0001}, {0xc78, 0x645f0001}, + {0xc78, 0x63600001}, {0xc78, 0x62610001}, + {0xc78, 0x61620001}, {0xc78, 0x60630001}, + {0xc78, 0x46640001}, {0xc78, 0x45650001}, + {0xc78, 0x44660001}, {0xc78, 0x43670001}, + {0xc78, 0x42680001}, {0xc78, 0x41690001}, + {0xc78, 0x406a0001}, {0xc78, 0x266b0001}, + {0xc78, 0x256c0001}, {0xc78, 0x246d0001}, + {0xc78, 0x236e0001}, {0xc78, 0x226f0001}, + {0xc78, 0x21700001}, {0xc78, 0x20710001}, + {0xc78, 0x06720001}, {0xc78, 0x05730001}, + {0xc78, 0x04740001}, {0xc78, 0x03750001}, + {0xc78, 0x02760001}, {0xc78, 0x01770001}, + {0xc78, 0x00780001}, {0xc78, 0x00790001}, + {0xc78, 0x007a0001}, {0xc78, 0x007b0001}, + {0xc78, 0x007c0001}, {0xc78, 0x007d0001}, + {0xc78, 0x007e0001}, {0xc78, 0x007f0001}, + {0xc78, 0x3800001e}, {0xc78, 0x3801001e}, + {0xc78, 0x3802001e}, {0xc78, 0x3803001e}, + {0xc78, 0x3804001e}, {0xc78, 0x3805001e}, + {0xc78, 0x3806001e}, {0xc78, 0x3807001e}, + {0xc78, 0x3808001e}, {0xc78, 0x3c09001e}, + {0xc78, 0x3e0a001e}, {0xc78, 0x400b001e}, + {0xc78, 0x440c001e}, {0xc78, 0x480d001e}, + {0xc78, 0x4c0e001e}, {0xc78, 0x500f001e}, + {0xc78, 0x5210001e}, {0xc78, 0x5611001e}, + {0xc78, 0x5a12001e}, {0xc78, 0x5e13001e}, + {0xc78, 0x6014001e}, {0xc78, 0x6015001e}, + {0xc78, 0x6016001e}, {0xc78, 0x6217001e}, + {0xc78, 0x6218001e}, {0xc78, 0x6219001e}, + {0xc78, 0x621a001e}, {0xc78, 0x621b001e}, + {0xc78, 0x621c001e}, {0xc78, 0x621d001e}, + {0xc78, 0x621e001e}, {0xc78, 0x621f001e}, + {0xffff, 0xffffffff} +}; + +static struct rtl8xxxu_rfregval rtl8723au_radioa_1t_init_table[] = { + {0x00, 0x00030159}, {0x01, 0x00031284}, + {0x02, 0x00098000}, {0x03, 0x00039c63}, + {0x04, 0x000210e7}, {0x09, 0x0002044f}, + {0x0a, 0x0001a3f1}, {0x0b, 0x00014787}, + {0x0c, 0x000896fe}, {0x0d, 0x0000e02c}, + {0x0e, 0x00039ce7}, {0x0f, 0x00000451}, + {0x19, 0x00000000}, {0x1a, 0x00030355}, + {0x1b, 0x00060a00}, {0x1c, 0x000fc378}, + {0x1d, 0x000a1250}, {0x1e, 0x0000024f}, + {0x1f, 0x00000000}, {0x20, 0x0000b614}, + {0x21, 0x0006c000}, {0x22, 0x00000000}, + {0x23, 0x00001558}, {0x24, 0x00000060}, + {0x25, 0x00000483}, {0x26, 0x0004f000}, + {0x27, 0x000ec7d9}, {0x28, 0x00057730}, + {0x29, 0x00004783}, {0x2a, 0x00000001}, + {0x2b, 0x00021334}, {0x2a, 0x00000000}, + {0x2b, 0x00000054}, {0x2a, 0x00000001}, + {0x2b, 0x00000808}, {0x2b, 0x00053333}, + {0x2c, 0x0000000c}, {0x2a, 0x00000002}, + {0x2b, 0x00000808}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000003}, + {0x2b, 0x00000808}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000004}, + {0x2b, 0x00000808}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000005}, + {0x2b, 0x00000808}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000006}, + {0x2b, 0x00000709}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000007}, + {0x2b, 0x00000709}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000008}, + {0x2b, 0x0000060a}, {0x2b, 0x0004b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000009}, + {0x2b, 0x0000060a}, {0x2b, 0x00053333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000a}, + {0x2b, 0x0000060a}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000b}, + {0x2b, 0x0000060a}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000c}, + {0x2b, 0x0000060a}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000d}, + {0x2b, 0x0000060a}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000e}, + {0x2b, 0x0000050b}, {0x2b, 0x00066666}, + {0x2c, 0x0000001a}, {0x2a, 0x000e0000}, + {0x10, 0x0004000f}, {0x11, 0x000e31fc}, + {0x10, 0x0006000f}, {0x11, 0x000ff9f8}, + {0x10, 0x0002000f}, {0x11, 0x000203f9}, + {0x10, 0x0003000f}, {0x11, 0x000ff500}, + {0x10, 0x00000000}, {0x11, 0x00000000}, + {0x10, 0x0008000f}, {0x11, 0x0003f100}, + {0x10, 0x0009000f}, {0x11, 0x00023100}, + {0x12, 0x00032000}, {0x12, 0x00071000}, + {0x12, 0x000b0000}, {0x12, 0x000fc000}, + {0x13, 0x000287b3}, {0x13, 0x000244b7}, + {0x13, 0x000204ab}, {0x13, 0x0001c49f}, + {0x13, 0x00018493}, {0x13, 0x0001429b}, + {0x13, 0x00010299}, {0x13, 0x0000c29c}, + {0x13, 0x000081a0}, {0x13, 0x000040ac}, + {0x13, 0x00000020}, {0x14, 0x0001944c}, + {0x14, 0x00059444}, {0x14, 0x0009944c}, + {0x14, 0x000d9444}, {0x15, 0x0000f474}, + {0x15, 0x0004f477}, {0x15, 0x0008f455}, + {0x15, 0x000cf455}, {0x16, 0x00000339}, + {0x16, 0x00040339}, {0x16, 0x00080339}, + {0x16, 0x000c0366}, {0x00, 0x00010159}, + {0x18, 0x0000f401}, {0xfe, 0x00000000}, + {0xfe, 0x00000000}, {0x1f, 0x00000003}, + {0xfe, 0x00000000}, {0xfe, 0x00000000}, + {0x1e, 0x00000247}, {0x1f, 0x00000000}, + {0x00, 0x00030159}, + {0xff, 0xffffffff} +}; + +static struct rtl8xxxu_rfregval rtl8192cu_radioa_2t_init_table[] = { + {0x00, 0x00030159}, {0x01, 0x00031284}, + {0x02, 0x00098000}, {0x03, 0x00018c63}, + {0x04, 0x000210e7}, {0x09, 0x0002044f}, + {0x0a, 0x0001adb1}, {0x0b, 0x00054867}, + {0x0c, 0x0008992e}, {0x0d, 0x0000e52c}, + {0x0e, 0x00039ce7}, {0x0f, 0x00000451}, + {0x19, 0x00000000}, {0x1a, 0x00010255}, + {0x1b, 0x00060a00}, {0x1c, 0x000fc378}, + {0x1d, 0x000a1250}, {0x1e, 0x0004445f}, + {0x1f, 0x00080001}, {0x20, 0x0000b614}, + {0x21, 0x0006c000}, {0x22, 0x00000000}, + {0x23, 0x00001558}, {0x24, 0x00000060}, + {0x25, 0x00000483}, {0x26, 0x0004f000}, + {0x27, 0x000ec7d9}, {0x28, 0x000577c0}, + {0x29, 0x00004783}, {0x2a, 0x00000001}, + {0x2b, 0x00021334}, {0x2a, 0x00000000}, + {0x2b, 0x00000054}, {0x2a, 0x00000001}, + {0x2b, 0x00000808}, {0x2b, 0x00053333}, + {0x2c, 0x0000000c}, {0x2a, 0x00000002}, + {0x2b, 0x00000808}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000003}, + {0x2b, 0x00000808}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000004}, + {0x2b, 0x00000808}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000005}, + {0x2b, 0x00000808}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000006}, + {0x2b, 0x00000709}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000007}, + {0x2b, 0x00000709}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000008}, + {0x2b, 0x0000060a}, {0x2b, 0x0004b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000009}, + {0x2b, 0x0000060a}, {0x2b, 0x00053333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000a}, + {0x2b, 0x0000060a}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000b}, + {0x2b, 0x0000060a}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000c}, + {0x2b, 0x0000060a}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000d}, + {0x2b, 0x0000060a}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000e}, + {0x2b, 0x0000050b}, {0x2b, 0x00066666}, + {0x2c, 0x0000001a}, {0x2a, 0x000e0000}, + {0x10, 0x0004000f}, {0x11, 0x000e31fc}, + {0x10, 0x0006000f}, {0x11, 0x000ff9f8}, + {0x10, 0x0002000f}, {0x11, 0x000203f9}, + {0x10, 0x0003000f}, {0x11, 0x000ff500}, + {0x10, 0x00000000}, {0x11, 0x00000000}, + {0x10, 0x0008000f}, {0x11, 0x0003f100}, + {0x10, 0x0009000f}, {0x11, 0x00023100}, + {0x12, 0x00032000}, {0x12, 0x00071000}, + {0x12, 0x000b0000}, {0x12, 0x000fc000}, + {0x13, 0x000287b3}, {0x13, 0x000244b7}, + {0x13, 0x000204ab}, {0x13, 0x0001c49f}, + {0x13, 0x00018493}, {0x13, 0x0001429b}, + {0x13, 0x00010299}, {0x13, 0x0000c29c}, + {0x13, 0x000081a0}, {0x13, 0x000040ac}, + {0x13, 0x00000020}, {0x14, 0x0001944c}, + {0x14, 0x00059444}, {0x14, 0x0009944c}, + {0x14, 0x000d9444}, {0x15, 0x0000f424}, + {0x15, 0x0004f424}, {0x15, 0x0008f424}, + {0x15, 0x000cf424}, {0x16, 0x000e0330}, + {0x16, 0x000a0330}, {0x16, 0x00060330}, + {0x16, 0x00020330}, {0x00, 0x00010159}, + {0x18, 0x0000f401}, {0xfe, 0x00000000}, + {0xfe, 0x00000000}, {0x1f, 0x00080003}, + {0xfe, 0x00000000}, {0xfe, 0x00000000}, + {0x1e, 0x00044457}, {0x1f, 0x00080000}, + {0x00, 0x00030159}, + {0xff, 0xffffffff} +}; + +static struct rtl8xxxu_rfregval rtl8192cu_radiob_2t_init_table[] = { + {0x00, 0x00030159}, {0x01, 0x00031284}, + {0x02, 0x00098000}, {0x03, 0x00018c63}, + {0x04, 0x000210e7}, {0x09, 0x0002044f}, + {0x0a, 0x0001adb1}, {0x0b, 0x00054867}, + {0x0c, 0x0008992e}, {0x0d, 0x0000e52c}, + {0x0e, 0x00039ce7}, {0x0f, 0x00000451}, + {0x12, 0x00032000}, {0x12, 0x00071000}, + {0x12, 0x000b0000}, {0x12, 0x000fc000}, + {0x13, 0x000287af}, {0x13, 0x000244b7}, + {0x13, 0x000204ab}, {0x13, 0x0001c49f}, + {0x13, 0x00018493}, {0x13, 0x00014297}, + {0x13, 0x00010295}, {0x13, 0x0000c298}, + {0x13, 0x0000819c}, {0x13, 0x000040a8}, + {0x13, 0x0000001c}, {0x14, 0x0001944c}, + {0x14, 0x00059444}, {0x14, 0x0009944c}, + {0x14, 0x000d9444}, {0x15, 0x0000f424}, + {0x15, 0x0004f424}, {0x15, 0x0008f424}, + {0x15, 0x000cf424}, {0x16, 0x000e0330}, + {0x16, 0x000a0330}, {0x16, 0x00060330}, + {0x16, 0x00020330}, + {0xff, 0xffffffff} +}; + +static struct rtl8xxxu_rfregval rtl8192cu_radioa_1t_init_table[] = { + {0x00, 0x00030159}, {0x01, 0x00031284}, + {0x02, 0x00098000}, {0x03, 0x00018c63}, + {0x04, 0x000210e7}, {0x09, 0x0002044f}, + {0x0a, 0x0001adb1}, {0x0b, 0x00054867}, + {0x0c, 0x0008992e}, {0x0d, 0x0000e52c}, + {0x0e, 0x00039ce7}, {0x0f, 0x00000451}, + {0x19, 0x00000000}, {0x1a, 0x00010255}, + {0x1b, 0x00060a00}, {0x1c, 0x000fc378}, + {0x1d, 0x000a1250}, {0x1e, 0x0004445f}, + {0x1f, 0x00080001}, {0x20, 0x0000b614}, + {0x21, 0x0006c000}, {0x22, 0x00000000}, + {0x23, 0x00001558}, {0x24, 0x00000060}, + {0x25, 0x00000483}, {0x26, 0x0004f000}, + {0x27, 0x000ec7d9}, {0x28, 0x000577c0}, + {0x29, 0x00004783}, {0x2a, 0x00000001}, + {0x2b, 0x00021334}, {0x2a, 0x00000000}, + {0x2b, 0x00000054}, {0x2a, 0x00000001}, + {0x2b, 0x00000808}, {0x2b, 0x00053333}, + {0x2c, 0x0000000c}, {0x2a, 0x00000002}, + {0x2b, 0x00000808}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000003}, + {0x2b, 0x00000808}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000004}, + {0x2b, 0x00000808}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000005}, + {0x2b, 0x00000808}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000006}, + {0x2b, 0x00000709}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000007}, + {0x2b, 0x00000709}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000008}, + {0x2b, 0x0000060a}, {0x2b, 0x0004b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000009}, + {0x2b, 0x0000060a}, {0x2b, 0x00053333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000a}, + {0x2b, 0x0000060a}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000b}, + {0x2b, 0x0000060a}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000c}, + {0x2b, 0x0000060a}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000d}, + {0x2b, 0x0000060a}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000e}, + {0x2b, 0x0000050b}, {0x2b, 0x00066666}, + {0x2c, 0x0000001a}, {0x2a, 0x000e0000}, + {0x10, 0x0004000f}, {0x11, 0x000e31fc}, + {0x10, 0x0006000f}, {0x11, 0x000ff9f8}, + {0x10, 0x0002000f}, {0x11, 0x000203f9}, + {0x10, 0x0003000f}, {0x11, 0x000ff500}, + {0x10, 0x00000000}, {0x11, 0x00000000}, + {0x10, 0x0008000f}, {0x11, 0x0003f100}, + {0x10, 0x0009000f}, {0x11, 0x00023100}, + {0x12, 0x00032000}, {0x12, 0x00071000}, + {0x12, 0x000b0000}, {0x12, 0x000fc000}, + {0x13, 0x000287b3}, {0x13, 0x000244b7}, + {0x13, 0x000204ab}, {0x13, 0x0001c49f}, + {0x13, 0x00018493}, {0x13, 0x0001429b}, + {0x13, 0x00010299}, {0x13, 0x0000c29c}, + {0x13, 0x000081a0}, {0x13, 0x000040ac}, + {0x13, 0x00000020}, {0x14, 0x0001944c}, + {0x14, 0x00059444}, {0x14, 0x0009944c}, + {0x14, 0x000d9444}, {0x15, 0x0000f405}, + {0x15, 0x0004f405}, {0x15, 0x0008f405}, + {0x15, 0x000cf405}, {0x16, 0x000e0330}, + {0x16, 0x000a0330}, {0x16, 0x00060330}, + {0x16, 0x00020330}, {0x00, 0x00010159}, + {0x18, 0x0000f401}, {0xfe, 0x00000000}, + {0xfe, 0x00000000}, {0x1f, 0x00080003}, + {0xfe, 0x00000000}, {0xfe, 0x00000000}, + {0x1e, 0x00044457}, {0x1f, 0x00080000}, + {0x00, 0x00030159}, + {0xff, 0xffffffff} +}; + +static struct rtl8xxxu_rfregval rtl8188ru_radioa_1t_highpa_table[] = { + {0x00, 0x00030159}, {0x01, 0x00031284}, + {0x02, 0x00098000}, {0x03, 0x00018c63}, + {0x04, 0x000210e7}, {0x09, 0x0002044f}, + {0x0a, 0x0001adb0}, {0x0b, 0x00054867}, + {0x0c, 0x0008992e}, {0x0d, 0x0000e529}, + {0x0e, 0x00039ce7}, {0x0f, 0x00000451}, + {0x19, 0x00000000}, {0x1a, 0x00000255}, + {0x1b, 0x00060a00}, {0x1c, 0x000fc378}, + {0x1d, 0x000a1250}, {0x1e, 0x0004445f}, + {0x1f, 0x00080001}, {0x20, 0x0000b614}, + {0x21, 0x0006c000}, {0x22, 0x0000083c}, + {0x23, 0x00001558}, {0x24, 0x00000060}, + {0x25, 0x00000483}, {0x26, 0x0004f000}, + {0x27, 0x000ec7d9}, {0x28, 0x000977c0}, + {0x29, 0x00004783}, {0x2a, 0x00000001}, + {0x2b, 0x00021334}, {0x2a, 0x00000000}, + {0x2b, 0x00000054}, {0x2a, 0x00000001}, + {0x2b, 0x00000808}, {0x2b, 0x00053333}, + {0x2c, 0x0000000c}, {0x2a, 0x00000002}, + {0x2b, 0x00000808}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000003}, + {0x2b, 0x00000808}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000004}, + {0x2b, 0x00000808}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000005}, + {0x2b, 0x00000808}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000006}, + {0x2b, 0x00000709}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000007}, + {0x2b, 0x00000709}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000008}, + {0x2b, 0x0000060a}, {0x2b, 0x0004b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000009}, + {0x2b, 0x0000060a}, {0x2b, 0x00053333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000a}, + {0x2b, 0x0000060a}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000b}, + {0x2b, 0x0000060a}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000c}, + {0x2b, 0x0000060a}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000d}, + {0x2b, 0x0000060a}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000e}, + {0x2b, 0x0000050b}, {0x2b, 0x00066666}, + {0x2c, 0x0000001a}, {0x2a, 0x000e0000}, + {0x10, 0x0004000f}, {0x11, 0x000e31fc}, + {0x10, 0x0006000f}, {0x11, 0x000ff9f8}, + {0x10, 0x0002000f}, {0x11, 0x000203f9}, + {0x10, 0x0003000f}, {0x11, 0x000ff500}, + {0x10, 0x00000000}, {0x11, 0x00000000}, + {0x10, 0x0008000f}, {0x11, 0x0003f100}, + {0x10, 0x0009000f}, {0x11, 0x00023100}, + {0x12, 0x000d8000}, {0x12, 0x00090000}, + {0x12, 0x00051000}, {0x12, 0x00012000}, + {0x13, 0x00028fb4}, {0x13, 0x00024fa8}, + {0x13, 0x000207a4}, {0x13, 0x0001c3b0}, + {0x13, 0x000183a4}, {0x13, 0x00014398}, + {0x13, 0x000101a4}, {0x13, 0x0000c198}, + {0x13, 0x000080a4}, {0x13, 0x00004098}, + {0x13, 0x00000000}, {0x14, 0x0001944c}, + {0x14, 0x00059444}, {0x14, 0x0009944c}, + {0x14, 0x000d9444}, {0x15, 0x0000f405}, + {0x15, 0x0004f405}, {0x15, 0x0008f405}, + {0x15, 0x000cf405}, {0x16, 0x000e0330}, + {0x16, 0x000a0330}, {0x16, 0x00060330}, + {0x16, 0x00020330}, {0x00, 0x00010159}, + {0x18, 0x0000f401}, {0xfe, 0x00000000}, + {0xfe, 0x00000000}, {0x1f, 0x00080003}, + {0xfe, 0x00000000}, {0xfe, 0x00000000}, + {0x1e, 0x00044457}, {0x1f, 0x00080000}, + {0x00, 0x00030159}, + {0xff, 0xffffffff} +}; + +static struct rtl8xxxu_rfregs rtl8xxxu_rfregs[] = { + { /* RF_A */ + .hssiparm1 = REG_FPGA0_XA_HSSI_PARM1, + .hssiparm2 = REG_FPGA0_XA_HSSI_PARM2, + .lssiparm = REG_FPGA0_XA_LSSI_PARM, + .hspiread = REG_HSPI_XA_READBACK, + .lssiread = REG_FPGA0_XA_LSSI_READBACK, + .rf_sw_ctrl = REG_FPGA0_XA_RF_SW_CTRL, + }, + { /* RF_B */ + .hssiparm1 = REG_FPGA0_XB_HSSI_PARM1, + .hssiparm2 = REG_FPGA0_XB_HSSI_PARM2, + .lssiparm = REG_FPGA0_XB_LSSI_PARM, + .hspiread = REG_HSPI_XB_READBACK, + .lssiread = REG_FPGA0_XB_LSSI_READBACK, + .rf_sw_ctrl = REG_FPGA0_XB_RF_SW_CTRL, + }, +}; + +static const u32 rtl8723au_iqk_phy_iq_bb_reg[RTL8XXXU_BB_REGS] = { + REG_OFDM0_XA_RX_IQ_IMBALANCE, + REG_OFDM0_XB_RX_IQ_IMBALANCE, + REG_OFDM0_ENERGY_CCA_THRES, + REG_OFDM0_AGCR_SSI_TABLE, + REG_OFDM0_XA_TX_IQ_IMBALANCE, + REG_OFDM0_XB_TX_IQ_IMBALANCE, + REG_OFDM0_XC_TX_AFE, + REG_OFDM0_XD_TX_AFE, + REG_OFDM0_RX_IQ_EXT_ANTA +}; + +static u8 rtl8xxxu_read8(struct rtl8xxxu_priv *priv, u16 addr) +{ + struct usb_device *udev = priv->udev; + int len; + u8 data; + + mutex_lock(&priv->usb_buf_mutex); + len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_READ, + addr, 0, &priv->usb_buf.val8, sizeof(u8), + RTW_USB_CONTROL_MSG_TIMEOUT); + data = priv->usb_buf.val8; + mutex_unlock(&priv->usb_buf_mutex); + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_READ) + dev_info(&udev->dev, "%s(%04x) = 0x%02x, len %i\n", + __func__, addr, data, len); + return data; +} + +static u16 rtl8xxxu_read16(struct rtl8xxxu_priv *priv, u16 addr) +{ + struct usb_device *udev = priv->udev; + int len; + u16 data; + + mutex_lock(&priv->usb_buf_mutex); + len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_READ, + addr, 0, &priv->usb_buf.val16, sizeof(u16), + RTW_USB_CONTROL_MSG_TIMEOUT); + data = le16_to_cpu(priv->usb_buf.val16); + mutex_unlock(&priv->usb_buf_mutex); + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_READ) + dev_info(&udev->dev, "%s(%04x) = 0x%04x, len %i\n", + __func__, addr, data, len); + return data; +} + +static u32 rtl8xxxu_read32(struct rtl8xxxu_priv *priv, u16 addr) +{ + struct usb_device *udev = priv->udev; + int len; + u32 data; + + mutex_lock(&priv->usb_buf_mutex); + len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_READ, + addr, 0, &priv->usb_buf.val32, sizeof(u32), + RTW_USB_CONTROL_MSG_TIMEOUT); + data = le32_to_cpu(priv->usb_buf.val32); + mutex_unlock(&priv->usb_buf_mutex); + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_READ) + dev_info(&udev->dev, "%s(%04x) = 0x%08x, len %i\n", + __func__, addr, data, len); + return data; +} + +static int rtl8xxxu_write8(struct rtl8xxxu_priv *priv, u16 addr, u8 val) +{ + struct usb_device *udev = priv->udev; + int ret; + + mutex_lock(&priv->usb_buf_mutex); + priv->usb_buf.val8 = val; + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE, + addr, 0, &priv->usb_buf.val8, sizeof(u8), + RTW_USB_CONTROL_MSG_TIMEOUT); + + mutex_unlock(&priv->usb_buf_mutex); + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_WRITE) + dev_info(&udev->dev, "%s(%04x) = 0x%02x\n", + __func__, addr, val); + return ret; +} + +static int rtl8xxxu_write16(struct rtl8xxxu_priv *priv, u16 addr, u16 val) +{ + struct usb_device *udev = priv->udev; + int ret; + + mutex_lock(&priv->usb_buf_mutex); + priv->usb_buf.val16 = cpu_to_le16(val); + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE, + addr, 0, &priv->usb_buf.val16, sizeof(u16), + RTW_USB_CONTROL_MSG_TIMEOUT); + mutex_unlock(&priv->usb_buf_mutex); + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_WRITE) + dev_info(&udev->dev, "%s(%04x) = 0x%04x\n", + __func__, addr, val); + return ret; +} + +static int rtl8xxxu_write32(struct rtl8xxxu_priv *priv, u16 addr, u32 val) +{ + struct usb_device *udev = priv->udev; + int ret; + + mutex_lock(&priv->usb_buf_mutex); + priv->usb_buf.val32 = cpu_to_le32(val); + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE, + addr, 0, &priv->usb_buf.val32, sizeof(u32), + RTW_USB_CONTROL_MSG_TIMEOUT); + mutex_unlock(&priv->usb_buf_mutex); + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_WRITE) + dev_info(&udev->dev, "%s(%04x) = 0x%08x\n", + __func__, addr, val); + return ret; +} + +static int +rtl8xxxu_writeN(struct rtl8xxxu_priv *priv, u16 addr, u8 *buf, u16 len) +{ + struct usb_device *udev = priv->udev; + int blocksize = priv->fops->writeN_block_size; + int ret, i, count, remainder; + + count = len / blocksize; + remainder = len % blocksize; + + for (i = 0; i < count; i++) { + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE, + addr, 0, buf, blocksize, + RTW_USB_CONTROL_MSG_TIMEOUT); + if (ret != blocksize) + goto write_error; + + addr += blocksize; + buf += blocksize; + } + + if (remainder) { + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE, + addr, 0, buf, remainder, + RTW_USB_CONTROL_MSG_TIMEOUT); + if (ret != remainder) + goto write_error; + } + + return len; + +write_error: + dev_info(&udev->dev, + "%s: Failed to write block at addr: %04x size: %04x\n", + __func__, addr, blocksize); + return -EAGAIN; +} + +static u32 rtl8xxxu_read_rfreg(struct rtl8xxxu_priv *priv, + enum rtl8xxxu_rfpath path, u8 reg) +{ + u32 hssia, val32, retval; + + hssia = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM2); + if (path != RF_A) + val32 = rtl8xxxu_read32(priv, rtl8xxxu_rfregs[path].hssiparm2); + else + val32 = hssia; + + val32 &= ~FPGA0_HSSI_PARM2_ADDR_MASK; + val32 |= (reg << FPGA0_HSSI_PARM2_ADDR_SHIFT); + val32 |= FPGA0_HSSI_PARM2_EDGE_READ; + hssia &= ~FPGA0_HSSI_PARM2_EDGE_READ; + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM2, hssia); + + udelay(10); + + rtl8xxxu_write32(priv, rtl8xxxu_rfregs[path].hssiparm2, val32); + udelay(100); + + hssia |= FPGA0_HSSI_PARM2_EDGE_READ; + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM2, hssia); + udelay(10); + + val32 = rtl8xxxu_read32(priv, rtl8xxxu_rfregs[path].hssiparm1); + if (val32 & FPGA0_HSSI_PARM1_PI) + retval = rtl8xxxu_read32(priv, rtl8xxxu_rfregs[path].hspiread); + else + retval = rtl8xxxu_read32(priv, rtl8xxxu_rfregs[path].lssiread); + + retval &= 0xfffff; + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_RFREG_READ) + dev_info(&priv->udev->dev, "%s(%02x) = 0x%06x\n", + __func__, reg, retval); + return retval; +} + +static int rtl8xxxu_write_rfreg(struct rtl8xxxu_priv *priv, + enum rtl8xxxu_rfpath path, u8 reg, u32 data) +{ + int ret, retval; + u32 dataaddr; + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_RFREG_WRITE) + dev_info(&priv->udev->dev, "%s(%02x) = 0x%06x\n", + __func__, reg, data); + + data &= FPGA0_LSSI_PARM_DATA_MASK; + dataaddr = (reg << FPGA0_LSSI_PARM_ADDR_SHIFT) | data; + + /* Use XB for path B */ + ret = rtl8xxxu_write32(priv, rtl8xxxu_rfregs[path].lssiparm, dataaddr); + if (ret != sizeof(dataaddr)) + retval = -EIO; + else + retval = 0; + + udelay(1); + + return retval; +} + +static int rtl8723a_h2c_cmd(struct rtl8xxxu_priv *priv, struct h2c_cmd *h2c) +{ + struct device *dev = &priv->udev->dev; + int mbox_nr, retry, retval = 0; + int mbox_reg, mbox_ext_reg; + u8 val8; + + mutex_lock(&priv->h2c_mutex); + + mbox_nr = priv->next_mbox; + mbox_reg = REG_HMBOX_0 + (mbox_nr * 4); + mbox_ext_reg = REG_HMBOX_EXT_0 + (mbox_nr * 2); + + /* + * MBOX ready? + */ + retry = 100; + do { + val8 = rtl8xxxu_read8(priv, REG_HMTFR); + if (!(val8 & BIT(mbox_nr))) + break; + } while (retry--); + + if (!retry) { + dev_dbg(dev, "%s: Mailbox busy\n", __func__); + retval = -EBUSY; + goto error; + } + + /* + * Need to swap as it's being swapped again by rtl8xxxu_write16/32() + */ + if (h2c->cmd.cmd & H2C_EXT) { + rtl8xxxu_write16(priv, mbox_ext_reg, + le16_to_cpu(h2c->raw.ext)); + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_H2C) + dev_info(dev, "H2C_EXT %04x\n", + le16_to_cpu(h2c->raw.ext)); + } + rtl8xxxu_write32(priv, mbox_reg, le32_to_cpu(h2c->raw.data)); + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_H2C) + dev_info(dev, "H2C %08x\n", le32_to_cpu(h2c->raw.data)); + + priv->next_mbox = (mbox_nr + 1) % H2C_MAX_MBOX; + +error: + mutex_unlock(&priv->h2c_mutex); + return retval; +} + +static void rtl8723a_enable_rf(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u32 val32; + + val8 = rtl8xxxu_read8(priv, REG_SPS0_CTRL); + val8 |= BIT(0) | BIT(3); + rtl8xxxu_write8(priv, REG_SPS0_CTRL, val8); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_PARM); + val32 &= ~(BIT(4) | BIT(5)); + val32 |= BIT(3); + if (priv->rf_paths == 2) { + val32 &= ~(BIT(20) | BIT(21)); + val32 |= BIT(19); + } + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_PARM, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); + val32 &= ~OFDM_RF_PATH_TX_MASK; + if (priv->tx_paths == 2) + val32 |= OFDM_RF_PATH_TX_A | OFDM_RF_PATH_TX_B; + else if (priv->rtlchip == 0x8192c || priv->rtlchip == 0x8191c) + val32 |= OFDM_RF_PATH_TX_B; + else + val32 |= OFDM_RF_PATH_TX_A; + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + val32 &= ~FPGA_RF_MODE_JAPAN; + rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); + + if (priv->rf_paths == 2) + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x63db25a0); + else + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x631b25a0); + + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0x32d95); + if (priv->rf_paths == 2) + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, 0x32d95); + + rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00); +} + +static void rtl8723a_disable_rf(struct rtl8xxxu_priv *priv) +{ + u8 sps0; + u32 val32; + + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); + + sps0 = rtl8xxxu_read8(priv, REG_SPS0_CTRL); + + /* RF RX code for preamble power saving */ + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_PARM); + val32 &= ~(BIT(3) | BIT(4) | BIT(5)); + if (priv->rf_paths == 2) + val32 &= ~(BIT(19) | BIT(20) | BIT(21)); + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_PARM, val32); + + /* Disable TX for four paths */ + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); + val32 &= ~OFDM_RF_PATH_TX_MASK; + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32); + + /* Enable power saving */ + val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + val32 |= FPGA_RF_MODE_JAPAN; + rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); + + /* AFE control register to power down bits [30:22] */ + if (priv->rf_paths == 2) + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00db25a0); + else + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x001b25a0); + + /* Power down RF module */ + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0); + if (priv->rf_paths == 2) + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, 0); + + sps0 &= ~(BIT(0) | BIT(3)); + rtl8xxxu_write8(priv, REG_SPS0_CTRL, sps0); +} + + +static void rtl8723a_stop_tx_beacon(struct rtl8xxxu_priv *priv) +{ + u8 val8; + + val8 = rtl8xxxu_read8(priv, REG_FWHW_TXQ_CTRL + 2); + val8 &= ~BIT(6); + rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL + 2, val8); + + rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 1, 0x64); + val8 = rtl8xxxu_read8(priv, REG_TBTT_PROHIBIT + 2); + val8 &= ~BIT(0); + rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 2, val8); +} + + +/* + * The rtl8723a has 3 channel groups for it's efuse settings. It only + * supports the 2.4GHz band, so channels 1 - 14: + * group 0: channels 1 - 3 + * group 1: channels 4 - 9 + * group 2: channels 10 - 14 + * + * Note: We index from 0 in the code + */ +static int rtl8723a_channel_to_group(int channel) +{ + int group; + + if (channel < 4) + group = 0; + else if (channel < 10) + group = 1; + else + group = 2; + + return group; +} + +static void rtl8723au_config_channel(struct ieee80211_hw *hw) +{ + struct rtl8xxxu_priv *priv = hw->priv; + u32 val32, rsr; + u8 val8, opmode; + bool ht = true; + int sec_ch_above, channel; + int i; + + opmode = rtl8xxxu_read8(priv, REG_BW_OPMODE); + rsr = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET); + channel = hw->conf.chandef.chan->hw_value; + + switch (hw->conf.chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + ht = false; + case NL80211_CHAN_WIDTH_20: + opmode |= BW_OPMODE_20MHZ; + rtl8xxxu_write8(priv, REG_BW_OPMODE, opmode); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + val32 &= ~FPGA_RF_MODE; + rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA1_RF_MODE); + val32 &= ~FPGA_RF_MODE; + rtl8xxxu_write32(priv, REG_FPGA1_RF_MODE, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_ANALOG2); + val32 |= FPGA0_ANALOG2_20MHZ; + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG2, val32); + break; + case NL80211_CHAN_WIDTH_40: + if (hw->conf.chandef.center_freq1 > + hw->conf.chandef.chan->center_freq) { + sec_ch_above = 1; + channel += 2; + } else { + sec_ch_above = 0; + channel -= 2; + } + + opmode &= ~BW_OPMODE_20MHZ; + rtl8xxxu_write8(priv, REG_BW_OPMODE, opmode); + rsr &= ~RSR_RSC_BANDWIDTH_40M; + if (sec_ch_above) + rsr |= RSR_RSC_UPPER_SUB_CHANNEL; + else + rsr |= RSR_RSC_LOWER_SUB_CHANNEL; + rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, rsr); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + val32 |= FPGA_RF_MODE; + rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA1_RF_MODE); + val32 |= FPGA_RF_MODE; + rtl8xxxu_write32(priv, REG_FPGA1_RF_MODE, val32); + + /* + * Set Control channel to upper or lower. These settings + * are required only for 40MHz + */ + val32 = rtl8xxxu_read32(priv, REG_CCK0_SYSTEM); + val32 &= ~CCK0_SIDEBAND; + if (!sec_ch_above) + val32 |= CCK0_SIDEBAND; + rtl8xxxu_write32(priv, REG_CCK0_SYSTEM, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM1_LSTF); + val32 &= ~OFDM_LSTF_PRIME_CH_MASK; /* 0xc00 */ + if (sec_ch_above) + val32 |= OFDM_LSTF_PRIME_CH_LOW; + else + val32 |= OFDM_LSTF_PRIME_CH_HIGH; + rtl8xxxu_write32(priv, REG_OFDM1_LSTF, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_ANALOG2); + val32 &= ~FPGA0_ANALOG2_20MHZ; + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG2, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_POWER_SAVE); + val32 &= ~(FPGA0_PS_LOWER_CHANNEL | FPGA0_PS_UPPER_CHANNEL); + if (sec_ch_above) + val32 |= FPGA0_PS_UPPER_CHANNEL; + else + val32 |= FPGA0_PS_LOWER_CHANNEL; + rtl8xxxu_write32(priv, REG_FPGA0_POWER_SAVE, val32); + break; + + default: + break; + } + + for (i = RF_A; i < priv->rf_paths; i++) { + val32 = rtl8xxxu_read_rfreg(priv, i, RF6052_REG_MODE_AG); + val32 &= ~MODE_AG_CHANNEL_MASK; + val32 |= channel; + rtl8xxxu_write_rfreg(priv, i, RF6052_REG_MODE_AG, val32); + } + + if (ht) + val8 = 0x0e; + else + val8 = 0x0a; + + rtl8xxxu_write8(priv, REG_SIFS_CCK + 1, val8); + rtl8xxxu_write8(priv, REG_SIFS_OFDM + 1, val8); + + rtl8xxxu_write16(priv, REG_R2T_SIFS, 0x0808); + rtl8xxxu_write16(priv, REG_T2T_SIFS, 0x0a0a); + + for (i = RF_A; i < priv->rf_paths; i++) { + val32 = rtl8xxxu_read_rfreg(priv, i, RF6052_REG_MODE_AG); + if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_40) + val32 &= ~MODE_AG_CHANNEL_20MHZ; + else + val32 |= MODE_AG_CHANNEL_20MHZ; + rtl8xxxu_write_rfreg(priv, i, RF6052_REG_MODE_AG, val32); + } +} + +static void +rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) +{ + u8 cck[RTL8723A_MAX_RF_PATHS], ofdm[RTL8723A_MAX_RF_PATHS]; + u8 ofdmbase[RTL8723A_MAX_RF_PATHS], mcsbase[RTL8723A_MAX_RF_PATHS]; + u32 val32, ofdm_a, ofdm_b, mcs_a, mcs_b; + u8 val8; + int group, i; + + group = rtl8723a_channel_to_group(channel); + + cck[0] = priv->cck_tx_power_index_A[group]; + cck[1] = priv->cck_tx_power_index_B[group]; + + ofdm[0] = priv->ht40_1s_tx_power_index_A[group]; + ofdm[1] = priv->ht40_1s_tx_power_index_B[group]; + + ofdmbase[0] = ofdm[0] + priv->ofdm_tx_power_index_diff[group].a; + ofdmbase[1] = ofdm[1] + priv->ofdm_tx_power_index_diff[group].b; + + mcsbase[0] = ofdm[0]; + mcsbase[1] = ofdm[1]; + if (!ht40) { + mcsbase[0] += priv->ht20_tx_power_index_diff[group].a; + mcsbase[1] += priv->ht20_tx_power_index_diff[group].b; + } + + if (priv->tx_paths > 1) { + if (ofdm[0] > priv->ht40_2s_tx_power_index_diff[group].a) + ofdm[0] -= priv->ht40_2s_tx_power_index_diff[group].a; + if (ofdm[1] > priv->ht40_2s_tx_power_index_diff[group].b) + ofdm[1] -= priv->ht40_2s_tx_power_index_diff[group].b; + } + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_CHANNEL) + dev_info(&priv->udev->dev, + "%s: Setting TX power CCK A: %02x, " + "CCK B: %02x, OFDM A: %02x, OFDM B: %02x\n", + __func__, cck[0], cck[1], ofdm[0], ofdm[1]); + + for (i = 0; i < RTL8723A_MAX_RF_PATHS; i++) { + if (cck[i] > RF6052_MAX_TX_PWR) + cck[i] = RF6052_MAX_TX_PWR; + if (ofdm[i] > RF6052_MAX_TX_PWR) + ofdm[i] = RF6052_MAX_TX_PWR; + } + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_A_CCK1_MCS32); + val32 &= 0xffff00ff; + val32 |= (cck[0] << 8); + rtl8xxxu_write32(priv, REG_TX_AGC_A_CCK1_MCS32, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11); + val32 &= 0xff; + val32 |= ((cck[0] << 8) | (cck[0] << 16) | (cck[0] << 24)); + rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11); + val32 &= 0xffffff00; + val32 |= cck[1]; + rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK1_55_MCS32); + val32 &= 0xff; + val32 |= ((cck[1] << 8) | (cck[1] << 16) | (cck[1] << 24)); + rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK1_55_MCS32, val32); + + ofdm_a = ofdmbase[0] | ofdmbase[0] << 8 | + ofdmbase[0] << 16 | ofdmbase[0] << 24; + ofdm_b = ofdmbase[1] | ofdmbase[1] << 8 | + ofdmbase[1] << 16 | ofdmbase[1] << 24; + rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE18_06, ofdm_a); + rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE18_06, ofdm_b); + + rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE54_24, ofdm_a); + rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE54_24, ofdm_b); + + mcs_a = mcsbase[0] | mcsbase[0] << 8 | + mcsbase[0] << 16 | mcsbase[0] << 24; + mcs_b = mcsbase[1] | mcsbase[1] << 8 | + mcsbase[1] << 16 | mcsbase[1] << 24; + + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS03_MCS00, mcs_a); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS03_MCS00, mcs_b); + + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS07_MCS04, mcs_a); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS07_MCS04, mcs_b); + + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS11_MCS08, mcs_a); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS11_MCS08, mcs_b); + + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS15_MCS12, mcs_a); + for (i = 0; i < 3; i++) { + if (i != 2) + val8 = (mcsbase[0] > 8) ? (mcsbase[0] - 8) : 0; + else + val8 = (mcsbase[0] > 6) ? (mcsbase[0] - 6) : 0; + rtl8xxxu_write8(priv, REG_OFDM0_XC_TX_IQ_IMBALANCE + i, val8); + } + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS15_MCS12, mcs_b); + for (i = 0; i < 3; i++) { + if (i != 2) + val8 = (mcsbase[1] > 8) ? (mcsbase[1] - 8) : 0; + else + val8 = (mcsbase[1] > 6) ? (mcsbase[1] - 6) : 0; + rtl8xxxu_write8(priv, REG_OFDM0_XD_TX_IQ_IMBALANCE + i, val8); + } +} + +static void rtl8xxxu_set_linktype(struct rtl8xxxu_priv *priv, + enum nl80211_iftype linktype) +{ + u16 val8; + + val8 = rtl8xxxu_read16(priv, REG_MSR); + val8 &= ~MSR_LINKTYPE_MASK; + + switch (linktype) { + case NL80211_IFTYPE_UNSPECIFIED: + val8 |= MSR_LINKTYPE_NONE; + break; + case NL80211_IFTYPE_ADHOC: + val8 |= MSR_LINKTYPE_ADHOC; + break; + case NL80211_IFTYPE_STATION: + val8 |= MSR_LINKTYPE_STATION; + break; + case NL80211_IFTYPE_AP: + val8 |= MSR_LINKTYPE_AP; + break; + default: + goto out; + } + + rtl8xxxu_write8(priv, REG_MSR, val8); +out: + return; +} + +static void +rtl8xxxu_set_retry(struct rtl8xxxu_priv *priv, u16 short_retry, u16 long_retry) +{ + u16 val16; + + val16 = ((short_retry << RETRY_LIMIT_SHORT_SHIFT) & + RETRY_LIMIT_SHORT_MASK) | + ((long_retry << RETRY_LIMIT_LONG_SHIFT) & + RETRY_LIMIT_LONG_MASK); + + rtl8xxxu_write16(priv, REG_RETRY_LIMIT, val16); +} + +static void +rtl8xxxu_set_spec_sifs(struct rtl8xxxu_priv *priv, u16 cck, u16 ofdm) +{ + u16 val16; + + val16 = ((cck << SPEC_SIFS_CCK_SHIFT) & SPEC_SIFS_CCK_MASK) | + ((ofdm << SPEC_SIFS_OFDM_SHIFT) & SPEC_SIFS_OFDM_MASK); + + rtl8xxxu_write16(priv, REG_SPEC_SIFS, val16); +} + +static void rtl8xxxu_print_chipinfo(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + char *cut; + + switch (priv->chip_cut) { + case 0: + cut = "A"; + break; + case 1: + cut = "B"; + break; + default: + cut = "unknown"; + } + + dev_info(dev, + "RTL%s rev %s (%s) %iT%iR, TX queues %i, WiFi=%i, BT=%i, GPS=%i, HI PA=%i\n", + priv->chip_name, cut, priv->vendor_umc ? "UMC" : "TSMC", + priv->tx_paths, priv->rx_paths, priv->ep_tx_count, + priv->has_wifi, priv->has_bluetooth, priv->has_gps, + priv->hi_pa); + + dev_info(dev, "RTL%s MAC: %pM\n", priv->chip_name, priv->mac_addr); +} + +static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + u32 val32, bonding; + u16 val16; + + val32 = rtl8xxxu_read32(priv, REG_SYS_CFG); + priv->chip_cut = (val32 & SYS_CFG_CHIP_VERSION_MASK) >> + SYS_CFG_CHIP_VERSION_SHIFT; + if (val32 & SYS_CFG_TRP_VAUX_EN) { + dev_info(dev, "Unsupported test chip\n"); + return -ENOTSUPP; + } + + if (val32 & SYS_CFG_BT_FUNC) { + sprintf(priv->chip_name, "8723AU"); + priv->rf_paths = 1; + priv->rx_paths = 1; + priv->tx_paths = 1; + priv->rtlchip = 0x8723a; + + val32 = rtl8xxxu_read32(priv, REG_MULTI_FUNC_CTRL); + if (val32 & MULTI_WIFI_FUNC_EN) + priv->has_wifi = 1; + if (val32 & MULTI_BT_FUNC_EN) + priv->has_bluetooth = 1; + if (val32 & MULTI_GPS_FUNC_EN) + priv->has_gps = 1; + } else if (val32 & SYS_CFG_TYPE_ID) { + bonding = rtl8xxxu_read32(priv, REG_HPON_FSM); + bonding &= HPON_FSM_BONDING_MASK; + if (bonding == HPON_FSM_BONDING_1T2R) { + sprintf(priv->chip_name, "8191CU"); + priv->rf_paths = 2; + priv->rx_paths = 2; + priv->tx_paths = 1; + priv->rtlchip = 0x8191c; + } else { + sprintf(priv->chip_name, "8192CU"); + priv->rf_paths = 2; + priv->rx_paths = 2; + priv->tx_paths = 2; + priv->rtlchip = 0x8192c; + } + priv->has_wifi = 1; + } else { + sprintf(priv->chip_name, "8188CU"); + priv->rf_paths = 1; + priv->rx_paths = 1; + priv->tx_paths = 1; + priv->rtlchip = 0x8188c; + priv->has_wifi = 1; + } + + if (val32 & SYS_CFG_VENDOR_ID) + priv->vendor_umc = 1; + + val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS); + priv->rom_rev = (val32 & GPIO_RF_RL_ID) >> 28; + + val16 = rtl8xxxu_read16(priv, REG_NORMAL_SIE_EP_TX); + if (val16 & NORMAL_SIE_EP_TX_HIGH_MASK) { + priv->ep_tx_high_queue = 1; + priv->ep_tx_count++; + } + + if (val16 & NORMAL_SIE_EP_TX_NORMAL_MASK) { + priv->ep_tx_normal_queue = 1; + priv->ep_tx_count++; + } + + if (val16 & NORMAL_SIE_EP_TX_LOW_MASK) { + priv->ep_tx_low_queue = 1; + priv->ep_tx_count++; + } + + /* + * Fallback for devices that do not provide REG_NORMAL_SIE_EP_TX + */ + if (!priv->ep_tx_count) { + switch (priv->nr_out_eps) { + case 3: + priv->ep_tx_low_queue = 1; + priv->ep_tx_count++; + case 2: + priv->ep_tx_normal_queue = 1; + priv->ep_tx_count++; + case 1: + priv->ep_tx_high_queue = 1; + priv->ep_tx_count++; + break; + default: + dev_info(dev, "Unsupported USB TX end-points\n"); + return -ENOTSUPP; + } + } + + return 0; +} + +static int rtl8723au_parse_efuse(struct rtl8xxxu_priv *priv) +{ + if (priv->efuse_wifi.efuse8723.rtl_id != cpu_to_le16(0x8129)) + return -EINVAL; + + ether_addr_copy(priv->mac_addr, priv->efuse_wifi.efuse8723.mac_addr); + + memcpy(priv->cck_tx_power_index_A, + priv->efuse_wifi.efuse8723.cck_tx_power_index_A, + sizeof(priv->cck_tx_power_index_A)); + memcpy(priv->cck_tx_power_index_B, + priv->efuse_wifi.efuse8723.cck_tx_power_index_B, + sizeof(priv->cck_tx_power_index_B)); + + memcpy(priv->ht40_1s_tx_power_index_A, + priv->efuse_wifi.efuse8723.ht40_1s_tx_power_index_A, + sizeof(priv->ht40_1s_tx_power_index_A)); + memcpy(priv->ht40_1s_tx_power_index_B, + priv->efuse_wifi.efuse8723.ht40_1s_tx_power_index_B, + sizeof(priv->ht40_1s_tx_power_index_B)); + + memcpy(priv->ht20_tx_power_index_diff, + priv->efuse_wifi.efuse8723.ht20_tx_power_index_diff, + sizeof(priv->ht20_tx_power_index_diff)); + memcpy(priv->ofdm_tx_power_index_diff, + priv->efuse_wifi.efuse8723.ofdm_tx_power_index_diff, + sizeof(priv->ofdm_tx_power_index_diff)); + + memcpy(priv->ht40_max_power_offset, + priv->efuse_wifi.efuse8723.ht40_max_power_offset, + sizeof(priv->ht40_max_power_offset)); + memcpy(priv->ht20_max_power_offset, + priv->efuse_wifi.efuse8723.ht20_max_power_offset, + sizeof(priv->ht20_max_power_offset)); + + dev_info(&priv->udev->dev, "Vendor: %.7s\n", + priv->efuse_wifi.efuse8723.vendor_name); + dev_info(&priv->udev->dev, "Product: %.41s\n", + priv->efuse_wifi.efuse8723.device_name); + return 0; +} + +#ifdef CONFIG_RTL8XXXU_UNTESTED + +static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv) +{ + int i; + + if (priv->efuse_wifi.efuse8192.rtl_id != cpu_to_le16(0x8129)) + return -EINVAL; + + ether_addr_copy(priv->mac_addr, priv->efuse_wifi.efuse8192.mac_addr); + + memcpy(priv->cck_tx_power_index_A, + priv->efuse_wifi.efuse8192.cck_tx_power_index_A, + sizeof(priv->cck_tx_power_index_A)); + memcpy(priv->cck_tx_power_index_B, + priv->efuse_wifi.efuse8192.cck_tx_power_index_B, + sizeof(priv->cck_tx_power_index_B)); + + memcpy(priv->ht40_1s_tx_power_index_A, + priv->efuse_wifi.efuse8192.ht40_1s_tx_power_index_A, + sizeof(priv->ht40_1s_tx_power_index_A)); + memcpy(priv->ht40_1s_tx_power_index_B, + priv->efuse_wifi.efuse8192.ht40_1s_tx_power_index_B, + sizeof(priv->ht40_1s_tx_power_index_B)); + memcpy(priv->ht40_2s_tx_power_index_diff, + priv->efuse_wifi.efuse8192.ht40_2s_tx_power_index_diff, + sizeof(priv->ht40_2s_tx_power_index_diff)); + + memcpy(priv->ht20_tx_power_index_diff, + priv->efuse_wifi.efuse8192.ht20_tx_power_index_diff, + sizeof(priv->ht20_tx_power_index_diff)); + memcpy(priv->ofdm_tx_power_index_diff, + priv->efuse_wifi.efuse8192.ofdm_tx_power_index_diff, + sizeof(priv->ofdm_tx_power_index_diff)); + + memcpy(priv->ht40_max_power_offset, + priv->efuse_wifi.efuse8192.ht40_max_power_offset, + sizeof(priv->ht40_max_power_offset)); + memcpy(priv->ht20_max_power_offset, + priv->efuse_wifi.efuse8192.ht20_max_power_offset, + sizeof(priv->ht20_max_power_offset)); + + dev_info(&priv->udev->dev, "Vendor: %.7s\n", + priv->efuse_wifi.efuse8192.vendor_name); + dev_info(&priv->udev->dev, "Product: %.20s\n", + priv->efuse_wifi.efuse8192.device_name); + + if (priv->efuse_wifi.efuse8192.rf_regulatory & 0x20) { + sprintf(priv->chip_name, "8188RU"); + priv->hi_pa = 1; + } + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_EFUSE) { + unsigned char *raw = priv->efuse_wifi.raw; + + dev_info(&priv->udev->dev, + "%s: dumping efuse (0x%02zx bytes):\n", + __func__, sizeof(struct rtl8192cu_efuse)); + for (i = 0; i < sizeof(struct rtl8192cu_efuse); i += 8) { + dev_info(&priv->udev->dev, "%02x: " + "%02x %02x %02x %02x %02x %02x %02x %02x\n", i, + raw[i], raw[i + 1], raw[i + 2], + raw[i + 3], raw[i + 4], raw[i + 5], + raw[i + 6], raw[i + 7]); + } + } + return 0; +} + +#endif + +static int +rtl8xxxu_read_efuse8(struct rtl8xxxu_priv *priv, u16 offset, u8 *data) +{ + int i; + u8 val8; + u32 val32; + + /* Write Address */ + rtl8xxxu_write8(priv, REG_EFUSE_CTRL + 1, offset & 0xff); + val8 = rtl8xxxu_read8(priv, REG_EFUSE_CTRL + 2); + val8 &= 0xfc; + val8 |= (offset >> 8) & 0x03; + rtl8xxxu_write8(priv, REG_EFUSE_CTRL + 2, val8); + + val8 = rtl8xxxu_read8(priv, REG_EFUSE_CTRL + 3); + rtl8xxxu_write8(priv, REG_EFUSE_CTRL + 3, val8 & 0x7f); + + /* Poll for data read */ + val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL); + for (i = 0; i < RTL8XXXU_MAX_REG_POLL; i++) { + val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL); + if (val32 & BIT(31)) + break; + } + + if (i == RTL8XXXU_MAX_REG_POLL) + return -EIO; + + udelay(50); + val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL); + + *data = val32 & 0xff; + return 0; +} + +static int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + int i, ret = 0; + u8 val8, word_mask, header, extheader; + u16 val16, efuse_addr, offset; + u32 val32; + + val16 = rtl8xxxu_read16(priv, REG_9346CR); + if (val16 & EEPROM_ENABLE) + priv->has_eeprom = 1; + if (val16 & EEPROM_BOOT) + priv->boot_eeprom = 1; + + val32 = rtl8xxxu_read32(priv, REG_EFUSE_TEST); + val32 = (val32 & ~EFUSE_SELECT_MASK) | EFUSE_WIFI_SELECT; + rtl8xxxu_write32(priv, REG_EFUSE_TEST, val32); + + dev_dbg(dev, "Booting from %s\n", + priv->boot_eeprom ? "EEPROM" : "EFUSE"); + + rtl8xxxu_write8(priv, REG_EFUSE_ACCESS, EFUSE_ACCESS_ENABLE); + + /* 1.2V Power: From VDDON with Power Cut(0x0000[15]), default valid */ + val16 = rtl8xxxu_read16(priv, REG_SYS_ISO_CTRL); + if (!(val16 & SYS_ISO_PWC_EV12V)) { + val16 |= SYS_ISO_PWC_EV12V; + rtl8xxxu_write16(priv, REG_SYS_ISO_CTRL, val16); + } + /* Reset: 0x0000[28], default valid */ + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + if (!(val16 & SYS_FUNC_ELDR)) { + val16 |= SYS_FUNC_ELDR; + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + } + + /* + * Clock: Gated(0x0008[5]) 8M(0x0008[1]) clock from ANA, default valid + */ + val16 = rtl8xxxu_read16(priv, REG_SYS_CLKR); + if (!(val16 & SYS_CLK_LOADER_ENABLE) || !(val16 & SYS_CLK_ANA8M)) { + val16 |= (SYS_CLK_LOADER_ENABLE | SYS_CLK_ANA8M); + rtl8xxxu_write16(priv, REG_SYS_CLKR, val16); + } + + /* Default value is 0xff */ + memset(priv->efuse_wifi.raw, 0xff, EFUSE_MAP_LEN_8723A); + + efuse_addr = 0; + while (efuse_addr < EFUSE_REAL_CONTENT_LEN_8723A) { + ret = rtl8xxxu_read_efuse8(priv, efuse_addr++, &header); + if (ret || header == 0xff) + goto exit; + + if ((header & 0x1f) == 0x0f) { /* extended header */ + offset = (header & 0xe0) >> 5; + + ret = rtl8xxxu_read_efuse8(priv, efuse_addr++, + &extheader); + if (ret) + goto exit; + /* All words disabled */ + if ((extheader & 0x0f) == 0x0f) + continue; + + offset |= ((extheader & 0xf0) >> 1); + word_mask = extheader & 0x0f; + } else { + offset = (header >> 4) & 0x0f; + word_mask = header & 0x0f; + } + + if (offset < EFUSE_MAX_SECTION_8723A) { + u16 map_addr; + /* Get word enable value from PG header */ + + /* We have 8 bits to indicate validity */ + map_addr = offset * 8; + if (map_addr >= EFUSE_MAP_LEN_8723A) { + dev_warn(dev, "%s: Illegal map_addr (%04x), " + "efuse corrupt!\n", + __func__, map_addr); + ret = -EINVAL; + goto exit; + } + for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { + /* Check word enable condition in the section */ + if (!(word_mask & BIT(i))) { + ret = rtl8xxxu_read_efuse8(priv, + efuse_addr++, + &val8); + if (ret) + goto exit; + priv->efuse_wifi.raw[map_addr++] = val8; + + ret = rtl8xxxu_read_efuse8(priv, + efuse_addr++, + &val8); + if (ret) + goto exit; + priv->efuse_wifi.raw[map_addr++] = val8; + } else + map_addr += 2; + } + } else { + dev_warn(dev, + "%s: Illegal offset (%04x), efuse corrupt!\n", + __func__, offset); + ret = -EINVAL; + goto exit; + } + } + +exit: + rtl8xxxu_write8(priv, REG_EFUSE_ACCESS, EFUSE_ACCESS_DISABLE); + + return ret; +} + +static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + int ret = 0, i; + u32 val32; + + /* Poll checksum report */ + for (i = 0; i < RTL8XXXU_FIRMWARE_POLL_MAX; i++) { + val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL); + if (val32 & MCU_FW_DL_CSUM_REPORT) + break; + } + + if (i == RTL8XXXU_FIRMWARE_POLL_MAX) { + dev_warn(dev, "Firmware checksum poll timed out\n"); + ret = -EAGAIN; + goto exit; + } + + val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL); + val32 |= MCU_FW_DL_READY; + val32 &= ~MCU_WINT_INIT_READY; + rtl8xxxu_write32(priv, REG_MCU_FW_DL, val32); + + /* Wait for firmware to become ready */ + for (i = 0; i < RTL8XXXU_FIRMWARE_POLL_MAX; i++) { + val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL); + if (val32 & MCU_WINT_INIT_READY) + break; + + udelay(100); + } + + if (i == RTL8XXXU_FIRMWARE_POLL_MAX) { + dev_warn(dev, "Firmware failed to start\n"); + ret = -EAGAIN; + goto exit; + } + +exit: + return ret; +} + +static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv) +{ + int pages, remainder, i, ret; + u8 val8; + u16 val16; + u32 val32; + u8 *fwptr; + + val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC + 1); + val8 |= 4; + rtl8xxxu_write8(priv, REG_SYS_FUNC + 1, val8); + + /* 8051 enable */ + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16 | SYS_FUNC_CPU_ENABLE); + + /* MCU firmware download enable */ + val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL); + rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8 | MCU_FW_DL_ENABLE); + + /* 8051 reset */ + val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL); + rtl8xxxu_write32(priv, REG_MCU_FW_DL, val32 & ~BIT(19)); + + /* Reset firmware download checksum */ + val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL); + rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8 | MCU_FW_DL_CSUM_REPORT); + + pages = priv->fw_size / RTL_FW_PAGE_SIZE; + remainder = priv->fw_size % RTL_FW_PAGE_SIZE; + + fwptr = priv->fw_data->data; + + for (i = 0; i < pages; i++) { + val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL + 2) & 0xF8; + rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8 | i); + + ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS, + fwptr, RTL_FW_PAGE_SIZE); + if (ret != RTL_FW_PAGE_SIZE) { + ret = -EAGAIN; + goto fw_abort; + } + + fwptr += RTL_FW_PAGE_SIZE; + } + + if (remainder) { + val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL + 2) & 0xF8; + rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8 | i); + ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS, + fwptr, remainder); + if (ret != remainder) { + ret = -EAGAIN; + goto fw_abort; + } + } + + ret = 0; +fw_abort: + /* MCU firmware download disable */ + val16 = rtl8xxxu_read16(priv, REG_MCU_FW_DL); + rtl8xxxu_write16(priv, REG_MCU_FW_DL, + val16 & (~MCU_FW_DL_ENABLE & 0xff)); + + return ret; +} + +static int rtl8xxxu_load_firmware(struct rtl8xxxu_priv *priv, char *fw_name) +{ + struct device *dev = &priv->udev->dev; + const struct firmware *fw; + int ret = 0; + u16 signature; + + dev_info(dev, "%s: Loading firmware %s\n", DRIVER_NAME, fw_name); + if (request_firmware(&fw, fw_name, &priv->udev->dev)) { + dev_warn(dev, "request_firmware(%s) failed\n", fw_name); + ret = -EAGAIN; + goto exit; + } + if (!fw) { + dev_warn(dev, "Firmware data not available\n"); + ret = -EINVAL; + goto exit; + } + + priv->fw_data = kmemdup(fw->data, fw->size, GFP_KERNEL); + priv->fw_size = fw->size - sizeof(struct rtl8xxxu_firmware_header); + + signature = le16_to_cpu(priv->fw_data->signature); + switch (signature & 0xfff0) { + case 0x92c0: + case 0x88c0: + case 0x2300: + break; + default: + ret = -EINVAL; + dev_warn(dev, "%s: Invalid firmware signature: 0x%04x\n", + __func__, signature); + } + + dev_info(dev, "Firmware revision %i.%i (signature 0x%04x)\n", + le16_to_cpu(priv->fw_data->major_version), + priv->fw_data->minor_version, signature); + +exit: + release_firmware(fw); + return ret; +} + +static int rtl8723au_load_firmware(struct rtl8xxxu_priv *priv) +{ + char *fw_name; + int ret; + + switch (priv->chip_cut) { + case 0: + fw_name = "rtlwifi/rtl8723aufw_A.bin"; + break; + case 1: + if (priv->enable_bluetooth) + fw_name = "rtlwifi/rtl8723aufw_B.bin"; + else + fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin"; + + break; + default: + return -EINVAL; + } + + ret = rtl8xxxu_load_firmware(priv, fw_name); + return ret; +} + +#ifdef CONFIG_RTL8XXXU_UNTESTED + +static int rtl8192cu_load_firmware(struct rtl8xxxu_priv *priv) +{ + char *fw_name; + int ret; + + if (!priv->vendor_umc) + fw_name = "rtlwifi/rtl8192cufw_TMSC.bin"; + else if (priv->chip_cut || priv->rtlchip == 0x8192c) + fw_name = "rtlwifi/rtl8192cufw_B.bin"; + else + fw_name = "rtlwifi/rtl8192cufw_A.bin"; + + ret = rtl8xxxu_load_firmware(priv, fw_name); + + return ret; +} + +#endif + +static void rtl8xxxu_firmware_self_reset(struct rtl8xxxu_priv *priv) +{ + u16 val16; + int i = 100; + + /* Inform 8051 to perform reset */ + rtl8xxxu_write8(priv, REG_HMTFR + 3, 0x20); + + for (i = 100; i > 0; i--) { + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + + if (!(val16 & SYS_FUNC_CPU_ENABLE)) { + dev_dbg(&priv->udev->dev, + "%s: Firmware self reset success!\n", __func__); + break; + } + udelay(50); + } + + if (!i) { + /* Force firmware reset */ + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 &= ~SYS_FUNC_CPU_ENABLE; + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + } +} + +static int +rtl8xxxu_init_mac(struct rtl8xxxu_priv *priv, struct rtl8xxxu_reg8val *array) +{ + int i, ret; + u16 reg; + u8 val; + + for (i = 0; ; i++) { + reg = array[i].reg; + val = array[i].val; + + if (reg == 0xffff && val == 0xff) + break; + + ret = rtl8xxxu_write8(priv, reg, val); + if (ret != 1) { + dev_warn(&priv->udev->dev, + "Failed to initialize MAC\n"); + return -EAGAIN; + } + } + + rtl8xxxu_write8(priv, REG_MAX_AGGR_NUM, 0x0a); + + return 0; +} + +static int rtl8xxxu_init_phy_regs(struct rtl8xxxu_priv *priv, + struct rtl8xxxu_reg32val *array) +{ + int i, ret; + u16 reg; + u32 val; + + for (i = 0; ; i++) { + reg = array[i].reg; + val = array[i].val; + + if (reg == 0xffff && val == 0xffffffff) + break; + + ret = rtl8xxxu_write32(priv, reg, val); + if (ret != sizeof(val)) { + dev_warn(&priv->udev->dev, + "Failed to initialize PHY\n"); + return -EAGAIN; + } + udelay(1); + } + + return 0; +} + +/* + * Most of this is black magic retrieved from the old rtl8723au driver + */ +static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) +{ + u8 val8, ldoa15, ldov12d, lpldo, ldohci12; + u32 val32; + + /* + * Todo: The vendor driver maintains a table of PHY register + * addresses, which is initialized here. Do we need this? + */ + + val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL); + udelay(2); + val8 |= AFE_PLL_320_ENABLE; + rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL, val8); + udelay(2); + + rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL + 1, 0xff); + udelay(2); + + val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC); + val8 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB; + rtl8xxxu_write8(priv, REG_SYS_FUNC, val8); + + /* AFE_XTAL_RF_GATE (bit 14) if addressing as 32 bit register */ + val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL); + val32 &= ~AFE_XTAL_RF_GATE; + if (priv->has_bluetooth) + val32 &= ~AFE_XTAL_BT_GATE; + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val32); + + /* 6. 0x1f[7:0] = 0x07 */ + val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; + rtl8xxxu_write8(priv, REG_RF_CTRL, val8); + + if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, rtl8188ru_phy_1t_highpa_table); + else if (priv->tx_paths == 2) + rtl8xxxu_init_phy_regs(priv, rtl8192cu_phy_2t_init_table); + else + rtl8xxxu_init_phy_regs(priv, rtl8723a_phy_1t_init_table); + + + if (priv->rtlchip == 0x8188c && priv->hi_pa && + priv->vendor_umc && priv->chip_cut == 1) + rtl8xxxu_write8(priv, REG_OFDM0_AGC_PARM1 + 2, 0x50); + + if (priv->tx_paths == 1 && priv->rx_paths == 2) { + /* + * For 1T2R boards, patch the registers. + * + * It looks like 8191/2 1T2R boards use path B for TX + */ + val32 = rtl8xxxu_read32(priv, REG_FPGA0_TX_INFO); + val32 &= ~(BIT(0) | BIT(1)); + val32 |= BIT(1); + rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA1_TX_INFO); + val32 &= ~0x300033; + val32 |= 0x200022; + rtl8xxxu_write32(priv, REG_FPGA1_TX_INFO, val32); + + val32 = rtl8xxxu_read32(priv, REG_CCK0_AFE_SETTING); + val32 &= 0xff000000; + val32 |= 0x45000000; + rtl8xxxu_write32(priv, REG_CCK0_AFE_SETTING, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); + val32 &= ~(OFDM_RF_PATH_RX_MASK | OFDM_RF_PATH_TX_MASK); + val32 |= (OFDM_RF_PATH_RX_A | OFDM_RF_PATH_RX_B | + OFDM_RF_PATH_TX_B); + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGC_PARM1); + val32 &= ~(BIT(4) | BIT(5)); + val32 |= BIT(4); + rtl8xxxu_write32(priv, REG_OFDM0_AGC_PARM1, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_CCK_RFON); + val32 &= ~(BIT(27) | BIT(26)); + val32 |= BIT(27); + rtl8xxxu_write32(priv, REG_TX_CCK_RFON, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_CCK_BBON); + val32 &= ~(BIT(27) | BIT(26)); + val32 |= BIT(27); + rtl8xxxu_write32(priv, REG_TX_CCK_BBON, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_OFDM_RFON); + val32 &= ~(BIT(27) | BIT(26)); + val32 |= BIT(27); + rtl8xxxu_write32(priv, REG_TX_OFDM_RFON, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_OFDM_BBON); + val32 &= ~(BIT(27) | BIT(26)); + val32 |= BIT(27); + rtl8xxxu_write32(priv, REG_TX_OFDM_BBON, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_TO_TX); + val32 &= ~(BIT(27) | BIT(26)); + val32 |= BIT(27); + rtl8xxxu_write32(priv, REG_TX_TO_TX, val32); + } + + if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table); + else + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_standard_table); + + if (priv->rtlchip == 0x8723a && + priv->efuse_wifi.efuse8723.version >= 0x01) { + val32 = rtl8xxxu_read32(priv, REG_MAC_PHY_CTRL); + + val8 = priv->efuse_wifi.efuse8723.xtal_k & 0x3f; + val32 &= 0xff000fff; + val32 |= ((val8 | (val8 << 6)) << 12); + + rtl8xxxu_write32(priv, REG_MAC_PHY_CTRL, val32); + } + + ldoa15 = LDOA15_ENABLE | LDOA15_OBUF; + ldov12d = LDOV12D_ENABLE | BIT(2) | (2 << LDOV12D_VADJ_SHIFT); + ldohci12 = 0x57; + lpldo = 1; + val32 = (lpldo << 24) | (ldohci12 << 16) | (ldov12d << 8) | ldoa15; + + rtl8xxxu_write32(priv, REG_LDOA15_CTRL, val32); + + return 0; +} + +static int rtl8xxxu_init_rf_regs(struct rtl8xxxu_priv *priv, + struct rtl8xxxu_rfregval *array, + enum rtl8xxxu_rfpath path) +{ + int i, ret; + u8 reg; + u32 val; + + for (i = 0; ; i++) { + reg = array[i].reg; + val = array[i].val; + + if (reg == 0xff && val == 0xffffffff) + break; + + switch (reg) { + case 0xfe: + msleep(50); + continue; + case 0xfd: + mdelay(5); + continue; + case 0xfc: + mdelay(1); + continue; + case 0xfb: + udelay(50); + continue; + case 0xfa: + udelay(5); + continue; + case 0xf9: + udelay(1); + continue; + } + + reg &= 0x3f; + + ret = rtl8xxxu_write_rfreg(priv, path, reg, val); + if (ret) { + dev_warn(&priv->udev->dev, + "Failed to initialize RF\n"); + return -EAGAIN; + } + udelay(1); + } + + return 0; +} + +static int rtl8xxxu_init_phy_rf(struct rtl8xxxu_priv *priv, + struct rtl8xxxu_rfregval *table, + enum rtl8xxxu_rfpath path) +{ + u32 val32; + u16 val16, rfsi_rfenv; + u16 reg_sw_ctrl, reg_int_oe, reg_hssi_parm2; + + switch (path) { + case RF_A: + reg_sw_ctrl = REG_FPGA0_XA_RF_SW_CTRL; + reg_int_oe = REG_FPGA0_XA_RF_INT_OE; + reg_hssi_parm2 = REG_FPGA0_XA_HSSI_PARM2; + break; + case RF_B: + reg_sw_ctrl = REG_FPGA0_XB_RF_SW_CTRL; + reg_int_oe = REG_FPGA0_XB_RF_INT_OE; + reg_hssi_parm2 = REG_FPGA0_XB_HSSI_PARM2; + break; + default: + dev_err(&priv->udev->dev, "%s:Unsupported RF path %c\n", + __func__, path + 'A'); + return -EINVAL; + } + /* For path B, use XB */ + rfsi_rfenv = rtl8xxxu_read16(priv, reg_sw_ctrl); + rfsi_rfenv &= FPGA0_RF_RFENV; + + /* + * These two we might be able to optimize into one + */ + val32 = rtl8xxxu_read32(priv, reg_int_oe); + val32 |= BIT(20); /* 0x10 << 16 */ + rtl8xxxu_write32(priv, reg_int_oe, val32); + udelay(1); + + val32 = rtl8xxxu_read32(priv, reg_int_oe); + val32 |= BIT(4); + rtl8xxxu_write32(priv, reg_int_oe, val32); + udelay(1); + + /* + * These two we might be able to optimize into one + */ + val32 = rtl8xxxu_read32(priv, reg_hssi_parm2); + val32 &= ~FPGA0_HSSI_3WIRE_ADDR_LEN; + rtl8xxxu_write32(priv, reg_hssi_parm2, val32); + udelay(1); + + val32 = rtl8xxxu_read32(priv, reg_hssi_parm2); + val32 &= ~FPGA0_HSSI_3WIRE_DATA_LEN; + rtl8xxxu_write32(priv, reg_hssi_parm2, val32); + udelay(1); + + rtl8xxxu_init_rf_regs(priv, table, path); + + /* For path B, use XB */ + val16 = rtl8xxxu_read16(priv, reg_sw_ctrl); + val16 &= ~FPGA0_RF_RFENV; + val16 |= rfsi_rfenv; + rtl8xxxu_write16(priv, reg_sw_ctrl, val16); + + return 0; +} + +static int rtl8xxxu_llt_write(struct rtl8xxxu_priv *priv, u8 address, u8 data) +{ + int ret = -EBUSY; + int count = 0; + u32 value; + + value = LLT_OP_WRITE | address << 8 | data; + + rtl8xxxu_write32(priv, REG_LLT_INIT, value); + + do { + value = rtl8xxxu_read32(priv, REG_LLT_INIT); + if ((value & LLT_OP_MASK) == LLT_OP_INACTIVE) { + ret = 0; + break; + } + } while (count++ < 20); + + return ret; +} + +static int rtl8xxxu_init_llt_table(struct rtl8xxxu_priv *priv, u8 last_tx_page) +{ + int ret; + int i; + + for (i = 0; i < last_tx_page; i++) { + ret = rtl8xxxu_llt_write(priv, i, i + 1); + if (ret) + goto exit; + } + + ret = rtl8xxxu_llt_write(priv, last_tx_page, 0xff); + if (ret) + goto exit; + + /* Mark remaining pages as a ring buffer */ + for (i = last_tx_page + 1; i < 0xff; i++) { + ret = rtl8xxxu_llt_write(priv, i, (i + 1)); + if (ret) + goto exit; + } + + /* Let last entry point to the start entry of ring buffer */ + ret = rtl8xxxu_llt_write(priv, 0xff, last_tx_page + 1); + if (ret) + goto exit; + +exit: + return ret; +} + +static int rtl8xxxu_init_queue_priority(struct rtl8xxxu_priv *priv) +{ + u16 val16, hi, lo; + u16 hiq, mgq, bkq, beq, viq, voq; + int hip, mgp, bkp, bep, vip, vop; + int ret = 0; + + switch (priv->ep_tx_count) { + case 1: + if (priv->ep_tx_high_queue) { + hi = TRXDMA_QUEUE_HIGH; + } else if (priv->ep_tx_low_queue) { + hi = TRXDMA_QUEUE_LOW; + } else if (priv->ep_tx_normal_queue) { + hi = TRXDMA_QUEUE_NORMAL; + } else { + hi = 0; + ret = -EINVAL; + } + + hiq = hi; + mgq = hi; + bkq = hi; + beq = hi; + viq = hi; + voq = hi; + + hip = 0; + mgp = 0; + bkp = 0; + bep = 0; + vip = 0; + vop = 0; + break; + case 2: + if (priv->ep_tx_high_queue && priv->ep_tx_low_queue) { + hi = TRXDMA_QUEUE_HIGH; + lo = TRXDMA_QUEUE_LOW; + } else if (priv->ep_tx_normal_queue && priv->ep_tx_low_queue) { + hi = TRXDMA_QUEUE_NORMAL; + lo = TRXDMA_QUEUE_LOW; + } else if (priv->ep_tx_high_queue && priv->ep_tx_normal_queue) { + hi = TRXDMA_QUEUE_HIGH; + lo = TRXDMA_QUEUE_NORMAL; + } else { + ret = -EINVAL; + hi = 0; + lo = 0; + } + + hiq = hi; + mgq = hi; + bkq = lo; + beq = lo; + viq = hi; + voq = hi; + + hip = 0; + mgp = 0; + bkp = 1; + bep = 1; + vip = 0; + vop = 0; + break; + case 3: + beq = TRXDMA_QUEUE_LOW; + bkq = TRXDMA_QUEUE_LOW; + viq = TRXDMA_QUEUE_NORMAL; + voq = TRXDMA_QUEUE_HIGH; + mgq = TRXDMA_QUEUE_HIGH; + hiq = TRXDMA_QUEUE_HIGH; + + hip = hiq ^ 3; + mgp = mgq ^ 3; + bkp = bkq ^ 3; + bep = beq ^ 3; + vip = viq ^ 3; + vop = viq ^ 3; + break; + default: + ret = -EINVAL; + } + + /* + * None of the vendor drivers are configuring the beacon + * queue here .... why? + */ + if (!ret) { + val16 = rtl8xxxu_read16(priv, REG_TRXDMA_CTRL); + val16 &= 0x7; + val16 |= (voq << TRXDMA_CTRL_VOQ_SHIFT) | + (viq << TRXDMA_CTRL_VIQ_SHIFT) | + (beq << TRXDMA_CTRL_BEQ_SHIFT) | + (bkq << TRXDMA_CTRL_BKQ_SHIFT) | + (mgq << TRXDMA_CTRL_MGQ_SHIFT) | + (hiq << TRXDMA_CTRL_HIQ_SHIFT); + rtl8xxxu_write16(priv, REG_TRXDMA_CTRL, val16); + + priv->pipe_out[TXDESC_QUEUE_VO] = + usb_sndbulkpipe(priv->udev, priv->out_ep[vop]); + priv->pipe_out[TXDESC_QUEUE_VI] = + usb_sndbulkpipe(priv->udev, priv->out_ep[vip]); + priv->pipe_out[TXDESC_QUEUE_BE] = + usb_sndbulkpipe(priv->udev, priv->out_ep[bep]); + priv->pipe_out[TXDESC_QUEUE_BK] = + usb_sndbulkpipe(priv->udev, priv->out_ep[bkp]); + priv->pipe_out[TXDESC_QUEUE_BEACON] = + usb_sndbulkpipe(priv->udev, priv->out_ep[0]); + priv->pipe_out[TXDESC_QUEUE_MGNT] = + usb_sndbulkpipe(priv->udev, priv->out_ep[mgp]); + priv->pipe_out[TXDESC_QUEUE_HIGH] = + usb_sndbulkpipe(priv->udev, priv->out_ep[hip]); + priv->pipe_out[TXDESC_QUEUE_CMD] = + usb_sndbulkpipe(priv->udev, priv->out_ep[0]); + } + + return ret; +} + +static void rtl8xxxu_fill_iqk_matrix_a(struct rtl8xxxu_priv *priv, + bool iqk_ok, int result[][8], + int candidate, bool tx_only) +{ + u32 oldval, x, tx0_a, reg; + int y, tx0_c; + u32 val32; + + if (!iqk_ok) + return; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE); + oldval = val32 >> 22; + + x = result[candidate][0]; + if ((x & 0x00000200) != 0) + x = x | 0xfffffc00; + tx0_a = (x * oldval) >> 8; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE); + val32 &= ~0x3ff; + val32 |= tx0_a; + rtl8xxxu_write32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES); + val32 &= ~BIT(31); + if ((x * oldval >> 7) & 0x1) + val32 |= BIT(31); + rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val32); + + y = result[candidate][1]; + if ((y & 0x00000200) != 0) + y = y | 0xfffffc00; + tx0_c = (y * oldval) >> 8; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XC_TX_AFE); + val32 &= ~0xf0000000; + val32 |= (((tx0_c & 0x3c0) >> 6) << 28); + rtl8xxxu_write32(priv, REG_OFDM0_XC_TX_AFE, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE); + val32 &= ~0x003f0000; + val32 |= ((tx0_c & 0x3f) << 16); + rtl8xxxu_write32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES); + val32 &= ~BIT(29); + if ((y * oldval >> 7) & 0x1) + val32 |= BIT(29); + rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val32); + + if (tx_only) { + dev_dbg(&priv->udev->dev, "%s: only TX\n", __func__); + return; + } + + reg = result[candidate][2]; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE); + val32 &= ~0x3ff; + val32 |= (reg & 0x3ff); + rtl8xxxu_write32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE, val32); + + reg = result[candidate][3] & 0x3F; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE); + val32 &= ~0xfc00; + val32 |= ((reg << 10) & 0xfc00); + rtl8xxxu_write32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE, val32); + + reg = (result[candidate][3] >> 6) & 0xF; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_RX_IQ_EXT_ANTA); + val32 &= ~0xf0000000; + val32 |= (reg << 28); + rtl8xxxu_write32(priv, REG_OFDM0_RX_IQ_EXT_ANTA, val32); +} + +static void rtl8xxxu_fill_iqk_matrix_b(struct rtl8xxxu_priv *priv, + bool iqk_ok, int result[][8], + int candidate, bool tx_only) +{ + u32 oldval, x, tx1_a, reg; + int y, tx1_c; + u32 val32; + + if (!iqk_ok) + return; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE); + oldval = val32 >> 22; + + x = result[candidate][4]; + if ((x & 0x00000200) != 0) + x = x | 0xfffffc00; + tx1_a = (x * oldval) >> 8; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE); + val32 &= ~0x3ff; + val32 |= tx1_a; + rtl8xxxu_write32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES); + val32 &= ~BIT(27); + if ((x * oldval >> 7) & 0x1) + val32 |= BIT(27); + rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val32); + + y = result[candidate][5]; + if ((y & 0x00000200) != 0) + y = y | 0xfffffc00; + tx1_c = (y * oldval) >> 8; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XD_TX_AFE); + val32 &= ~0xf0000000; + val32 |= (((tx1_c & 0x3c0) >> 6) << 28); + rtl8xxxu_write32(priv, REG_OFDM0_XD_TX_AFE, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE); + val32 &= ~0x003f0000; + val32 |= ((tx1_c & 0x3f) << 16); + rtl8xxxu_write32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES); + val32 &= ~BIT(25); + if ((y * oldval >> 7) & 0x1) + val32 |= BIT(25); + rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val32); + + if (tx_only) { + dev_dbg(&priv->udev->dev, "%s: only TX\n", __func__); + return; + } + + reg = result[candidate][6]; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE); + val32 &= ~0x3ff; + val32 |= (reg & 0x3ff); + rtl8xxxu_write32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE, val32); + + reg = result[candidate][7] & 0x3f; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE); + val32 &= ~0xfc00; + val32 |= ((reg << 10) & 0xfc00); + rtl8xxxu_write32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE, val32); + + reg = (result[candidate][7] >> 6) & 0xf; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGCR_SSI_TABLE); + val32 &= ~0x0000f000; + val32 |= (reg << 12); + rtl8xxxu_write32(priv, REG_OFDM0_AGCR_SSI_TABLE, val32); +} + +#define MAX_TOLERANCE 5 + +static bool rtl8xxxu_simularity_compare(struct rtl8xxxu_priv *priv, + int result[][8], int c1, int c2) +{ + u32 i, j, diff, simubitmap, bound = 0; + int candidate[2] = {-1, -1}; /* for path A and path B */ + bool retval = true; + + if (priv->tx_paths > 1) + bound = 8; + else + bound = 4; + + simubitmap = 0; + + for (i = 0; i < bound; i++) { + diff = (result[c1][i] > result[c2][i]) ? + (result[c1][i] - result[c2][i]) : + (result[c2][i] - result[c1][i]); + if (diff > MAX_TOLERANCE) { + if ((i == 2 || i == 6) && !simubitmap) { + if (result[c1][i] + result[c1][i + 1] == 0) + candidate[(i / 4)] = c2; + else if (result[c2][i] + result[c2][i + 1] == 0) + candidate[(i / 4)] = c1; + else + simubitmap = simubitmap | (1 << i); + } else { + simubitmap = simubitmap | (1 << i); + } + } + } + + if (simubitmap == 0) { + for (i = 0; i < (bound / 4); i++) { + if (candidate[i] >= 0) { + for (j = i * 4; j < (i + 1) * 4 - 2; j++) + result[3][j] = result[candidate[i]][j]; + retval = false; + } + } + return retval; + } else if (!(simubitmap & 0x0f)) { + /* path A OK */ + for (i = 0; i < 4; i++) + result[3][i] = result[c1][i]; + } else if (!(simubitmap & 0xf0) && priv->tx_paths > 1) { + /* path B OK */ + for (i = 4; i < 8; i++) + result[3][i] = result[c1][i]; + } + + return false; +} + +static void +rtl8xxxu_save_mac_regs(struct rtl8xxxu_priv *priv, const u32 *reg, u32 *backup) +{ + int i; + + for (i = 0; i < (RTL8XXXU_MAC_REGS - 1); i++) + backup[i] = rtl8xxxu_read8(priv, reg[i]); + + backup[i] = rtl8xxxu_read32(priv, reg[i]); +} + +static void rtl8xxxu_restore_mac_regs(struct rtl8xxxu_priv *priv, + const u32 *reg, u32 *backup) +{ + int i; + + for (i = 0; i < (RTL8XXXU_MAC_REGS - 1); i++) + rtl8xxxu_write8(priv, reg[i], backup[i]); + + rtl8xxxu_write32(priv, reg[i], backup[i]); +} + +static void rtl8xxxu_save_regs(struct rtl8xxxu_priv *priv, const u32 *regs, + u32 *backup, int count) +{ + int i; + + for (i = 0; i < count; i++) + backup[i] = rtl8xxxu_read32(priv, regs[i]); +} + +static void rtl8xxxu_restore_regs(struct rtl8xxxu_priv *priv, const u32 *regs, + u32 *backup, int count) +{ + int i; + + for (i = 0; i < count; i++) + rtl8xxxu_write32(priv, regs[i], backup[i]); +} + + +static void rtl8xxxu_path_adda_on(struct rtl8xxxu_priv *priv, const u32 *regs, + bool path_a_on) +{ + u32 path_on; + int i; + + path_on = path_a_on ? 0x04db25a4 : 0x0b1b25a4; + if (priv->tx_paths == 1) { + path_on = 0x0bdb25a0; + rtl8xxxu_write32(priv, regs[0], 0x0b1b25a0); + } else { + rtl8xxxu_write32(priv, regs[0], path_on); + } + + for (i = 1 ; i < RTL8XXXU_ADDA_REGS ; i++) + rtl8xxxu_write32(priv, regs[i], path_on); +} + +static void rtl8xxxu_mac_calibration(struct rtl8xxxu_priv *priv, + const u32 *regs, u32 *backup) +{ + int i = 0; + + rtl8xxxu_write8(priv, regs[i], 0x3f); + + for (i = 1 ; i < (RTL8XXXU_MAC_REGS - 1); i++) + rtl8xxxu_write8(priv, regs[i], (u8)(backup[i] & ~BIT(3))); + + rtl8xxxu_write8(priv, regs[i], (u8)(backup[i] & ~BIT(5))); +} + +static int rtl8xxxu_iqk_path_a(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_e94, reg_e9c, reg_ea4, val32; + int result = 0; + + /* path-A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x10008c1f); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x10008c1f); + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82140102); + + val32 = (priv->rf_paths > 1) ? 0x28160202 : + /*IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID)?0x28160202: */ + 0x28160502; + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, val32); + + /* path-B IQK setting */ + if (priv->rf_paths > 1) { + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x10008c22); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x10008c22); + rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82140102); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28160202); + } + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x001028d1); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000); + + mdelay(1); + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); + reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); + reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2); + + if (!(reg_eac & BIT(28)) && + ((reg_e94 & 0x03ff0000) != 0x01420000) && + ((reg_e9c & 0x03ff0000) != 0x00420000)) + result |= 0x01; + else /* If TX not OK, ignore RX */ + goto out; + + /* If TX is OK, check whether RX is OK */ + if (!(reg_eac & BIT(27)) && + ((reg_ea4 & 0x03ff0000) != 0x01320000) && + ((reg_eac & 0x03ff0000) != 0x00360000)) + result |= 0x02; + else + dev_warn(&priv->udev->dev, "%s: Path A RX IQK failed!\n", + __func__); +out: + return result; +} + +static int rtl8xxxu_iqk_path_b(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc; + int result = 0; + + /* One shot, path B LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_CONT, 0x00000002); + rtl8xxxu_write32(priv, REG_IQK_AGC_CONT, 0x00000000); + + mdelay(1); + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + reg_ec4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); + reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); + + if (!(reg_eac & BIT(31)) && + ((reg_eb4 & 0x03ff0000) != 0x01420000) && + ((reg_ebc & 0x03ff0000) != 0x00420000)) + result |= 0x01; + else + goto out; + + if (!(reg_eac & BIT(30)) && + (((reg_ec4 & 0x03ff0000) >> 16) != 0x132) && + (((reg_ecc & 0x03ff0000) >> 16) != 0x36)) + result |= 0x02; + else + dev_warn(&priv->udev->dev, "%s: Path B RX IQK failed!\n", + __func__); +out: + return result; +} + +static void rtl8xxxu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, + int result[][8], int t) +{ + struct device *dev = &priv->udev->dev; + u32 i, val32; + int path_a_ok, path_b_ok; + int retry = 2; + const u32 adda_regs[RTL8XXXU_ADDA_REGS] = { + REG_FPGA0_XCD_SWITCH_CTRL, REG_BLUETOOTH, + REG_RX_WAIT_CCA, REG_TX_CCK_RFON, + REG_TX_CCK_BBON, REG_TX_OFDM_RFON, + REG_TX_OFDM_BBON, REG_TX_TO_RX, + REG_TX_TO_TX, REG_RX_CCK, + REG_RX_OFDM, REG_RX_WAIT_RIFS, + REG_RX_TO_RX, REG_STANDBY, + REG_SLEEP, REG_PMPD_ANAEN + }; + const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = { + REG_TXPAUSE, REG_BEACON_CTRL, + REG_BEACON_CTRL_1, REG_GPIO_MUXCFG + }; + const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = { + REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR, + REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B, + REG_FPGA0_XAB_RF_SW_CTRL, REG_FPGA0_XA_RF_INT_OE, + REG_FPGA0_XB_RF_INT_OE, REG_FPGA0_RF_MODE + }; + + /* + * Note: IQ calibration must be performed after loading + * PHY_REG.txt , and radio_a, radio_b.txt + */ + + if (t == 0) { + /* Save ADDA parameters, turn Path A ADDA on */ + rtl8xxxu_save_regs(priv, adda_regs, priv->adda_backup, + RTL8XXXU_ADDA_REGS); + rtl8xxxu_save_mac_regs(priv, iqk_mac_regs, priv->mac_backup); + rtl8xxxu_save_regs(priv, iqk_bb_regs, + priv->bb_backup, RTL8XXXU_BB_REGS); + } + + rtl8xxxu_path_adda_on(priv, adda_regs, true); + + if (t == 0) { + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM1); + if (val32 & FPGA0_HSSI_PARM1_PI) + priv->pi_enabled = 1; + } + + if (!priv->pi_enabled) { + /* Switch BB to PI mode to do IQ Calibration. */ + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100); + rtl8xxxu_write32(priv, REG_FPGA0_XB_HSSI_PARM1, 0x01000100); + } + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + val32 &= ~FPGA_RF_MODE_CCK; + rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); + + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x03a05600); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000800e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x22204000); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_SW_CTRL); + val32 |= (FPGA0_RF_PAPE | (FPGA0_RF_PAPE << FPGA0_RF_BD_CTRL_SHIFT)); + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_RF_INT_OE); + val32 &= ~BIT(10); + rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, val32); + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XB_RF_INT_OE); + val32 &= ~BIT(10); + rtl8xxxu_write32(priv, REG_FPGA0_XB_RF_INT_OE, val32); + + if (priv->tx_paths > 1) { + rtl8xxxu_write32(priv, REG_FPGA0_XA_LSSI_PARM, 0x00010000); + rtl8xxxu_write32(priv, REG_FPGA0_XB_LSSI_PARM, 0x00010000); + } + + /* MAC settings */ + rtl8xxxu_mac_calibration(priv, iqk_mac_regs, priv->mac_backup); + + /* Page B init */ + rtl8xxxu_write32(priv, REG_CONFIG_ANT_A, 0x00080000); + + if (priv->tx_paths > 1) + rtl8xxxu_write32(priv, REG_CONFIG_ANT_B, 0x00080000); + + /* IQ calibration setting */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + for (i = 0; i < retry; i++) { + path_a_ok = rtl8xxxu_iqk_path_a(priv); + if (path_a_ok == 0x03) { + val32 = rtl8xxxu_read32(priv, + REG_TX_POWER_BEFORE_IQK_A); + result[t][0] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, + REG_TX_POWER_AFTER_IQK_A); + result[t][1] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, + REG_RX_POWER_BEFORE_IQK_A_2); + result[t][2] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, + REG_RX_POWER_AFTER_IQK_A_2); + result[t][3] = (val32 >> 16) & 0x3ff; + break; + } else if (i == (retry - 1) && path_a_ok == 0x01) { + /* TX IQK OK */ + dev_dbg(dev, "%s: Path A IQK Only Tx Success!!\n", + __func__); + + val32 = rtl8xxxu_read32(priv, + REG_TX_POWER_BEFORE_IQK_A); + result[t][0] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, + REG_TX_POWER_AFTER_IQK_A); + result[t][1] = (val32 >> 16) & 0x3ff; + } + } + + if (!path_a_ok) + dev_dbg(dev, "%s: Path A IQK failed!\n", __func__); + + if (priv->tx_paths > 1) { + /* + * Path A into standby + */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x0); + rtl8xxxu_write32(priv, REG_FPGA0_XA_LSSI_PARM, 0x00010000); + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* Turn Path B ADDA on */ + rtl8xxxu_path_adda_on(priv, adda_regs, false); + + for (i = 0; i < retry; i++) { + path_b_ok = rtl8xxxu_iqk_path_b(priv); + if (path_b_ok == 0x03) { + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + result[t][4] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + result[t][5] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); + result[t][6] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); + result[t][7] = (val32 >> 16) & 0x3ff; + break; + } else if (i == (retry - 1) && path_b_ok == 0x01) { + /* TX IQK OK */ + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + result[t][4] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + result[t][5] = (val32 >> 16) & 0x3ff; + } + } + + if (!path_b_ok) + dev_dbg(dev, "%s: Path B IQK failed!\n", __func__); + } + + /* Back to BB mode, load original value */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0); + + if (t) { + if (!priv->pi_enabled) { + /* + * Switch back BB to SI mode after finishing + * IQ Calibration + */ + val32 = 0x01000000; + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, val32); + rtl8xxxu_write32(priv, REG_FPGA0_XB_HSSI_PARM1, val32); + } + + /* Reload ADDA power saving parameters */ + rtl8xxxu_restore_regs(priv, adda_regs, priv->adda_backup, + RTL8XXXU_ADDA_REGS); + + /* Reload MAC parameters */ + rtl8xxxu_restore_mac_regs(priv, iqk_mac_regs, priv->mac_backup); + + /* Reload BB parameters */ + rtl8xxxu_restore_regs(priv, iqk_bb_regs, + priv->bb_backup, RTL8XXXU_BB_REGS); + + /* Restore RX initial gain */ + rtl8xxxu_write32(priv, REG_FPGA0_XA_LSSI_PARM, 0x00032ed3); + + if (priv->tx_paths > 1) { + rtl8xxxu_write32(priv, REG_FPGA0_XB_LSSI_PARM, + 0x00032ed3); + } + + /* Load 0xe30 IQC default value */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x01008c00); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x01008c00); + } +} + +static void rtl8723a_phy_iq_calibrate(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + int result[4][8]; /* last is final result */ + int i, candidate; + bool path_a_ok, path_b_ok; + u32 reg_e94, reg_e9c, reg_ea4, reg_eac; + u32 reg_eb4, reg_ebc, reg_ec4, reg_ecc; + s32 reg_tmp = 0; + bool simu; + + memset(result, 0, sizeof(result)); + candidate = -1; + + path_a_ok = false; + path_b_ok = false; + + rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + + for (i = 0; i < 3; i++) { + rtl8xxxu_phy_iqcalibrate(priv, result, i); + + if (i == 1) { + simu = rtl8xxxu_simularity_compare(priv, result, 0, 1); + if (simu) { + candidate = 0; + break; + } + } + + if (i == 2) { + simu = rtl8xxxu_simularity_compare(priv, result, 0, 2); + if (simu) { + candidate = 0; + break; + } + + simu = rtl8xxxu_simularity_compare(priv, result, 1, 2); + if (simu) { + candidate = 1; + } else { + for (i = 0; i < 8; i++) + reg_tmp += result[3][i]; + + if (reg_tmp) + candidate = 3; + else + candidate = -1; + } + } + } + + for (i = 0; i < 4; i++) { + reg_e94 = result[i][0]; + reg_e9c = result[i][1]; + reg_ea4 = result[i][2]; + reg_eac = result[i][3]; + reg_eb4 = result[i][4]; + reg_ebc = result[i][5]; + reg_ec4 = result[i][6]; + reg_ecc = result[i][7]; + } + + if (candidate >= 0) { + reg_e94 = result[candidate][0]; + priv->rege94 = reg_e94; + reg_e9c = result[candidate][1]; + priv->rege9c = reg_e9c; + reg_ea4 = result[candidate][2]; + reg_eac = result[candidate][3]; + reg_eb4 = result[candidate][4]; + priv->regeb4 = reg_eb4; + reg_ebc = result[candidate][5]; + priv->regebc = reg_ebc; + reg_ec4 = result[candidate][6]; + reg_ecc = result[candidate][7]; + dev_dbg(dev, "%s: candidate is %x\n", __func__, candidate); + dev_dbg(dev, + "%s: e94 =%x e9c=%x ea4=%x eac=%x eb4=%x ebc=%x ec4=%x " + "ecc=%x\n ", __func__, reg_e94, reg_e9c, + reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc); + path_a_ok = true; + path_b_ok = true; + } else { + reg_e94 = reg_eb4 = priv->rege94 = priv->regeb4 = 0x100; + reg_e9c = reg_ebc = priv->rege9c = priv->regebc = 0x0; + } + + if (reg_e94 && candidate >= 0) + rtl8xxxu_fill_iqk_matrix_a(priv, path_a_ok, result, + candidate, (reg_ea4 == 0)); + + if (priv->tx_paths > 1 && reg_eb4) + rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result, + candidate, (reg_ec4 == 0)); + + rtl8xxxu_save_regs(priv, rtl8723au_iqk_phy_iq_bb_reg, + priv->bb_recovery_backup, RTL8XXXU_BB_REGS); +} + +static void rtl8723a_phy_lc_calibrate(struct rtl8xxxu_priv *priv) +{ + u32 val32; + u32 rf_amode, rf_bmode = 0, lstf; + + /* Check continuous TX and Packet TX */ + lstf = rtl8xxxu_read32(priv, REG_OFDM1_LSTF); + + if (lstf & OFDM_LSTF_MASK) { + /* Disable all continuous TX */ + val32 = lstf & ~OFDM_LSTF_MASK; + rtl8xxxu_write32(priv, REG_OFDM1_LSTF, val32); + + /* Read original RF mode Path A */ + rf_amode = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_AC); + + /* Set RF mode to standby Path A */ + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, + (rf_amode & 0x8ffff) | 0x10000); + + /* Path-B */ + if (priv->tx_paths > 1) { + rf_bmode = rtl8xxxu_read_rfreg(priv, RF_B, + RF6052_REG_AC); + + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, + (rf_bmode & 0x8ffff) | 0x10000); + } + } else { + /* Deal with Packet TX case */ + /* block all queues */ + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); + } + + /* Start LC calibration */ + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG); + val32 |= 0x08000; + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, val32); + + msleep(100); + + /* Restore original parameters */ + if (lstf & OFDM_LSTF_MASK) { + /* Path-A */ + rtl8xxxu_write32(priv, REG_OFDM1_LSTF, lstf); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, rf_amode); + + /* Path-B */ + if (priv->tx_paths > 1) + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, + rf_bmode); + } else /* Deal with Packet TX case */ + rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00); +} + +static int rtl8xxxu_set_mac(struct rtl8xxxu_priv *priv) +{ + int i; + u16 reg; + + reg = REG_MACID; + + for (i = 0; i < ETH_ALEN; i++) + rtl8xxxu_write8(priv, reg + i, priv->mac_addr[i]); + + return 0; +} + +static int rtl8xxxu_set_bssid(struct rtl8xxxu_priv *priv, const u8 *bssid) +{ + int i; + u16 reg; + + dev_dbg(&priv->udev->dev, "%s: (%pM)\n", __func__, bssid); + + reg = REG_BSSID; + + for (i = 0; i < ETH_ALEN; i++) + rtl8xxxu_write8(priv, reg + i, bssid[i]); + + return 0; +} + +static void +rtl8xxxu_set_ampdu_factor(struct rtl8xxxu_priv *priv, u8 ampdu_factor) +{ + u8 vals[4] = { 0x41, 0xa8, 0x72, 0xb9 }; + u8 max_agg = 0xf; + int i; + + ampdu_factor = 1 << (ampdu_factor + 2); + if (ampdu_factor > max_agg) + ampdu_factor = max_agg; + + for (i = 0; i < 4; i++) { + if ((vals[i] & 0xf0) > (ampdu_factor << 4)) + vals[i] = (vals[i] & 0x0f) | (ampdu_factor << 4); + + if ((vals[i] & 0x0f) > ampdu_factor) + vals[i] = (vals[i] & 0xf0) | ampdu_factor; + + rtl8xxxu_write8(priv, REG_AGGLEN_LMT + i, vals[i]); + } +} + +static void rtl8xxxu_set_ampdu_min_space(struct rtl8xxxu_priv *priv, u8 density) +{ + u8 val8; + + val8 = rtl8xxxu_read8(priv, REG_AMPDU_MIN_SPACE); + val8 &= 0xf8; + val8 |= density; + rtl8xxxu_write8(priv, REG_AMPDU_MIN_SPACE, val8); +} + +static int rtl8xxxu_active_to_emu(struct rtl8xxxu_priv *priv) +{ + u8 val8; + int count, ret; + + /* Start of rtl8723AU_card_enable_flow */ + /* Act to Cardemu sequence*/ + /* Turn off RF */ + rtl8xxxu_write8(priv, REG_RF_CTRL, 0); + + /* 0x004E[7] = 0, switch DPDT_SEL_P output from register 0x0065[2] */ + val8 = rtl8xxxu_read8(priv, REG_LEDCFG2); + val8 &= ~LEDCFG2_DPDT_SELECT; + rtl8xxxu_write8(priv, REG_LEDCFG2, val8); + + /* 0x0005[1] = 1 turn off MAC by HW state machine*/ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 |= BIT(1); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + if ((val8 & BIT(1)) == 0) + break; + udelay(10); + } + + if (!count) { + dev_warn(&priv->udev->dev, "%s: Disabling MAC timed out\n", + __func__); + ret = -EBUSY; + goto exit; + } + + /* 0x0000[5] = 1 analog Ips to digital, 1:isolation */ + val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL); + val8 |= SYS_ISO_ANALOG_IPS; + rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8); + + /* 0x0020[0] = 0 disable LDOA12 MACRO block*/ + val8 = rtl8xxxu_read8(priv, REG_LDOA15_CTRL); + val8 &= ~LDOA15_ENABLE; + rtl8xxxu_write8(priv, REG_LDOA15_CTRL, val8); + +exit: + return ret; +} + +static int rtl8xxxu_active_to_lps(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u8 val32; + int count, ret; + + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); + + /* + * Poll - wait for RX packet to complete + */ + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val32 = rtl8xxxu_read32(priv, 0x5f8); + if (!val32) + break; + udelay(10); + } + + if (!count) { + dev_warn(&priv->udev->dev, + "%s: RX poll timed out (0x05f8)\n", __func__); + ret = -EBUSY; + goto exit; + } + + /* Disable CCK and OFDM, clock gated */ + val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC); + val8 &= ~SYS_FUNC_BBRSTB; + rtl8xxxu_write8(priv, REG_SYS_FUNC, val8); + + udelay(2); + + /* Reset baseband */ + val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC); + val8 &= ~SYS_FUNC_BB_GLB_RSTN; + rtl8xxxu_write8(priv, REG_SYS_FUNC, val8); + + /* Reset MAC TRX */ + val8 = rtl8xxxu_read8(priv, REG_CR); + val8 = CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE; + rtl8xxxu_write8(priv, REG_CR, val8); + + /* Reset MAC TRX */ + val8 = rtl8xxxu_read8(priv, REG_CR + 1); + val8 &= ~BIT(1); /* CR_SECURITY_ENABLE */ + rtl8xxxu_write8(priv, REG_CR + 1, val8); + + /* Respond TX OK to scheduler */ + val8 = rtl8xxxu_read8(priv, REG_DUAL_TSF_RST); + val8 |= DUAL_TSF_TX_OK; + rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, val8); + +exit: + return ret; +} + +static void rtl8xxxu_disabled_to_emu(struct rtl8xxxu_priv *priv) +{ + u8 val8; + + /* Clear suspend enable and power down enable*/ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 &= ~(BIT(3) | BIT(7)); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + /* 0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/ + val8 = rtl8xxxu_read8(priv, REG_GPIO_INTM + 2); + val8 &= ~BIT(0); + rtl8xxxu_write8(priv, REG_GPIO_INTM + 2, val8); + + /* 0x04[12:11] = 11 enable WL suspend*/ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 &= ~(BIT(3) | BIT(4)); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); +} + +static int rtl8xxxu_emu_to_active(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u32 val32; + int count, ret = 0; + + /* 0x20[0] = 1 enable LDOA12 MACRO block for all interface*/ + val8 = rtl8xxxu_read8(priv, REG_LDOA15_CTRL); + val8 |= LDOA15_ENABLE; + rtl8xxxu_write8(priv, REG_LDOA15_CTRL, val8); + + /* 0x67[0] = 0 to disable BT_GPS_SEL pins*/ + val8 = rtl8xxxu_read8(priv, 0x0067); + val8 &= ~BIT(4); + rtl8xxxu_write8(priv, 0x0067, val8); + + mdelay(1); + + /* 0x00[5] = 0 release analog Ips to digital, 1:isolation */ + val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL); + val8 &= ~SYS_ISO_ANALOG_IPS; + rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8); + + /* disable SW LPS 0x04[10]= 0 */ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 &= ~BIT(2); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + /* wait till 0x04[17] = 1 power ready*/ + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); + if (val32 & BIT(17)) + break; + + udelay(10); + } + + if (!count) { + ret = -EBUSY; + goto exit; + } + + /* We should be able to optimize the following three entries into one */ + + /* release WLON reset 0x04[16]= 1*/ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 2); + val8 |= BIT(0); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 2, val8); + + /* disable HWPDN 0x04[15]= 0*/ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 &= ~BIT(7); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + /* disable WL suspend*/ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 &= ~(BIT(3) | BIT(4)); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + /* set, then poll until 0 */ + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); + val32 |= APS_FSMCO_MAC_ENABLE; + rtl8xxxu_write32(priv, REG_APS_FSMCO, val32); + + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); + if ((val32 & APS_FSMCO_MAC_ENABLE) == 0) { + ret = 0; + break; + } + udelay(10); + } + + if (!count) { + ret = -EBUSY; + goto exit; + } + + /* 0x4C[23] = 0x4E[7] = 1, switch DPDT_SEL_P output from WL BB */ + /* + * Note: Vendor driver actually clears this bit, despite the + * documentation claims it's being set! + */ + val8 = rtl8xxxu_read8(priv, REG_LEDCFG2); + val8 |= LEDCFG2_DPDT_SELECT; + val8 &= ~LEDCFG2_DPDT_SELECT; + rtl8xxxu_write8(priv, REG_LEDCFG2, val8); + +exit: + return ret; +} + +static int rtl8xxxu_emu_to_disabled(struct rtl8xxxu_priv *priv) +{ + u8 val8; + + /* 0x0007[7:0] = 0x20 SOP option to disable BG/MB */ + rtl8xxxu_write8(priv, REG_APS_FSMCO + 3, 0x20); + + /* 0x04[12:11] = 01 enable WL suspend */ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 &= ~BIT(4); + val8 |= BIT(3); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 |= BIT(7); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + /* 0x48[16] = 1 to enable GPIO9 as EXT wakeup */ + val8 = rtl8xxxu_read8(priv, REG_GPIO_INTM + 2); + val8 |= BIT(0); + rtl8xxxu_write8(priv, REG_GPIO_INTM + 2, val8); + + return 0; +} + +static int rtl8723au_power_on(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u16 val16; + u32 val32; + int ret; + + /* + * RSV_CTRL 0x001C[7:0] = 0x00, unlock ISO/CLK/Power control register + */ + rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0); + + rtl8xxxu_disabled_to_emu(priv); + + ret = rtl8xxxu_emu_to_active(priv); + if (ret) + goto exit; + + /* + * 0x0004[19] = 1, reset 8051 + */ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 2); + val8 |= BIT(3); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 2, val8); + + /* + * Enable MAC DMA/WMAC/SCHEDULE/SEC block + * Set CR bit10 to enable 32k calibration. + */ + val16 = rtl8xxxu_read16(priv, REG_CR); + val16 |= (CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE | + CR_TXDMA_ENABLE | CR_RXDMA_ENABLE | + CR_PROTOCOL_ENABLE | CR_SCHEDULE_ENABLE | + CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE | + CR_SECURITY_ENABLE | CR_CALTIMER_ENABLE); + rtl8xxxu_write16(priv, REG_CR, val16); + + /* For EFuse PG */ + val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL); + val32 &= ~(BIT(28) | BIT(29) | BIT(30)); + val32 |= (0x06 << 28); + rtl8xxxu_write32(priv, REG_EFUSE_CTRL, val32); +exit: + return ret; +} + +#ifdef CONFIG_RTL8XXXU_UNTESTED + +static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u16 val16; + u32 val32; + int i; + + for (i = 100; i; i--) { + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO); + if (val8 & APS_FSMCO_PFM_ALDN) + break; + } + + if (!i) { + pr_info("%s: Poll failed\n", __func__); + return -ENODEV; + } + + /* + * RSV_CTRL 0x001C[7:0] = 0x00, unlock ISO/CLK/Power control register + */ + rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0); + rtl8xxxu_write8(priv, REG_SPS0_CTRL, 0x2b); + udelay(100); + + val8 = rtl8xxxu_read8(priv, REG_LDOV12D_CTRL); + if (!(val8 & LDOV12D_ENABLE)) { + pr_info("%s: Enabling LDOV12D (%02x)\n", __func__, val8); + val8 |= LDOV12D_ENABLE; + rtl8xxxu_write8(priv, REG_LDOV12D_CTRL, val8); + + udelay(100); + + val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL); + val8 &= ~SYS_ISO_MD2PP; + rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8); + } + + /* + * Auto enable WLAN + */ + val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO); + val16 |= APS_FSMCO_MAC_ENABLE; + rtl8xxxu_write16(priv, REG_APS_FSMCO, val16); + + for (i = 1000; i; i--) { + val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO); + if (!(val16 & APS_FSMCO_MAC_ENABLE)) + break; + } + if (!i) { + pr_info("%s: FSMCO_MAC_ENABLE poll failed\n", __func__); + return -EBUSY; + } + + /* + * Enable radio, GPIO, LED + */ + val16 = APS_FSMCO_HW_SUSPEND | APS_FSMCO_ENABLE_POWERDOWN | + APS_FSMCO_PFM_ALDN; + rtl8xxxu_write16(priv, REG_APS_FSMCO, val16); + + /* + * Release RF digital isolation + */ + val16 = rtl8xxxu_read16(priv, REG_SYS_ISO_CTRL); + val16 &= ~SYS_ISO_DIOR; + rtl8xxxu_write16(priv, REG_SYS_ISO_CTRL, val16); + + val8 = rtl8xxxu_read8(priv, REG_APSD_CTRL); + val8 &= ~APSD_CTRL_OFF; + rtl8xxxu_write8(priv, REG_APSD_CTRL, val8); + for (i = 200; i; i--) { + val8 = rtl8xxxu_read8(priv, REG_APSD_CTRL); + if (!(val8 & APSD_CTRL_OFF_STATUS)) + break; + } + + if (!i) { + pr_info("%s: APSD_CTRL poll failed\n", __func__); + return -EBUSY; + } + + /* + * Enable MAC DMA/WMAC/SCHEDULE/SEC block + */ + val16 = rtl8xxxu_read16(priv, REG_CR); + val16 |= CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE | + CR_TXDMA_ENABLE | CR_RXDMA_ENABLE | CR_PROTOCOL_ENABLE | + CR_SCHEDULE_ENABLE | CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE; + rtl8xxxu_write16(priv, REG_CR, val16); + + /* + * Workaround for 8188RU LNA power leakage problem. + */ + if (priv->rtlchip == 0x8188c && priv->hi_pa) { + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM); + val32 &= ~BIT(1); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32); + } + return 0; +} + +#endif + +static void rtl8xxxu_power_off(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u16 val16; + u32 val32; + + /* + * Workaround for 8188RU LNA power leakage problem. + */ + if (priv->rtlchip == 0x8188c && priv->hi_pa) { + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM); + val32 |= BIT(1); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32); + } + + rtl8xxxu_active_to_lps(priv); + + /* Turn off RF */ + rtl8xxxu_write8(priv, REG_RF_CTRL, 0x00); + + /* Reset Firmware if running in RAM */ + if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL) + rtl8xxxu_firmware_self_reset(priv); + + /* Reset MCU */ + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 &= ~SYS_FUNC_CPU_ENABLE; + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + + /* Reset MCU ready status */ + rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00); + + rtl8xxxu_active_to_emu(priv); + rtl8xxxu_emu_to_disabled(priv); + + /* Reset MCU IO Wrapper */ + val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1); + val8 &= ~BIT(0); + rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8); + + val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1); + val8 |= BIT(0); + rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8); + + /* RSV_CTRL 0x1C[7:0] = 0x0e lock ISO/CLK/Power control register */ + rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0e); +} + +static void rtl8xxxu_init_bt(struct rtl8xxxu_priv *priv) +{ + if (!priv->has_bluetooth) + return; +} + +static int rtl8xxxu_init_device(struct ieee80211_hw *hw) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + struct rtl8xxxu_rfregval *rftable; + bool macpower; + int ret; + u8 val8; + u16 val16; + u32 val32; + + /* Check if MAC is already powered on */ + val8 = rtl8xxxu_read8(priv, REG_CR); + + /* + * Fix 92DU-VC S3 hang with the reason is that secondary mac is not + * initialized. First MAC returns 0xea, second MAC returns 0x00 + */ + if (val8 == 0xea) + macpower = false; + else + macpower = true; + + ret = priv->fops->power_on(priv); + if (ret < 0) { + dev_warn(dev, "%s: Failed power on\n", __func__); + goto exit; + } + + dev_dbg(dev, "%s: macpower %i\n", __func__, macpower); + if (!macpower) { + ret = rtl8xxxu_init_llt_table(priv, TX_TOTAL_PAGE_NUM); + if (ret) { + dev_warn(dev, "%s: LLT table init failed\n", __func__); + goto exit; + } + } + + ret = rtl8xxxu_download_firmware(priv); + dev_dbg(dev, "%s: download_fiwmare %i\n", __func__, ret); + if (ret) + goto exit; + ret = rtl8xxxu_start_firmware(priv); + dev_dbg(dev, "%s: start_fiwmare %i\n", __func__, ret); + if (ret) + goto exit; + + ret = rtl8xxxu_init_mac(priv, rtl8723a_mac_init_table); + dev_dbg(dev, "%s: init_mac %i\n", __func__, ret); + if (ret) + goto exit; + + ret = rtl8xxxu_init_phy_bb(priv); + dev_dbg(dev, "%s: init_phy_bb %i\n", __func__, ret); + if (ret) + goto exit; + + switch(priv->rtlchip) { + case 0x8723a: + rftable = rtl8723au_radioa_1t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + break; + case 0x8188c: + if (priv->hi_pa) + rftable = rtl8188ru_radioa_1t_highpa_table; + else + rftable = rtl8192cu_radioa_1t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + break; + case 0x8191c: + rftable = rtl8192cu_radioa_1t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + break; + case 0x8192c: + rftable = rtl8192cu_radioa_2t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + if (ret) + break; + rftable = rtl8192cu_radiob_2t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B); + break; + default: + ret = -EINVAL; + } + + if (ret) + goto exit; + + /* Reduce 80M spur */ + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); + + /* RFSW Control - clear bit 14 ?? */ + rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003); + /* 0x07000760 */ + val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | + FPGA0_RF_ANTSWB | FPGA0_RF_PAPE | + ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB | FPGA0_RF_PAPE) << + FPGA0_RF_BD_CTRL_SHIFT); + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); + /* 0x860[6:5]= 00 - why? - this sets antenna B */ + rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66F60210); + + priv->rf_mode_ag[0] = rtl8xxxu_read_rfreg(priv, RF_A, + RF6052_REG_MODE_AG); + + dev_dbg(dev, "%s: macpower %i\n", __func__, macpower); + if (!macpower) { + if (priv->ep_tx_normal_queue) + val8 = TX_PAGE_NUM_NORM_PQ; + else + val8 = 0; + + rtl8xxxu_write8(priv, REG_RQPN_NPQ, val8); + + val32 = (TX_PAGE_NUM_PUBQ << RQPN_NORM_PQ_SHIFT) | RQPN_LOAD; + + if (priv->ep_tx_high_queue) + val32 |= (TX_PAGE_NUM_HI_PQ << RQPN_HI_PQ_SHIFT); + if (priv->ep_tx_low_queue) + val32 |= (TX_PAGE_NUM_LO_PQ << RQPN_LO_PQ_SHIFT); + + rtl8xxxu_write32(priv, REG_RQPN, val32); + + /* + * Set TX buffer boundary + */ + val8 = TX_TOTAL_PAGE_NUM + 1; + rtl8xxxu_write8(priv, REG_TXPKTBUF_BCNQ_BDNY, val8); + rtl8xxxu_write8(priv, REG_TXPKTBUF_MGQ_BDNY, val8); + rtl8xxxu_write8(priv, REG_TXPKTBUF_WMAC_LBK_BF_HD, val8); + rtl8xxxu_write8(priv, REG_TRXFF_BNDY, val8); + rtl8xxxu_write8(priv, REG_TDECTRL + 1, val8); + } + + ret = rtl8xxxu_init_queue_priority(priv); + dev_dbg(dev, "%s: init_queue_priority %i\n", __func__, ret); + if (ret) + goto exit; + + /* + * Set RX page boundary + */ + rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x27ff); + /* + * Transfer page size is always 128 + */ + val8 = (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_RX_SHIFT) | + (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_TX_SHIFT); + rtl8xxxu_write8(priv, REG_PBP, val8); + + /* + * Unit in 8 bytes, not obvious what it is used for + */ + rtl8xxxu_write8(priv, REG_RX_DRVINFO_SZ, 4); + + /* + * Enable all interrupts - not obvious USB needs to do this + */ + rtl8xxxu_write32(priv, REG_HISR, 0xffffffff); + rtl8xxxu_write32(priv, REG_HIMR, 0xffffffff); + + rtl8xxxu_set_mac(priv); + rtl8xxxu_set_linktype(priv, NL80211_IFTYPE_STATION); + + /* + * Configure initial WMAC settings + */ + val32 = RCR_ACCEPT_PHYS_MATCH | RCR_ACCEPT_MCAST | RCR_ACCEPT_BCAST | + /* RCR_CHECK_BSSID_MATCH | RCR_CHECK_BSSID_BEACON | */ + RCR_ACCEPT_MGMT_FRAME | RCR_HTC_LOC_CTRL | + RCR_APPEND_PHYSTAT | RCR_APPEND_ICV | RCR_APPEND_MIC; + rtl8xxxu_write32(priv, REG_RCR, val32); + + /* + * Accept all multicast + */ + rtl8xxxu_write32(priv, REG_MAR, 0xffffffff); + rtl8xxxu_write32(priv, REG_MAR + 4, 0xffffffff); + + /* + * Init adaptive controls + */ + val32 = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET); + val32 &= ~RESPONSE_RATE_BITMAP_ALL; + val32 |= RESPONSE_RATE_RRSR_CCK_ONLY_1M; + rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, val32); + + /* CCK = 0x0a, OFDM = 0x10 */ + rtl8xxxu_set_spec_sifs(priv, 0x10, 0x10); + rtl8xxxu_set_retry(priv, 0x30, 0x30); + rtl8xxxu_set_spec_sifs(priv, 0x0a, 0x10); + + /* + * Init EDCA + */ + rtl8xxxu_write16(priv, REG_MAC_SPEC_SIFS, 0x100a); + + /* Set CCK SIFS */ + rtl8xxxu_write16(priv, REG_SIFS_CCK, 0x100a); + + /* Set OFDM SIFS */ + rtl8xxxu_write16(priv, REG_SIFS_OFDM, 0x100a); + + /* TXOP */ + rtl8xxxu_write32(priv, REG_EDCA_BE_PARAM, 0x005ea42b); + rtl8xxxu_write32(priv, REG_EDCA_BK_PARAM, 0x0000a44f); + rtl8xxxu_write32(priv, REG_EDCA_VI_PARAM, 0x005ea324); + rtl8xxxu_write32(priv, REG_EDCA_VO_PARAM, 0x002fa226); + + /* Set data auto rate fallback retry count */ + rtl8xxxu_write32(priv, REG_DARFRC, 0x00000000); + rtl8xxxu_write32(priv, REG_DARFRC + 4, 0x10080404); + rtl8xxxu_write32(priv, REG_RARFRC, 0x04030201); + rtl8xxxu_write32(priv, REG_RARFRC + 4, 0x08070605); + + val8 = rtl8xxxu_read8(priv, REG_FWHW_TXQ_CTRL); + val8 |= FWHW_TXQ_CTRL_AMPDU_RETRY; + rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL, val8); + + /* Set ACK timeout */ + rtl8xxxu_write8(priv, REG_ACKTO, 0x40); + + /* + * Initialize beacon parameters + */ + val16 = BEACON_DISABLE_TSF_UPDATE | (BEACON_DISABLE_TSF_UPDATE << 8); + rtl8xxxu_write16(priv, REG_BEACON_CTRL, val16); + rtl8xxxu_write16(priv, REG_TBTT_PROHIBIT, 0x6404); + rtl8xxxu_write8(priv, REG_DRIVER_EARLY_INT, DRIVER_EARLY_INT_TIME); + rtl8xxxu_write8(priv, REG_BEACON_DMA_TIME, BEACON_DMA_ATIME_INT_TIME); + rtl8xxxu_write16(priv, REG_BEACON_TCFG, 0x660F); + + /* + * Enable CCK and OFDM block + */ + val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + val32 |= (FPGA_RF_MODE_CCK | FPGA_RF_MODE_OFDM); + rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); + + /* + * Invalidate all CAM entries - bit 30 is undocumented + */ + rtl8xxxu_write32(priv, REG_CAM_CMD, CAM_CMD_POLLING | BIT(30)); + + /* + * Start out with default power levels for channel 6, 20MHz + */ + rtl8723a_set_tx_power(priv, 1, false); + + /* Let the 8051 take control of antenna setting */ + val8 = rtl8xxxu_read8(priv, REG_LEDCFG2); + val8 |= LEDCFG2_DPDT_SELECT; + rtl8xxxu_write8(priv, REG_LEDCFG2, val8); + + rtl8xxxu_write8(priv, REG_HWSEQ_CTRL, 0xff); + + /* Disable BAR - not sure if this has any effect on USB */ + rtl8xxxu_write32(priv, REG_BAR_MODE_CTRL, 0x0201ffff); + + rtl8xxxu_write16(priv, REG_FAST_EDCA_CTRL, 0); + + /* + * Not sure if we should get into this at all + */ + if (priv->iqk_initialized) { + rtl8xxxu_restore_regs(priv, rtl8723au_iqk_phy_iq_bb_reg, + priv->bb_recovery_backup, + RTL8XXXU_BB_REGS); + } else { + rtl8723a_phy_iq_calibrate(priv); + priv->iqk_initialized = true; + } + + /* + * This should enable thermal meter + */ + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_T_METER, 0x60); + + rtl8723a_phy_lc_calibrate(priv); + + /* fix USB interface interference issue */ + rtl8xxxu_write8(priv, 0xfe40, 0xe0); + rtl8xxxu_write8(priv, 0xfe41, 0x8d); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, 0xfd0320); + + /* Solve too many protocol error on USB bus */ + /* Can't do this for 8188/8192 UMC A cut parts */ + rtl8xxxu_write8(priv, 0xfe40, 0xe6); + rtl8xxxu_write8(priv, 0xfe41, 0x94); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + + rtl8xxxu_write8(priv, 0xfe40, 0xe0); + rtl8xxxu_write8(priv, 0xfe41, 0x19); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + + rtl8xxxu_write8(priv, 0xfe40, 0xe5); + rtl8xxxu_write8(priv, 0xfe41, 0x91); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + + rtl8xxxu_write8(priv, 0xfe40, 0xe2); + rtl8xxxu_write8(priv, 0xfe41, 0x81); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + + /* Init BT hw config. */ + rtl8xxxu_init_bt(priv); + + /* + * Not sure if we really need to save these parameters, but the + * vendor driver does + */ + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM2); + if (val32 & FPGA0_HSSI_PARM2_CCK_HIGH_PWR) + priv->path_a_hi_power = 1; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); + priv->path_a_rf_paths = val32 & OFDM_RF_PATH_RX_MASK; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1); + priv->path_a_ig_value = val32 & OFDM0_X_AGC_CORE1_IGI_MASK; + + /* Set NAV_UPPER to 30000us */ + val8 = ((30000 + NAV_UPPER_UNIT - 1) / NAV_UPPER_UNIT); + rtl8xxxu_write8(priv, REG_NAV_UPPER, val8); + + /* + * 2011/03/09 MH debug only, UMC-B cut pass 2500 S5 test, + * but we need to fin root cause. + */ + val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + if ((val32 & 0xff000000) != 0x83000000) { + val32 |= FPGA_RF_MODE_CCK; + rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); + } + + val32 = rtl8xxxu_read32(priv, REG_FWHW_TXQ_CTRL); + val32 |= FWHW_TXQ_CTRL_XMIT_MGMT_ACK; + /* ack for xmit mgmt frames. */ + rtl8xxxu_write32(priv, REG_FWHW_TXQ_CTRL, val32); + +exit: + return ret; +} + +static void rtl8xxxu_disable_device(struct ieee80211_hw *hw) +{ + struct rtl8xxxu_priv *priv = hw->priv; + + rtl8xxxu_power_off(priv); +} + +static void rtl8xxxu_cam_write(struct rtl8xxxu_priv *priv, + struct ieee80211_key_conf *key, const u8 *mac) +{ + u32 cmd, val32, addr, ctrl; + int j, i, tmp_debug; + + tmp_debug = rtl8xxxu_debug; + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_KEY) + rtl8xxxu_debug |= RTL8XXXU_DEBUG_REG_WRITE; + + /* + * This is a bit of a hack - the lower bits of the cipher + * suite selector happens to match the cipher index in the CAM + */ + addr = key->keyidx << CAM_CMD_KEY_SHIFT; + ctrl = (key->cipher & 0x0f) << 2 | key->keyidx | CAM_WRITE_VALID; + + for (j = 5; j >= 0; j--) { + switch (j) { + case 0: + val32 = ctrl | (mac[0] << 16) | (mac[1] << 24); + break; + case 1: + val32 = mac[2] | (mac[3] << 8) | + (mac[4] << 16) | (mac[5] << 24); + break; + default: + i = (j - 2) << 2; + val32 = key->key[i] | (key->key[i + 1] << 8) | + key->key[i + 2] << 16 | key->key[i + 3] << 24; + break; + } + + rtl8xxxu_write32(priv, REG_CAM_WRITE, val32); + cmd = CAM_CMD_POLLING | CAM_CMD_WRITE | (addr + j); + rtl8xxxu_write32(priv, REG_CAM_CMD, cmd); + udelay(100); + } + + rtl8xxxu_debug = tmp_debug; +} + +static void rtl8xxxu_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, const u8* mac) +{ + struct rtl8xxxu_priv *priv = hw->priv; + u8 val8; + + val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); + val8 |= BEACON_DISABLE_TSF_UPDATE; + rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); +} + +static void rtl8xxxu_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtl8xxxu_priv *priv = hw->priv; + u8 val8; + + val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); + val8 &= ~BEACON_DISABLE_TSF_UPDATE; + rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); +} + +static void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv, + u32 ramask, int sgi) +{ + struct h2c_cmd h2c; + + h2c.ramask.cmd = H2C_SET_RATE_MASK; + h2c.ramask.mask_lo = cpu_to_le16(ramask & 0xffff); + h2c.ramask.mask_hi = cpu_to_le16(ramask >> 16); + + h2c.ramask.arg = 0x80; + if (sgi) + h2c.ramask.arg |= 0x20; + + dev_dbg(&priv->udev->dev, "%s: rate mask %08x, arg %02x\n", __func__, + ramask, h2c.ramask.arg); + rtl8723a_h2c_cmd(priv, &h2c); +} + +static void rtl8xxxu_set_basic_rates(struct rtl8xxxu_priv *priv, u32 rate_cfg) +{ + u32 val32; + u8 rate_idx = 0; + + rate_cfg &= RESPONSE_RATE_BITMAP_ALL; + + val32 = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET); + val32 &= ~RESPONSE_RATE_BITMAP_ALL; + val32 |= rate_cfg; + rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, val32); + + dev_dbg(&priv->udev->dev, "%s: rates %08x\n", __func__, rate_cfg); + + while (rate_cfg) { + rate_cfg = (rate_cfg >> 1); + rate_idx++; + } + rtl8xxxu_write8(priv, REG_INIRTS_RATE_SEL, rate_idx); +} + +static void +rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, u32 changed) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + struct ieee80211_sta *sta; + u32 val32; + u8 val8; + + if (changed & BSS_CHANGED_ASSOC) { + struct h2c_cmd h2c; + + dev_dbg(dev, "Changed ASSOC: %i!\n", bss_conf->assoc); + + memset(&h2c, 0, sizeof(struct h2c_cmd)); + rtl8xxxu_set_linktype(priv, vif->type); + + if (bss_conf->assoc) { + u32 ramask; + int sgi = 0; + + rcu_read_lock(); + sta = ieee80211_find_sta(vif, bss_conf->bssid); + if (!sta) { + dev_info(dev, "%s: ASSOC no sta found\n", + __func__); + rcu_read_unlock(); + goto error; + } + + if (sta->ht_cap.ht_supported) + dev_info(dev, "%s: HT supported\n", __func__); + if (sta->vht_cap.vht_supported) + dev_info(dev, "%s: VHT supported\n", __func__); + + /* TODO: Set bits 28-31 for rate adaptive id */ + ramask = (sta->supp_rates[0] & 0xfff) | + sta->ht_cap.mcs.rx_mask[0] << 12 | + sta->ht_cap.mcs.rx_mask[1] << 20; + if (sta->ht_cap.cap & + (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20)) + sgi = 1; + rcu_read_unlock(); + + rtl8xxxu_update_rate_mask(priv, ramask, sgi); + + val32 = rtl8xxxu_read32(priv, REG_RCR); + val32 |= RCR_CHECK_BSSID_MATCH | RCR_CHECK_BSSID_BEACON; + rtl8xxxu_write32(priv, REG_RCR, val32); + + /* Enable RX of data frames */ + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0xffff); + + rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff); + + rtl8723a_stop_tx_beacon(priv); + + /* joinbss sequence */ + rtl8xxxu_write16(priv, REG_BCN_PSR_RPT, + 0xc000 | bss_conf->aid); + + h2c.joinbss.data = H2C_JOIN_BSS_CONNECT; + } else { + val32 = rtl8xxxu_read32(priv, REG_RCR); + val32 &= ~(RCR_CHECK_BSSID_MATCH | + RCR_CHECK_BSSID_BEACON); + rtl8xxxu_write32(priv, REG_RCR, val32); + + val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); + val8 |= BEACON_DISABLE_TSF_UPDATE; + rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); + + /* Disable RX of data frames */ + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x0000); + h2c.joinbss.data = H2C_JOIN_BSS_DISCONNECT; + } + h2c.joinbss.cmd = H2C_JOIN_BSS_REPORT; + rtl8723a_h2c_cmd(priv, &h2c); + } + + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + dev_dbg(dev, "Changed ERP_PREAMBLE: Use short preamble %i\n", + bss_conf->use_short_preamble); + val32 = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET); + if (bss_conf->use_short_preamble) + val32 |= RSR_ACK_SHORT_PREAMBLE; + else + val32 &= ~RSR_ACK_SHORT_PREAMBLE; + rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, val32); + } + + if (changed & BSS_CHANGED_ERP_SLOT) { + dev_dbg(dev, "Changed ERP_SLOT: short_slot_time %i\n", + bss_conf->use_short_slot); + + if (bss_conf->use_short_slot) + val8 = 9; + else + val8 = 20; + rtl8xxxu_write8(priv, REG_SLOT, val8); + } + + if (changed & BSS_CHANGED_BSSID) { + dev_dbg(dev, "Changed BSSID!\n"); + rtl8xxxu_set_bssid(priv, bss_conf->bssid); + } + + if (changed & BSS_CHANGED_BASIC_RATES) { + dev_dbg(dev, "Changed BASIC_RATES!\n"); + rtl8xxxu_set_basic_rates(priv, bss_conf->basic_rates); + } +error: + return; +} + +static u32 rtl8xxxu_80211_to_rtl_queue(u32 queue) +{ + u32 rtlqueue; + + switch (queue) { + case IEEE80211_AC_VO: + rtlqueue = TXDESC_QUEUE_VO; + break; + case IEEE80211_AC_VI: + rtlqueue = TXDESC_QUEUE_VI; + break; + case IEEE80211_AC_BE: + rtlqueue = TXDESC_QUEUE_BE; + break; + case IEEE80211_AC_BK: + rtlqueue = TXDESC_QUEUE_BK; + break; + default: + rtlqueue = TXDESC_QUEUE_BE; + } + + return rtlqueue; +} + +static u32 rtl8xxxu_queue_select(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + u32 queue; + + if (ieee80211_is_mgmt(hdr->frame_control)) + queue = TXDESC_QUEUE_MGNT; + else + queue = rtl8xxxu_80211_to_rtl_queue(skb_get_queue_mapping(skb)); + + return queue; +} + +static void rtl8xxxu_calc_tx_desc_csum(struct rtl8xxxu_tx_desc *tx_desc) +{ + __le16 *ptr = (__le16 *)tx_desc; + u16 csum = 0; + int i; + + /* + * Clear csum field before calculation, as the csum field is + * in the middle of the struct. + */ + tx_desc->csum = cpu_to_le16(0); + + for (i = 0; i < (sizeof(struct rtl8xxxu_tx_desc) / sizeof(u16)); i++) + csum = csum ^ le16_to_cpu(ptr[i]); + + tx_desc->csum |= cpu_to_le16(csum); +} + +static void rtl8xxxu_free_tx_resources(struct rtl8xxxu_priv *priv) +{ + struct rtl8xxxu_tx_urb *tx_urb, *tmp; + unsigned long flags; + + spin_lock_irqsave(&priv->tx_urb_lock, flags); + list_for_each_entry_safe(tx_urb, tmp, &priv->tx_urb_free_list, list) { + list_del(&tx_urb->list); + priv->tx_urb_free_count--; + usb_free_urb(&tx_urb->urb); + } + spin_unlock_irqrestore(&priv->tx_urb_lock, flags); +} + +static struct rtl8xxxu_tx_urb * +rtl8xxxu_alloc_tx_urb(struct rtl8xxxu_priv *priv) +{ + struct rtl8xxxu_tx_urb *tx_urb; + unsigned long flags; + + spin_lock_irqsave(&priv->tx_urb_lock, flags); + tx_urb = list_first_entry_or_null(&priv->tx_urb_free_list, + struct rtl8xxxu_tx_urb, list); + if (tx_urb) { + list_del(&tx_urb->list); + priv->tx_urb_free_count--; + if (priv->tx_urb_free_count < RTL8XXXU_TX_URB_LOW_WATER && + !priv->tx_stopped) { + priv->tx_stopped = true; + ieee80211_stop_queues(priv->hw); + } + } + + spin_unlock_irqrestore(&priv->tx_urb_lock, flags); + + return tx_urb; +} + +static void rtl8xxxu_free_tx_urb(struct rtl8xxxu_priv *priv, + struct rtl8xxxu_tx_urb *tx_urb) +{ + unsigned long flags; + + INIT_LIST_HEAD(&tx_urb->list); + + spin_lock_irqsave(&priv->tx_urb_lock, flags); + + list_add(&tx_urb->list, &priv->tx_urb_free_list); + priv->tx_urb_free_count++; + if (priv->tx_urb_free_count > RTL8XXXU_TX_URB_HIGH_WATER && + priv->tx_stopped) { + priv->tx_stopped = false; + ieee80211_wake_queues(priv->hw); + } + + spin_unlock_irqrestore(&priv->tx_urb_lock, flags); +} + +static void rtl8xxxu_tx_complete(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *)urb->context; + struct ieee80211_tx_info *tx_info; + struct ieee80211_hw *hw; + struct rtl8xxxu_tx_urb *tx_urb = + container_of(urb, struct rtl8xxxu_tx_urb, urb); + + tx_info = IEEE80211_SKB_CB(skb); + hw = tx_info->rate_driver_data[0]; + + skb_pull(skb, sizeof(struct rtl8xxxu_tx_desc)); + + ieee80211_tx_info_clear_status(tx_info); + tx_info->status.rates[0].idx = -1; + tx_info->status.rates[0].count = 0; + + if (!urb->status) + tx_info->flags |= IEEE80211_TX_STAT_ACK; + + ieee80211_tx_status_irqsafe(hw, skb); + + rtl8xxxu_free_tx_urb(hw->priv, tx_urb); +} + +static void rtl8xxxu_dump_action(struct device *dev, + struct ieee80211_hdr *hdr) +{ + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)hdr; + u16 cap, timeout; + + if (!(rtl8xxxu_debug & RTL8XXXU_DEBUG_ACTION)) + return; + + switch (mgmt->u.action.u.addba_resp.action_code) { + case WLAN_ACTION_ADDBA_RESP: + cap = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); + timeout = le16_to_cpu(mgmt->u.action.u.addba_resp.timeout); + dev_info(dev, "WLAN_ACTION_ADDBA_RESP: " + "timeout %i, tid %02x, buf_size %02x, policy %02x, " + "status %02x\n", + timeout, + (cap & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2, + (cap & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6, + (cap >> 1) & 0x1, + le16_to_cpu(mgmt->u.action.u.addba_resp.status)); + break; + case WLAN_ACTION_ADDBA_REQ: + cap = le16_to_cpu(mgmt->u.action.u.addba_req.capab); + timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); + dev_info(dev, "WLAN_ACTION_ADDBA_REQ: " + "timeout %i, tid %02x, buf_size %02x, policy %02x\n", + timeout, + (cap & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2, + (cap & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6, + (cap >> 1) & 0x1); + break; + default: + dev_info(dev, "action frame %02x\n", + mgmt->u.action.u.addba_resp.action_code); + break; + } +} + +static void rtl8xxxu_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info); + struct rtl8xxxu_priv *priv = hw->priv; + struct rtl8xxxu_tx_desc *tx_desc; + struct rtl8xxxu_tx_urb *tx_urb; + struct ieee80211_sta *sta = NULL; + struct ieee80211_vif *vif = tx_info->control.vif; + struct device *dev = &priv->udev->dev; + u32 queue, rate; + u16 pktlen = skb->len; + u16 seq_number; + u16 rate_flag = tx_info->control.rates[0].flags; + int ret; + + if (skb_headroom(skb) < sizeof(struct rtl8xxxu_tx_desc)) { + dev_warn(dev, + "%s: Not enough headroom (%i) for tx descriptor\n", + __func__, skb_headroom(skb)); + goto error; + } + + if (unlikely(skb->len > (65535 - sizeof(struct rtl8xxxu_tx_desc)))) { + dev_warn(dev, "%s: Trying to send over-sized skb (%i)\n", + __func__, skb->len); + goto error; + } + + tx_urb = rtl8xxxu_alloc_tx_urb(priv); + if (!tx_urb) { + dev_warn(dev, "%s: Unable to allocate tx urb\n", __func__); + goto error; + } + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX) + dev_info(dev, "%s: TX rate: %d (%d), pkt size %d\n", + __func__, tx_rate->bitrate, tx_rate->hw_value, pktlen); + + if (ieee80211_is_action(hdr->frame_control)) + rtl8xxxu_dump_action(dev, hdr); + + tx_info->rate_driver_data[0] = hw; + + if (control && control->sta) + sta = control->sta; + + tx_desc = (struct rtl8xxxu_tx_desc *) + skb_push(skb, sizeof(struct rtl8xxxu_tx_desc)); + + memset(tx_desc, 0, sizeof(struct rtl8xxxu_tx_desc)); + tx_desc->pkt_size = cpu_to_le16(pktlen); + tx_desc->pkt_offset = sizeof(struct rtl8xxxu_tx_desc); + + tx_desc->txdw0 = + TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT; + if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || + is_broadcast_ether_addr(ieee80211_get_DA(hdr))) + tx_desc->txdw0 |= TXDESC_BROADMULTICAST; + + queue = rtl8xxxu_queue_select(hw, skb); + tx_desc->txdw1 = cpu_to_le32(queue << TXDESC_QUEUE_SHIFT); + + if (tx_info->control.hw_key) { + switch (tx_info->control.hw_key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + tx_desc->txdw1 |= cpu_to_le32(TXDESC_SEC_RC4); + break; + case WLAN_CIPHER_SUITE_CCMP: + tx_desc->txdw1 |= cpu_to_le32(TXDESC_SEC_AES); + break; + default: + break; + } + } + + seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); + tx_desc->txdw3 = cpu_to_le32((u32)seq_number << TXDESC_SEQ_SHIFT); + + if (rate_flag & IEEE80211_TX_RC_MCS) + rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0; + else + rate = tx_rate->hw_value; + tx_desc->txdw5 = cpu_to_le32(rate); + + if (ieee80211_is_data(hdr->frame_control)) + tx_desc->txdw5 |= cpu_to_le32(0x0001ff00); + + /* (tx_info->flags & IEEE80211_TX_CTL_AMPDU) && */ + if (ieee80211_is_data_qos(hdr->frame_control) && sta) { + if (sta->ht_cap.ht_supported) { + u32 ampdu, val32; + + ampdu = (u32)sta->ht_cap.ampdu_density; + val32 = ampdu << TXDESC_AMPDU_DENSITY_SHIFT; + tx_desc->txdw2 |= cpu_to_le32(val32); + tx_desc->txdw1 |= cpu_to_le32(TXDESC_AGG_ENABLE); + } else + tx_desc->txdw1 |= cpu_to_le32(TXDESC_BK); + } else + tx_desc->txdw1 |= cpu_to_le32(TXDESC_BK); + + if (ieee80211_is_data_qos(hdr->frame_control)) + tx_desc->txdw4 |= cpu_to_le32(TXDESC_QOS); + if (rate_flag & IEEE80211_TX_RC_USE_SHORT_PREAMBLE || + (sta && vif && vif->bss_conf.use_short_preamble)) + tx_desc->txdw4 |= cpu_to_le32(TXDESC_SHORT_PREAMBLE); + if (rate_flag & IEEE80211_TX_RC_SHORT_GI || + (ieee80211_is_data_qos(hdr->frame_control) && + sta && sta->ht_cap.cap & + (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20))) { + tx_desc->txdw5 |= cpu_to_le32(TXDESC_SHORT_GI); + } + if (ieee80211_is_mgmt(hdr->frame_control)) { + tx_desc->txdw5 = cpu_to_le32(tx_rate->hw_value); + tx_desc->txdw4 |= cpu_to_le32(TXDESC_USE_DRIVER_RATE); + tx_desc->txdw5 |= cpu_to_le32(6 << TXDESC_RETRY_LIMIT_SHIFT); + tx_desc->txdw5 |= cpu_to_le32(TXDESC_RETRY_LIMIT_ENABLE); + } + + if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) { + /* Use RTS rate 24M - does the mac80211 tell us which to use? */ + tx_desc->txdw4 |= cpu_to_le32(DESC_RATE_24M); + tx_desc->txdw4 |= cpu_to_le32(TXDESC_RTS_CTS_ENABLE); + tx_desc->txdw4 |= cpu_to_le32(TXDESC_HW_RTS_ENABLE); + } + + rtl8xxxu_calc_tx_desc_csum(tx_desc); + + usb_fill_bulk_urb(&tx_urb->urb, priv->udev, priv->pipe_out[queue], + skb->data, skb->len, rtl8xxxu_tx_complete, skb); + + usb_anchor_urb(&tx_urb->urb, &priv->tx_anchor); + ret = usb_submit_urb(&tx_urb->urb, GFP_ATOMIC); + if (ret) { + usb_unanchor_urb(&tx_urb->urb); + rtl8xxxu_free_tx_urb(priv, tx_urb); + goto error; + } + return; +error: + dev_kfree_skb(skb); +} + +static void rtl8xxxu_rx_parse_phystats(struct rtl8xxxu_priv *priv, + struct ieee80211_rx_status *rx_status, + struct rtl8xxxu_rx_desc *rx_desc, + struct rtl8723au_phy_stats *phy_stats) +{ + if (phy_stats->sgi_en) + rx_status->flag |= RX_FLAG_SHORT_GI; + + if (rx_desc->rxmcs < DESC_RATE_6M) { + /* + * Handle PHY stats for CCK rates + */ + u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a; + + switch (cck_agc_rpt & 0xc0) { + case 0xc0: + rx_status->signal = -46 - (cck_agc_rpt & 0x3e); + break; + case 0x80: + rx_status->signal = -26 - (cck_agc_rpt & 0x3e); + break; + case 0x40: + rx_status->signal = -12 - (cck_agc_rpt & 0x3e); + break; + case 0x00: + rx_status->signal = 16 - (cck_agc_rpt & 0x3e); + break; + } + } else { + rx_status->signal = + (phy_stats->cck_sig_qual_ofdm_pwdb_all >> 1) - 110; + } +} + +static void rtl8xxxu_free_rx_resources(struct rtl8xxxu_priv *priv) +{ + struct rtl8xxxu_rx_urb *rx_urb, *tmp; + unsigned long flags; + + spin_lock_irqsave(&priv->rx_urb_lock, flags); + + list_for_each_entry_safe(rx_urb, tmp, + &priv->rx_urb_pending_list, list) { + list_del(&rx_urb->list); + priv->rx_urb_pending_count--; + usb_free_urb(&rx_urb->urb); + } + + spin_unlock_irqrestore(&priv->rx_urb_lock, flags); +} + +static void rtl8xxxu_queue_rx_urb(struct rtl8xxxu_priv *priv, + struct rtl8xxxu_rx_urb *rx_urb) +{ + struct sk_buff *skb; + unsigned long flags; + int pending = 0; + + spin_lock_irqsave(&priv->rx_urb_lock, flags); + + if (!priv->shutdown) { + list_add_tail(&rx_urb->list, &priv->rx_urb_pending_list); + priv->rx_urb_pending_count++; + pending = priv->rx_urb_pending_count; + } else { + skb = (struct sk_buff *)rx_urb->urb.context; + dev_kfree_skb(skb); + usb_free_urb(&rx_urb->urb); + } + + spin_unlock_irqrestore(&priv->rx_urb_lock, flags); + + if (pending > RTL8XXXU_RX_URB_PENDING_WATER) + schedule_work(&priv->rx_urb_wq); +} + +static void rtl8xxxu_rx_urb_work(struct work_struct *work) +{ + struct rtl8xxxu_priv *priv; + struct rtl8xxxu_rx_urb *rx_urb, *tmp; + struct list_head local; + struct sk_buff *skb; + unsigned long flags; + int ret; + + priv = container_of(work, struct rtl8xxxu_priv, rx_urb_wq); + INIT_LIST_HEAD(&local); + + spin_lock_irqsave(&priv->rx_urb_lock, flags); + + list_splice_init(&priv->rx_urb_pending_list, &local); + priv->rx_urb_pending_count = 0; + + spin_unlock_irqrestore(&priv->rx_urb_lock, flags); + + list_for_each_entry_safe(rx_urb, tmp, &local, list) { + list_del_init(&rx_urb->list); + ret = rtl8xxxu_submit_rx_urb(priv, rx_urb); + /* + * If out of memory or temporary error, put it back on the + * queue and try again. Otherwise the device is dead/gone + * and we should drop it. + */ + switch (ret) { + case 0: + break; + case -ENOMEM: + case -EAGAIN: + rtl8xxxu_queue_rx_urb(priv, rx_urb); + break; + default: + pr_info("failed to requeue urb %i\n", ret); + skb = (struct sk_buff *)rx_urb->urb.context; + dev_kfree_skb(skb); + usb_free_urb(&rx_urb->urb); + } + } +} + +static void rtl8xxxu_rx_complete(struct urb *urb) +{ + struct rtl8xxxu_rx_urb *rx_urb = + container_of(urb, struct rtl8xxxu_rx_urb, urb); + struct ieee80211_hw *hw = rx_urb->hw; + struct rtl8xxxu_priv *priv = hw->priv; + struct sk_buff *skb = (struct sk_buff *)urb->context; + struct rtl8xxxu_rx_desc *rx_desc = (struct rtl8xxxu_rx_desc *)skb->data; + struct rtl8723au_phy_stats *phy_stats; + struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); + struct ieee80211_mgmt *mgmt; + struct device *dev = &priv->udev->dev; + __le32 *_rx_desc_le = (__le32 *)skb->data; + u32 *_rx_desc = (u32 *)skb->data; + int cnt, len, drvinfo_sz, desc_shift, i; + + for (i = 0; i < (sizeof(struct rtl8xxxu_rx_desc) / sizeof(u32)); i++) + _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); + + cnt = rx_desc->frag; + len = rx_desc->pktlen; + drvinfo_sz = rx_desc->drvinfo_sz * 8; + desc_shift = rx_desc->shift; + skb_put(skb, urb->actual_length); + + if (urb->status == 0) { + skb_pull(skb, sizeof(struct rtl8xxxu_rx_desc)); + phy_stats = (struct rtl8723au_phy_stats *)skb->data; + + skb_pull(skb, drvinfo_sz + desc_shift); + + mgmt = (struct ieee80211_mgmt *)skb->data; + + memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); + + if (rx_desc->phy_stats) + rtl8xxxu_rx_parse_phystats(priv, rx_status, + rx_desc, phy_stats); + + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; + + rx_status->mactime = le32_to_cpu(rx_desc->tsfl); + rx_status->flag |= RX_FLAG_MACTIME_START; + + if (!rx_desc->swdec) + rx_status->flag |= RX_FLAG_DECRYPTED; + if (rx_desc->crc32) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + if (rx_desc->bw) + rx_status->flag |= RX_FLAG_40MHZ; + + if (rx_desc->rxht) { + rx_status->flag |= RX_FLAG_HT; + rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0; + } else { + rx_status->rate_idx = rx_desc->rxmcs; + } + + ieee80211_rx_irqsafe(hw, skb); + skb = NULL; + rx_urb->urb.context = NULL; + rtl8xxxu_queue_rx_urb(priv, rx_urb); + } else { + dev_dbg(dev, "%s: status %i\n", __func__, urb->status); + goto cleanup; + } + return; + +cleanup: + usb_free_urb(urb); + dev_kfree_skb(skb); + return; +} + +static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_priv *priv, + struct rtl8xxxu_rx_urb *rx_urb) +{ + struct sk_buff *skb; + int skb_size; + int ret; + + skb_size = sizeof(struct rtl8xxxu_rx_desc) + RTL_RX_BUFFER_SIZE; + skb = __netdev_alloc_skb(NULL, skb_size, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + memset(skb->data, 0, sizeof(struct rtl8xxxu_rx_desc)); + usb_fill_bulk_urb(&rx_urb->urb, priv->udev, priv->pipe_in, skb->data, + skb_size, rtl8xxxu_rx_complete, skb); + usb_anchor_urb(&rx_urb->urb, &priv->rx_anchor); + ret = usb_submit_urb(&rx_urb->urb, GFP_ATOMIC); + if (ret) + usb_unanchor_urb(&rx_urb->urb); + return ret; +} + +static void rtl8xxxu_int_complete(struct urb *urb) +{ + struct rtl8xxxu_priv *priv = (struct rtl8xxxu_priv *)urb->context; + struct device *dev = &priv->udev->dev; + int ret; + + dev_dbg(dev, "%s: status %i\n", __func__, urb->status); + if (urb->status == 0) { + usb_anchor_urb(urb, &priv->int_anchor); + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) + usb_unanchor_urb(urb); + } else { + dev_info(dev, "%s: Error %i\n", __func__, urb->status); + } +} + + +static int rtl8xxxu_submit_int_urb(struct ieee80211_hw *hw) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct urb *urb; + u32 val32; + int ret; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + return -ENOMEM; + + usb_fill_int_urb(urb, priv->udev, priv->pipe_interrupt, + priv->int_buf, USB_INTR_CONTENT_LENGTH, + rtl8xxxu_int_complete, priv, 1); + usb_anchor_urb(urb, &priv->int_anchor); + ret = usb_submit_urb(urb, GFP_KERNEL); + if (ret) { + usb_unanchor_urb(urb); + goto error; + } + + val32 = rtl8xxxu_read32(priv, REG_USB_HIMR); + val32 |= USB_HIMR_CPWM; + rtl8xxxu_write32(priv, REG_USB_HIMR, val32); + +error: + return ret; +} + +static int rtl8xxxu_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtl8xxxu_priv *priv = hw->priv; + int ret; + u8 val8; + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + rtl8723a_stop_tx_beacon(priv); + + val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); + val8 |= BEACON_ATIM | BEACON_FUNCTION_ENABLE | + BEACON_DISABLE_TSF_UPDATE; + rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); + ret = 0; + break; + default: + ret = -EOPNOTSUPP; + } + + rtl8xxxu_set_linktype(priv, vif->type); + + return ret; +} + +static void rtl8xxxu_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtl8xxxu_priv *priv = hw->priv; + + dev_dbg(&priv->udev->dev, "%s\n", __func__); +} + +static int rtl8xxxu_config(struct ieee80211_hw *hw, u32 changed) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + u16 val16; + int ret = 0, channel; + bool ht40; + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_CHANNEL) + dev_info(dev, + "%s: channel: %i (changed %08x chandef.width %02x)\n", + __func__, hw->conf.chandef.chan->hw_value, + changed, hw->conf.chandef.width); + + if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { + val16 = ((hw->conf.long_frame_max_tx_count << + RETRY_LIMIT_LONG_SHIFT) & RETRY_LIMIT_LONG_MASK) | + ((hw->conf.short_frame_max_tx_count << + RETRY_LIMIT_SHORT_SHIFT) & RETRY_LIMIT_SHORT_MASK); + rtl8xxxu_write16(priv, REG_RETRY_LIMIT, val16); + } + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + switch (hw->conf.chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + ht40 = false; + break; + case NL80211_CHAN_WIDTH_40: + ht40 = true; + break; + default: + ret = -ENOTSUPP; + goto exit; + } + + channel = hw->conf.chandef.chan->hw_value; + + rtl8723a_set_tx_power(priv, channel, ht40); + + rtl8723au_config_channel(hw); + } + +exit: + return ret; +} + +static int rtl8xxxu_conf_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u16 queue, + const struct ieee80211_tx_queue_params *param) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + u32 val32; + u8 aifs, acm_ctrl, acm_bit; + + aifs = param->aifs; + + val32 = aifs | + fls(param->cw_min) << EDCA_PARAM_ECW_MIN_SHIFT | + fls(param->cw_max) << EDCA_PARAM_ECW_MAX_SHIFT | + (u32)param->txop << EDCA_PARAM_TXOP_SHIFT; + + acm_ctrl = rtl8xxxu_read8(priv, REG_ACM_HW_CTRL); + dev_dbg(dev, + "%s: IEEE80211 queue %02x val %08x, acm %i, acm_ctrl %02x\n", + __func__, queue, val32, param->acm, acm_ctrl); + + switch (queue) { + case IEEE80211_AC_VO: + acm_bit = ACM_HW_CTRL_VO; + rtl8xxxu_write32(priv, REG_EDCA_VO_PARAM, val32); + break; + case IEEE80211_AC_VI: + acm_bit = ACM_HW_CTRL_VI; + rtl8xxxu_write32(priv, REG_EDCA_VI_PARAM, val32); + break; + case IEEE80211_AC_BE: + acm_bit = ACM_HW_CTRL_BE; + rtl8xxxu_write32(priv, REG_EDCA_BE_PARAM, val32); + break; + case IEEE80211_AC_BK: + acm_bit = ACM_HW_CTRL_BK; + rtl8xxxu_write32(priv, REG_EDCA_BK_PARAM, val32); + break; + default: + acm_bit = 0; + break; + } + + if (param->acm) + acm_ctrl |= acm_bit; + else + acm_ctrl &= ~acm_bit; + rtl8xxxu_write8(priv, REG_ACM_HW_CTRL, acm_ctrl); + + return 0; +} + +static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, u64 multicast) +{ + struct rtl8xxxu_priv *priv = hw->priv; + + dev_dbg(&priv->udev->dev, "%s: changed_flags %08x, total_flags %08x\n", + __func__, changed_flags, *total_flags); + + *total_flags &= (FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC); +} + +static int rtl8xxxu_set_rts_threshold(struct ieee80211_hw *hw, u32 rts) +{ + if (rts > 2347) + return -EINVAL; + + return 0; +} + +static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + u8 mac_addr[ETH_ALEN]; + u8 val8; + u16 val16; + u32 val32; + int retval = -EOPNOTSUPP; + + dev_dbg(dev, "%s: cmd %02x, cipher %08x, index %i\n", + __func__, cmd, key->cipher, key->keyidx); + + if (vif->type != NL80211_IFTYPE_STATION) + return -EOPNOTSUPP; + + if (key->keyidx > 3) + return -EOPNOTSUPP; + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + + break; + case WLAN_CIPHER_SUITE_CCMP: + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; + break; + case WLAN_CIPHER_SUITE_TKIP: + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + default: + return -EOPNOTSUPP; + } + + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { + dev_dbg(dev, "%s: pairwise key\n", __func__); + ether_addr_copy(mac_addr, sta->addr); + } else { + dev_dbg(dev, "%s: group key\n", __func__); + eth_broadcast_addr(mac_addr); + } + + val16 = rtl8xxxu_read16(priv, REG_CR); + val16 |= CR_SECURITY_ENABLE; + rtl8xxxu_write16(priv, REG_CR, val16); + + val8 = SEC_CFG_TX_SEC_ENABLE | SEC_CFG_TXBC_USE_DEFKEY | + SEC_CFG_RX_SEC_ENABLE | SEC_CFG_RXBC_USE_DEFKEY; + val8 |= SEC_CFG_TX_USE_DEFKEY | SEC_CFG_RX_USE_DEFKEY; + rtl8xxxu_write8(priv, REG_SECURITY_CFG, val8); + + switch (cmd) { + case SET_KEY: + key->hw_key_idx = key->keyidx; + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + rtl8xxxu_cam_write(priv, key, mac_addr); + retval = 0; + break; + case DISABLE_KEY: + rtl8xxxu_write32(priv, REG_CAM_WRITE, 0x00000000); + val32 = CAM_CMD_POLLING | CAM_CMD_WRITE | + key->keyidx << CAM_CMD_KEY_SHIFT; + rtl8xxxu_write32(priv, REG_CAM_CMD, val32); + retval = 0; + break; + default: + dev_warn(dev, "%s: Unsupported command %02x\n", __func__, cmd); + } + + return retval; +} + +static int +rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, + bool amsdu) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + u8 ampdu_factor, ampdu_density; + + switch (action) { + case IEEE80211_AMPDU_TX_START: + dev_info(dev, "%s: IEEE80211_AMPDU_TX_START\n", __func__); + ampdu_factor = sta->ht_cap.ampdu_factor; + ampdu_density = sta->ht_cap.ampdu_density; + rtl8xxxu_set_ampdu_factor(priv, ampdu_factor); + rtl8xxxu_set_ampdu_min_space(priv, ampdu_density); + dev_dbg(dev, + "Changed HT: ampdu_factor %02x, ampdu_density %02x\n", + ampdu_factor, ampdu_density); + break; + case IEEE80211_AMPDU_TX_STOP_FLUSH: + dev_info(dev, "%s: IEEE80211_AMPDU_TX_STOP_FLUSH\n", __func__); + rtl8xxxu_set_ampdu_factor(priv, 0); + rtl8xxxu_set_ampdu_min_space(priv, 0); + break; + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: + dev_info(dev, "%s: IEEE80211_AMPDU_TX_STOP_FLUSH_CONT\n", + __func__); + rtl8xxxu_set_ampdu_factor(priv, 0); + rtl8xxxu_set_ampdu_min_space(priv, 0); + break; + case IEEE80211_AMPDU_RX_START: + dev_info(dev, "%s: IEEE80211_AMPDU_RX_START\n", __func__); + break; + case IEEE80211_AMPDU_RX_STOP: + dev_info(dev, "%s: IEEE80211_AMPDU_RX_STOP\n", __func__); + break; + default: + break; + } + return 0; +} + +static int rtl8xxxu_start(struct ieee80211_hw *hw) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct rtl8xxxu_rx_urb *rx_urb; + struct rtl8xxxu_tx_urb *tx_urb; + unsigned long flags; + int ret, i; + + ret = 0; + + init_usb_anchor(&priv->rx_anchor); + init_usb_anchor(&priv->tx_anchor); + init_usb_anchor(&priv->int_anchor); + + rtl8723a_enable_rf(priv); + ret = rtl8xxxu_submit_int_urb(hw); + if (ret) + goto exit; + + for (i = 0; i < RTL8XXXU_TX_URBS; i++) { + tx_urb = kmalloc(sizeof(struct rtl8xxxu_tx_urb), GFP_KERNEL); + if (!tx_urb) { + if (!i) + ret = -ENOMEM; + + goto error_out; + } + usb_init_urb(&tx_urb->urb); + INIT_LIST_HEAD(&tx_urb->list); + tx_urb->hw = hw; + list_add(&tx_urb->list, &priv->tx_urb_free_list); + priv->tx_urb_free_count++; + } + + priv->tx_stopped = false; + + spin_lock_irqsave(&priv->rx_urb_lock, flags); + priv->shutdown = false; + spin_unlock_irqrestore(&priv->rx_urb_lock, flags); + + for (i = 0; i < RTL8XXXU_RX_URBS; i++) { + rx_urb = kmalloc(sizeof(struct rtl8xxxu_rx_urb), GFP_KERNEL); + if (!rx_urb) { + if (!i) + ret = -ENOMEM; + + goto error_out; + } + usb_init_urb(&rx_urb->urb); + INIT_LIST_HEAD(&rx_urb->list); + rx_urb->hw = hw; + + ret = rtl8xxxu_submit_rx_urb(priv, rx_urb); + } +exit: + /* + * Disable all data frames + */ + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x0000); + /* + * Accept all mgmt frames + */ + rtl8xxxu_write16(priv, REG_RXFLTMAP0, 0xffff); + + rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, 0x6954341e); + + return ret; + +error_out: + rtl8xxxu_free_tx_resources(priv); + /* + * Disable all data and mgmt frames + */ + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x0000); + rtl8xxxu_write16(priv, REG_RXFLTMAP0, 0x0000); + + return ret; +} + +static void rtl8xxxu_stop(struct ieee80211_hw *hw) +{ + struct rtl8xxxu_priv *priv = hw->priv; + unsigned long flags; + + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); + + rtl8xxxu_write16(priv, REG_RXFLTMAP0, 0x0000); + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x0000); + + spin_lock_irqsave(&priv->rx_urb_lock, flags); + priv->shutdown = true; + spin_unlock_irqrestore(&priv->rx_urb_lock, flags); + + usb_kill_anchored_urbs(&priv->rx_anchor); + usb_kill_anchored_urbs(&priv->tx_anchor); + usb_kill_anchored_urbs(&priv->int_anchor); + + rtl8723a_disable_rf(priv); + + /* + * Disable interrupts + */ + rtl8xxxu_write32(priv, REG_USB_HIMR, 0); + + rtl8xxxu_free_rx_resources(priv); + rtl8xxxu_free_tx_resources(priv); +} + +static const struct ieee80211_ops rtl8xxxu_ops = { + .tx = rtl8xxxu_tx, + .add_interface = rtl8xxxu_add_interface, + .remove_interface = rtl8xxxu_remove_interface, + .config = rtl8xxxu_config, + .conf_tx = rtl8xxxu_conf_tx, + .bss_info_changed = rtl8xxxu_bss_info_changed, + .configure_filter = rtl8xxxu_configure_filter, + .set_rts_threshold = rtl8xxxu_set_rts_threshold, + .start = rtl8xxxu_start, + .stop = rtl8xxxu_stop, + .sw_scan_start = rtl8xxxu_sw_scan_start, + .sw_scan_complete = rtl8xxxu_sw_scan_complete, + .set_key = rtl8xxxu_set_key, + .ampdu_action = rtl8xxxu_ampdu_action, +}; + +static int rtl8xxxu_parse_usb(struct rtl8xxxu_priv *priv, + struct usb_interface *interface) +{ + struct usb_interface_descriptor *interface_desc; + struct usb_host_interface *host_interface; + struct usb_endpoint_descriptor *endpoint; + struct device *dev = &priv->udev->dev; + int i, j = 0, endpoints; + u8 dir, xtype, num; + int ret = 0; + + host_interface = &interface->altsetting[0]; + interface_desc = &host_interface->desc; + endpoints = interface_desc->bNumEndpoints; + + for (i = 0; i < endpoints; i++) { + endpoint = &host_interface->endpoint[i].desc; + + dir = endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK; + num = usb_endpoint_num(endpoint); + xtype = usb_endpoint_type(endpoint); + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB) + dev_dbg(dev, + "%s: endpoint: dir %02x, # %02x, type %02x\n", + __func__, dir, num, xtype); + if (usb_endpoint_dir_in(endpoint) && + usb_endpoint_xfer_bulk(endpoint)) { + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB) + dev_dbg(dev, "%s: in endpoint num %i\n", + __func__, num); + + if (priv->pipe_in) { + dev_warn(dev, + "%s: Too many IN pipes\n", __func__); + ret = -EINVAL; + goto exit; + } + + priv->pipe_in = usb_rcvbulkpipe(priv->udev, num); + } + + if (usb_endpoint_dir_in(endpoint) && + usb_endpoint_xfer_int(endpoint)) { + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB) + dev_dbg(dev, "%s: interrupt endpoint num %i\n", + __func__, num); + + if (priv->pipe_interrupt) { + dev_warn(dev, "%s: Too many INTERRUPT pipes\n", + __func__); + ret = -EINVAL; + goto exit; + } + + priv->pipe_interrupt = usb_rcvintpipe(priv->udev, num); + } + + if (usb_endpoint_dir_out(endpoint) && + usb_endpoint_xfer_bulk(endpoint)) { + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB) + dev_dbg(dev, "%s: out endpoint num %i\n", + __func__, num); + if (j >= RTL8XXXU_OUT_ENDPOINTS) { + dev_warn(dev, + "%s: Too many OUT pipes\n", __func__); + ret = -EINVAL; + goto exit; + } + priv->out_ep[j++] = num; + } + } +exit: + priv->nr_out_eps = j; + return ret; +} + +static int rtl8xxxu_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct rtl8xxxu_priv *priv; + struct ieee80211_hw *hw; + struct usb_device *udev; + struct ieee80211_supported_band *sband; + int ret = 0; + int untested = 1; + + udev = usb_get_dev(interface_to_usbdev(interface)); + + switch (id->idVendor) { + case USB_VENDOR_ID_REALTEK: + switch(id->idProduct) { + case 0x1724: + case 0x8176: + case 0x8178: + case 0x817f: + untested = 0; + break; + } + break; + case 0x7392: + if (id->idProduct == 0x7811) + untested = 0; + break; + default: + break; + } + + if (untested) { + rtl8xxxu_debug = RTL8XXXU_DEBUG_EFUSE; + dev_info(&udev->dev, + "This Realtek USB WiFi dongle (0x%04x:0x%04x) is untested!\n", + id->idVendor, id->idProduct); + dev_info(&udev->dev, + "Please report results to Jes.Sorensen@gmail.com\n"); + } + + hw = ieee80211_alloc_hw(sizeof(struct rtl8xxxu_priv), &rtl8xxxu_ops); + if (!hw) { + ret = -ENOMEM; + goto exit; + } + + priv = hw->priv; + priv->hw = hw; + priv->udev = udev; + priv->fops = (struct rtl8xxxu_fileops *)id->driver_info; + mutex_init(&priv->usb_buf_mutex); + mutex_init(&priv->h2c_mutex); + INIT_LIST_HEAD(&priv->tx_urb_free_list); + spin_lock_init(&priv->tx_urb_lock); + INIT_LIST_HEAD(&priv->rx_urb_pending_list); + spin_lock_init(&priv->rx_urb_lock); + INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work); + + usb_set_intfdata(interface, hw); + + ret = rtl8xxxu_parse_usb(priv, interface); + if (ret) + goto exit; + + ret = rtl8xxxu_identify_chip(priv); + if (ret) { + dev_err(&udev->dev, "Fatal - failed to identify chip\n"); + goto exit; + } + + ret = rtl8xxxu_read_efuse(priv); + if (ret) { + dev_err(&udev->dev, "Fatal - failed to read EFuse\n"); + goto exit; + } + + ret = priv->fops->parse_efuse(priv); + if (ret) { + dev_err(&udev->dev, "Fatal - failed to parse EFuse\n"); + goto exit; + } + + rtl8xxxu_print_chipinfo(priv); + + ret = priv->fops->load_firmware(priv); + if (ret) { + dev_err(&udev->dev, "Fatal - failed to load firmware\n"); + goto exit; + } + + ret = rtl8xxxu_init_device(hw); + + hw->wiphy->max_scan_ssids = 1; + hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + hw->queues = 4; + + sband = &rtl8xxxu_supported_band; + sband->ht_cap.ht_supported = true; + sband->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + sband->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; + sband->ht_cap.cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40; + memset(&sband->ht_cap.mcs, 0, sizeof(sband->ht_cap.mcs)); + sband->ht_cap.mcs.rx_mask[0] = 0xff; + sband->ht_cap.mcs.rx_mask[4] = 0x01; + if (priv->rf_paths > 1) { + sband->ht_cap.mcs.rx_mask[1] = 0xff; + sband->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + } + sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; + /* + * Some APs will negotiate HT20_40 in a noisy environment leading + * to miserable performance. Rather than defaulting to this, only + * enable it if explicitly requested at module load time. + */ + if (rtl8xxxu_ht40_2g) { + dev_info(&udev->dev, "Enabling HT_20_40 on the 2.4GHz band\n"); + sband->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; + } + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + + hw->wiphy->rts_threshold = 2347; + + SET_IEEE80211_DEV(priv->hw, &interface->dev); + SET_IEEE80211_PERM_ADDR(hw, priv->mac_addr); + + hw->extra_tx_headroom = sizeof(struct rtl8xxxu_tx_desc); + ieee80211_hw_set(hw, SIGNAL_DBM); + /* + * The firmware handles rate control + */ + ieee80211_hw_set(hw, HAS_RATE_CONTROL); + ieee80211_hw_set(hw, AMPDU_AGGREGATION); + + ret = ieee80211_register_hw(priv->hw); + if (ret) { + dev_err(&udev->dev, "%s: Failed to register: %i\n", + __func__, ret); + goto exit; + } + +exit: + if (ret < 0) + usb_put_dev(udev); + return ret; +} + +static void rtl8xxxu_disconnect(struct usb_interface *interface) +{ + struct rtl8xxxu_priv *priv; + struct ieee80211_hw *hw; + + hw = usb_get_intfdata(interface); + priv = hw->priv; + + rtl8xxxu_disable_device(hw); + usb_set_intfdata(interface, NULL); + + dev_info(&priv->udev->dev, "disconnecting\n"); + + ieee80211_unregister_hw(hw); + + kfree(priv->fw_data); + mutex_destroy(&priv->usb_buf_mutex); + mutex_destroy(&priv->h2c_mutex); + + usb_put_dev(priv->udev); + ieee80211_free_hw(hw); +} + +static struct rtl8xxxu_fileops rtl8723au_fops = { + .parse_efuse = rtl8723au_parse_efuse, + .load_firmware = rtl8723au_load_firmware, + .power_on = rtl8723au_power_on, + .writeN_block_size = 1024, +}; + +#ifdef CONFIG_RTL8XXXU_UNTESTED + +static struct rtl8xxxu_fileops rtl8192cu_fops = { + .parse_efuse = rtl8192cu_parse_efuse, + .load_firmware = rtl8192cu_load_firmware, + .power_on = rtl8192cu_power_on, + .writeN_block_size = 128, +}; + +#endif + +static struct usb_device_id dev_table[] = { +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8724, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8723au_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x1724, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8723au_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x0724, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8723au_fops}, +#ifdef CONFIG_RTL8XXXU_UNTESTED +/* Still supported by rtlwifi */ +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8176, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8178, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817f, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +/* Tested by Larry Finger */ +{USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0x7811, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +/* Currently untested 8188 series devices */ +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8191, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8170, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8177, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817a, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817b, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817d, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817e, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x818a, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x317f, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x1058, 0x0631, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x094c, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1102, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x06f8, 0xe033, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8189, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9041, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17ba, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x1e1e, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x5088, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0052, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x005c, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0eb0, 0x9071, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x103c, 0x1629, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x13d3, 0x3357, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3308, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330b, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0x4902, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab2a, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab2e, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xed17, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x648b, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x4855, 0x0090, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x4856, 0x0091, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0xcdab, 0x8010, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x317f, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, /* Netcore 8188RU */ +{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff7, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff9, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaffa, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff8, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaffb, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaffc, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0x1201, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +/* Currently untested 8192 series devices */ +{USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x0950, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1004, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x2102, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x2103, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0586, 0x341f, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x06f8, 0xe035, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17ab, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0061, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0070, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0789, 0x016d, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x07aa, 0x0056, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8178, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9021, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0xf001, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x2e2e, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0019, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0020, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3307, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3309, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330a, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab2b, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x624d, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0100, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x4855, 0x0091, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0x7822, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +#endif +{ } +}; + +static struct usb_driver rtl8xxxu_driver = { + .name = DRIVER_NAME, + .probe = rtl8xxxu_probe, + .disconnect = rtl8xxxu_disconnect, + .id_table = dev_table, + .disable_hub_initiated_lpm = 1, +}; + +static int __init rtl8xxxu_module_init(void) +{ + int res; + + res = usb_register(&rtl8xxxu_driver); + if (res < 0) + pr_err(DRIVER_NAME ": usb_register() failed (%i)\n", res); + + return res; +} + +static void __exit rtl8xxxu_module_exit(void) +{ + usb_deregister(&rtl8xxxu_driver); +} + + +MODULE_DEVICE_TABLE(usb, dev_table); + +module_init(rtl8xxxu_module_init); +module_exit(rtl8xxxu_module_exit); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h new file mode 100644 index 000000000000..f2a1bac6c8ec --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -0,0 +1,676 @@ +/* + * Copyright (c) 2014 - 2015 Jes Sorensen <Jes.Sorensen@redhat.com> + * + * 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. + * + * Register definitions taken from original Realtek rtl8723au driver + */ + +#include <asm/byteorder.h> + +#define RTL8XXXU_DEBUG_REG_WRITE 0x01 +#define RTL8XXXU_DEBUG_REG_READ 0x02 +#define RTL8XXXU_DEBUG_RFREG_WRITE 0x04 +#define RTL8XXXU_DEBUG_RFREG_READ 0x08 +#define RTL8XXXU_DEBUG_CHANNEL 0x10 +#define RTL8XXXU_DEBUG_TX 0x20 +#define RTL8XXXU_DEBUG_TX_DUMP 0x40 +#define RTL8XXXU_DEBUG_RX 0x80 +#define RTL8XXXU_DEBUG_RX_DUMP 0x100 +#define RTL8XXXU_DEBUG_USB 0x200 +#define RTL8XXXU_DEBUG_KEY 0x400 +#define RTL8XXXU_DEBUG_H2C 0x800 +#define RTL8XXXU_DEBUG_ACTION 0x1000 +#define RTL8XXXU_DEBUG_EFUSE 0x2000 + +#define RTW_USB_CONTROL_MSG_TIMEOUT 500 +#define RTL8XXXU_MAX_REG_POLL 500 +#define USB_INTR_CONTENT_LENGTH 56 + +#define RTL8XXXU_OUT_ENDPOINTS 3 + +#define REALTEK_USB_READ 0xc0 +#define REALTEK_USB_WRITE 0x40 +#define REALTEK_USB_CMD_REQ 0x05 +#define REALTEK_USB_CMD_IDX 0x00 + +#define TX_TOTAL_PAGE_NUM 0xf8 +/* (HPQ + LPQ + NPQ + PUBQ) = TX_TOTAL_PAGE_NUM */ +#define TX_PAGE_NUM_PUBQ 0xe7 +#define TX_PAGE_NUM_HI_PQ 0x0c +#define TX_PAGE_NUM_LO_PQ 0x02 +#define TX_PAGE_NUM_NORM_PQ 0x02 + +#define RTL_FW_PAGE_SIZE 4096 +#define RTL8XXXU_FIRMWARE_POLL_MAX 1000 + +#define RTL8723A_CHANNEL_GROUPS 3 +#define RTL8723A_MAX_RF_PATHS 2 +#define RF6052_MAX_TX_PWR 0x3f + +#define EFUSE_MAP_LEN_8723A 256 +#define EFUSE_MAX_SECTION_8723A 32 +#define EFUSE_REAL_CONTENT_LEN_8723A 512 +#define EFUSE_BT_MAP_LEN_8723A 1024 +#define EFUSE_MAX_WORD_UNIT 4 + +struct rtl8xxxu_rx_desc { +#ifdef __LITTLE_ENDIAN + u32 pktlen:14; + u32 crc32:1; + u32 icverr:1; + u32 drvinfo_sz:4; + u32 security:3; + u32 qos:1; + u32 shift:2; + u32 phy_stats:1; + u32 swdec:1; + u32 ls:1; + u32 fs:1; + u32 eor:1; + u32 own:1; + + u32 macid:5; + u32 tid:4; + u32 hwrsvd:4; + u32 amsdu:1; + u32 paggr:1; + u32 faggr:1; + u32 a1fit:4; + u32 a2fit:4; + u32 pam:1; + u32 pwr:1; + u32 md:1; + u32 mf:1; + u32 type:2; + u32 mc:1; + u32 bc:1; + + u32 seq:12; + u32 frag:4; + u32 nextpktlen:14; + u32 nextind:1; + u32 reserved0:1; + + u32 rxmcs:6; + u32 rxht:1; + u32 gf:1; + u32 splcp:1; + u32 bw:1; + u32 htc:1; + u32 eosp:1; + u32 bssidfit:2; + u32 reserved1:16; + u32 unicastwake:1; + u32 magicwake:1; + + u32 pattern0match:1; + u32 pattern1match:1; + u32 pattern2match:1; + u32 pattern3match:1; + u32 pattern4match:1; + u32 pattern5match:1; + u32 pattern6match:1; + u32 pattern7match:1; + u32 pattern8match:1; + u32 pattern9match:1; + u32 patternamatch:1; + u32 patternbmatch:1; + u32 patterncmatch:1; + u32 reserved2:19; +#else + u32 own:1; + u32 eor:1; + u32 fs:1; + u32 ls:1; + u32 swdec:1; + u32 phy_stats:1; + u32 shift:2; + u32 qos:1; + u32 security:3; + u32 drvinfo_sz:4; + u32 icverr:1; + u32 crc32:1; + u32 pktlen:14; + + u32 bc:1; + u32 mc:1; + u32 type:2; + u32 mf:1; + u32 md:1; + u32 pwr:1; + u32 pam:1; + u32 a2fit:4; + u32 a1fit:4; + u32 faggr:1; + u32 paggr:1; + u32 amsdu:1; + u32 hwrsvd:4; + u32 tid:4; + u32 macid:5; + + u32 reserved0:1; + u32 nextind:1; + u32 nextpktlen:14; + u32 frag:4; + u32 seq:12; + + u32 magicwake:1; + u32 unicastwake:1; + u32 reserved1:16; + u32 bssidfit:2; + u32 eosp:1; + u32 htc:1; + u32 bw:1; + u32 splcp:1; + u32 gf:1; + u32 rxht:1; + u32 rxmcs:6; + + u32 reserved2:19; + u32 patterncmatch:1; + u32 patternbmatch:1; + u32 patternamatch:1; + u32 pattern9match:1; + u32 pattern8match:1; + u32 pattern7match:1; + u32 pattern6match:1; + u32 pattern5match:1; + u32 pattern4match:1; + u32 pattern3match:1; + u32 pattern2match:1; + u32 pattern1match:1; + u32 pattern0match:1; +#endif + __le32 tsfl; +#if 0 + u32 bassn:12; + u32 bavld:1; + u32 reserved3:19; +#endif +}; + +struct rtl8xxxu_tx_desc { + __le16 pkt_size; + u8 pkt_offset; + u8 txdw0; + __le32 txdw1; + __le32 txdw2; + __le32 txdw3; + __le32 txdw4; + __le32 txdw5; + __le32 txdw6; + __le16 csum; + __le16 txdw7; +}; + +/* CCK Rates, TxHT = 0 */ +#define DESC_RATE_1M 0x00 +#define DESC_RATE_2M 0x01 +#define DESC_RATE_5_5M 0x02 +#define DESC_RATE_11M 0x03 + +/* OFDM Rates, TxHT = 0 */ +#define DESC_RATE_6M 0x04 +#define DESC_RATE_9M 0x05 +#define DESC_RATE_12M 0x06 +#define DESC_RATE_18M 0x07 +#define DESC_RATE_24M 0x08 +#define DESC_RATE_36M 0x09 +#define DESC_RATE_48M 0x0a +#define DESC_RATE_54M 0x0b + +/* MCS Rates, TxHT = 1 */ +#define DESC_RATE_MCS0 0x0c +#define DESC_RATE_MCS1 0x0d +#define DESC_RATE_MCS2 0x0e +#define DESC_RATE_MCS3 0x0f +#define DESC_RATE_MCS4 0x10 +#define DESC_RATE_MCS5 0x11 +#define DESC_RATE_MCS6 0x12 +#define DESC_RATE_MCS7 0x13 +#define DESC_RATE_MCS8 0x14 +#define DESC_RATE_MCS9 0x15 +#define DESC_RATE_MCS10 0x16 +#define DESC_RATE_MCS11 0x17 +#define DESC_RATE_MCS12 0x18 +#define DESC_RATE_MCS13 0x19 +#define DESC_RATE_MCS14 0x1a +#define DESC_RATE_MCS15 0x1b +#define DESC_RATE_MCS15_SG 0x1c +#define DESC_RATE_MCS32 0x20 + +#define TXDESC_OFFSET_SZ 0 +#define TXDESC_OFFSET_SHT 16 +#if 0 +#define TXDESC_BMC BIT(24) +#define TXDESC_LSG BIT(26) +#define TXDESC_FSG BIT(27) +#define TXDESC_OWN BIT(31) +#else +#define TXDESC_BROADMULTICAST BIT(0) +#define TXDESC_LAST_SEGMENT BIT(2) +#define TXDESC_FIRST_SEGMENT BIT(3) +#define TXDESC_OWN BIT(7) +#endif + +/* Word 1 */ +#define TXDESC_PKT_OFFSET_SZ 0 +#define TXDESC_AGG_ENABLE BIT(5) +#define TXDESC_BK BIT(6) +#define TXDESC_QUEUE_SHIFT 8 +#define TXDESC_QUEUE_MASK 0x1f00 +#define TXDESC_QUEUE_BK 0x2 +#define TXDESC_QUEUE_BE 0x0 +#define TXDESC_QUEUE_VI 0x5 +#define TXDESC_QUEUE_VO 0x7 +#define TXDESC_QUEUE_BEACON 0x10 +#define TXDESC_QUEUE_HIGH 0x11 +#define TXDESC_QUEUE_MGNT 0x12 +#define TXDESC_QUEUE_CMD 0x13 +#define TXDESC_QUEUE_MAX (TXDESC_QUEUE_CMD + 1) + +#define DESC_RATE_ID_SHIFT 16 +#define DESC_RATE_ID_MASK 0xf +#define TXDESC_NAVUSEHDR BIT(20) +#define TXDESC_SEC_RC4 0x00400000 +#define TXDESC_SEC_AES 0x00c00000 +#define TXDESC_PKT_OFFSET_SHIFT 26 +#define TXDESC_AGG_EN BIT(29) +#define TXDESC_HWPC BIT(31) + +/* Word 2 */ +#define TXDESC_ACK_REPORT BIT(19) +#define TXDESC_AMPDU_DENSITY_SHIFT 20 + +/* Word 3 */ +#define TXDESC_SEQ_SHIFT 16 +#define TXDESC_SEQ_MASK 0x0fff0000 + +/* Word 4 */ +#define TXDESC_QOS BIT(6) +#define TXDESC_HW_SEQ_ENABLE BIT(7) +#define TXDESC_USE_DRIVER_RATE BIT(8) +#define TXDESC_DISABLE_DATA_FB BIT(10) +#define TXDESC_CTS_SELF_ENABLE BIT(11) +#define TXDESC_RTS_CTS_ENABLE BIT(12) +#define TXDESC_HW_RTS_ENABLE BIT(13) +#define TXDESC_PRIME_CH_OFF_LOWER BIT(20) +#define TXDESC_PRIME_CH_OFF_UPPER BIT(21) +#define TXDESC_SHORT_PREAMBLE BIT(24) +#define TXDESC_DATA_BW BIT(25) +#define TXDESC_RTS_DATA_BW BIT(27) +#define TXDESC_RTS_PRIME_CH_OFF_LOWER BIT(28) +#define TXDESC_RTS_PRIME_CH_OFF_UPPER BIT(29) + +/* Word 5 */ +#define TXDESC_RTS_RATE_SHIFT 0 +#define TXDESC_RTS_RATE_MASK 0x3f +#define TXDESC_SHORT_GI BIT(6) +#define TXDESC_CCX_TAG BIT(7) +#define TXDESC_RETRY_LIMIT_ENABLE BIT(17) +#define TXDESC_RETRY_LIMIT_SHIFT 18 +#define TXDESC_RETRY_LIMIT_MASK 0x00fc0000 + +/* Word 6 */ +#define TXDESC_MAX_AGG_SHIFT 11 + +struct phy_rx_agc_info { +#ifdef __LITTLE_ENDIAN + u8 gain:7, trsw:1; +#else + u8 trsw:1, gain:7; +#endif +}; + +struct rtl8723au_phy_stats { + struct phy_rx_agc_info path_agc[RTL8723A_MAX_RF_PATHS]; + u8 ch_corr[RTL8723A_MAX_RF_PATHS]; + u8 cck_sig_qual_ofdm_pwdb_all; + u8 cck_agc_rpt_ofdm_cfosho_a; + u8 cck_rpt_b_ofdm_cfosho_b; + u8 reserved_1; + u8 noise_power_db_msb; + u8 path_cfotail[RTL8723A_MAX_RF_PATHS]; + u8 pcts_mask[RTL8723A_MAX_RF_PATHS]; + s8 stream_rxevm[RTL8723A_MAX_RF_PATHS]; + u8 path_rxsnr[RTL8723A_MAX_RF_PATHS]; + u8 noise_power_db_lsb; + u8 reserved_2[3]; + u8 stream_csi[RTL8723A_MAX_RF_PATHS]; + u8 stream_target_csi[RTL8723A_MAX_RF_PATHS]; + s8 sig_evm; + u8 reserved_3; + +#ifdef __LITTLE_ENDIAN + u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */ + u8 sgi_en:1; + u8 rxsc:2; + u8 idle_long:1; + u8 r_ant_train_en:1; + u8 antenna_select_b:1; + u8 antenna_select:1; +#else /* _BIG_ENDIAN_ */ + u8 antenna_select:1; + u8 antenna_select_b:1; + u8 r_ant_train_en:1; + u8 idle_long:1; + u8 rxsc:2; + u8 sgi_en:1; + u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */ +#endif +}; + +/* + * Regs to backup + */ +#define RTL8XXXU_ADDA_REGS 16 +#define RTL8XXXU_MAC_REGS 4 +#define RTL8XXXU_BB_REGS 9 + +struct rtl8xxxu_firmware_header { + __le16 signature; /* 92C0: test chip; 92C, + 88C0: test chip; + 88C1: MP A-cut; + 92C1: MP A-cut */ + u8 category; /* AP/NIC and USB/PCI */ + u8 function; + + __le16 major_version; /* FW Version */ + u8 minor_version; /* FW Subversion, default 0x00 */ + u8 reserved1; + + u8 month; /* Release time Month field */ + u8 date; /* Release time Date field */ + u8 hour; /* Release time Hour field */ + u8 minute; /* Release time Minute field */ + + __le16 ramcodesize; /* Size of RAM code */ + u16 reserved2; + + __le32 svn_idx; /* SVN entry index */ + u32 reserved3; + + u32 reserved4; + u32 reserved5; + + u8 data[0]; +}; + +/* + * The 8723au has 3 channel groups: 1-3, 4-9, and 10-14 + */ +struct rtl8723au_idx { +#ifdef __LITTLE_ENDIAN + int a:4; + int b:4; +#else + int b:4; + int a:4; +#endif +} __attribute__((packed)); + +struct rtl8723au_efuse { + __le16 rtl_id; + u8 res0[0xe]; + u8 cck_tx_power_index_A[3]; /* 0x10 */ + u8 cck_tx_power_index_B[3]; + u8 ht40_1s_tx_power_index_A[3]; /* 0x16 */ + u8 ht40_1s_tx_power_index_B[3]; + /* + * The following entries are half-bytes split as: + * bits 0-3: path A, bits 4-7: path B, all values 4 bits signed + */ + struct rtl8723au_idx ht20_tx_power_index_diff[3]; + struct rtl8723au_idx ofdm_tx_power_index_diff[3]; + struct rtl8723au_idx ht40_max_power_offset[3]; + struct rtl8723au_idx ht20_max_power_offset[3]; + u8 channel_plan; /* 0x28 */ + u8 tssi_a; + u8 thermal_meter; + u8 rf_regulatory; + u8 rf_option_2; + u8 rf_option_3; + u8 rf_option_4; + u8 res7; + u8 version /* 0x30 */; + u8 customer_id_major; + u8 customer_id_minor; + u8 xtal_k; + u8 chipset; /* 0x34 */ + u8 res8[0x82]; + u8 vid; /* 0xb7 */ + u8 res9; + u8 pid; /* 0xb9 */ + u8 res10[0x0c]; + u8 mac_addr[ETH_ALEN]; /* 0xc6 */ + u8 res11[2]; + u8 vendor_name[7]; + u8 res12[2]; + u8 device_name[0x29]; /* 0xd7 */ +}; + +struct rtl8192cu_efuse { + __le16 rtl_id; + __le16 hpon; + u8 res0[2]; + __le16 clk; + __le16 testr; + __le16 vid; + __le16 did; + __le16 svid; + __le16 smid; /* 0x10 */ + u8 res1[4]; + u8 mac_addr[ETH_ALEN]; /* 0x16 */ + u8 res2[2]; + u8 vendor_name[7]; + u8 res3[3]; + u8 device_name[0x14]; /* 0x28 */ + u8 res4[0x1e]; /* 0x3c */ + u8 cck_tx_power_index_A[3]; /* 0x5a */ + u8 cck_tx_power_index_B[3]; + u8 ht40_1s_tx_power_index_A[3]; /* 0x60 */ + u8 ht40_1s_tx_power_index_B[3]; + /* + * The following entries are half-bytes split as: + * bits 0-3: path A, bits 4-7: path B, all values 4 bits signed + */ + struct rtl8723au_idx ht40_2s_tx_power_index_diff[3]; + struct rtl8723au_idx ht20_tx_power_index_diff[3]; /* 0x69 */ + struct rtl8723au_idx ofdm_tx_power_index_diff[3]; + struct rtl8723au_idx ht40_max_power_offset[3]; /* 0x6f */ + struct rtl8723au_idx ht20_max_power_offset[3]; + u8 channel_plan; /* 0x75 */ + u8 tssi_a; + u8 tssi_b; + u8 thermal_meter; /* xtal_k */ /* 0x78 */ + u8 rf_regulatory; + u8 rf_option_2; + u8 rf_option_3; + u8 rf_option_4; + u8 res5[1]; /* 0x7d */ + u8 version; + u8 customer_id; +}; + +struct rtl8xxxu_reg8val { + u16 reg; + u8 val; +}; + +struct rtl8xxxu_reg32val { + u16 reg; + u32 val; +}; + +struct rtl8xxxu_rfregval { + u8 reg; + u32 val; +}; + +enum rtl8xxxu_rfpath { + RF_A = 0, + RF_B = 1, +}; + +struct rtl8xxxu_rfregs { + u16 hssiparm1; + u16 hssiparm2; + u16 lssiparm; + u16 hspiread; + u16 lssiread; + u16 rf_sw_ctrl; +}; + +#define H2C_MAX_MBOX 4 +#define H2C_EXT BIT(7) +#define H2C_SET_POWER_MODE 1 +#define H2C_JOIN_BSS_REPORT 2 +#define H2C_JOIN_BSS_DISCONNECT 0 +#define H2C_JOIN_BSS_CONNECT 1 +#define H2C_SET_RSSI 5 +#define H2C_SET_RATE_MASK (6 | H2C_EXT) + +struct h2c_cmd { + union { + struct { + u8 cmd; + u8 data[5]; + } __packed cmd; + struct { + __le32 data; + __le16 ext; + } __packed raw; + struct { + u8 cmd; + u8 data; + u8 pad[4]; + } __packed joinbss; + struct { + u8 cmd; + __le16 mask_hi; + u8 arg; + __le16 mask_lo; + } __packed ramask; + }; +}; + +struct rtl8xxxu_fileops; + +struct rtl8xxxu_priv { + struct ieee80211_hw *hw; + struct usb_device *udev; + struct rtl8xxxu_fileops *fops; + + spinlock_t tx_urb_lock; + struct list_head tx_urb_free_list; + int tx_urb_free_count; + bool tx_stopped; + + spinlock_t rx_urb_lock; + struct list_head rx_urb_pending_list; + int rx_urb_pending_count; + bool shutdown; + struct work_struct rx_urb_wq; + + u8 mac_addr[ETH_ALEN]; + char chip_name[8]; + u8 cck_tx_power_index_A[3]; /* 0x10 */ + u8 cck_tx_power_index_B[3]; + u8 ht40_1s_tx_power_index_A[3]; /* 0x16 */ + u8 ht40_1s_tx_power_index_B[3]; + /* + * The following entries are half-bytes split as: + * bits 0-3: path A, bits 4-7: path B, all values 4 bits signed + */ + struct rtl8723au_idx ht40_2s_tx_power_index_diff[3]; + struct rtl8723au_idx ht20_tx_power_index_diff[3]; + struct rtl8723au_idx ofdm_tx_power_index_diff[3]; + struct rtl8723au_idx ht40_max_power_offset[3]; + struct rtl8723au_idx ht20_max_power_offset[3]; + u32 chip_cut:4; + u32 rom_rev:4; + u32 has_wifi:1; + u32 has_bluetooth:1; + u32 enable_bluetooth:1; + u32 has_gps:1; + u32 hi_pa:1; + u32 vendor_umc:1; + u32 has_polarity_ctrl:1; + u32 has_eeprom:1; + u32 boot_eeprom:1; + u32 ep_tx_high_queue:1; + u32 ep_tx_normal_queue:1; + u32 ep_tx_low_queue:1; + u32 path_a_hi_power:1; + u32 path_a_rf_paths:4; + unsigned int pipe_interrupt; + unsigned int pipe_in; + unsigned int pipe_out[TXDESC_QUEUE_MAX]; + u8 out_ep[RTL8XXXU_OUT_ENDPOINTS]; + u8 path_a_ig_value; + u8 ep_tx_count; + u8 rf_paths; + u8 rx_paths; + u8 tx_paths; + u32 rf_mode_ag[2]; + u32 rege94; + u32 rege9c; + u32 regeb4; + u32 regebc; + int next_mbox; + int nr_out_eps; + + struct mutex h2c_mutex; + + struct usb_anchor rx_anchor; + struct usb_anchor tx_anchor; + struct usb_anchor int_anchor; + struct rtl8xxxu_firmware_header *fw_data; + size_t fw_size; + struct mutex usb_buf_mutex; + union { + __le32 val32; + __le16 val16; + u8 val8; + } usb_buf; + union { + u8 raw[EFUSE_MAP_LEN_8723A]; + struct rtl8723au_efuse efuse8723; + struct rtl8192cu_efuse efuse8192; + } efuse_wifi; + u32 adda_backup[RTL8XXXU_ADDA_REGS]; + u32 mac_backup[RTL8XXXU_MAC_REGS]; + u32 bb_backup[RTL8XXXU_BB_REGS]; + u32 bb_recovery_backup[RTL8XXXU_BB_REGS]; + u32 rtlchip; + u8 pi_enabled:1; + u8 iqk_initialized:1; + u8 int_buf[USB_INTR_CONTENT_LENGTH]; +}; + +struct rtl8xxxu_rx_urb { + struct urb urb; + struct ieee80211_hw *hw; + struct list_head list; +}; + +struct rtl8xxxu_tx_urb { + struct urb urb; + struct ieee80211_hw *hw; + struct list_head list; +}; + +struct rtl8xxxu_fileops { + int (*parse_efuse) (struct rtl8xxxu_priv *priv); + int (*load_firmware) (struct rtl8xxxu_priv *priv); + int (*power_on) (struct rtl8xxxu_priv *priv); + int writeN_block_size; +}; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h new file mode 100644 index 000000000000..23208f79b97c --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -0,0 +1,981 @@ +/* + * Copyright (c) 2014 - 2015 Jes Sorensen <Jes.Sorensen@redhat.com> + * + * 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. + * + * Register definitions taken from original Realtek rtl8723au driver + */ + +/* 0x0000 ~ 0x00FF System Configuration */ +#define REG_SYS_ISO_CTRL 0x0000 +#define SYS_ISO_MD2PP BIT(0) +#define SYS_ISO_ANALOG_IPS BIT(5) +#define SYS_ISO_DIOR BIT(9) +#define SYS_ISO_PWC_EV25V BIT(14) +#define SYS_ISO_PWC_EV12V BIT(15) + +#define REG_SYS_FUNC 0x0002 +#define SYS_FUNC_BBRSTB BIT(0) +#define SYS_FUNC_BB_GLB_RSTN BIT(1) +#define SYS_FUNC_USBA BIT(2) +#define SYS_FUNC_UPLL BIT(3) +#define SYS_FUNC_USBD BIT(4) +#define SYS_FUNC_DIO_PCIE BIT(5) +#define SYS_FUNC_PCIEA BIT(6) +#define SYS_FUNC_PPLL BIT(7) +#define SYS_FUNC_PCIED BIT(8) +#define SYS_FUNC_DIOE BIT(9) +#define SYS_FUNC_CPU_ENABLE BIT(10) +#define SYS_FUNC_DCORE BIT(11) +#define SYS_FUNC_ELDR BIT(12) +#define SYS_FUNC_DIO_RF BIT(13) +#define SYS_FUNC_HWPDN BIT(14) +#define SYS_FUNC_MREGEN BIT(15) + +#define REG_APS_FSMCO 0x0004 +#define APS_FSMCO_PFM_ALDN BIT(1) +#define APS_FSMCO_PFM_WOWL BIT(3) +#define APS_FSMCO_ENABLE_POWERDOWN BIT(4) +#define APS_FSMCO_MAC_ENABLE BIT(8) +#define APS_FSMCO_MAC_OFF BIT(9) +#define APS_FSMCO_HW_SUSPEND BIT(11) +#define APS_FSMCO_PCIE BIT(12) +#define APS_FSMCO_HW_POWERDOWN BIT(15) +#define APS_FSMCO_WLON_RESET BIT(16) + +#define REG_SYS_CLKR 0x0008 +#define SYS_CLK_ANAD16V_ENABLE BIT(0) +#define SYS_CLK_ANA8M BIT(1) +#define SYS_CLK_MACSLP BIT(4) +#define SYS_CLK_LOADER_ENABLE BIT(5) +#define SYS_CLK_80M_SSC_DISABLE BIT(7) +#define SYS_CLK_80M_SSC_ENABLE_HO BIT(8) +#define SYS_CLK_PHY_SSC_RSTB BIT(9) +#define SYS_CLK_SEC_CLK_ENABLE BIT(10) +#define SYS_CLK_MAC_CLK_ENABLE BIT(11) +#define SYS_CLK_ENABLE BIT(12) +#define SYS_CLK_RING_CLK_ENABLE BIT(13) + +#define REG_9346CR 0x000a +#define EEPROM_BOOT BIT(4) +#define EEPROM_ENABLE BIT(5) + +#define REG_EE_VPD 0x000c +#define REG_AFE_MISC 0x0010 +#define REG_SPS0_CTRL 0x0011 +#define REG_SPS_OCP_CFG 0x0018 +#define REG_RSV_CTRL 0x001c + +#define REG_RF_CTRL 0x001f +#define RF_ENABLE BIT(0) +#define RF_RSTB BIT(1) +#define RF_SDMRSTB BIT(2) + +#define REG_LDOA15_CTRL 0x0020 +#define LDOA15_ENABLE BIT(0) +#define LDOA15_STANDBY BIT(1) +#define LDOA15_OBUF BIT(2) +#define LDOA15_REG_VOS BIT(3) +#define LDOA15_VOADJ_SHIFT 4 + +#define REG_LDOV12D_CTRL 0x0021 +#define LDOV12D_ENABLE BIT(0) +#define LDOV12D_STANDBY BIT(1) +#define LDOV12D_VADJ_SHIFT 4 + +#define REG_LDOHCI12_CTRL 0x0022 + +#define REG_LPLDO_CTRL 0x0023 +#define LPLDO_HSM BIT(2) +#define LPLDO_LSM_DIS BIT(3) + +#define REG_AFE_XTAL_CTRL 0x0024 +#define AFE_XTAL_ENABLE BIT(0) +#define AFE_XTAL_B_SELECT BIT(1) +#define AFE_XTAL_GATE_USB BIT(8) +#define AFE_XTAL_GATE_AFE BIT(11) +#define AFE_XTAL_RF_GATE BIT(14) +#define AFE_XTAL_GATE_DIG BIT(17) +#define AFE_XTAL_BT_GATE BIT(20) + +#define REG_AFE_PLL_CTRL 0x0028 +#define AFE_PLL_ENABLE BIT(0) +#define AFE_PLL_320_ENABLE BIT(1) +#define APE_PLL_FREF_SELECT BIT(2) +#define AFE_PLL_EDGE_SELECT BIT(3) +#define AFE_PLL_WDOGB BIT(4) +#define AFE_PLL_LPF_ENABLE BIT(5) + +#define REG_MAC_PHY_CTRL 0x002c + +#define REG_EFUSE_CTRL 0x0030 +#define REG_EFUSE_TEST 0x0034 +#define EFUSE_TRPT BIT(7) + /* 00: Wifi Efuse, 01: BT Efuse0, 10: BT Efuse1, 11: BT Efuse2 */ +#define EFUSE_CELL_SEL (BIT(8) | BIT(9)) +#define EFUSE_LDOE25_ENABLE BIT(31) +#define EFUSE_SELECT_MASK 0x0300 +#define EFUSE_WIFI_SELECT 0x0000 +#define EFUSE_BT0_SELECT 0x0100 +#define EFUSE_BT1_SELECT 0x0200 +#define EFUSE_BT2_SELECT 0x0300 + +#define EFUSE_ACCESS_ENABLE 0x69 /* RTL8723 only */ +#define EFUSE_ACCESS_DISABLE 0x00 /* RTL8723 only */ + +#define REG_PWR_DATA 0x0038 +#define REG_CAL_TIMER 0x003c +#define REG_ACLK_MON 0x003e +#define REG_GPIO_MUXCFG 0x0040 +#define REG_GPIO_IO_SEL 0x0042 +#define REG_MAC_PINMUX_CFG 0x0043 +#define REG_GPIO_PIN_CTRL 0x0044 +#define REG_GPIO_INTM 0x0048 +#define REG_LEDCFG0 0x004c +#define REG_LEDCFG1 0x004d +#define REG_LEDCFG2 0x004e +#define LEDCFG2_DPDT_SELECT BIT(7) +#define REG_LEDCFG3 0x004f +#define REG_LEDCFG REG_LEDCFG2 +#define REG_FSIMR 0x0050 +#define REG_FSISR 0x0054 +#define REG_HSIMR 0x0058 +#define REG_HSISR 0x005c +/* RTL8723 WIFI/BT/GPS Multi-Function GPIO Pin Control. */ +#define REG_GPIO_PIN_CTRL_2 0x0060 +/* RTL8723 WIFI/BT/GPS Multi-Function GPIO Select. */ +#define REG_GPIO_IO_SEL_2 0x0062 + +/* RTL8723 only WIFI/BT/GPS Multi-Function control source. */ +#define REG_MULTI_FUNC_CTRL 0x0068 + +#define MULTI_FN_WIFI_HW_PWRDOWN_EN BIT(0) /* Enable GPIO[9] as WiFi HW + powerdown source */ +#define MULTI_FN_WIFI_HW_PWRDOWN_SL BIT(1) /* WiFi HW powerdown polarity + control */ +#define MULTI_WIFI_FUNC_EN BIT(2) /* WiFi function enable */ + +#define MULTI_WIFI_HW_ROF_EN BIT(3) /* Enable GPIO[9] as WiFi RF HW + powerdown source */ +#define MULTI_BT_HW_PWRDOWN_EN BIT(16) /* Enable GPIO[11] as BT HW + powerdown source */ +#define MULTI_BT_HW_PWRDOWN_SL BIT(17) /* BT HW powerdown polarity + control */ +#define MULTI_BT_FUNC_EN BIT(18) /* BT function enable */ +#define MULTI_BT_HW_ROF_EN BIT(19) /* Enable GPIO[11] as BT/GPS + RF HW powerdown source */ +#define MULTI_GPS_HW_PWRDOWN_EN BIT(20) /* Enable GPIO[10] as GPS HW + powerdown source */ +#define MULTI_GPS_HW_PWRDOWN_SL BIT(21) /* GPS HW powerdown polarity + control */ +#define MULTI_GPS_FUNC_EN BIT(22) /* GPS function enable */ + +#define REG_MCU_FW_DL 0x0080 +#define MCU_FW_DL_ENABLE BIT(0) +#define MCU_FW_DL_READY BIT(1) +#define MCU_FW_DL_CSUM_REPORT BIT(2) +#define MCU_MAC_INIT_READY BIT(3) +#define MCU_BB_INIT_READY BIT(4) +#define MCU_RF_INIT_READY BIT(5) +#define MCU_WINT_INIT_READY BIT(6) +#define MCU_FW_RAM_SEL BIT(7) /* 1: RAM, 0:ROM */ +#define MCU_CP_RESET BIT(23) + +#define REG_HMBOX_EXT_0 0x0088 +#define REG_HMBOX_EXT_1 0x008a +#define REG_HMBOX_EXT_2 0x008c +#define REG_HMBOX_EXT_3 0x008e +/* Host suspend counter on FPGA platform */ +#define REG_HOST_SUSP_CNT 0x00bc +/* Efuse access protection for RTL8723 */ +#define REG_EFUSE_ACCESS 0x00cf +#define REG_BIST_SCAN 0x00d0 +#define REG_BIST_RPT 0x00d4 +#define REG_BIST_ROM_RPT 0x00d8 +#define REG_USB_SIE_INTF 0x00e0 +#define REG_PCIE_MIO_INTF 0x00e4 +#define REG_PCIE_MIO_INTD 0x00e8 +#define REG_HPON_FSM 0x00ec +#define HPON_FSM_BONDING_MASK (BIT(22) | BIT(23)) +#define HPON_FSM_BONDING_1T2R BIT(22) +#define REG_SYS_CFG 0x00f0 +#define SYS_CFG_XCLK_VLD BIT(0) +#define SYS_CFG_ACLK_VLD BIT(1) +#define SYS_CFG_UCLK_VLD BIT(2) +#define SYS_CFG_PCLK_VLD BIT(3) +#define SYS_CFG_PCIRSTB BIT(4) +#define SYS_CFG_V15_VLD BIT(5) +#define SYS_CFG_TRP_B15V_EN BIT(7) +#define SYS_CFG_SIC_IDLE BIT(8) +#define SYS_CFG_BD_MAC2 BIT(9) +#define SYS_CFG_BD_MAC1 BIT(10) +#define SYS_CFG_IC_MACPHY_MODE BIT(11) +#define SYS_CFG_CHIP_VER (BIT(12) | BIT(13) | BIT(14) | BIT(15)) +#define SYS_CFG_BT_FUNC BIT(16) +#define SYS_CFG_VENDOR_ID BIT(19) +#define SYS_CFG_PAD_HWPD_IDN BIT(22) +#define SYS_CFG_TRP_VAUX_EN BIT(23) +#define SYS_CFG_TRP_BT_EN BIT(24) +#define SYS_CFG_BD_PKG_SEL BIT(25) +#define SYS_CFG_BD_HCI_SEL BIT(26) +#define SYS_CFG_TYPE_ID BIT(27) +#define SYS_CFG_RTL_ID BIT(23) /* TestChip ID, + 1:Test(RLE); 0:MP(RL) */ +#define SYS_CFG_SPS_SEL BIT(24) /* 1:LDO regulator mode; + 0:Switching regulator mode*/ +#define SYS_CFG_CHIP_VERSION_MASK 0xf000 /* Bit 12 - 15 */ +#define SYS_CFG_CHIP_VERSION_SHIFT 12 + +#define REG_GPIO_OUTSTS 0x00f4 /* For RTL8723 only. */ +#define GPIO_EFS_HCI_SEL (BIT(0) | BIT(1)) +#define GPIO_PAD_HCI_SEL (BIT(2) | BIT(3)) +#define GPIO_HCI_SEL (BIT(4) | BIT(5)) +#define GPIO_PKG_SEL_HCI BIT(6) +#define GPIO_FEN_GPS BIT(7) +#define GPIO_FEN_BT BIT(8) +#define GPIO_FEN_WL BIT(9) +#define GPIO_FEN_PCI BIT(10) +#define GPIO_FEN_USB BIT(11) +#define GPIO_BTRF_HWPDN_N BIT(12) +#define GPIO_WLRF_HWPDN_N BIT(13) +#define GPIO_PDN_BT_N BIT(14) +#define GPIO_PDN_GPS_N BIT(15) +#define GPIO_BT_CTL_HWPDN BIT(16) +#define GPIO_GPS_CTL_HWPDN BIT(17) +#define GPIO_PPHY_SUSB BIT(20) +#define GPIO_UPHY_SUSB BIT(21) +#define GPIO_PCI_SUSEN BIT(22) +#define GPIO_USB_SUSEN BIT(23) +#define GPIO_RF_RL_ID (BIT(31) | BIT(30) | BIT(29) | BIT(28)) + +/* 0x0100 ~ 0x01FF MACTOP General Configuration */ +#define REG_CR 0x0100 +#define CR_HCI_TXDMA_ENABLE BIT(0) +#define CR_HCI_RXDMA_ENABLE BIT(1) +#define CR_TXDMA_ENABLE BIT(2) +#define CR_RXDMA_ENABLE BIT(3) +#define CR_PROTOCOL_ENABLE BIT(4) +#define CR_SCHEDULE_ENABLE BIT(5) +#define CR_MAC_TX_ENABLE BIT(6) +#define CR_MAC_RX_ENABLE BIT(7) +#define CR_SW_BEACON_ENABLE BIT(8) +#define CR_SECURITY_ENABLE BIT(9) +#define CR_CALTIMER_ENABLE BIT(10) + +/* Media Status Register */ +#define REG_MSR 0x0102 +#define MSR_LINKTYPE_MASK 0x3 +#define MSR_LINKTYPE_NONE 0x0 +#define MSR_LINKTYPE_ADHOC 0x1 +#define MSR_LINKTYPE_STATION 0x2 +#define MSR_LINKTYPE_AP 0x3 + +#define REG_PBP 0x0104 +#define PBP_PAGE_SIZE_RX_SHIFT 0 +#define PBP_PAGE_SIZE_TX_SHIFT 4 +#define PBP_PAGE_SIZE_64 0x0 +#define PBP_PAGE_SIZE_128 0x1 +#define PBP_PAGE_SIZE_256 0x2 +#define PBP_PAGE_SIZE_512 0x3 +#define PBP_PAGE_SIZE_1024 0x4 + +#define REG_TRXDMA_CTRL 0x010c +#define TRXDMA_CTRL_VOQ_SHIFT 4 +#define TRXDMA_CTRL_VIQ_SHIFT 6 +#define TRXDMA_CTRL_BEQ_SHIFT 8 +#define TRXDMA_CTRL_BKQ_SHIFT 10 +#define TRXDMA_CTRL_MGQ_SHIFT 12 +#define TRXDMA_CTRL_HIQ_SHIFT 14 +#define TRXDMA_QUEUE_LOW 1 +#define TRXDMA_QUEUE_NORMAL 2 +#define TRXDMA_QUEUE_HIGH 3 + +#define REG_TRXFF_BNDY 0x0114 +#define REG_TRXFF_STATUS 0x0118 +#define REG_RXFF_PTR 0x011c +#define REG_HIMR 0x0120 +#define REG_HISR 0x0124 +#define REG_HIMRE 0x0128 +#define REG_HISRE 0x012c +#define REG_CPWM 0x012f +#define REG_FWIMR 0x0130 +#define REG_FWISR 0x0134 +#define REG_PKTBUF_DBG_CTRL 0x0140 +#define REG_PKTBUF_DBG_DATA_L 0x0144 +#define REG_PKTBUF_DBG_DATA_H 0x0148 + +#define REG_TC0_CTRL 0x0150 +#define REG_TC1_CTRL 0x0154 +#define REG_TC2_CTRL 0x0158 +#define REG_TC3_CTRL 0x015c +#define REG_TC4_CTRL 0x0160 +#define REG_TCUNIT_BASE 0x0164 +#define REG_MBIST_START 0x0174 +#define REG_MBIST_DONE 0x0178 +#define REG_MBIST_FAIL 0x017c +#define REG_C2HEVT_MSG_NORMAL 0x01a0 +#define REG_C2HEVT_CLEAR 0x01af +#define REG_C2HEVT_MSG_TEST 0x01b8 +#define REG_MCUTST_1 0x01c0 +#define REG_FMTHR 0x01c8 +#define REG_HMTFR 0x01cc +#define REG_HMBOX_0 0x01d0 +#define REG_HMBOX_1 0x01d4 +#define REG_HMBOX_2 0x01d8 +#define REG_HMBOX_3 0x01dc + +#define REG_LLT_INIT 0x01e0 +#define LLT_OP_INACTIVE 0x0 +#define LLT_OP_WRITE (0x1 << 30) +#define LLT_OP_READ (0x2 << 30) +#define LLT_OP_MASK (0x3 << 30) + +#define REG_BB_ACCEESS_CTRL 0x01e8 +#define REG_BB_ACCESS_DATA 0x01ec + +/* 0x0200 ~ 0x027F TXDMA Configuration */ +#define REG_RQPN 0x0200 +#define RQPN_HI_PQ_SHIFT 0 +#define RQPN_LO_PQ_SHIFT 8 +#define RQPN_NORM_PQ_SHIFT 16 +#define RQPN_LOAD BIT(31) + +#define REG_FIFOPAGE 0x0204 +#define REG_TDECTRL 0x0208 +#define REG_TXDMA_OFFSET_CHK 0x020c +#define REG_TXDMA_STATUS 0x0210 +#define REG_RQPN_NPQ 0x0214 + +/* 0x0280 ~ 0x02FF RXDMA Configuration */ +#define REG_RXDMA_AGG_PG_TH 0x0280 +#define REG_RXPKT_NUM 0x0284 +#define REG_RXDMA_STATUS 0x0288 + +#define REG_RF_BB_CMD_ADDR 0x02c0 +#define REG_RF_BB_CMD_DATA 0x02c4 + +/* spec version 11 */ +/* 0x0400 ~ 0x047F Protocol Configuration */ +#define REG_VOQ_INFORMATION 0x0400 +#define REG_VIQ_INFORMATION 0x0404 +#define REG_BEQ_INFORMATION 0x0408 +#define REG_BKQ_INFORMATION 0x040c +#define REG_MGQ_INFORMATION 0x0410 +#define REG_HGQ_INFORMATION 0x0414 +#define REG_BCNQ_INFORMATION 0x0418 + +#define REG_CPU_MGQ_INFORMATION 0x041c +#define REG_FWHW_TXQ_CTRL 0x0420 +#define FWHW_TXQ_CTRL_AMPDU_RETRY BIT(7) +#define FWHW_TXQ_CTRL_XMIT_MGMT_ACK BIT(12) + +#define REG_HWSEQ_CTRL 0x0423 +#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 +#define REG_TXPKTBUF_MGQ_BDNY 0x0425 +#define REG_LIFETIME_EN 0x0426 +#define REG_MULTI_BCNQ_OFFSET 0x0427 + +#define REG_SPEC_SIFS 0x0428 +#define SPEC_SIFS_CCK_MASK 0x00ff +#define SPEC_SIFS_CCK_SHIFT 0 +#define SPEC_SIFS_OFDM_MASK 0xff00 +#define SPEC_SIFS_OFDM_SHIFT 8 + +#define REG_RETRY_LIMIT 0x042a +#define RETRY_LIMIT_LONG_SHIFT 0 +#define RETRY_LIMIT_LONG_MASK 0x003f +#define RETRY_LIMIT_SHORT_SHIFT 8 +#define RETRY_LIMIT_SHORT_MASK 0x3f00 + +#define REG_DARFRC 0x0430 +#define REG_RARFRC 0x0438 +#define REG_RESPONSE_RATE_SET 0x0440 +#define RESPONSE_RATE_BITMAP_ALL 0xfffff +#define RESPONSE_RATE_RRSR_CCK_ONLY_1M 0xffff1 +#define RSR_1M BIT(0) +#define RSR_2M BIT(1) +#define RSR_5_5M BIT(2) +#define RSR_11M BIT(3) +#define RSR_6M BIT(4) +#define RSR_9M BIT(5) +#define RSR_12M BIT(6) +#define RSR_18M BIT(7) +#define RSR_24M BIT(8) +#define RSR_36M BIT(9) +#define RSR_48M BIT(10) +#define RSR_54M BIT(11) +#define RSR_MCS0 BIT(12) +#define RSR_MCS1 BIT(13) +#define RSR_MCS2 BIT(14) +#define RSR_MCS3 BIT(15) +#define RSR_MCS4 BIT(16) +#define RSR_MCS5 BIT(17) +#define RSR_MCS6 BIT(18) +#define RSR_MCS7 BIT(19) +#define RSR_RSC_LOWER_SUB_CHANNEL BIT(21) /* 0x200000 */ +#define RSR_RSC_UPPER_SUB_CHANNEL BIT(22) /* 0x400000 */ +#define RSR_RSC_BANDWIDTH_40M (RSR_RSC_UPPER_SUB_CHANNEL | \ + RSR_RSC_LOWER_SUB_CHANNEL) +#define RSR_ACK_SHORT_PREAMBLE BIT(23) + +#define REG_ARFR0 0x0444 +#define REG_ARFR1 0x0448 +#define REG_ARFR2 0x044c +#define REG_ARFR3 0x0450 +#define REG_AGGLEN_LMT 0x0458 +#define REG_AMPDU_MIN_SPACE 0x045c +#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045d +#define REG_FAST_EDCA_CTRL 0x0460 +#define REG_RD_RESP_PKT_TH 0x0463 +#define REG_INIRTS_RATE_SEL 0x0480 +#define REG_INIDATA_RATE_SEL 0x0484 + +#define REG_POWER_STATUS 0x04a4 +#define REG_POWER_STAGE1 0x04b4 +#define REG_POWER_STAGE2 0x04b8 +#define REG_PKT_VO_VI_LIFE_TIME 0x04c0 +#define REG_PKT_BE_BK_LIFE_TIME 0x04c2 +#define REG_STBC_SETTING 0x04c4 +#define REG_PROT_MODE_CTRL 0x04c8 +#define REG_MAX_AGGR_NUM 0x04ca +#define REG_RTS_MAX_AGGR_NUM 0x04cb +#define REG_BAR_MODE_CTRL 0x04cc +#define REG_RA_TRY_RATE_AGG_LMT 0x04cf +#define REG_NQOS_SEQ 0x04dc +#define REG_QOS_SEQ 0x04de +#define REG_NEED_CPU_HANDLE 0x04e0 +#define REG_PKT_LOSE_RPT 0x04e1 +#define REG_PTCL_ERR_STATUS 0x04e2 +#define REG_DUMMY 0x04fc + +/* 0x0500 ~ 0x05FF EDCA Configuration */ +#define REG_EDCA_VO_PARAM 0x0500 +#define REG_EDCA_VI_PARAM 0x0504 +#define REG_EDCA_BE_PARAM 0x0508 +#define REG_EDCA_BK_PARAM 0x050c +#define EDCA_PARAM_ECW_MIN_SHIFT 8 +#define EDCA_PARAM_ECW_MAX_SHIFT 12 +#define EDCA_PARAM_TXOP_SHIFT 16 +#define REG_BEACON_TCFG 0x0510 +#define REG_PIFS 0x0512 +#define REG_RDG_PIFS 0x0513 +#define REG_SIFS_CCK 0x0514 +#define REG_SIFS_OFDM 0x0516 +#define REG_TSFTR_SYN_OFFSET 0x0518 +#define REG_AGGR_BREAK_TIME 0x051a +#define REG_SLOT 0x051b +#define REG_TX_PTCL_CTRL 0x0520 +#define REG_TXPAUSE 0x0522 +#define REG_DIS_TXREQ_CLR 0x0523 +#define REG_RD_CTRL 0x0524 +#define REG_TBTT_PROHIBIT 0x0540 +#define REG_RD_NAV_NXT 0x0544 +#define REG_NAV_PROT_LEN 0x0546 + +#define REG_BEACON_CTRL 0x0550 +#define REG_BEACON_CTRL_1 0x0551 +#define BEACON_ATIM BIT(0) +#define BEACON_CTRL_MBSSID BIT(1) +#define BEACON_CTRL_TX_BEACON_RPT BIT(2) +#define BEACON_FUNCTION_ENABLE BIT(3) +#define BEACON_DISABLE_TSF_UPDATE BIT(4) + +#define REG_MBID_NUM 0x0552 +#define REG_DUAL_TSF_RST 0x0553 +#define DUAL_TSF_RESET_TSF0 BIT(0) +#define DUAL_TSF_RESET_TSF1 BIT(1) +#define DUAL_TSF_RESET_P2P BIT(4) +#define DUAL_TSF_TX_OK BIT(5) + +/* The same as REG_MBSSID_BCN_SPACE */ +#define REG_BCN_INTERVAL 0x0554 +#define REG_MBSSID_BCN_SPACE 0x0554 + +#define REG_DRIVER_EARLY_INT 0x0558 +#define DRIVER_EARLY_INT_TIME 5 + +#define REG_BEACON_DMA_TIME 0x0559 +#define BEACON_DMA_ATIME_INT_TIME 2 + +#define REG_ATIMWND 0x055a +#define REG_BCN_MAX_ERR 0x055d +#define REG_RXTSF_OFFSET_CCK 0x055e +#define REG_RXTSF_OFFSET_OFDM 0x055f +#define REG_TSFTR 0x0560 +#define REG_TSFTR1 0x0568 +#define REG_INIT_TSFTR 0x0564 +#define REG_ATIMWND_1 0x0570 +#define REG_PSTIMER 0x0580 +#define REG_TIMER0 0x0584 +#define REG_TIMER1 0x0588 +#define REG_ACM_HW_CTRL 0x05c0 +#define ACM_HW_CTRL_BK BIT(0) +#define ACM_HW_CTRL_BE BIT(1) +#define ACM_HW_CTRL_VI BIT(2) +#define ACM_HW_CTRL_VO BIT(3) +#define REG_ACM_RST_CTRL 0x05c1 +#define REG_ACMAVG 0x05c2 +#define REG_VO_ADMTIME 0x05c4 +#define REG_VI_ADMTIME 0x05c6 +#define REG_BE_ADMTIME 0x05c8 +#define REG_EDCA_RANDOM_GEN 0x05cc +#define REG_SCH_TXCMD 0x05d0 + +/* define REG_FW_TSF_SYNC_CNT 0x04a0 */ +#define REG_FW_RESET_TSF_CNT_1 0x05fc +#define REG_FW_RESET_TSF_CNT_0 0x05fd +#define REG_FW_BCN_DIS_CNT 0x05fe + +/* 0x0600 ~ 0x07FF WMAC Configuration */ +#define REG_APSD_CTRL 0x0600 +#define APSD_CTRL_OFF BIT(6) +#define APSD_CTRL_OFF_STATUS BIT(7) +#define REG_BW_OPMODE 0x0603 +#define BW_OPMODE_20MHZ BIT(2) +#define BW_OPMODE_5G BIT(1) +#define BW_OPMODE_11J BIT(0) + +#define REG_TCR 0x0604 + +/* Receive Configuration Register */ +#define REG_RCR 0x0608 +#define RCR_ACCEPT_AP BIT(0) /* Accept all unicast packet */ +#define RCR_ACCEPT_PHYS_MATCH BIT(1) /* Accept phys match packet */ +#define RCR_ACCEPT_MCAST BIT(2) +#define RCR_ACCEPT_BCAST BIT(3) +#define RCR_ACCEPT_ADDR3 BIT(4) /* Accept address 3 match + packet */ +#define RCR_ACCEPT_PM BIT(5) /* Accept power management + packet */ +#define RCR_CHECK_BSSID_MATCH BIT(6) /* Accept BSSID match packet */ +#define RCR_CHECK_BSSID_BEACON BIT(7) /* Accept BSSID match packet + (Rx beacon, probe rsp) */ +#define RCR_ACCEPT_CRC32 BIT(8) /* Accept CRC32 error packet */ +#define RCR_ACCEPT_ICV BIT(9) /* Accept ICV error packet */ +#define RCR_ACCEPT_DATA_FRAME BIT(11) +#define RCR_ACCEPT_CTRL_FRAME BIT(12) +#define RCR_ACCEPT_MGMT_FRAME BIT(13) +#define RCR_HTC_LOC_CTRL BIT(14) /* MFC<--HTC=1 MFC-->HTC=0 */ +#define RCR_MFBEN BIT(22) +#define RCR_LSIGEN BIT(23) +#define RCR_MULTI_BSSID_ENABLE BIT(24) /* Enable Multiple BssId */ +#define RCR_ACCEPT_BA_SSN BIT(27) /* Accept BA SSN */ +#define RCR_APPEND_PHYSTAT BIT(28) +#define RCR_APPEND_ICV BIT(29) +#define RCR_APPEND_MIC BIT(30) +#define RCR_APPEND_FCS BIT(31) /* WMAC append FCS after */ + +#define REG_RX_PKT_LIMIT 0x060c +#define REG_RX_DLK_TIME 0x060d +#define REG_RX_DRVINFO_SZ 0x060f + +#define REG_MACID 0x0610 +#define REG_BSSID 0x0618 +#define REG_MAR 0x0620 +#define REG_MBIDCAMCFG 0x0628 + +#define REG_USTIME_EDCA 0x0638 +#define REG_MAC_SPEC_SIFS 0x063a + +/* 20100719 Joseph: Hardware register definition change. (HW datasheet v54) */ + /* [15:8]SIFS_R2T_OFDM, [7:0]SIFS_R2T_CCK */ +#define REG_R2T_SIFS 0x063c + /* [15:8]SIFS_T2T_OFDM, [7:0]SIFS_T2T_CCK */ +#define REG_T2T_SIFS 0x063e +#define REG_ACKTO 0x0640 +#define REG_CTS2TO 0x0641 +#define REG_EIFS 0x0642 + +/* WMA, BA, CCX */ +#define REG_NAV_CTRL 0x0650 +/* In units of 128us */ +#define REG_NAV_UPPER 0x0652 +#define NAV_UPPER_UNIT 128 + +#define REG_BACAMCMD 0x0654 +#define REG_BACAMCONTENT 0x0658 +#define REG_LBDLY 0x0660 +#define REG_FWDLY 0x0661 +#define REG_RXERR_RPT 0x0664 +#define REG_WMAC_TRXPTCL_CTL 0x0668 + +/* Security */ +#define REG_CAM_CMD 0x0670 +#define CAM_CMD_POLLING BIT(31) +#define CAM_CMD_WRITE BIT(16) +#define CAM_CMD_KEY_SHIFT 3 +#define REG_CAM_WRITE 0x0674 +#define CAM_WRITE_VALID BIT(15) +#define REG_CAM_READ 0x0678 +#define REG_CAM_DEBUG 0x067c +#define REG_SECURITY_CFG 0x0680 +#define SEC_CFG_TX_USE_DEFKEY BIT(0) +#define SEC_CFG_RX_USE_DEFKEY BIT(1) +#define SEC_CFG_TX_SEC_ENABLE BIT(2) +#define SEC_CFG_RX_SEC_ENABLE BIT(3) +#define SEC_CFG_SKBYA2 BIT(4) +#define SEC_CFG_NO_SKMC BIT(5) +#define SEC_CFG_TXBC_USE_DEFKEY BIT(6) +#define SEC_CFG_RXBC_USE_DEFKEY BIT(7) + +/* Power */ +#define REG_WOW_CTRL 0x0690 +#define REG_PSSTATUS 0x0691 +#define REG_PS_RX_INFO 0x0692 +#define REG_LPNAV_CTRL 0x0694 +#define REG_WKFMCAM_CMD 0x0698 +#define REG_WKFMCAM_RWD 0x069c +#define REG_RXFLTMAP0 0x06a0 +#define REG_RXFLTMAP1 0x06a2 +#define REG_RXFLTMAP2 0x06a4 +#define REG_BCN_PSR_RPT 0x06a8 +#define REG_CALB32K_CTRL 0x06ac +#define REG_PKT_MON_CTRL 0x06b4 +#define REG_BT_COEX_TABLE 0x06c0 +#define REG_WMAC_RESP_TXINFO 0x06d8 + +#define REG_MACID1 0x0700 +#define REG_BSSID1 0x0708 + +#define REG_FPGA0_RF_MODE 0x0800 +#define FPGA_RF_MODE BIT(0) +#define FPGA_RF_MODE_JAPAN BIT(1) +#define FPGA_RF_MODE_CCK BIT(24) +#define FPGA_RF_MODE_OFDM BIT(25) + +#define REG_FPGA0_TX_INFO 0x0804 +#define REG_FPGA0_PSD_FUNC 0x0808 +#define REG_FPGA0_TX_GAIN 0x080c +#define REG_FPGA0_RF_TIMING1 0x0810 +#define REG_FPGA0_RF_TIMING2 0x0814 +#define REG_FPGA0_POWER_SAVE 0x0818 +#define FPGA0_PS_LOWER_CHANNEL BIT(26) +#define FPGA0_PS_UPPER_CHANNEL BIT(27) + +#define REG_FPGA0_XA_HSSI_PARM1 0x0820 /* RF 3 wire register */ +#define FPGA0_HSSI_PARM1_PI BIT(8) +#define REG_FPGA0_XA_HSSI_PARM2 0x0824 +#define REG_FPGA0_XB_HSSI_PARM1 0x0828 +#define REG_FPGA0_XB_HSSI_PARM2 0x082c +#define FPGA0_HSSI_3WIRE_DATA_LEN 0x800 +#define FPGA0_HSSI_3WIRE_ADDR_LEN 0x400 +#define FPGA0_HSSI_PARM2_ADDR_SHIFT 23 +#define FPGA0_HSSI_PARM2_ADDR_MASK 0x7f800000 /* 0xff << 23 */ +#define FPGA0_HSSI_PARM2_CCK_HIGH_PWR BIT(9) +#define FPGA0_HSSI_PARM2_EDGE_READ BIT(31) + +#define REG_TX_AGC_B_RATE18_06 0x0830 +#define REG_TX_AGC_B_RATE54_24 0x0834 +#define REG_TX_AGC_B_CCK1_55_MCS32 0x0838 +#define REG_TX_AGC_B_MCS03_MCS00 0x083c + +#define REG_FPGA0_XA_LSSI_PARM 0x0840 +#define REG_FPGA0_XB_LSSI_PARM 0x0844 +#define FPGA0_LSSI_PARM_ADDR_SHIFT 20 +#define FPGA0_LSSI_PARM_ADDR_MASK 0x0ff00000 +#define FPGA0_LSSI_PARM_DATA_MASK 0x000fffff + +#define REG_TX_AGC_B_MCS07_MCS04 0x0848 +#define REG_TX_AGC_B_MCS11_MCS08 0x084c + +#define REG_FPGA0_XCD_SWITCH_CTRL 0x085c + +#define REG_FPGA0_XA_RF_INT_OE 0x0860 /* RF Channel switch */ +#define REG_FPGA0_XB_RF_INT_OE 0x0864 +#define FPGA0_INT_OE_ANTENNA_AB_OPEN 0x000 +#define FPGA0_INT_OE_ANTENNA_A BIT(8) +#define FPGA0_INT_OE_ANTENNA_B BIT(9) +#define FPGA0_INT_OE_ANTENNA_MASK (FPGA0_INT_OE_ANTENNA_A | \ + FPGA0_INT_OE_ANTENNA_B) + +#define REG_TX_AGC_B_MCS15_MCS12 0x0868 +#define REG_TX_AGC_B_CCK11_A_CCK2_11 0x086c + +#define REG_FPGA0_XAB_RF_SW_CTRL 0x0870 +#define REG_FPGA0_XA_RF_SW_CTRL 0x0870 /* 16 bit */ +#define REG_FPGA0_XB_RF_SW_CTRL 0x0872 /* 16 bit */ +#define REG_FPGA0_XCD_RF_SW_CTRL 0x0874 +#define REG_FPGA0_XC_RF_SW_CTRL 0x0874 /* 16 bit */ +#define REG_FPGA0_XD_RF_SW_CTRL 0x0876 /* 16 bit */ +#define FPGA0_RF_3WIRE_DATA BIT(0) +#define FPGA0_RF_3WIRE_CLOC BIT(1) +#define FPGA0_RF_3WIRE_LOAD BIT(2) +#define FPGA0_RF_3WIRE_RW BIT(3) +#define FPGA0_RF_3WIRE_MASK 0xf +#define FPGA0_RF_RFENV BIT(4) +#define FPGA0_RF_TRSW BIT(5) /* Useless now */ +#define FPGA0_RF_TRSWB BIT(6) +#define FPGA0_RF_ANTSW BIT(8) +#define FPGA0_RF_ANTSWB BIT(9) +#define FPGA0_RF_PAPE BIT(10) +#define FPGA0_RF_PAPE5G BIT(11) +#define FPGA0_RF_BD_CTRL_SHIFT 16 + +#define REG_FPGA0_XAB_RF_PARM 0x0878 /* Antenna select path in ODM */ +#define REG_FPGA0_XA_RF_PARM 0x0878 /* 16 bit */ +#define REG_FPGA0_XB_RF_PARM 0x087a /* 16 bit */ +#define REG_FPGA0_XCD_RF_PARM 0x087c +#define REG_FPGA0_XC_RF_PARM 0x087c /* 16 bit */ +#define REG_FPGA0_XD_RF_PARM 0x087e /* 16 bit */ +#define FPGA0_RF_PARM_RFA_ENABLE BIT(1) +#define FPGA0_RF_PARM_RFB_ENABLE BIT(17) +#define FPGA0_RF_PARM_CLK_GATE BIT(31) + +#define REG_FPGA0_ANALOG1 0x0880 +#define REG_FPGA0_ANALOG2 0x0884 +#define FPGA0_ANALOG2_20MHZ BIT(10) +#define REG_FPGA0_ANALOG3 0x0888 +#define REG_FPGA0_ANALOG4 0x088c + +#define REG_FPGA0_XA_LSSI_READBACK 0x08a0 /* Tranceiver LSSI Readback */ +#define REG_FPGA0_XB_LSSI_READBACK 0x08a4 +#define REG_HSPI_XA_READBACK 0x08b8 /* Transceiver A HSPI read */ +#define REG_HSPI_XB_READBACK 0x08bc /* Transceiver B HSPI read */ + +#define REG_FPGA1_RF_MODE 0x0900 + +#define REG_FPGA1_TX_INFO 0x090c + +#define REG_CCK0_SYSTEM 0x0a00 +#define CCK0_SIDEBAND BIT(4) + +#define REG_CCK0_AFE_SETTING 0x0a04 + +#define REG_CONFIG_ANT_A 0x0b68 +#define REG_CONFIG_ANT_B 0x0b6c + +#define REG_OFDM0_TRX_PATH_ENABLE 0x0c04 +#define OFDM_RF_PATH_RX_MASK 0x0f +#define OFDM_RF_PATH_RX_A BIT(0) +#define OFDM_RF_PATH_RX_B BIT(1) +#define OFDM_RF_PATH_RX_C BIT(2) +#define OFDM_RF_PATH_RX_D BIT(3) +#define OFDM_RF_PATH_TX_MASK 0xf0 +#define OFDM_RF_PATH_TX_A BIT(4) +#define OFDM_RF_PATH_TX_B BIT(5) +#define OFDM_RF_PATH_TX_C BIT(6) +#define OFDM_RF_PATH_TX_D BIT(7) + +#define REG_OFDM0_TR_MUX_PAR 0x0c08 + +#define REG_OFDM0_XA_RX_IQ_IMBALANCE 0x0c14 +#define REG_OFDM0_XB_RX_IQ_IMBALANCE 0x0c1c + +#define REG_OFDM0_ENERGY_CCA_THRES 0x0c4c + +#define REG_OFDM0_XA_AGC_CORE1 0x0c50 +#define REG_OFDM0_XA_AGC_CORE2 0x0c54 +#define REG_OFDM0_XB_AGC_CORE1 0x0c58 +#define REG_OFDM0_XB_AGC_CORE2 0x0c5c +#define REG_OFDM0_XC_AGC_CORE1 0x0c60 +#define REG_OFDM0_XC_AGC_CORE2 0x0c64 +#define REG_OFDM0_XD_AGC_CORE1 0x0c68 +#define REG_OFDM0_XD_AGC_CORE2 0x0c6c +#define OFDM0_X_AGC_CORE1_IGI_MASK 0x0000007F + +#define REG_OFDM0_AGC_PARM1 0x0c70 + +#define REG_OFDM0_AGCR_SSI_TABLE 0x0c78 + +#define REG_OFDM0_XA_TX_IQ_IMBALANCE 0x0c80 +#define REG_OFDM0_XB_TX_IQ_IMBALANCE 0x0c88 +#define REG_OFDM0_XC_TX_IQ_IMBALANCE 0x0c90 +#define REG_OFDM0_XD_TX_IQ_IMBALANCE 0x0c98 + +#define REG_OFDM0_XC_TX_AFE 0x0c94 +#define REG_OFDM0_XD_TX_AFE 0x0c9c + +#define REG_OFDM0_RX_IQ_EXT_ANTA 0x0ca0 + +#define REG_OFDM1_LSTF 0x0d00 +#define OFDM_LSTF_PRIME_CH_LOW BIT(10) +#define OFDM_LSTF_PRIME_CH_HIGH BIT(11) +#define OFDM_LSTF_PRIME_CH_MASK (OFDM_LSTF_PRIME_CH_LOW | \ + OFDM_LSTF_PRIME_CH_HIGH) +#define OFDM_LSTF_CONTINUE_TX BIT(28) +#define OFDM_LSTF_SINGLE_CARRIER BIT(29) +#define OFDM_LSTF_SINGLE_TONE BIT(30) +#define OFDM_LSTF_MASK 0x70000000 + +#define REG_OFDM1_TRX_PATH_ENABLE 0x0d04 + +#define REG_TX_AGC_A_RATE18_06 0x0e00 +#define REG_TX_AGC_A_RATE54_24 0x0e04 +#define REG_TX_AGC_A_CCK1_MCS32 0x0e08 +#define REG_TX_AGC_A_MCS03_MCS00 0x0e10 +#define REG_TX_AGC_A_MCS07_MCS04 0x0e14 +#define REG_TX_AGC_A_MCS11_MCS08 0x0e18 +#define REG_TX_AGC_A_MCS15_MCS12 0x0e1c + +#define REG_FPGA0_IQK 0x0e28 + +#define REG_TX_IQK_TONE_A 0x0e30 +#define REG_RX_IQK_TONE_A 0x0e34 +#define REG_TX_IQK_PI_A 0x0e38 +#define REG_RX_IQK_PI_A 0x0e3c + +#define REG_TX_IQK 0x0e40 +#define REG_RX_IQK 0x0e44 +#define REG_IQK_AGC_PTS 0x0e48 +#define REG_IQK_AGC_RSP 0x0e4c +#define REG_TX_IQK_TONE_B 0x0e50 +#define REG_RX_IQK_TONE_B 0x0e54 +#define REG_TX_IQK_PI_B 0x0e58 +#define REG_RX_IQK_PI_B 0x0e5c +#define REG_IQK_AGC_CONT 0x0e60 + +#define REG_BLUETOOTH 0x0e6c +#define REG_RX_WAIT_CCA 0x0e70 +#define REG_TX_CCK_RFON 0x0e74 +#define REG_TX_CCK_BBON 0x0e78 +#define REG_TX_OFDM_RFON 0x0e7c +#define REG_TX_OFDM_BBON 0x0e80 +#define REG_TX_TO_RX 0x0e84 +#define REG_TX_TO_TX 0x0e88 +#define REG_RX_CCK 0x0e8c + +#define REG_TX_POWER_BEFORE_IQK_A 0x0e94 +#define REG_TX_POWER_AFTER_IQK_A 0x0e9c + +#define REG_RX_POWER_BEFORE_IQK_A 0x0ea0 +#define REG_RX_POWER_BEFORE_IQK_A_2 0x0ea4 +#define REG_RX_POWER_AFTER_IQK_A 0x0ea8 +#define REG_RX_POWER_AFTER_IQK_A_2 0x0eac + +#define REG_TX_POWER_BEFORE_IQK_B 0x0eb4 +#define REG_TX_POWER_AFTER_IQK_B 0x0ebc + +#define REG_RX_POWER_BEFORE_IQK_B 0x0ec0 +#define REG_RX_POWER_BEFORE_IQK_B_2 0x0ec4 +#define REG_RX_POWER_AFTER_IQK_B 0x0ec8 +#define REG_RX_POWER_AFTER_IQK_B_2 0x0ecc + +#define REG_RX_OFDM 0x0ed0 +#define REG_RX_WAIT_RIFS 0x0ed4 +#define REG_RX_TO_RX 0x0ed8 +#define REG_STANDBY 0x0edc +#define REG_SLEEP 0x0ee0 +#define REG_PMPD_ANAEN 0x0eec + +#define REG_FW_START_ADDRESS 0x1000 + +#define REG_USB_INFO 0xfe17 +#define REG_USB_HIMR 0xfe38 +#define USB_HIMR_TIMEOUT2 BIT(31) +#define USB_HIMR_TIMEOUT1 BIT(30) +#define USB_HIMR_PSTIMEOUT BIT(29) +#define USB_HIMR_GTINT4 BIT(28) +#define USB_HIMR_GTINT3 BIT(27) +#define USB_HIMR_TXBCNERR BIT(26) +#define USB_HIMR_TXBCNOK BIT(25) +#define USB_HIMR_TSF_BIT32_TOGGLE BIT(24) +#define USB_HIMR_BCNDMAINT3 BIT(23) +#define USB_HIMR_BCNDMAINT2 BIT(22) +#define USB_HIMR_BCNDMAINT1 BIT(21) +#define USB_HIMR_BCNDMAINT0 BIT(20) +#define USB_HIMR_BCNDOK3 BIT(19) +#define USB_HIMR_BCNDOK2 BIT(18) +#define USB_HIMR_BCNDOK1 BIT(17) +#define USB_HIMR_BCNDOK0 BIT(16) +#define USB_HIMR_HSISR_IND BIT(15) +#define USB_HIMR_BCNDMAINT_E BIT(14) +/* RSVD BIT(13) */ +#define USB_HIMR_CTW_END BIT(12) +/* RSVD BIT(11) */ +#define USB_HIMR_C2HCMD BIT(10) +#define USB_HIMR_CPWM2 BIT(9) +#define USB_HIMR_CPWM BIT(8) +#define USB_HIMR_HIGHDOK BIT(7) /* High Queue DMA OK + Interrupt */ +#define USB_HIMR_MGNTDOK BIT(6) /* Management Queue DMA OK + Interrupt */ +#define USB_HIMR_BKDOK BIT(5) /* AC_BK DMA OK Interrupt */ +#define USB_HIMR_BEDOK BIT(4) /* AC_BE DMA OK Interrupt */ +#define USB_HIMR_VIDOK BIT(3) /* AC_VI DMA OK Interrupt */ +#define USB_HIMR_VODOK BIT(2) /* AC_VO DMA Interrupt */ +#define USB_HIMR_RDU BIT(1) /* Receive Descriptor + Unavailable */ +#define USB_HIMR_ROK BIT(0) /* Receive DMA OK Interrupt */ + +#define REG_USB_SPECIAL_OPTION 0xfe55 +#define REG_USB_DMA_AGG_TO 0xfe5b +#define REG_USB_AGG_TO 0xfe5c +#define REG_USB_AGG_TH 0xfe5d + +#define REG_NORMAL_SIE_VID 0xfe60 /* 0xfe60 - 0xfe61 */ +#define REG_NORMAL_SIE_PID 0xfe62 /* 0xfe62 - 0xfe63 */ +#define REG_NORMAL_SIE_OPTIONAL 0xfe64 +#define REG_NORMAL_SIE_EP 0xfe65 /* 0xfe65 - 0xfe67 */ +#define REG_NORMAL_SIE_EP_TX 0xfe66 +#define NORMAL_SIE_EP_TX_HIGH_MASK 0x000f +#define NORMAL_SIE_EP_TX_NORMAL_MASK 0x00f0 +#define NORMAL_SIE_EP_TX_LOW_MASK 0x0f00 + +#define REG_NORMAL_SIE_PHY 0xfe68 /* 0xfe68 - 0xfe6b */ +#define REG_NORMAL_SIE_OPTIONAL2 0xfe6c +#define REG_NORMAL_SIE_GPS_EP 0xfe6d /* RTL8723 only */ +#define REG_NORMAL_SIE_MAC_ADDR 0xfe70 /* 0xfe70 - 0xfe75 */ +#define REG_NORMAL_SIE_STRING 0xfe80 /* 0xfe80 - 0xfedf */ + +/* RF6052 registers */ +#define RF6052_REG_AC 0x00 +#define RF6052_REG_IQADJ_G1 0x01 +#define RF6052_REG_IQADJ_G2 0x02 +#define RF6052_REG_BS_PA_APSET_G1_G4 0x03 +#define RF6052_REG_BS_PA_APSET_G5_G8 0x04 +#define RF6052_REG_POW_TRSW 0x05 +#define RF6052_REG_GAIN_RX 0x06 +#define RF6052_REG_GAIN_TX 0x07 +#define RF6052_REG_TXM_IDAC 0x08 +#define RF6052_REG_IPA_G 0x09 +#define RF6052_REG_TXBIAS_G 0x0a +#define RF6052_REG_TXPA_AG 0x0b +#define RF6052_REG_IPA_A 0x0c +#define RF6052_REG_TXBIAS_A 0x0d +#define RF6052_REG_BS_PA_APSET_G9_G11 0x0e +#define RF6052_REG_BS_IQGEN 0x0f +#define RF6052_REG_MODE1 0x10 +#define RF6052_REG_MODE2 0x11 +#define RF6052_REG_RX_AGC_HP 0x12 +#define RF6052_REG_TX_AGC 0x13 +#define RF6052_REG_BIAS 0x14 +#define RF6052_REG_IPA 0x15 +#define RF6052_REG_TXBIAS 0x16 +#define RF6052_REG_POW_ABILITY 0x17 +#define RF6052_REG_MODE_AG 0x18 /* RF channel and BW switch */ +#define MODE_AG_CHANNEL_MASK 0x3ff +#define MODE_AG_CHANNEL_20MHZ BIT(10) + +#define RF6052_REG_TOP 0x19 +#define RF6052_REG_RX_G1 0x1a +#define RF6052_REG_RX_G2 0x1b +#define RF6052_REG_RX_BB2 0x1c +#define RF6052_REG_RX_BB1 0x1d +#define RF6052_REG_RCK1 0x1e +#define RF6052_REG_RCK2 0x1f +#define RF6052_REG_TX_G1 0x20 +#define RF6052_REG_TX_G2 0x21 +#define RF6052_REG_TX_G3 0x22 +#define RF6052_REG_TX_BB1 0x23 +#define RF6052_REG_T_METER 0x24 +#define RF6052_REG_SYN_G1 0x25 /* RF TX Power control */ +#define RF6052_REG_SYN_G2 0x26 /* RF TX Power control */ +#define RF6052_REG_SYN_G3 0x27 /* RF TX Power control */ +#define RF6052_REG_SYN_G4 0x28 /* RF TX Power control */ +#define RF6052_REG_SYN_G5 0x29 /* RF TX Power control */ +#define RF6052_REG_SYN_G6 0x2a /* RF TX Power control */ +#define RF6052_REG_SYN_G7 0x2b /* RF TX Power control */ +#define RF6052_REG_SYN_G8 0x2c /* RF TX Power control */ + +#define RF6052_REG_RCK_OS 0x30 /* RF TX PA control */ + +#define RF6052_REG_TXPA_G1 0x31 /* RF TX PA control */ +#define RF6052_REG_TXPA_G2 0x32 /* RF TX PA control */ +#define RF6052_REG_TXPA_G3 0x33 /* RF TX PA control */ diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/realtek/rtlwifi/Kconfig index 73067cac289c..73067cac289c 100644 --- a/drivers/net/wireless/rtlwifi/Kconfig +++ b/drivers/net/wireless/realtek/rtlwifi/Kconfig diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/realtek/rtlwifi/Makefile index ad6d3c52ec57..ad6d3c52ec57 100644 --- a/drivers/net/wireless/rtlwifi/Makefile +++ b/drivers/net/wireless/realtek/rtlwifi/Makefile diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 0517a4f2d3f2..0517a4f2d3f2 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h index 74233d601a90..74233d601a90 100644 --- a/drivers/net/wireless/rtlwifi/base.h +++ b/drivers/net/wireless/realtek/rtlwifi/base.h diff --git a/drivers/net/wireless/rtlwifi/btcoexist/Makefile b/drivers/net/wireless/realtek/rtlwifi/btcoexist/Makefile index 47ceecfcb7dc..47ceecfcb7dc 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/Makefile +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/Makefile diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbt_precomp.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h index 39b9a3309cfd..39b9a3309cfd 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbt_precomp.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c index 53261d6f8578..53261d6f8578 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h index 75e1f7d0db06..75e1f7d0db06 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c index c4acd403e5f6..c4acd403e5f6 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h index 75f8094b7a34..75f8094b7a34 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c index f2b9d11adc9e..f2b9d11adc9e 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h index 567f354caf95..567f354caf95 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c index b72e5377bdbc..b72e5377bdbc 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h index 20e904890fc2..20e904890fc2 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c index cf819f02ed23..cf819f02ed23 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h index b4cf1f53d510..b4cf1f53d510 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c index b2791c893417..b2791c893417 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h index 0a903ea179ef..0a903ea179ef 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h diff --git a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c index b9b0cb7af8ea..b9b0cb7af8ea 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c diff --git a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h index ccd5a0f91e3b..ccd5a0f91e3b 100644 --- a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/realtek/rtlwifi/cam.c index 8fe8b4cfae6c..8fe8b4cfae6c 100644 --- a/drivers/net/wireless/rtlwifi/cam.c +++ b/drivers/net/wireless/realtek/rtlwifi/cam.c diff --git a/drivers/net/wireless/rtlwifi/cam.h b/drivers/net/wireless/realtek/rtlwifi/cam.h index e2e647d511c1..e2e647d511c1 100644 --- a/drivers/net/wireless/rtlwifi/cam.h +++ b/drivers/net/wireless/realtek/rtlwifi/cam.h diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index 585d0883c7e5..c925a4dff599 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c @@ -1373,7 +1373,7 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct rtl_priv *rtlpriv = rtl_priv(hw); diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/realtek/rtlwifi/core.h index 782ac2fc4b28..782ac2fc4b28 100644 --- a/drivers/net/wireless/rtlwifi/core.h +++ b/drivers/net/wireless/realtek/rtlwifi/core.h diff --git a/drivers/net/wireless/rtlwifi/debug.c b/drivers/net/wireless/realtek/rtlwifi/debug.c index fd25abad2b9e..fd25abad2b9e 100644 --- a/drivers/net/wireless/rtlwifi/debug.c +++ b/drivers/net/wireless/realtek/rtlwifi/debug.c diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/realtek/rtlwifi/debug.h index fc794b3e9f4a..fc794b3e9f4a 100644 --- a/drivers/net/wireless/rtlwifi/debug.h +++ b/drivers/net/wireless/realtek/rtlwifi/debug.h diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/realtek/rtlwifi/efuse.c index 0b4082c9272a..0b4082c9272a 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/realtek/rtlwifi/efuse.c diff --git a/drivers/net/wireless/rtlwifi/efuse.h b/drivers/net/wireless/realtek/rtlwifi/efuse.h index be02e7894c61..be02e7894c61 100644 --- a/drivers/net/wireless/rtlwifi/efuse.h +++ b/drivers/net/wireless/realtek/rtlwifi/efuse.h diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index f46c9d7f6528..f46c9d7f6528 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/realtek/rtlwifi/pci.h index 5da6703942d9..5da6703942d9 100644 --- a/drivers/net/wireless/rtlwifi/pci.h +++ b/drivers/net/wireless/realtek/rtlwifi/pci.h diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c index b69321d45f04..b69321d45f04 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/realtek/rtlwifi/ps.c diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/realtek/rtlwifi/ps.h index 29dfc514212d..29dfc514212d 100644 --- a/drivers/net/wireless/rtlwifi/ps.h +++ b/drivers/net/wireless/realtek/rtlwifi/ps.h diff --git a/drivers/net/wireless/rtlwifi/pwrseqcmd.h b/drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h index 17ce0cb2c35c..17ce0cb2c35c 100644 --- a/drivers/net/wireless/rtlwifi/pwrseqcmd.h +++ b/drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/realtek/rtlwifi/rc.c index 74c14ce28238..74c14ce28238 100644 --- a/drivers/net/wireless/rtlwifi/rc.c +++ b/drivers/net/wireless/realtek/rtlwifi/rc.c diff --git a/drivers/net/wireless/rtlwifi/rc.h b/drivers/net/wireless/realtek/rtlwifi/rc.h index f29643d60d6b..f29643d60d6b 100644 --- a/drivers/net/wireless/rtlwifi/rc.h +++ b/drivers/net/wireless/realtek/rtlwifi/rc.h diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c index a62bf0a65c32..a62bf0a65c32 100644 --- a/drivers/net/wireless/rtlwifi/regd.c +++ b/drivers/net/wireless/realtek/rtlwifi/regd.c diff --git a/drivers/net/wireless/rtlwifi/regd.h b/drivers/net/wireless/realtek/rtlwifi/regd.h index f7f15bce35dd..f7f15bce35dd 100644 --- a/drivers/net/wireless/rtlwifi/regd.h +++ b/drivers/net/wireless/realtek/rtlwifi/regd.h diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/Makefile index a85419a37651..a85419a37651 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/Makefile diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h index 0532b9852444..0532b9852444 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c index ce4da9d79fbd..ce4da9d79fbd 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h index 071ccee69eae..071ccee69eae 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c index 629125658b87..629125658b87 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h index 21bd4a5337ab..21bd4a5337ab 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c index 8ee83b093c0d..8ee83b093c0d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h index 1850fde881b5..1850fde881b5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c index b504bd092fc4..b504bd092fc4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h index 4b325b75faaf..4b325b75faaf 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c index a2bb02c7b837..a2bb02c7b837 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h index b29bd77210f4..b29bd77210f4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c index 02013df968a0..02013df968a0 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h index f2d9c6116e5c..f2d9c6116e5c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h index 15400ee6c04b..15400ee6c04b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c index 40893cef7dfe..40893cef7dfe 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h index 0eca030e3238..0eca030e3238 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c index 11344121c55e..11344121c55e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h index 22398c3753a6..22398c3753a6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c index 68bcb7fe6a65..68bcb7fe6a65 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h index 403c4ddd236f..403c4ddd236f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c index 791efbe6b18c..791efbe6b18c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h index eab5ae0eb46c..eab5ae0eb46c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/Makefile index aee42d7ae8a2..aee42d7ae8a2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/Makefile +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/Makefile diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c index 03cbe4cf110b..03cbe4cf110b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h index 4422e31fedd9..4422e31fedd9 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c index 43fcb25c885f..43fcb25c885f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h index 864806c19ca7..864806c19ca7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/main.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c index 918b1d129e77..918b1d129e77 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/main.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c index 77e61b19bf36..77e61b19bf36 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h index 64bc49f4dbc6..64bc49f4dbc6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/Makefile index c0cb0cfe7d37..c0cb0cfe7d37 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/Makefile diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h index 690a7a1675e2..690a7a1675e2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c index 09898cf2e07a..09898cf2e07a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h index 38ba707015f5..38ba707015f5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c index 04eb5c3f8464..04eb5c3f8464 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h index 98a086822aac..98a086822aac 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c index 8283e9b27639..8283e9b27639 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h index c5761066d383..c5761066d383 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c index 1ee5a6ae9960..1ee5a6ae9960 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h index e5e1353a94c3..e5e1353a94c3 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h index dc8460c0b32f..dc8460c0b32f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c index a9c406f33d0a..a9c406f33d0a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h index ebd72cae10b6..ebd72cae10b6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c index de6cb6c3a48c..de6cb6c3a48c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h index d2367a5d0cf5..d2367a5d0cf5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c index 752f943a84ae..752f943a84ae 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h index 8b79161f71be..8b79161f71be 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c index 84ddd4d07a1d..84ddd4d07a1d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h index 4bec4b07e3e0..4bec4b07e3e0 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/Makefile index ad2de6b839ef..ad2de6b839ef 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/Makefile +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/Makefile diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h index 74a479ac323d..74a479ac323d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c index c16209a336ea..c16209a336ea 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h index fafa6bac2a3f..fafa6bac2a3f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c index 25db369b5d18..34ce06441d1b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c @@ -1946,6 +1946,14 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rtl_write_word(rtlpriv, REG_RXFLTMAP2, *(u16 *)val); mac->rx_data_filter = *(u16 *)val; break; + case HW_VAR_KEEP_ALIVE:{ + u8 array[2]; + array[0] = 0xff; + array[1] = *((u8 *)val); + rtl92c_fill_h2c_cmd(hw, H2C_92C_KEEP_ALIVE_CTRL, 2, + array); + break; + } default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "switch case not processed\n"); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h index 67588083e6cc..67588083e6cc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c index 75a2deb23af1..75a2deb23af1 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h index 0f372278b7af..0f372278b7af 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c index 035713311a4a..035713311a4a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h index 553a4bfac668..553a4bfac668 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c index c972fa50926d..c972fa50926d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h index 42b068660483..42b068660483 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h index 8b81465c629b..8b81465c629b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c index 5624ade92cc0..5624ade92cc0 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h index 6f987de5b441..6f987de5b441 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c index fd4a5353d216..fd4a5353d216 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h index a1310abd0d54..a1310abd0d54 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c index 7903c154de00..7903c154de00 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h index 4b020e9e30b1..4b020e9e30b1 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c index 95880fe4106e..95880fe4106e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h index fd8051dcd98a..fd8051dcd98a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/Makefile index e3213c8264b6..e3213c8264b6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/Makefile +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/Makefile diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h index 0a443ed17cf4..0a443ed17cf4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c index 7c1db7e7572d..7c1db7e7572d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h index f2d318ceeb28..f2d318ceeb28 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c index 62ef8209718f..62ef8209718f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h index 8a38daa316cb..8a38daa316cb 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/fw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c index f49b60d31450..f49b60d31450 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h index 1bc7b1a96d4a..1bc7b1a96d4a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c index 76a57ae4af3e..76a57ae4af3e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h index a29df30c3025..a29df30c3025 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c index bb06fe836fe7..bb06fe836fe7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h index 48d5c6835b6a..48d5c6835b6a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h index 315a298bab06..315a298bab06 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c index 6a6ac540d5b5..6a6ac540d5b5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h index 7303d12c266f..7303d12c266f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c index b19d0398215f..b19d0398215f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h index 0e6035b8fd86..0e6035b8fd86 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c index 8ea6f528dfa6..8ea6f528dfa6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h index 8b724a86117a..8b724a86117a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c index 1feaa629dd4f..1feaa629dd4f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h index fb5cf0634e8d..fb5cf0634e8d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/Makefile index 0315eeda9b60..0315eeda9b60 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/Makefile +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/Makefile diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h index 60f5728b4e2d..60f5728b4e2d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c index 459f3d0efa2f..459f3d0efa2f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h index 107d5a488fa8..107d5a488fa8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c index 0708eedd9671..0708eedd9671 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h index 069da1e7e80a..069da1e7e80a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c index 5f14308e8eb3..5f14308e8eb3 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h index 05413f189685..05413f189685 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c index 8388e371c8e2..8388e371c8e2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h index 8ef640a2ef7f..8ef640a2ef7f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c index 018340aedf09..018340aedf09 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h index c6e97c8df54c..c6e97c8df54c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c index 1a701d007f0c..1a701d007f0c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h index 781eeaa6af49..781eeaa6af49 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h index 1eaa1fab550d..1eaa1fab550d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c index c9bc33cd1090..c9bc33cd1090 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h index 039c0133ad6b..039c0133ad6b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c index c31c6bfb536d..c31c6bfb536d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h index 21433d0332d0..21433d0332d0 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c index abcdd0670fd8..abcdd0670fd8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h index bff9df88815d..bff9df88815d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c index d39ee67f6113..d39ee67f6113 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h index 8f78ac9e6040..8f78ac9e6040 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/Makefile index b7eb13819cbc..b7eb13819cbc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/Makefile +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/Makefile diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h index 41466f957cdc..41466f957cdc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c index 9bae5a92e30f..9bae5a92e30f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h index de6ac796c74d..de6ac796c74d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c index 331b1584a1a2..331b1584a1a2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h index b1e44b86e8ed..b1e44b86e8ed 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c index 12b0978ba4fa..12b0978ba4fa 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h index 4cacee10f31e..4cacee10f31e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c index 44949b5cbb87..44949b5cbb87 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h index 2182dbeb5f32..2182dbeb5f32 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c index 4b4612fe2fdb..4b4612fe2fdb 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h index 8acf4765a7a6..8acf4765a7a6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h index e13043479b71..e13043479b71 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c index 78a81c1e390b..78a81c1e390b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h index 8a29eb94ab17..8a29eb94ab17 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c index e1fd27c888bf..e1fd27c888bf 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h index 2eb88862ebe4..2eb88862ebe4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c index f1a73f75127e..f1a73f75127e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h index 2feb73b71a4f..2feb73b71a4f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c index 125b29bd2f93..125b29bd2f93 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h index 5a13f17e3b41..5a13f17e3b41 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/Makefile index 6220672a96f4..6220672a96f4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/Makefile diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/btc.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h index 06c448c010fd..06c448c010fd 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/btc.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h index bcdf2273688e..bcdf2273688e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c index 4c1c96c96a5a..4c1c96c96a5a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h index 57111052e86b..57111052e86b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c index b7c0d38ee5b5..b7c0d38ee5b5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h index 9d1fe25db953..9d1fe25db953 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c index 5aac45d5a974..5aac45d5a974 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h index bcd64a22acc0..bcd64a22acc0 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c index 00a0531cc5f4..00a0531cc5f4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h index 3723d7476717..3723d7476717 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c index a4b7eac6856f..a4b7eac6856f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h index 32c1ace97c3f..32c1ace97c3f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c index 13173351cbfd..13173351cbfd 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h index c22b19f542a6..c22b19f542a6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c index d367097f490b..d367097f490b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h index b85f5c7c5c01..b85f5c7c5c01 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c index 2f7f81af8a55..2f7f81af8a55 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h index 4ac7db526f15..4ac7db526f15 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h index 306059f9b9cc..306059f9b9cc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c index 9ebc8281ff99..9ebc8281ff99 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h index 7b44ebc0fac9..7b44ebc0fac9 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c index 3859b3e3d158..3859b3e3d158 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h index 46478780d262..46478780d262 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c index 61e86045f15c..61e86045f15c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h index 57a548ceba7d..57a548ceba7d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c index 2f7c144d7980..2f7c144d7980 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h index 017da7e194d8..017da7e194d8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/Makefile index a77c34102792..a77c34102792 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/Makefile +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/Makefile diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h index 025ea5c0f3f6..025ea5c0f3f6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c index 3a81cdba8ca3..3a81cdba8ca3 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h index f752a2cad63d..f752a2cad63d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c index d5da0f3c1217..d5da0f3c1217 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h index 067429669bda..067429669bda 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/fw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c index c983d2fe147f..c983d2fe147f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h index eae863d08de8..eae863d08de8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c index 4196efb723a2..4196efb723a2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h index c57de379ee8d..c57de379ee8d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c index b7b73cbe346d..b7b73cbe346d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h index 9021d4745ab7..9021d4745ab7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c index a1bb1f6116fb..a1bb1f6116fb 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h index 0fee5e0e55c2..0fee5e0e55c2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h index 03581d2a5da0..03581d2a5da0 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c index 5ed4492d3c80..5ed4492d3c80 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h index f423e157020f..f423e157020f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c index d091f1d5f91e..d091f1d5f91e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h index a7b25e769950..a7b25e769950 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c index a180761e8810..a180761e8810 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h index dc17001632f7..dc17001632f7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c index 338ec9a9d09b..338ec9a9d09b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h index 45949ac4854c..45949ac4854c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/Makefile index 345a68adcf38..345a68adcf38 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723com/Makefile +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/Makefile diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c index 064340641913..064340641913 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723com/dm_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/dm_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h index 5c1b94ce2f86..5c1b94ce2f86 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723com/dm_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c index a2f5e89bedfe..a2f5e89bedfe 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h index 8ea372d1626e..8ea372d1626e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/main.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c index 9014a94fac6a..9014a94fac6a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723com/main.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/phy_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c index 75cbd1509b52..75cbd1509b52 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723com/phy_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/phy_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h index 83b891a9adb8..83b891a9adb8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723com/phy_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/Makefile index f7a26f71197e..f7a26f71197e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/Makefile +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/Makefile diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h index dfbdf539de1a..dfbdf539de1a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c index b57cfd965196..b57cfd965196 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h index 625a6bbb21fc..625a6bbb21fc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c index 525eb234627c..525eb234627c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h index 8f5b4aade3c9..8f5b4aade3c9 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/fw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c index 6e9418ed90c2..6e9418ed90c2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h index a3553e3abaa1..a3553e3abaa1 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c index ba1946a0280e..ba1946a0280e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h index 038e64e18ae8..038e64e18ae8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c index 9b4d8a637915..9b4d8a637915 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h index c411f0a95cc4..c411f0a95cc4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c index 9ddf78a187dd..9ddf78a187dd 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h index 36b3e91d996e..36b3e91d996e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h index 1d6110f9c1fb..1d6110f9c1fb 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c index 2922538160e5..2922538160e5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h index efd22bd0b139..efd22bd0b139 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c index 8ee141a55bc5..8ee141a55bc5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h index d001e7ce3052..d001e7ce3052 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c index 62a0fb76f080..62a0fb76f080 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h index 24bcff6bc507..24bcff6bc507 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c index 174743aef943..174743aef943 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h index 31409042d8dd..31409042d8dd 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h diff --git a/drivers/net/wireless/rtlwifi/stats.c b/drivers/net/wireless/realtek/rtlwifi/stats.c index d8b30690b00d..d8b30690b00d 100644 --- a/drivers/net/wireless/rtlwifi/stats.c +++ b/drivers/net/wireless/realtek/rtlwifi/stats.c diff --git a/drivers/net/wireless/rtlwifi/stats.h b/drivers/net/wireless/realtek/rtlwifi/stats.h index 2b57dffef572..2b57dffef572 100644 --- a/drivers/net/wireless/rtlwifi/stats.h +++ b/drivers/net/wireless/realtek/rtlwifi/stats.h diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c index 2721cf89fb16..2721cf89fb16 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c diff --git a/drivers/net/wireless/rtlwifi/usb.h b/drivers/net/wireless/realtek/rtlwifi/usb.h index 685273ca9561..685273ca9561 100644 --- a/drivers/net/wireless/rtlwifi/usb.h +++ b/drivers/net/wireless/realtek/rtlwifi/usb.h diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 4544752a2ba8..4544752a2ba8 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 71a825c750cf..a13d1f2b5912 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1236,7 +1236,7 @@ static int set_rts_threshold(struct usbnet *usbdev, u32 rts_threshold) netdev_dbg(usbdev->net, "%s(): %i\n", __func__, rts_threshold); - if (rts_threshold < 0 || rts_threshold > 2347) + if (rts_threshold == -1 || rts_threshold > 2347) rts_threshold = 2347; tmp = cpu_to_le32(rts_threshold); diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 7e804324bfa7..b5bcc933a2a6 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -664,6 +664,7 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw, * @tid: Traffic identifier. * @ssn: Pointer to ssn value. * @buf_size: Buffer size (for kernel version > 2.6.38). + * @amsdu: is AMSDU in AMPDU allowed * * Return: status: 0 on success, negative error code on failure. */ @@ -673,7 +674,8 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_sta *sta, unsigned short tid, unsigned short *ssn, - unsigned char buf_size) + unsigned char buf_size, + bool amsdu) { int status = -EOPNOTSUPP; struct rsi_hw *adapter = hw->priv; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 9524564f873b..9733b31a780d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -7937,7 +7937,7 @@ EXPORT_SYMBOL_GPL(rt2800_get_tsf); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv; int ret = 0; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 1609b8a7f7eb..440790b92b19 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -220,7 +220,7 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size); + u8 buf_size, bool amsdu); int rt2800_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey); void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 48a2cad29477..7e8bb1198ae9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -266,7 +266,7 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, if (beacon_diff > beacon_int) beacon_diff = 0; - autowake_timeout = (conf->max_sleep_period * beacon_int) - beacon_diff; + autowake_timeout = (conf->ps_dtim_period * beacon_int) - beacon_diff; queue_delayed_work(rt2x00dev->workqueue, &rt2x00dev->autowakeup_work, autowake_timeout - 15); diff --git a/drivers/net/wireless/ti/wl12xx/scan.c b/drivers/net/wireless/ti/wl12xx/scan.c index 7c355fff2c5e..ebed13af9852 100644 --- a/drivers/net/wireless/ti/wl12xx/scan.c +++ b/drivers/net/wireless/ti/wl12xx/scan.c @@ -350,7 +350,8 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, cfg->bss_type = SCAN_BSS_TYPE_ANY; /* currently NL80211 supports only a single interval */ for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++) - cfg->intervals[i] = cpu_to_le32(req->interval); + cfg->intervals[i] = cpu_to_le32(req->scan_plans[0].interval * + MSEC_PER_SEC); cfg->ssid_len = 0; ret = wlcore_scan_sched_scan_ssid_list(wl, wlvif, req); diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index abbf054fb6da..50cce42089a5 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -2115,3 +2115,4 @@ MODULE_PARM_DESC(num_rx_desc_param, MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); MODULE_FIRMWARE(WL18XX_FW_NAME); +MODULE_FIRMWARE(WL18XX_CONF_FILE_NAME); diff --git a/drivers/net/wireless/ti/wl18xx/scan.c b/drivers/net/wireless/ti/wl18xx/scan.c index c938c494c785..bc15aa2c3efa 100644 --- a/drivers/net/wireless/ti/wl18xx/scan.c +++ b/drivers/net/wireless/ti/wl18xx/scan.c @@ -228,13 +228,15 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl, wl18xx_adjust_channels(cmd, cmd_channels); if (c->num_short_intervals && c->long_interval && - c->long_interval > req->interval) { - cmd->short_cycles_msec = cpu_to_le16(req->interval); + c->long_interval > req->scan_plans[0].interval * MSEC_PER_SEC) { + cmd->short_cycles_msec = + cpu_to_le16(req->scan_plans[0].interval * MSEC_PER_SEC); cmd->long_cycles_msec = cpu_to_le16(c->long_interval); cmd->short_cycles_count = c->num_short_intervals; } else { cmd->short_cycles_msec = 0; - cmd->long_cycles_msec = cpu_to_le16(req->interval); + cmd->long_cycles_msec = + cpu_to_le16(req->scan_plans[0].interval * MSEC_PER_SEC); cmd->short_cycles_count = 0; } wl1271_debug(DEBUG_SCAN, "short_interval: %d, long_interval: %d, num_short: %d", diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index e819369d8f8f..ec7f6af3fab2 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5263,7 +5263,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct wl1271 *wl = hw->priv; struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index a1b6040e6491..906be6aa4eb6 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -318,7 +318,7 @@ struct wl1271 { bool watchdog_recovery; /* Reg domain last configuration */ - u32 reg_ch_conf_last[2]; + u32 reg_ch_conf_last[2] __aligned(8); /* Reg domain pending configuration */ u32 reg_ch_conf_pending[2]; |