Skip to content

Commit

Permalink
rtw88: update Realtek's rtw88 driver
Browse files Browse the repository at this point in the history
Update rtw88 based on wireless-testing at
4e051428044d5c47cd2c81c3b154788efe07ee11 (tag: wt-2022-06-10).

This is in preparation to apply USB changes to work on these and
LinuxKPI for them over the next weeks, as well to debug a
reported issue, and possibly extract and upstream some local fixes.

(cherry picked from commit 9c95173)
  • Loading branch information
Bjoern A. Zeeb authored and Bjoern A. Zeeb committed Jul 1, 2022
1 parent a478f4a commit 54f9ddf
Show file tree
Hide file tree
Showing 34 changed files with 741 additions and 188 deletions.
298 changes: 276 additions & 22 deletions sys/contrib/dev/rtw88/coex.c

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions sys/contrib/dev/rtw88/coex.h
Expand Up @@ -11,6 +11,7 @@

#define COEX_MIN_DELAY 10 /* delay unit in ms */
#define COEX_RFK_TIMEOUT 600 /* RFK timeout in ms */
#define COEX_BT_GAMEHID_CNT 800

#define COEX_RF_OFF 0x0
#define COEX_RF_ON 0x1
Expand Down Expand Up @@ -172,6 +173,7 @@ enum coex_bt_profile {
enum coex_wl_link_mode {
COEX_WLINK_2G1PORT = 0x0,
COEX_WLINK_5G = 0x3,
COEX_WLINK_2GFREE = 0x7,
COEX_WLINK_MAX
};

Expand Down Expand Up @@ -401,9 +403,12 @@ void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type);
void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type);
void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type);
void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length);
void rtw_coex_bt_hid_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length);
void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length);
void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type);
void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type);
void rtw_coex_wl_status_check(struct rtw_dev *rtwdev);
void rtw_coex_query_bt_hid_list(struct rtw_dev *rtwdev);
void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m);

static inline bool rtw_coex_disabled(struct rtw_dev *rtwdev)
Expand Down
12 changes: 5 additions & 7 deletions sys/contrib/dev/rtw88/debug.c
Expand Up @@ -269,11 +269,7 @@ static int rtw_debugfs_get_rsvd_page(struct seq_file *m, void *v)
for (i = 0 ; i < buf_size ; i += 8) {
if (i % page_size == 0)
seq_printf(m, "PAGE %d\n", (i + offset) / page_size);
seq_printf(m, "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
*(buf + i), *(buf + i + 1),
*(buf + i + 2), *(buf + i + 3),
*(buf + i + 4), *(buf + i + 5),
*(buf + i + 6), *(buf + i + 7));
seq_printf(m, "%8ph\n", buf + i);
}
vfree(buf);

Expand Down Expand Up @@ -390,7 +386,7 @@ static ssize_t rtw_debugfs_set_h2c(struct file *filp,
&param[0], &param[1], &param[2], &param[3],
&param[4], &param[5], &param[6], &param[7]);
if (num != 8) {
rtw_info(rtwdev, "invalid H2C command format for debug\n");
rtw_warn(rtwdev, "invalid H2C command format for debug\n");
return -EINVAL;
}

Expand Down Expand Up @@ -715,8 +711,10 @@ static int rtw_debugfs_get_phy_info(struct seq_file *m, void *v)
seq_printf(m, "Current CH(fc) = %u\n", rtwdev->hal.current_channel);
seq_printf(m, "Current BW = %u\n", rtwdev->hal.current_band_width);
seq_printf(m, "Current IGI = 0x%x\n", dm_info->igi_history[0]);
seq_printf(m, "TP {Tx, Rx} = {%u, %u}Mbps\n\n",
seq_printf(m, "TP {Tx, Rx} = {%u, %u}Mbps\n",
stats->tx_throughput, stats->rx_throughput);
seq_printf(m, "1SS for TX and RX = %c\n\n", rtwdev->hal.txrx_1ss ?
'Y' : 'N');

seq_puts(m, "==========[Tx Phy Info]========\n");
seq_puts(m, "[Tx Rate] = ");
Expand Down
1 change: 1 addition & 0 deletions sys/contrib/dev/rtw88/debug.h
Expand Up @@ -23,6 +23,7 @@ enum rtw_debug_mask {
RTW_DBG_PATH_DIV = 0x00004000,
RTW_DBG_ADAPTIVITY = 0x00008000,
RTW_DBG_HW_SCAN = 0x00010000,
RTW_DBG_STATE = 0x00020000,

#if defined(__FreeBSD__)
RTW_DBG_IO_RW = 0x80000000,
Expand Down
100 changes: 81 additions & 19 deletions sys/contrib/dev/rtw88/fw.c
Expand Up @@ -233,6 +233,9 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
case C2H_BT_INFO:
rtw_coex_bt_info_notify(rtwdev, c2h->payload, len);
break;
case C2H_BT_HID_INFO:
rtw_coex_bt_hid_info_notify(rtwdev, c2h->payload, len);
break;
case C2H_WLAN_INFO:
rtw_coex_wl_fwdbginfo_notify(rtwdev, c2h->payload, len);
break;
Expand Down Expand Up @@ -538,6 +541,18 @@ void rtw_fw_coex_tdma_type(struct rtw_dev *rtwdev,
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
}

void rtw_fw_coex_query_hid_info(struct rtw_dev *rtwdev, u8 sub_id, u8 data)
{
u8 h2c_pkt[H2C_PKT_SIZE] = {0};

SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_QUERY_BT_HID_INFO);

SET_COEX_QUERY_HID_INFO_SUBID(h2c_pkt, sub_id);
SET_COEX_QUERY_HID_INFO_DATA1(h2c_pkt, data);

rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
}

void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data)
{
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
Expand Down Expand Up @@ -570,10 +585,10 @@ void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
}

