diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-15 18:42:13 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-15 18:42:13 -0700 |
commit | 9ff9b0d392ea08090cd1780fb196f36dbb586529 (patch) | |
tree | 276a3a5c4525b84dee64eda30b423fc31bf94850 /drivers/net/wireless/realtek/rtw88 | |
parent | 840e5bb326bbcb16ce82dd2416d2769de4839aea (diff) | |
parent | 105faa8742437c28815b2a3eb8314ebc5fd9288c (diff) | |
download | linux-next-9ff9b0d392ea08090cd1780fb196f36dbb586529.tar.gz |
Merge tag 'net-next-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking updates from Jakub Kicinski:
- Add redirect_neigh() BPF packet redirect helper, allowing to limit
stack traversal in common container configs and improving TCP
back-pressure.
Daniel reports ~10Gbps => ~15Gbps single stream TCP performance gain.
- Expand netlink policy support and improve policy export to user
space. (Ge)netlink core performs request validation according to
declared policies. Expand the expressiveness of those policies
(min/max length and bitmasks). Allow dumping policies for particular
commands. This is used for feature discovery by user space (instead
of kernel version parsing or trial and error).
- Support IGMPv3/MLDv2 multicast listener discovery protocols in
bridge.
- Allow more than 255 IPv4 multicast interfaces.
- Add support for Type of Service (ToS) reflection in SYN/SYN-ACK
packets of TCPv6.
- In Multi-patch TCP (MPTCP) support concurrent transmission of data on
multiple subflows in a load balancing scenario. Enhance advertising
addresses via the RM_ADDR/ADD_ADDR options.
- Support SMC-Dv2 version of SMC, which enables multi-subnet
deployments.
- Allow more calls to same peer in RxRPC.
- Support two new Controller Area Network (CAN) protocols - CAN-FD and
ISO 15765-2:2016.
- Add xfrm/IPsec compat layer, solving the 32bit user space on 64bit
kernel problem.
- Add TC actions for implementing MPLS L2 VPNs.
- Improve nexthop code - e.g. handle various corner cases when nexthop
objects are removed from groups better, skip unnecessary
notifications and make it easier to offload nexthops into HW by
converting to a blocking notifier.
- Support adding and consuming TCP header options by BPF programs,
opening the doors for easy experimental and deployment-specific TCP
option use.
- Reorganize TCP congestion control (CC) initialization to simplify
life of TCP CC implemented in BPF.
- Add support for shipping BPF programs with the kernel and loading
them early on boot via the User Mode Driver mechanism, hence reusing
all the user space infra we have.
- Support sleepable BPF programs, initially targeting LSM and tracing.
- Add bpf_d_path() helper for returning full path for given 'struct
path'.
- Make bpf_tail_call compatible with bpf-to-bpf calls.
- Allow BPF programs to call map_update_elem on sockmaps.
- Add BPF Type Format (BTF) support for type and enum discovery, as
well as support for using BTF within the kernel itself (current use
is for pretty printing structures).
- Support listing and getting information about bpf_links via the bpf
syscall.
- Enhance kernel interfaces around NIC firmware update. Allow
specifying overwrite mask to control if settings etc. are reset
during update; report expected max time operation may take to users;
support firmware activation without machine reboot incl. limits of
how much impact reset may have (e.g. dropping link or not).
- Extend ethtool configuration interface to report IEEE-standard
counters, to limit the need for per-vendor logic in user space.
- Adopt or extend devlink use for debug, monitoring, fw update in many
drivers (dsa loop, ice, ionic, sja1105, qed, mlxsw, mv88e6xxx,
dpaa2-eth).
- In mlxsw expose critical and emergency SFP module temperature alarms.
Refactor port buffer handling to make the defaults more suitable and
support setting these values explicitly via the DCBNL interface.
- Add XDP support for Intel's igb driver.
- Support offloading TC flower classification and filtering rules to
mscc_ocelot switches.
- Add PTP support for Marvell Octeontx2 and PP2.2 hardware, as well as
fixed interval period pulse generator and one-step timestamping in
dpaa-eth.
- Add support for various auth offloads in WiFi APs, e.g. SAE (WPA3)
offload.
- Add Lynx PHY/PCS MDIO module, and convert various drivers which have
this HW to use it. Convert mvpp2 to split PCS.
- Support Marvell Prestera 98DX3255 24-port switch ASICs, as well as
7-port Mediatek MT7531 IP.
- Add initial support for QCA6390 and IPQ6018 in ath11k WiFi driver,
and wcn3680 support in wcn36xx.
- Improve performance for packets which don't require much offloads on
recent Mellanox NICs by 20% by making multiple packets share a
descriptor entry.
- Move chelsio inline crypto drivers (for TLS and IPsec) from the
crypto subtree to drivers/net. Move MDIO drivers out of the phy
directory.
- Clean up a lot of W=1 warnings, reportedly the actively developed
subsections of networking drivers should now build W=1 warning free.
- Make sure drivers don't use in_interrupt() to dynamically adapt their
code. Convert tasklets to use new tasklet_setup API (sadly this
conversion is not yet complete).
* tag 'net-next-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (2583 commits)
Revert "bpfilter: Fix build error with CONFIG_BPFILTER_UMH"
net, sockmap: Don't call bpf_prog_put() on NULL pointer
bpf, selftest: Fix flaky tcp_hdr_options test when adding addr to lo
bpf, sockmap: Add locking annotations to iterator
netfilter: nftables: allow re-computing sctp CRC-32C in 'payload' statements
net: fix pos incrementment in ipv6_route_seq_next
net/smc: fix invalid return code in smcd_new_buf_create()
net/smc: fix valid DMBE buffer sizes
net/smc: fix use-after-free of delayed events
bpfilter: Fix build error with CONFIG_BPFILTER_UMH
cxgb4/ch_ipsec: Replace the module name to ch_ipsec from chcr
net: sched: Fix suspicious RCU usage while accessing tcf_tunnel_info
bpf: Fix register equivalence tracking.
rxrpc: Fix loss of final ack on shutdown
rxrpc: Fix bundle counting for exclusive connections
netfilter: restore NF_INET_NUMHOOKS
ibmveth: Identify ingress large send packets.
ibmveth: Switch order of ibmveth_helper calls.
cxgb4: handle 4-tuple PEDIT to NAT mode translation
selftests: Add VRF route leaking tests
...
Diffstat (limited to 'drivers/net/wireless/realtek/rtw88')
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/debug.c | 32 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/fw.c | 86 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/fw.h | 18 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/mac.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/mac80211.c | 81 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/main.c | 205 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/main.h | 32 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/pci.c | 38 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/pci.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/phy.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/reg.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/rtw8821c.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/rtw8822b.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/rtw8822c.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/rtw8822c_table.c | 32 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/tx.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/tx.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/util.h | 2 |
18 files changed, 437 insertions, 159 deletions
diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c index f769c982cc91..3852c4f0ac0b 100644 --- a/drivers/net/wireless/realtek/rtw88/debug.c +++ b/drivers/net/wireless/realtek/rtw88/debug.c @@ -229,7 +229,8 @@ static int rtw_debugfs_get_rsvd_page(struct seq_file *m, void *v) if (!buf) return -ENOMEM; - ret = rtw_dump_drv_rsvd_page(rtwdev, offset, buf_size, (u32 *)buf); + ret = rtw_fw_dump_fifo(rtwdev, RTW_FW_FIFO_SEL_RSVD_PAGE, offset, + buf_size, (u32 *)buf); if (ret) { rtw_err(rtwdev, "failed to dump rsvd page\n"); vfree(buf); @@ -427,12 +428,11 @@ static int rtw_debug_get_mac_page(struct seq_file *m, void *v) { struct rtw_debugfs_priv *debugfs_priv = m->private; struct rtw_dev *rtwdev = debugfs_priv->rtwdev; - u32 val; u32 page = debugfs_priv->cb_data; int i, n; int max = 0xff; - val = rtw_read32(rtwdev, debugfs_priv->cb_data); + rtw_read32(rtwdev, debugfs_priv->cb_data); for (n = 0; n <= max; ) { seq_printf(m, "\n%8.8x ", n + page); for (i = 0; i < 4 && n <= max; i++, n += 4) @@ -447,12 +447,11 @@ static int rtw_debug_get_bb_page(struct seq_file *m, void *v) { struct rtw_debugfs_priv *debugfs_priv = m->private; struct rtw_dev *rtwdev = debugfs_priv->rtwdev; - u32 val; u32 page = debugfs_priv->cb_data; int i, n; int max = 0xff; - val = rtw_read32(rtwdev, debugfs_priv->cb_data); + rtw_read32(rtwdev, debugfs_priv->cb_data); for (n = 0; n <= max; ) { seq_printf(m, "\n%8.8x ", n + page); for (i = 0; i < 4 && n <= max; i++, n += 4) @@ -545,6 +544,28 @@ static void rtw_print_rate(struct seq_file *m, u8 rate) } } +#define case_REGD(src) \ + case RTW_REGD_##src: return #src + +static const char *rtw_get_regd_string(u8 regd) +{ + switch (regd) { + case_REGD(FCC); + case_REGD(MKK); + case_REGD(ETSI); + case_REGD(IC); + case_REGD(KCC); + case_REGD(ACMA); + case_REGD(CHILE); + case_REGD(UKRAINE); + case_REGD(MEXICO); + case_REGD(CN); + case_REGD(WW); + default: + return "Unknown"; + } +} + static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v) { struct rtw_debugfs_priv *debugfs_priv = m->private; @@ -556,6 +577,7 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v) u8 ch = hal->current_channel; u8 regd = rtwdev->regd.txpwr_regd; + seq_printf(m, "regulatory: %s\n", rtw_get_regd_string(regd)); seq_printf(m, "%-4s %-10s %-3s%6s %-4s %4s (%-4s %-4s) %-4s\n", "path", "rate", "pwr", "", "base", "", "byr", "lmt", "rem"); diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 63b00bc19000..042015bc8055 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -193,6 +193,15 @@ void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset, } EXPORT_SYMBOL(rtw_fw_c2h_cmd_rx_irqsafe); +void rtw_fw_c2h_cmd_isr(struct rtw_dev *rtwdev) +{ + if (rtw_read8(rtwdev, REG_MCU_TST_CFG) == VAL_FW_TRIGGER) + rtw_fw_recovery(rtwdev); + else + rtw_warn(rtwdev, "unhandled firmware c2h interrupt\n"); +} +EXPORT_SYMBOL(rtw_fw_c2h_cmd_isr); + static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, u8 *h2c) { @@ -1404,29 +1413,16 @@ free: return ret; } -int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev, - u32 offset, u32 size, u32 *buf) +static void rtw_fw_read_fifo_page(struct rtw_dev *rtwdev, u32 offset, u32 size, + u32 *buf, u32 residue, u16 start_pg) { - struct rtw_fifo_conf *fifo = &rtwdev->fifo; - u32 residue, i; - u16 start_pg; + u32 i; u16 idx = 0; u16 ctl; u8 rcr; - if (size & 0x3) { - rtw_warn(rtwdev, "should be 4-byte aligned\n"); - return -EINVAL; - } - - offset += fifo->rsvd_boundary << TX_PAGE_SIZE_SHIFT; - residue = offset & (FIFO_PAGE_SIZE - 1); - start_pg = offset >> FIFO_PAGE_SIZE_SHIFT; - start_pg += RSVD_PAGE_START_ADDR; - rcr = rtw_read8(rtwdev, REG_RCR + 2); ctl = rtw_read16(rtwdev, REG_PKTBUF_DBG_CTRL) & 0xf000; - /* disable rx clock gate */ rtw_write8(rtwdev, REG_RCR, rcr | BIT(3)); @@ -1448,6 +1444,64 @@ int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev, out: rtw_write16(rtwdev, REG_PKTBUF_DBG_CTRL, ctl); rtw_write8(rtwdev, REG_RCR + 2, rcr); +} + +static void rtw_fw_read_fifo(struct rtw_dev *rtwdev, enum rtw_fw_fifo_sel sel, + u32 offset, u32 size, u32 *buf) +{ + struct rtw_chip_info *chip = rtwdev->chip; + u32 start_pg, residue; + + if (sel >= RTW_FW_FIFO_MAX) { + rtw_dbg(rtwdev, RTW_DBG_FW, "wrong fw fifo sel\n"); + return; + } + if (sel == RTW_FW_FIFO_SEL_RSVD_PAGE) + offset += rtwdev->fifo.rsvd_boundary << TX_PAGE_SIZE_SHIFT; + residue = offset & (FIFO_PAGE_SIZE - 1); + start_pg = (offset >> FIFO_PAGE_SIZE_SHIFT) + chip->fw_fifo_addr[sel]; + + rtw_fw_read_fifo_page(rtwdev, offset, size, buf, residue, start_pg); +} + +static bool rtw_fw_dump_check_size(struct rtw_dev *rtwdev, + enum rtw_fw_fifo_sel sel, + u32 start_addr, u32 size) +{ + switch (sel) { + case RTW_FW_FIFO_SEL_TX: + case RTW_FW_FIFO_SEL_RX: + if ((start_addr + size) > rtwdev->chip->fw_fifo_addr[sel]) + return false; + /*fall through*/ + default: + return true; + } +} + +int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size, + u32 *buffer) +{ + if (!rtwdev->chip->fw_fifo_addr) { + rtw_dbg(rtwdev, RTW_DBG_FW, "chip not support dump fw fifo\n"); + return -ENOTSUPP; + } + + if (size == 0 || !buffer) + return -EINVAL; + + if (size & 0x3) { + rtw_dbg(rtwdev, RTW_DBG_FW, "not 4byte alignment\n"); + return -EINVAL; + } + + if (!rtw_fw_dump_check_size(rtwdev, fifo_sel, addr, size)) { + rtw_dbg(rtwdev, RTW_DBG_FW, "fw fifo dump size overflow\n"); + return -EINVAL; + } + + rtw_fw_read_fifo(rtwdev, fifo_sel, addr, size, buffer); + return 0; } diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h index 686dcd3bbda6..08644540d259 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.h +++ b/drivers/net/wireless/realtek/rtw88/fw.h @@ -16,7 +16,6 @@ #define FIFO_PAGE_SIZE_SHIFT 12 #define FIFO_PAGE_SIZE 4096 -#define RSVD_PAGE_START_ADDR 0x780 #define FIFO_DUMP_ADDR 0x8000 #define DLFW_PAGE_SIZE_SHIFT_LEGACY 12 @@ -508,6 +507,20 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) #define SET_NLO_LOC_NLO_INFO(h2c_pkt, value) \ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) +#define GET_FW_DUMP_LEN(_header) \ + le32_get_bits(*((__le32 *)(_header) + 0x00), GENMASK(15, 0)) +#define GET_FW_DUMP_SEQ(_header) \ + le32_get_bits(*((__le32 *)(_header) + 0x00), GENMASK(22, 16)) +#define GET_FW_DUMP_MORE(_header) \ + le32_get_bits(*((__le32 *)(_header) + 0x00), BIT(23)) +#define GET_FW_DUMP_VERSION(_header) \ + le32_get_bits(*((__le32 *)(_header) + 0x00), GENMASK(31, 24)) +#define GET_FW_DUMP_TLV_TYPE(_header) \ + le32_get_bits(*((__le32 *)(_header) + 0x01), GENMASK(15, 0)) +#define GET_FW_DUMP_TLV_LEN(_header) \ + le32_get_bits(*((__le32 *)(_header) + 0x01), GENMASK(31, 16)) +#define GET_FW_DUMP_TLV_VAL(_header) \ + le32_get_bits(*((__le32 *)(_header) + 0x02), GENMASK(31, 0)) static inline struct rtw_c2h_cmd *get_c2h_from_skb(struct sk_buff *skb) { u32 pkt_offset; @@ -564,5 +577,8 @@ void rtw_fw_update_pkt_probe_req(struct rtw_dev *rtwdev, struct cfg80211_ssid *ssid); void rtw_fw_channel_switch(struct rtw_dev *rtwdev, bool enable); void rtw_fw_h2c_cmd_dbg(struct rtw_dev *rtwdev, u8 *h2c); +void rtw_fw_c2h_cmd_isr(struct rtw_dev *rtwdev); +int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size, + u32 *buffer); #endif diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index 19b9b7ab016b..59028b121b00 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -114,18 +114,13 @@ static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev) static bool do_pwr_poll_cmd(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target) { - u32 cnt; + u32 val; target &= mask; - for (cnt = 0; cnt < RTW_PWR_POLLING_CNT; cnt++) { - if ((rtw_read8(rtwdev, addr) & mask) == target) - return true; - - udelay(50); - } - - return false; + return read_poll_timeout_atomic(rtw_read8, val, (val & mask) == target, + 50, 50 * RTW_PWR_POLLING_CNT, false, + rtwdev, addr) == 0; } static int rtw_pwr_cmd_polling(struct rtw_dev *rtwdev, diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index 6b199152abcf..c92fba2fa480 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -358,13 +358,10 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, rtw_leave_lps_deep(rtwdev); if (changed & BSS_CHANGED_ASSOC) { - enum rtw_net_type net_type; - + rtw_vif_assoc_changed(rtwvif, conf); if (conf->assoc) { rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_FINISH); - net_type = RTW_NET_MGD_LINKED; - rtwvif->aid = conf->aid; rtw_fw_download_rsvd_page(rtwdev); rtw_send_rsvd_page_h2c(rtwdev); rtw_coex_media_status_notify(rtwdev, conf->assoc); @@ -372,12 +369,9 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, rtw_bf_assoc(rtwdev, vif, conf); } else { rtw_leave_lps(rtwdev); - net_type = RTW_NET_NO_LINK; - rtwvif->aid = 0; rtw_bf_disassoc(rtwdev, vif, conf); } - rtwvif->net_type = net_type; config |= PORT_SET_NET_TYPE; config |= PORT_SET_AID; } @@ -429,56 +423,17 @@ static int rtw_ops_conf_tx(struct ieee80211_hw *hw, return 0; } -static u8 rtw_acquire_macid(struct rtw_dev *rtwdev) -{ - unsigned long mac_id; - - mac_id = find_first_zero_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM); - if (mac_id < RTW_MAX_MAC_ID_NUM) - set_bit(mac_id, rtwdev->mac_id_map); - - return mac_id; -} - -static void rtw_release_macid(struct rtw_dev *rtwdev, u8 mac_id) -{ - clear_bit(mac_id, rtwdev->mac_id_map); -} - static int rtw_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct rtw_dev *rtwdev = hw->priv; - struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; - int i; int ret = 0; mutex_lock(&rtwdev->mutex); - - si->mac_id = rtw_acquire_macid(rtwdev); - if (si->mac_id >= RTW_MAX_MAC_ID_NUM) { - ret = -ENOSPC; - goto out; - } - - si->sta = sta; - si->vif = vif; - si->init_ra_lv = 1; - ewma_rssi_init(&si->avg_rssi); - for (i = 0; i < ARRAY_SIZE(sta->txq); i++) - rtw_txq_init(rtwdev, sta->txq[i]); - - rtw_update_sta_info(rtwdev, si); - rtw_fw_media_status_report(rtwdev, si->mac_id, true); - - rtwdev->sta_cnt++; - - rtw_info(rtwdev, "sta %pM joined with macid %d\n", - sta->addr, si->mac_id); - -out: + ret = rtw_sta_add(rtwdev, sta, vif); mutex_unlock(&rtwdev->mutex); + return ret; } @@ -487,25 +442,11 @@ static int rtw_ops_sta_remove(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct rtw_dev *rtwdev = hw->priv; - struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; - int i; mutex_lock(&rtwdev->mutex); - - rtw_release_macid(rtwdev, si->mac_id); - rtw_fw_media_status_report(rtwdev, si->mac_id, false); - - for (i = 0; i < ARRAY_SIZE(sta->txq); i++) - rtw_txq_cleanup(rtwdev, sta->txq[i]); - - kfree(si->mask); - - rtwdev->sta_cnt--; - - rtw_info(rtwdev, "sta %pM with macid %d left\n", - sta->addr, si->mac_id); - + rtw_sta_remove(rtwdev, sta, true); mutex_unlock(&rtwdev->mutex); + return 0; } @@ -845,6 +786,17 @@ static void rtw_ops_set_wakeup(struct ieee80211_hw *hw, bool enabled) } #endif +static void rtw_reconfig_complete(struct ieee80211_hw *hw, + enum ieee80211_reconfig_type reconfig_type) +{ + struct rtw_dev *rtwdev = hw->priv; + + mutex_lock(&rtwdev->mutex); + if (reconfig_type == IEEE80211_RECONFIG_TYPE_RESTART) + clear_bit(RTW_FLAG_RESTARTING, rtwdev->flags); + mutex_unlock(&rtwdev->mutex); +} + const struct ieee80211_ops rtw_ops = { .tx = rtw_ops_tx, .wake_tx_queue = rtw_ops_wake_tx_queue, @@ -871,6 +823,7 @@ const struct ieee80211_ops rtw_ops = { .set_bitrate_mask = rtw_ops_set_bitrate_mask, .set_antenna = rtw_ops_set_antenna, .get_antenna = rtw_ops_get_antenna, + .reconfig_complete = rtw_reconfig_complete, #ifdef CONFIG_PM .suspend = rtw_ops_suspend, .resume = rtw_ops_resume, diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 54044abf30d7..565efd880624 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -259,6 +259,198 @@ static void rtw_c2h_work(struct work_struct *work) } } +static u8 rtw_acquire_macid(struct rtw_dev *rtwdev) +{ + unsigned long mac_id; + + mac_id = find_first_zero_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM); + if (mac_id < RTW_MAX_MAC_ID_NUM) + set_bit(mac_id, rtwdev->mac_id_map); + + return mac_id; +} + +int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, + struct ieee80211_vif *vif) +{ + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + int i; + + si->mac_id = rtw_acquire_macid(rtwdev); + if (si->mac_id >= RTW_MAX_MAC_ID_NUM) + return -ENOSPC; + + si->sta = sta; + si->vif = vif; + si->init_ra_lv = 1; + ewma_rssi_init(&si->avg_rssi); + for (i = 0; i < ARRAY_SIZE(sta->txq); i++) + rtw_txq_init(rtwdev, sta->txq[i]); + + rtw_update_sta_info(rtwdev, si); + rtw_fw_media_status_report(rtwdev, si->mac_id, true); + + rtwdev->sta_cnt++; + rtw_info(rtwdev, "sta %pM joined with macid %d\n", + sta->addr, si->mac_id); + + return 0; +} + +void rtw_sta_remove(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, + bool fw_exist) +{ + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + int i; + + rtw_release_macid(rtwdev, si->mac_id); + if (fw_exist) + rtw_fw_media_status_report(rtwdev, si->mac_id, false); + + for (i = 0; i < ARRAY_SIZE(sta->txq); i++) + rtw_txq_cleanup(rtwdev, sta->txq[i]); + + kfree(si->mask); + + rtwdev->sta_cnt--; + rtw_info(rtwdev, "sta %pM with macid %d left\n", + sta->addr, si->mac_id); +} + +static bool rtw_fw_dump_crash_log(struct rtw_dev *rtwdev) +{ + u32 size = rtwdev->chip->fw_rxff_size; + u32 *buf; + u8 seq; + bool ret = true; + + buf = vmalloc(size); + if (!buf) + goto exit; + + if (rtw_fw_dump_fifo(rtwdev, RTW_FW_FIFO_SEL_RXBUF_FW, 0, size, buf)) { + rtw_dbg(rtwdev, RTW_DBG_FW, "dump fw fifo fail\n"); + goto free_buf; + } + + if (GET_FW_DUMP_LEN(buf) == 0) { + rtw_dbg(rtwdev, RTW_DBG_FW, "fw crash dump's length is 0\n"); + goto free_buf; + } + + seq = GET_FW_DUMP_SEQ(buf); + if (seq > 0 && seq != (rtwdev->fw.prev_dump_seq + 1)) { + rtw_dbg(rtwdev, RTW_DBG_FW, + "fw crash dump's seq is wrong: %d\n", seq); + goto free_buf; + } + if (seq == 0 && + (GET_FW_DUMP_TLV_TYPE(buf) != FW_CD_TYPE || + GET_FW_DUMP_TLV_LEN(buf) != FW_CD_LEN || + GET_FW_DUMP_TLV_VAL(buf) != FW_CD_VAL)) { + rtw_dbg(rtwdev, RTW_DBG_FW, "fw crash dump's tlv is wrong\n"); + goto free_buf; + } + + print_hex_dump_bytes("rtw88 fw dump: ", DUMP_PREFIX_OFFSET, buf, size); + + if (GET_FW_DUMP_MORE(buf) == 1) { + rtwdev->fw.prev_dump_seq = seq; + ret = false; + } + +free_buf: + vfree(buf); +exit: + rtw_write8(rtwdev, REG_MCU_TST_CFG, 0); + + return ret; +} + +void rtw_vif_assoc_changed(struct rtw_vif *rtwvif, + struct ieee80211_bss_conf *conf) +{ + if (conf && conf->assoc) { + rtwvif->aid = conf->aid; + rtwvif->net_type = RTW_NET_MGD_LINKED; + } else { + rtwvif->aid = 0; + rtwvif->net_type = RTW_NET_NO_LINK; + } +} + +static void rtw_reset_key_iter(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, + void *data) +{ + struct rtw_dev *rtwdev = (struct rtw_dev *)data; + struct rtw_sec_desc *sec = &rtwdev->sec; + + rtw_sec_clear_cam(rtwdev, sec, key->hw_key_idx); +} + +static void rtw_reset_sta_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw_dev *rtwdev = (struct rtw_dev *)data; + + if (rtwdev->sta_cnt == 0) { + rtw_warn(rtwdev, "sta count before reset should not be 0\n"); + return; + } + rtw_sta_remove(rtwdev, sta, false); +} + +static void rtw_reset_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) +{ + struct rtw_dev *rtwdev = (struct rtw_dev *)data; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + + rtw_bf_disassoc(rtwdev, vif, NULL); + rtw_vif_assoc_changed(rtwvif, NULL); + rtw_txq_cleanup(rtwdev, vif->txq); +} + +void rtw_fw_recovery(struct rtw_dev *rtwdev) +{ + if (!test_bit(RTW_FLAG_RESTARTING, rtwdev->flags)) + ieee80211_queue_work(rtwdev->hw, &rtwdev->fw_recovery_work); +} + +static void rtw_fw_recovery_work(struct work_struct *work) +{ + struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, + fw_recovery_work); + + /* rtw_fw_dump_crash_log() returns false indicates that there are + * still more log to dump. Driver set 0x1cf[7:0] = 0x1 to tell firmware + * to dump the remaining part of the log, and firmware will trigger an + * IMR_C2HCMD interrupt to inform driver the log is ready. + */ + if (!rtw_fw_dump_crash_log(rtwdev)) { + rtw_write8(rtwdev, REG_HRCV_MSG, 1); + return; + } + rtwdev->fw.prev_dump_seq = 0; + + WARN(1, "firmware crash, start reset and recover\n"); + + mutex_lock(&rtwdev->mutex); + + set_bit(RTW_FLAG_RESTARTING, rtwdev->flags); + rcu_read_lock(); + rtw_iterate_keys_rcu(rtwdev, NULL, rtw_reset_key_iter, rtwdev); + rcu_read_unlock(); + rtw_iterate_stas_atomic(rtwdev, rtw_reset_sta_iter, rtwdev); + rtw_iterate_vifs_atomic(rtwdev, rtw_reset_vif_iter, rtwdev); + rtw_enter_ips(rtwdev); + + mutex_unlock(&rtwdev->mutex); + + ieee80211_restart_hw(rtwdev->hw); +} + struct rtw_txq_ba_iter_data { }; @@ -474,10 +666,10 @@ static u8 hw_bw_cap_to_bitamp(u8 bw_cap) case EFUSE_HW_CAP_IGNORE: case EFUSE_HW_CAP_SUPP_BW80: bw |= BIT(RTW_CHANNEL_WIDTH_80); - /* fall through */ + fallthrough; case EFUSE_HW_CAP_SUPP_BW40: bw |= BIT(RTW_CHANNEL_WIDTH_40); - /* fall through */ + fallthrough; default: bw |= BIT(RTW_CHANNEL_WIDTH_20); break; @@ -1422,8 +1614,7 @@ int rtw_core_init(struct rtw_dev *rtwdev) timer_setup(&rtwdev->tx_report.purge_timer, rtw_tx_report_purge_timer, 0); - tasklet_init(&rtwdev->tx_tasklet, rtw_tx_tasklet, - (unsigned long)rtwdev); + tasklet_setup(&rtwdev->tx_tasklet, rtw_tx_tasklet); INIT_DELAYED_WORK(&rtwdev->watch_dog_work, rtw_watch_dog_work); INIT_DELAYED_WORK(&coex->bt_relink_work, rtw_coex_bt_relink_work); @@ -1432,6 +1623,7 @@ int rtw_core_init(struct rtw_dev *rtwdev) INIT_DELAYED_WORK(&coex->wl_remain_work, rtw_coex_wl_remain_work); INIT_DELAYED_WORK(&coex->bt_remain_work, rtw_coex_bt_remain_work); INIT_WORK(&rtwdev->c2h_work, rtw_c2h_work); + INIT_WORK(&rtwdev->fw_recovery_work, rtw_fw_recovery_work); INIT_WORK(&rtwdev->ba_work, rtw_txq_ba_work); skb_queue_head_init(&rtwdev->c2h_queue); skb_queue_head_init(&rtwdev->coex.queue); @@ -1473,6 +1665,9 @@ int rtw_core_init(struct rtw_dev *rtwdev) ret = rtw_load_firmware(rtwdev, RTW_WOWLAN_FW); if (ret) { rtw_warn(rtwdev, "no wow firmware loaded\n"); + wait_for_completion(&rtwdev->fw.completion); + if (rtwdev->fw.firmware) + release_firmware(rtwdev->fw.firmware); return ret; } } @@ -1487,6 +1682,8 @@ void rtw_core_deinit(struct rtw_dev *rtwdev) struct rtw_rsvd_page *rsvd_pkt, *tmp; unsigned long flags; + rtw_wait_firmware_completion(rtwdev); + if (fw->firmware) release_firmware(fw->firmware); diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 276b5d381467..ffb02e614217 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -359,6 +359,7 @@ enum rtw_flags { RTW_FLAG_DIG_DISABLE, RTW_FLAG_BUSY_TRAFFIC, RTW_FLAG_WOWLAN, + RTW_FLAG_RESTARTING, NUM_OF_RTW_FLAGS, }; @@ -1082,6 +1083,17 @@ enum rtw_wlan_cpu { RTW_WCPU_11N, }; +enum rtw_fw_fifo_sel { + RTW_FW_FIFO_SEL_TX, + RTW_FW_FIFO_SEL_RX, + RTW_FW_FIFO_SEL_RSVD_PAGE, + RTW_FW_FIFO_SEL_REPORT, + RTW_FW_FIFO_SEL_LLT, + RTW_FW_FIFO_SEL_RXBUF_FW, + + RTW_FW_FIFO_MAX, +}; + /* hardware configuration for each IC */ struct rtw_chip_info { struct rtw_chip_ops *ops; @@ -1098,6 +1110,7 @@ struct rtw_chip_info { u32 ptct_efuse_size; u32 txff_size; u32 rxff_size; + u32 fw_rxff_size; u8 band; u8 page_size; u8 csi_buf_pg_num; @@ -1108,6 +1121,8 @@ struct rtw_chip_info { bool rx_ldpc; u8 max_power_index; + u16 fw_fifo_addr[RTW_FW_FIFO_MAX]; + bool ht_supported; bool vht_supported; u8 lps_deep_mode_supported; @@ -1606,6 +1621,9 @@ struct rtw_fifo_conf { const struct rtw_rqpn *rqpn; }; +#define FW_CD_TYPE 0xffff +#define FW_CD_LEN 4 +#define FW_CD_VAL 0xaabbccdd struct rtw_fw_state { const struct firmware *firmware; struct rtw_dev *rtwdev; @@ -1614,6 +1632,7 @@ struct rtw_fw_state { u8 sub_version; u8 sub_index; u16 h2c_version; + u8 prev_dump_seq; }; struct rtw_hal { @@ -1699,6 +1718,7 @@ struct rtw_dev { /* c2h cmd queue & handler work */ struct sk_buff_head c2h_queue; struct work_struct c2h_work; + struct work_struct fw_recovery_work; /* used to protect txqs list */ spinlock_t txq_lock; @@ -1799,6 +1819,11 @@ static inline bool rtw_chip_has_rx_ldpc(struct rtw_dev *rtwdev) return rtwdev->chip->rx_ldpc; } +static inline void rtw_release_macid(struct rtw_dev *rtwdev, u8 mac_id) +{ + clear_bit(mac_id, rtwdev->mac_id_map); +} + void rtw_get_channel_params(struct cfg80211_chan_def *chandef, struct rtw_channel_params *ch_param); bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target); @@ -1821,5 +1846,12 @@ void rtw_core_deinit(struct rtw_dev *rtwdev); int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw); void rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw); u16 rtw_desc_to_bitrate(u8 desc_rate); +void rtw_vif_assoc_changed(struct rtw_vif *rtwvif, + struct ieee80211_bss_conf *conf); +int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, + struct ieee80211_vif *vif); +void rtw_sta_remove(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, + bool fw_exist); +void rtw_fw_recovery(struct rtw_dev *rtwdev); #endif diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index 3413973bc475..676d861aaf99 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -109,7 +109,7 @@ static void rtw_pci_free_tx_ring_skbs(struct rtw_dev *rtwdev, tx_data = rtw_pci_get_tx_data(skb); dma = tx_data->dma; - pci_unmap_single(pdev, dma, skb->len, PCI_DMA_TODEVICE); + dma_unmap_single(&pdev->dev, dma, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); } } @@ -125,7 +125,7 @@ static void rtw_pci_free_tx_ring(struct rtw_dev *rtwdev, rtw_pci_free_tx_ring_skbs(rtwdev, tx_ring); /* free the ring itself */ - pci_free_consistent(pdev, ring_sz, head, tx_ring->r.dma); + dma_free_coherent(&pdev->dev, ring_sz, head, tx_ring->r.dma); tx_ring->r.head = NULL; } @@ -144,7 +144,7 @@ static void rtw_pci_free_rx_ring_skbs(struct rtw_dev *rtwdev, continue; dma = *((dma_addr_t *)skb->cb); - pci_unmap_single(pdev, dma, buf_sz, PCI_DMA_FROMDEVICE); + dma_unmap_single(&pdev->dev, dma, buf_sz, DMA_FROM_DEVICE); dev_kfree_skb(skb); rx_ring->buf[i] = NULL; } @@ -159,7 +159,7 @@ static void rtw_pci_free_rx_ring(struct rtw_dev *rtwdev, rtw_pci_free_rx_ring_skbs(rtwdev, rx_ring); - pci_free_consistent(pdev, ring_sz, head, rx_ring->r.dma); + dma_free_coherent(&pdev->dev, ring_sz, head, rx_ring->r.dma); } static void rtw_pci_free_trx_ring(struct rtw_dev *rtwdev) @@ -194,7 +194,7 @@ static int rtw_pci_init_tx_ring(struct rtw_dev *rtwdev, return -EINVAL; } - head = pci_zalloc_consistent(pdev, ring_sz, &dma); + head = dma_alloc_coherent(&pdev->dev, ring_sz, &dma, GFP_KERNEL); if (!head) { rtw_err(rtwdev, "failed to allocate tx ring\n"); return -ENOMEM; @@ -223,8 +223,8 @@ static int rtw_pci_reset_rx_desc(struct rtw_dev *rtwdev, struct sk_buff *skb, if (!skb) return -EINVAL; - dma = pci_map_single(pdev, skb->data, buf_sz, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(pdev, dma)) + dma = dma_map_single(&pdev->dev, skb->data, buf_sz, DMA_FROM_DEVICE); + if (dma_mapping_error(&pdev->dev, dma)) return -EBUSY; *((dma_addr_t *)skb->cb) = dma; @@ -272,7 +272,7 @@ static int rtw_pci_init_rx_ring(struct rtw_dev *rtwdev, return -EINVAL; } - head = pci_zalloc_consistent(pdev, ring_sz, &dma); + head = dma_alloc_coherent(&pdev->dev, ring_sz, &dma, GFP_KERNEL); if (!head) { rtw_err(rtwdev, "failed to allocate rx ring\n"); return -ENOMEM; @@ -311,11 +311,11 @@ err_out: if (!skb) continue; dma = *((dma_addr_t *)skb->cb); - pci_unmap_single(pdev, dma, buf_sz, PCI_DMA_FROMDEVICE); + dma_unmap_single(&pdev->dev, dma, buf_sz, DMA_FROM_DEVICE); dev_kfree_skb_any(skb); rx_ring->buf[i] = NULL; } - pci_free_consistent(pdev, ring_sz, head, dma); + dma_free_coherent(&pdev->dev, ring_sz, head, dma); rtw_err(rtwdev, "failed to init rx buffer\n"); @@ -389,6 +389,7 @@ static int rtw_pci_init(struct rtw_dev *rtwdev) IMR_VODOK | IMR_ROK | IMR_BCNDMAINT_E | + IMR_C2HCMD | 0; rtwpci->irq_mask[1] = IMR_TXFOVW | 0; @@ -675,8 +676,7 @@ static void rtw_pci_release_rsvd_page(struct rtw_pci *rtwpci, tx_data = rtw_pci_get_tx_data(prev); dma = tx_data->dma; - pci_unmap_single(rtwpci->pdev, dma, prev->len, - PCI_DMA_TODEVICE); + dma_unmap_single(&rtwpci->pdev->dev, dma, prev->len, DMA_TO_DEVICE); dev_kfree_skb_any(prev); } @@ -755,9 +755,9 @@ static int rtw_pci_tx_write_data(struct rtw_dev *rtwdev, memset(pkt_desc, 0, tx_pkt_desc_sz); pkt_info->qsel = rtw_pci_get_tx_qsel(skb, queue); rtw_tx_fill_tx_desc(pkt_info, skb); - dma = pci_map_single(rtwpci->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(rtwpci->pdev, dma)) + dma = dma_map_single(&rtwpci->pdev->dev, skb->data, skb->len, + DMA_TO_DEVICE); + if (dma_mapping_error(&rtwpci->pdev->dev, dma)) return -EBUSY; /* after this we got dma mapped, there is no way back */ @@ -896,8 +896,8 @@ static void rtw_pci_tx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, break; } tx_data = rtw_pci_get_tx_data(skb); - pci_unmap_single(rtwpci->pdev, tx_data->dma, skb->len, - PCI_DMA_TODEVICE); + dma_unmap_single(&rtwpci->pdev->dev, tx_data->dma, skb->len, + DMA_TO_DEVICE); /* just free command packets from host to card */ if (hw_queue == RTW_TX_QUEUE_H2C) { @@ -1080,6 +1080,8 @@ static irqreturn_t rtw_pci_interrupt_threadfn(int irq, void *dev) rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_H2C); if (irq_status[0] & IMR_ROK) rtw_pci_rx_isr(rtwdev, rtwpci, RTW_RX_QUEUE_MPDU); + if (unlikely(irq_status[0] & IMR_C2HCMD)) + rtw_fw_c2h_cmd_isr(rtwdev); /* all of the jobs for this interrupt have been done */ rtw_pci_enable_interrupt(rtwdev, rtwpci); @@ -1599,6 +1601,8 @@ void rtw_pci_shutdown(struct pci_dev *pdev) if (chip->ops->shutdown) chip->ops->shutdown(rtwdev); + + pci_set_power_state(pdev, PCI_D3hot); } EXPORT_SYMBOL(rtw_pci_shutdown); diff --git a/drivers/net/wireless/realtek/rtw88/pci.h b/drivers/net/wireless/realtek/rtw88/pci.h index 024c2bc275cb..ca17aa9cf7dc 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.h +++ b/drivers/net/wireless/realtek/rtw88/pci.h @@ -9,8 +9,8 @@ #define RTK_BEQ_TX_DESC_NUM 256 #define RTK_MAX_RX_DESC_NUM 512 -/* 8K + rx desc size */ -#define RTK_PCI_RX_BUF_SIZE (8192 + 24) +/* 11K + rx desc size */ +#define RTK_PCI_RX_BUF_SIZE (11454 + 24) #define RTK_PCI_CTRL 0x300 #define BIT_RST_TRXDMA_INTF BIT(20) diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index 8d93f3159746..5cd9cc42648e 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -147,12 +147,13 @@ void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi) { struct rtw_chip_info *chip = rtwdev->chip; struct rtw_hal *hal = &rtwdev->hal; - const struct rtw_hw_reg *dig_cck = &chip->dig_cck[0]; u32 addr, mask; u8 path; - if (dig_cck) + if (chip->dig_cck) { + const struct rtw_hw_reg *dig_cck = &chip->dig_cck[0]; rtw_write32_mask(rtwdev, dig_cck->addr, dig_cck->mask, igi >> 1); + } for (path = 0; path < hal->rf_path_num; path++) { addr = chip->dig[path].addr; @@ -1522,7 +1523,7 @@ static u8 rtw_get_channel_group(u8 channel) switch (channel) { default: WARN_ON(1); - /* fall through */ + fallthrough; case 1: case 2: case 36: @@ -1668,7 +1669,7 @@ static u8 rtw_phy_get_2g_tx_power_index(struct rtw_dev *rtwdev, switch (bandwidth) { default: WARN_ON(1); - /* fall through */ + fallthrough; case RTW_CHANNEL_WIDTH_20: tx_power += pwr_idx_2g->ht_1s_diff.bw20 * factor; if (above_2ss) @@ -1712,7 +1713,7 @@ static u8 rtw_phy_get_5g_tx_power_index(struct rtw_dev *rtwdev, switch (bandwidth) { default: WARN_ON(1); - /* fall through */ + fallthrough; case RTW_CHANNEL_WIDTH_20: tx_power += pwr_idx_5g->ht_1s_diff.bw20 * factor; if (above_2ss) diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h index 8f468d6b5f78..86b94c008a27 100644 --- a/drivers/net/wireless/realtek/rtw88/reg.h +++ b/drivers/net/wireless/realtek/rtw88/reg.h @@ -126,6 +126,9 @@ BIT_WINTINI_RDY | BIT_RAM_DL_SEL) #define FW_READY_MASK 0xffff +#define REG_MCU_TST_CFG 0x84 +#define VAL_FW_TRIGGER 0x1 + #define REG_EFUSE_ACCESS 0x00CF #define EFUSE_ACCESS_ON 0x69 #define EFUSE_ACCESS_OFF 0x00 @@ -616,6 +619,8 @@ #define BIT_ANAPAR_BTPS BIT(22) #define REG_RSTB_SEL 0x1c38 +#define REG_HRCV_MSG 0x1cf + #define REG_IGN_GNTBT4 0x4160 #define RF_MODE 0x00 diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c index d8863d8a5468..da2e7415be8f 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c @@ -68,7 +68,7 @@ static const u32 rtw8821c_txscale_tbl[] = { 0x2d3, 0x2fe, 0x32b, 0x35c, 0x38e, 0x3c4, 0x3fe }; -static const u8 rtw8821c_get_swing_index(struct rtw_dev *rtwdev) +static u8 rtw8821c_get_swing_index(struct rtw_dev *rtwdev) { u8 i = 0; u32 swing, table_value; diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index 351cd055a295..22d0dd640ac9 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -1009,12 +1009,12 @@ static int rtw8822b_set_antenna(struct rtw_dev *rtwdev, antenna_tx, antenna_rx); if (!rtw8822b_check_rf_path(antenna_tx)) { - rtw_info(rtwdev, "unsupport tx path 0x%x\n", antenna_tx); + rtw_info(rtwdev, "unsupported tx path 0x%x\n", antenna_tx); return -EINVAL; } if (!rtw8822b_check_rf_path(antenna_rx)) { - rtw_info(rtwdev, "unsupport rx path 0x%x\n", antenna_rx); + rtw_info(rtwdev, "unsupported rx path 0x%x\n", antenna_rx); return -EINVAL; } @@ -2442,6 +2442,7 @@ struct rtw_chip_info rtw8822b_hw_spec = { .ptct_efuse_size = 96, .txff_size = 262144, .rxff_size = 24576, + .fw_rxff_size = 12288, .txgi_factor = 1, .is_pwr_by_rate_dec = true, .max_power_index = 0x3f, @@ -2504,6 +2505,8 @@ struct rtw_chip_info rtw8822b_hw_spec = { .coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8822b), .coex_info_hw_regs = coex_info_hw_regs_8822b, + + .fw_fifo_addr = {0x780, 0x700, 0x780, 0x660, 0x650, 0x680}, }; EXPORT_SYMBOL(rtw8822b_hw_spec); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 426808413baa..e37300e98517 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -154,25 +154,16 @@ static void rtw8822c_rf_minmax_cmp(struct rtw_dev *rtwdev, u32 value, } } -static void swap_u32(u32 *v1, u32 *v2) -{ - u32 tmp; - - tmp = *v1; - *v1 = *v2; - *v2 = tmp; -} - static void __rtw8822c_dac_iq_sort(struct rtw_dev *rtwdev, u32 *v1, u32 *v2) { if (*v1 >= 0x200 && *v2 >= 0x200) { if (*v1 > *v2) - swap_u32(v1, v2); + swap(*v1, *v2); } else if (*v1 < 0x200 && *v2 < 0x200) { if (*v1 > *v2) - swap_u32(v1, v2); + swap(*v1, *v2); } else if (*v1 < 0x200 && *v2 >= 0x200) { - swap_u32(v1, v2); + swap(*v1, *v2); } } @@ -2014,7 +2005,7 @@ static int rtw8822c_set_antenna(struct rtw_dev *rtwdev, case BB_PATH_AB: break; default: - rtw_info(rtwdev, "unsupport tx path 0x%x\n", antenna_tx); + rtw_info(rtwdev, "unsupported tx path 0x%x\n", antenna_tx); return -EINVAL; } @@ -2024,7 +2015,7 @@ static int rtw8822c_set_antenna(struct rtw_dev *rtwdev, case BB_PATH_AB: break; default: - rtw_info(rtwdev, "unsupport rx path 0x%x\n", antenna_rx); + rtw_info(rtwdev, "unsupported rx path 0x%x\n", antenna_rx); return -EINVAL; } @@ -4303,6 +4294,7 @@ struct rtw_chip_info rtw8822c_hw_spec = { .ptct_efuse_size = 124, .txff_size = 262144, .rxff_size = 24576, + .fw_rxff_size = 12288, .txgi_factor = 2, .is_pwr_by_rate_dec = false, .max_power_index = 0x7f, @@ -4373,6 +4365,8 @@ struct rtw_chip_info rtw8822c_hw_spec = { .coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8822c), .coex_info_hw_regs = coex_info_hw_regs_8822c, + + .fw_fifo_addr = {0x780, 0x700, 0x780, 0x660, 0x650, 0x680}, }; EXPORT_SYMBOL(rtw8822c_hw_spec); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c b/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c index 08d01a7bb1bf..3a204a7533df 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c @@ -23889,7 +23889,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 11, 60, }, { 8, 0, 0, 0, 11, 72, }, { 9, 0, 0, 0, 11, 60, }, - { 0, 0, 0, 0, 12, 52, }, + { 0, 0, 0, 0, 12, 44, }, { 2, 0, 0, 0, 12, 60, }, { 1, 0, 0, 0, 12, 68, }, { 3, 0, 0, 0, 12, 52, }, @@ -23899,7 +23899,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 12, 60, }, { 8, 0, 0, 0, 12, 52, }, { 9, 0, 0, 0, 12, 60, }, - { 0, 0, 0, 0, 13, 48, }, + { 0, 0, 0, 0, 13, 40, }, { 2, 0, 0, 0, 13, 60, }, { 1, 0, 0, 0, 13, 68, }, { 3, 0, 0, 0, 13, 48, }, @@ -24029,7 +24029,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 1, 11, 60, }, { 8, 0, 0, 1, 11, 52, }, { 9, 0, 0, 1, 11, 60, }, - { 0, 0, 0, 1, 12, 40, }, + { 0, 0, 0, 1, 12, 32, }, { 2, 0, 0, 1, 12, 60, }, { 1, 0, 0, 1, 12, 76, }, { 3, 0, 0, 1, 12, 40, }, @@ -24039,7 +24039,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 1, 12, 60, }, { 8, 0, 0, 1, 12, 40, }, { 9, 0, 0, 1, 12, 60, }, - { 0, 0, 0, 1, 13, 28, }, + { 0, 0, 0, 1, 13, 20, }, { 2, 0, 0, 1, 13, 60, }, { 1, 0, 0, 1, 13, 76, }, { 3, 0, 0, 1, 13, 28, }, @@ -24169,7 +24169,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 2, 11, 60, }, { 8, 0, 0, 2, 11, 52, }, { 9, 0, 0, 2, 11, 60, }, - { 0, 0, 0, 2, 12, 40, }, + { 0, 0, 0, 2, 12, 32, }, { 2, 0, 0, 2, 12, 60, }, { 1, 0, 0, 2, 12, 76, }, { 3, 0, 0, 2, 12, 40, }, @@ -24179,7 +24179,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 2, 12, 60, }, { 8, 0, 0, 2, 12, 40, }, { 9, 0, 0, 2, 12, 60, }, - { 0, 0, 0, 2, 13, 28, }, + { 0, 0, 0, 2, 13, 20, }, { 2, 0, 0, 2, 13, 60, }, { 1, 0, 0, 2, 13, 76, }, { 3, 0, 0, 2, 13, 28, }, @@ -24309,7 +24309,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 3, 11, 36, }, { 8, 0, 0, 3, 11, 52, }, { 9, 0, 0, 3, 11, 36, }, - { 0, 0, 0, 3, 12, 40, }, + { 0, 0, 0, 3, 12, 32, }, { 2, 0, 0, 3, 12, 36, }, { 1, 0, 0, 3, 12, 66, }, { 3, 0, 0, 3, 12, 40, }, @@ -24319,7 +24319,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 3, 12, 36, }, { 8, 0, 0, 3, 12, 40, }, { 9, 0, 0, 3, 12, 36, }, - { 0, 0, 0, 3, 13, 28, }, + { 0, 0, 0, 3, 13, 20, }, { 2, 0, 0, 3, 13, 36, }, { 1, 0, 0, 3, 13, 66, }, { 3, 0, 0, 3, 13, 28, }, @@ -25844,7 +25844,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 7, 0, 0, 0, 11, 60, }, { 8, 0, 0, 0, 11, 72, }, { 9, 0, 0, 0, 11, 60, }, - { 0, 0, 0, 0, 12, 52, }, + { 0, 0, 0, 0, 12, 44, }, { 2, 0, 0, 0, 12, 60, }, { 1, 0, 0, 0, 12, 68, }, { 3, 0, 0, 0, 12, 52, }, @@ -25854,7 +25854,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 7, 0, 0, 0, 12, 60, }, { 8, 0, 0, 0, 12, 52, }, { 9, 0, 0, 0, 12, 60, }, - { 0, 0, 0, 0, 13, 48, }, + { 0, 0, 0, 0, 13, 40, }, { 2, 0, 0, 0, 13, 60, }, { 1, 0, 0, 0, 13, 68, }, { 3, 0, 0, 0, 13, 48, }, @@ -25984,7 +25984,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 7, 0, 0, 1, 11, 60, }, { 8, 0, 0, 1, 11, 52, }, { 9, 0, 0, 1, 11, 60, }, - { 0, 0, 0, 1, 12, 40, }, + { 0, 0, 0, 1, 12, 32, }, { 2, 0, 0, 1, 12, 60, }, { 1, 0, 0, 1, 12, 76, }, { 3, 0, 0, 1, 12, 40, }, @@ -25994,7 +25994,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 7, 0, 0, 1, 12, 60, }, { 8, 0, 0, 1, 12, 40, }, { 9, 0, 0, 1, 12, 60, }, - { 0, 0, 0, 1, 13, 28, }, + { 0, 0, 0, 1, 13, 20, }, { 2, 0, 0, 1, 13, 60, }, { 1, 0, 0, 1, 13, 76, }, { 3, 0, 0, 1, 13, 28, }, @@ -26124,7 +26124,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 7, 0, 0, 2, 11, 60, }, { 8, 0, 0, 2, 11, 52, }, { 9, 0, 0, 2, 11, 60, }, - { 0, 0, 0, 2, 12, 40, }, + { 0, 0, 0, 2, 12, 32, }, { 2, 0, 0, 2, 12, 60, }, { 1, 0, 0, 2, 12, 76, }, { 3, 0, 0, 2, 12, 40, }, @@ -26134,7 +26134,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 7, 0, 0, 2, 12, 60, }, { 8, 0, 0, 2, 12, 40, }, { 9, 0, 0, 2, 12, 60, }, - { 0, 0, 0, 2, 13, 28, }, + { 0, 0, 0, 2, 13, 20, }, { 2, 0, 0, 2, 13, 60, }, { 1, 0, 0, 2, 13, 76, }, { 3, 0, 0, 2, 13, 28, }, @@ -26264,7 +26264,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 7, 0, 0, 3, 11, 36, }, { 8, 0, 0, 3, 11, 52, }, { 9, 0, 0, 3, 11, 36, }, - { 0, 0, 0, 3, 12, 40, }, + { 0, 0, 0, 3, 12, 32, }, { 2, 0, 0, 3, 12, 36, }, { 1, 0, 0, 3, 12, 66, }, { 3, 0, 0, 3, 12, 40, }, @@ -26274,7 +26274,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 7, 0, 0, 3, 12, 36, }, { 8, 0, 0, 3, 12, 40, }, { 9, 0, 0, 3, 12, 36, }, - { 0, 0, 0, 3, 13, 28, }, + { 0, 0, 0, 3, 13, 20, }, { 2, 0, 0, 3, 13, 36, }, { 1, 0, 0, 3, 13, 66, }, { 3, 0, 0, 3, 13, 28, }, diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c index 7fcc992b01a8..ca8072177ae3 100644 --- a/drivers/net/wireless/realtek/rtw88/tx.c +++ b/drivers/net/wireless/realtek/rtw88/tx.c @@ -587,9 +587,9 @@ static void rtw_txq_push(struct rtw_dev *rtwdev, rcu_read_unlock(); } -void rtw_tx_tasklet(unsigned long data) +void rtw_tx_tasklet(struct tasklet_struct *t) { - struct rtw_dev *rtwdev = (void *)data; + struct rtw_dev *rtwdev = from_tasklet(rtwdev, t, tx_tasklet); struct rtw_txq *rtwtxq, *tmp; spin_lock_bh(&rtwdev->txq_lock); diff --git a/drivers/net/wireless/realtek/rtw88/tx.h b/drivers/net/wireless/realtek/rtw88/tx.h index cfe84eef5923..6673dbcaa21c 100644 --- a/drivers/net/wireless/realtek/rtw88/tx.h +++ b/drivers/net/wireless/realtek/rtw88/tx.h @@ -94,7 +94,7 @@ void rtw_tx(struct rtw_dev *rtwdev, struct sk_buff *skb); void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq); void rtw_txq_cleanup(struct rtw_dev *rtwdev, struct ieee80211_txq *txq); -void rtw_tx_tasklet(unsigned long data); +void rtw_tx_tasklet(struct tasklet_struct *t); void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev, struct rtw_tx_pkt_info *pkt_info, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/realtek/rtw88/util.h b/drivers/net/wireless/realtek/rtw88/util.h index 41c10e7144df..0c23b5069be0 100644 --- a/drivers/net/wireless/realtek/rtw88/util.h +++ b/drivers/net/wireless/realtek/rtw88/util.h @@ -17,6 +17,8 @@ struct rtw_dev; ieee80211_iterate_stations_atomic(rtwdev->hw, iterator, data) #define rtw_iterate_keys(rtwdev, vif, iterator, data) \ ieee80211_iter_keys(rtwdev->hw, vif, iterator, data) +#define rtw_iterate_keys_rcu(rtwdev, vif, iterator, data) \ + ieee80211_iter_keys_rcu((rtwdev)->hw, vif, iterator, data) static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) { |