void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si,
bool reset_ra_mask)
{
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
bool no_update = si->updated;
bool disable_pt = true;

SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RA_INFO);
Expand All @@ -584,7 +599,7 @@ void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
SET_RA_INFO_SGI_EN(h2c_pkt, si->sgi_enable);
SET_RA_INFO_BW_MODE(h2c_pkt, si->bw_mode);
SET_RA_INFO_LDPC(h2c_pkt, !!si->ldpc_en);
SET_RA_INFO_NO_UPDATE(h2c_pkt, no_update);
SET_RA_INFO_NO_UPDATE(h2c_pkt, !reset_ra_mask);
SET_RA_INFO_VHT_EN(h2c_pkt, si->vht_enable);
SET_RA_INFO_DIS_PT(h2c_pkt, disable_pt);
SET_RA_INFO_RA_MASK0(h2c_pkt, (si->ra_mask & 0xff));
Expand All @@ -593,7 +608,6 @@ void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
SET_RA_INFO_RA_MASK3(h2c_pkt, (si->ra_mask & 0xff000000) >> 24);

si->init_ra_lv = 0;
si->updated = true;

rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
}
Expand Down Expand Up @@ -635,7 +649,7 @@ void rtw_fw_beacon_filter_config(struct rtw_dev *rtwdev, bool connect,
s32 threshold = bss_conf->cqm_rssi_thold + rssi_offset;
u8 h2c_pkt[H2C_PKT_SIZE] = {0};

if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER) || !si)
if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER))
return;

if (!connect) {
Expand All @@ -645,6 +659,10 @@ void rtw_fw_beacon_filter_config(struct rtw_dev *rtwdev, bool connect,

return;
}

if (!si)
return;

SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_BCN_FILTER_OFFLOAD_P0);
ether_addr_copy(&h2c_pkt[1], bss_conf->bssid);
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
Expand Down Expand Up @@ -1033,6 +1051,7 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw,
struct rtw_vif *rtwvif;
struct sk_buff *skb_new;
struct cfg80211_ssid *ssid;
u16 tim_offset = 0;

if (rsvd_pkt->type == RSVD_DUMMY) {
skb_new = alloc_skb(1, GFP_KERNEL);
Expand All @@ -1051,7 +1070,8 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw,

switch (rsvd_pkt->type) {
case RSVD_BEACON:
skb_new = ieee80211_beacon_get(hw, vif);
skb_new = ieee80211_beacon_get_tim(hw, vif, &tim_offset, NULL);
rsvd_pkt->tim_offset = tim_offset;
break;
case RSVD_PS_POLL:
skb_new = ieee80211_pspoll_get(hw, vif);
Expand Down Expand Up @@ -1582,6 +1602,16 @@ int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev)
return ret;
}

void rtw_fw_update_beacon_work(struct work_struct *work)
{
struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
update_beacon_work);

mutex_lock(&rtwdev->mutex);
rtw_fw_download_rsvd_page(rtwdev);
mutex_unlock(&rtwdev->mutex);
}

static void rtw_fw_read_fifo_page(struct rtw_dev *rtwdev, u32 offset, u32 size,
u32 *buf, u32 residue, u16 start_pg)
{
Expand Down Expand Up @@ -1766,7 +1796,7 @@ void rtw_fw_adaptivity(struct rtw_dev *rtwdev)

SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_ADAPTIVITY);
SET_ADAPTIVITY_MODE(h2c_pkt, dm_info->edcca_mode);
SET_ADAPTIVITY_OPTION(h2c_pkt, 2);
SET_ADAPTIVITY_OPTION(h2c_pkt, 1);
SET_ADAPTIVITY_IGI(h2c_pkt, dm_info->igi_history[0]);
SET_ADAPTIVITY_L2H(h2c_pkt, dm_info->l2h_th_ini);
SET_ADAPTIVITY_DENSITY(h2c_pkt, dm_info->scan_density);
Expand All @@ -1784,9 +1814,9 @@ void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start)
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
}

static void rtw_append_probe_req_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
struct sk_buff_head *list,
struct rtw_vif *rtwvif)
static int rtw_append_probe_req_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
struct sk_buff_head *list, u8 *bands,
struct rtw_vif *rtwvif)
{
struct ieee80211_scan_ies *ies = rtwvif->scan_ies;
struct rtw_chip_info *chip = rtwdev->chip;
Expand All @@ -1797,19 +1827,24 @@ static void rtw_append_probe_req_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
if (!(BIT(idx) & chip->band))
continue;
new = skb_copy(skb, GFP_KERNEL);
if (!new)
return -ENOMEM;
skb_put_data(new, ies->ies[idx], ies->len[idx]);
skb_put_data(new, ies->common_ies, ies->common_ie_len);
skb_queue_tail(list, new);
(*bands)++;
}

return 0;
}

static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_ssids,
static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_probes,
struct sk_buff_head *probe_req_list)
{
struct rtw_chip_info *chip = rtwdev->chip;
struct sk_buff *skb, *tmp;
u8 page_offset = 1, *buf, page_size = chip->page_size;
u8 pages = page_offset + num_ssids * RTW_PROBE_PG_CNT;
u8 pages = page_offset + num_probes * RTW_PROBE_PG_CNT;
u16 pg_addr = rtwdev->fifo.rsvd_h2c_info_addr, loc;
u16 buf_offset = page_size * page_offset;
u8 tx_desc_sz = chip->tx_pkt_desc_sz;
Expand Down Expand Up @@ -1851,6 +1886,8 @@ static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_ssids,
rtwdev->scan_info.probe_pg_size = page_offset;
out:
kfree(buf);
skb_queue_walk_safe(probe_req_list, skb, tmp)
kfree_skb(skb);

return ret;
}
Expand All @@ -1860,20 +1897,35 @@ static int rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev,
{
struct cfg80211_scan_request *req = rtwvif->scan_req;
struct sk_buff_head list;
struct sk_buff *skb;
u8 num = req->n_ssids, i;
struct sk_buff *skb, *tmp;
u8 num = req->n_ssids, i, bands = 0;
int ret;

skb_queue_head_init(&list);
for (i = 0; i < num; i++) {
skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr,
req->ssids[i].ssid,
req->ssids[i].ssid_len,
req->ie_len);
rtw_append_probe_req_ie(rtwdev, skb, &list, rtwvif);
if (!skb) {
ret = -ENOMEM;
goto out;
}
ret = rtw_append_probe_req_ie(rtwdev, skb, &list, &bands,
rtwvif);
if (ret)
goto out;

kfree_skb(skb);
}

return _rtw_hw_scan_update_probe_req(rtwdev, num, &list);
return _rtw_hw_scan_update_probe_req(rtwdev, num * bands, &list);

out:
skb_queue_walk_safe(&list, skb, tmp)
kfree_skb(skb);

return ret;
}

static int rtw_add_chan_info(struct rtw_dev *rtwdev, struct rtw_chan_info *info,
Expand Down Expand Up @@ -2017,20 +2069,27 @@ void rtw_hw_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct cfg80211_scan_info info = {
.aborted = aborted,
};
struct rtw_hw_scan_info *scan_info = &rtwdev->scan_info;
struct rtw_hal *hal = &rtwdev->hal;
struct rtw_vif *rtwvif;
u8 chan = scan_info->op_chan;

if (!vif)
return;

rtwdev->hal.rcr |= BIT_CBSSID_BCN;
rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr);

rtw_core_scan_complete(rtwdev, vif);
rtw_core_scan_complete(rtwdev, vif, true);

rtwvif = (struct rtw_vif *)vif->drv_priv;
if (rtwvif->net_type == RTW_NET_MGD_LINKED) {
hal->current_channel = chan;
hal->current_band_type = chan > 14 ? RTW_BAND_5G : RTW_BAND_2G;
}
ieee80211_wake_queues(rtwdev->hw);
ieee80211_scan_completed(rtwdev->hw, &info);

rtwvif = (struct rtw_vif *)vif->drv_priv;
rtwvif->scan_req = NULL;
rtwvif->scan_ies = NULL;
rtwdev->scan_info.scanning_vif = NULL;
Expand Down Expand Up @@ -2112,7 +2171,7 @@ void rtw_hw_scan_status_report(struct rtw_dev *rtwdev, struct sk_buff *skb)
rtw_hw_scan_complete(rtwdev, vif, aborted);

if (aborted)
rtw_info(rtwdev, "HW scan aborted with code: %d\n", rc);
rtw_dbg(rtwdev, RTW_DBG_HW_SCAN, "HW scan aborted with code: %d\n", rc);
}

void rtw_store_op_chan(struct rtw_dev *rtwdev)
Expand All @@ -2139,6 +2198,9 @@ void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb)
enum rtw_scan_notify_id id;
u8 chan, status;

if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
return;

c2h = get_c2h_from_skb(skb);
chan = GET_CHAN_SWITCH_CENTRAL_CH(c2h->payload);
id = GET_CHAN_SWITCH_ID(c2h->payload);
Expand Down
14 changes: 13 additions & 1 deletion sys/contrib/dev/rtw88/fw.h
Expand Up @@ -47,6 +47,7 @@ enum rtw_c2h_cmd_id {
C2H_CCX_TX_RPT = 0x03,
C2H_BT_INFO = 0x09,
C2H_BT_MP_INFO = 0x0b,
C2H_BT_HID_INFO = 0x45,
C2H_RA_RPT = 0x0c,
C2H_HW_FEATURE_REPORT = 0x19,
C2H_WLAN_INFO = 0x27,
Expand Down Expand Up @@ -171,6 +172,7 @@ struct rtw_rsvd_page {
struct sk_buff *skb;
enum rtw_rsvd_packet_type type;
u8 page;
u16 tim_offset;
bool add_txdesc;
struct cfg80211_ssid *ssid;
u16 probe_req_size;
Expand Down Expand Up @@ -529,6 +531,7 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
#define H2C_CMD_QUERY_BT_MP_INFO 0x67
#define H2C_CMD_BT_WIFI_CONTROL 0x69
#define H2C_CMD_WIFI_CALIBRATION 0x6d
#define H2C_CMD_QUERY_BT_HID_INFO 0x73

#define H2C_CMD_KEEP_ALIVE 0x03
#define H2C_CMD_DISCONNECT_DECISION 0x04
Expand Down Expand Up @@ -681,6 +684,11 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
#define SET_BT_WIFI_CONTROL_DATA5(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16))

#define SET_COEX_QUERY_HID_INFO_SUBID(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
#define SET_COEX_QUERY_HID_INFO_DATA1(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))

#define SET_KEEP_ALIVE_ENABLE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
#define SET_KEEP_ALIVE_ADOPT(h2c_pkt, value) \
Expand Down Expand Up @@ -780,9 +788,12 @@ void rtw_fw_force_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl);
void rtw_fw_bt_ignore_wlan_action(struct rtw_dev *rtwdev, bool enable);
void rtw_fw_coex_tdma_type(struct rtw_dev *rtwdev,
u8 para1, u8 para2, u8 para3, u8 para4, u8 para5);
void rtw_fw_coex_query_hid_info(struct rtw_dev *rtwdev, u8 sub_id, u8 data);

void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data);
void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si,
bool reset_ra_mask);
void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool conn);
void rtw_fw_update_wl_phy_info(struct rtw_dev *rtwdev);
void rtw_fw_beacon_filter_config(struct rtw_dev *rtwdev, bool connect,
Expand All @@ -798,6 +809,7 @@ void rtw_add_rsvd_page_pno(struct rtw_dev *rtwdev,
void rtw_add_rsvd_page_sta(struct rtw_dev *rtwdev,
struct rtw_vif *rtwvif);
int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev);
void rtw_fw_update_beacon_work(struct work_struct *work);
void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev);
int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev,
u32 offset, u32 size, u32 *buf);
Expand Down
2 changes: 1 addition & 1 deletion sys/contrib/dev/rtw88/mac.c
Expand Up @@ -75,7 +75,7 @@ static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev)

switch (rtw_hci_type(rtwdev)) {
case RTW_HCI_TYPE_PCIE:
rtw_write32_set(rtwdev, REG_HCI_OPT_CTRL, BIT_BT_DIG_CLK_EN);
rtw_write32_set(rtwdev, REG_HCI_OPT_CTRL, BIT_USB_SUS_DIS);
break;
case RTW_HCI_TYPE_USB:
break;
Expand Down

0 comments on commit 54f9ddf

Please sign in to comment.