diff --git a/ath10k-4.16/htt_tx.c b/ath10k-4.16/htt_tx.c index 0855630..baf97ad 100644 --- a/ath10k-4.16/htt_tx.c +++ b/ath10k-4.16/htt_tx.c @@ -1065,6 +1065,44 @@ static u8 ath10k_htt_tx_get_tid(struct sk_buff *skb, bool is_eth) return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST; } +/* Copied from ieee80211_is_robust_mgmt_frame, but disable the check for has_protected + * since we do tx hw crypt, and it won't actually be encrypted even when this flag is + * set. + */ +bool ieee80211_is_robust_mgmt_frame_tx(struct ieee80211_hdr *hdr) +{ + if (ieee80211_is_disassoc(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control)) + return true; + + if (ieee80211_is_action(hdr->frame_control)) { + u8 *category; + + /* + * Action frames, excluding Public Action frames, are Robust + * Management Frames. However, if we are looking at a Protected + * frame, skip the check since the data may be encrypted and + * the frame has already been found to be a Robust Management + * Frame (by the other end). + */ + /* + if (ieee80211_has_protected(hdr->frame_control)) + return true; + */ + category = ((u8 *) hdr) + 24; + return *category != WLAN_CATEGORY_PUBLIC && + *category != WLAN_CATEGORY_HT && + *category != WLAN_CATEGORY_WNM_UNPROTECTED && + *category != WLAN_CATEGORY_SELF_PROTECTED && + *category != WLAN_CATEGORY_UNPROT_DMG && + *category != WLAN_CATEGORY_VHT && + *category != WLAN_CATEGORY_VENDOR_SPECIFIC; + } + + return false; +} + + int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) { struct ath10k *ar = htt->ar; @@ -1327,9 +1365,7 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, } if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT)) { - if ((ieee80211_is_action(hdr->frame_control) || - ieee80211_is_deauth(hdr->frame_control) || - ieee80211_is_disassoc(hdr->frame_control)) && + if (ieee80211_is_robust_mgmt_frame_tx(hdr) && ieee80211_has_protected(hdr->frame_control)) { skb_put(msdu, IEEE80211_CCMP_MIC_LEN); } else if (txmode == ATH10K_HW_TXRX_RAW && diff --git a/ath10k-4.19/htt_tx.c b/ath10k-4.19/htt_tx.c index be19214..744e1f3 100644 --- a/ath10k-4.19/htt_tx.c +++ b/ath10k-4.19/htt_tx.c @@ -1065,6 +1065,44 @@ static u8 ath10k_htt_tx_get_tid(struct sk_buff *skb, bool is_eth) return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST; } +/* Copied from ieee80211_is_robust_mgmt_frame, but disable the check for has_protected + * since we do tx hw crypt, and it won't actually be encrypted even when this flag is + * set. + */ +bool ieee80211_is_robust_mgmt_frame_tx(struct ieee80211_hdr *hdr) +{ + if (ieee80211_is_disassoc(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control)) + return true; + + if (ieee80211_is_action(hdr->frame_control)) { + u8 *category; + + /* + * Action frames, excluding Public Action frames, are Robust + * Management Frames. However, if we are looking at a Protected + * frame, skip the check since the data may be encrypted and + * the frame has already been found to be a Robust Management + * Frame (by the other end). + */ + /* + if (ieee80211_has_protected(hdr->frame_control)) + return true; + */ + category = ((u8 *) hdr) + 24; + return *category != WLAN_CATEGORY_PUBLIC && + *category != WLAN_CATEGORY_HT && + *category != WLAN_CATEGORY_WNM_UNPROTECTED && + *category != WLAN_CATEGORY_SELF_PROTECTED && + *category != WLAN_CATEGORY_UNPROT_DMG && + *category != WLAN_CATEGORY_VHT && + *category != WLAN_CATEGORY_VENDOR_SPECIFIC; + } + + return false; +} + + int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) { struct ath10k *ar = htt->ar; @@ -1323,9 +1361,7 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, } if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT)) { - if ((ieee80211_is_action(hdr->frame_control) || - ieee80211_is_deauth(hdr->frame_control) || - ieee80211_is_disassoc(hdr->frame_control)) && + if (ieee80211_is_robust_mgmt_frame_tx(hdr) && ieee80211_has_protected(hdr->frame_control)) { skb_put(msdu, IEEE80211_CCMP_MIC_LEN); } else if (txmode == ATH10K_HW_TXRX_RAW && diff --git a/ath10k-4.20/htt_tx.c b/ath10k-4.20/htt_tx.c index cb65237..5323af1 100644 --- a/ath10k-4.20/htt_tx.c +++ b/ath10k-4.20/htt_tx.c @@ -1119,6 +1119,44 @@ static u8 ath10k_htt_tx_get_tid(struct sk_buff *skb, bool is_eth) return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST; } +/* Copied from ieee80211_is_robust_mgmt_frame, but disable the check for has_protected + * since we do tx hw crypt, and it won't actually be encrypted even when this flag is + * set. + */ +bool ieee80211_is_robust_mgmt_frame_tx(struct ieee80211_hdr *hdr) +{ + if (ieee80211_is_disassoc(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control)) + return true; + + if (ieee80211_is_action(hdr->frame_control)) { + u8 *category; + + /* + * Action frames, excluding Public Action frames, are Robust + * Management Frames. However, if we are looking at a Protected + * frame, skip the check since the data may be encrypted and + * the frame has already been found to be a Robust Management + * Frame (by the other end). + */ + /* + if (ieee80211_has_protected(hdr->frame_control)) + return true; + */ + category = ((u8 *) hdr) + 24; + return *category != WLAN_CATEGORY_PUBLIC && + *category != WLAN_CATEGORY_HT && + *category != WLAN_CATEGORY_WNM_UNPROTECTED && + *category != WLAN_CATEGORY_SELF_PROTECTED && + *category != WLAN_CATEGORY_UNPROT_DMG && + *category != WLAN_CATEGORY_VHT && + *category != WLAN_CATEGORY_VENDOR_SPECIFIC; + } + + return false; +} + + int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) { struct ath10k *ar = htt->ar; @@ -1467,9 +1505,7 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, } if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT)) { - if ((ieee80211_is_action(hdr->frame_control) || - ieee80211_is_deauth(hdr->frame_control) || - ieee80211_is_disassoc(hdr->frame_control)) && + if (ieee80211_is_robust_mgmt_frame_tx(hdr) && ieee80211_has_protected(hdr->frame_control)) { skb_put(msdu, IEEE80211_CCMP_MIC_LEN); } else if (txmode == ATH10K_HW_TXRX_RAW && diff --git a/ath10k-5.1/Kconfig b/ath10k-5.2/Kconfig similarity index 98% rename from ath10k-5.1/Kconfig rename to ath10k-5.2/Kconfig index a7fb544..3522f25 100644 --- a/ath10k-5.1/Kconfig +++ b/ath10k-5.2/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only config ATH10K tristate "Atheros 802.11ac wireless cards support" depends on MAC80211 && HAS_DMA diff --git a/ath10k-5.1/Makefile b/ath10k-5.2/Makefile similarity index 100% rename from ath10k-5.1/Makefile rename to ath10k-5.2/Makefile diff --git a/ath10k-5.1/ahb.c b/ath10k-5.2/ahb.c similarity index 100% rename from ath10k-5.1/ahb.c rename to ath10k-5.2/ahb.c diff --git a/ath10k-5.1/ahb.h b/ath10k-5.2/ahb.h similarity index 100% rename from ath10k-5.1/ahb.h rename to ath10k-5.2/ahb.h diff --git a/ath10k-5.1/bmi.c b/ath10k-5.2/bmi.c similarity index 100% rename from ath10k-5.1/bmi.c rename to ath10k-5.2/bmi.c diff --git a/ath10k-5.1/bmi.h b/ath10k-5.2/bmi.h similarity index 100% rename from ath10k-5.1/bmi.h rename to ath10k-5.2/bmi.h diff --git a/ath10k-5.1/ce.c b/ath10k-5.2/ce.c similarity index 99% rename from ath10k-5.1/ce.c rename to ath10k-5.2/ce.c index 24b983e..eca87f7 100644 --- a/ath10k-5.1/ce.c +++ b/ath10k-5.2/ce.c @@ -1855,7 +1855,7 @@ void ath10k_ce_dump_registers(struct ath10k *ar, struct ath10k_ce_crash_data ce_data; u32 addr, id; - lockdep_assert_held(&ar->data_lock); + lockdep_assert_held(&ar->dump_mutex); ath10k_err(ar, "Copy Engine register dump:\n"); diff --git a/ath10k-5.1/ce.h b/ath10k-5.2/ce.h similarity index 100% rename from ath10k-5.1/ce.h rename to ath10k-5.2/ce.h diff --git a/ath10k-5.1/core.c b/ath10k-5.2/core.c similarity index 99% rename from ath10k-5.1/core.c rename to ath10k-5.2/core.c index f7b2d68..2bda95a 100644 --- a/ath10k-5.1/core.c +++ b/ath10k-5.2/core.c @@ -1751,7 +1751,7 @@ int ath10k_core_fetch_board_file(struct ath10k *ar, int bd_ie_type) int offset = (ar->hw_params.cal_data_len - (addrs * 4)) / 4; /* Start of configAddr */ /*ath10k_dbg(ar, ATH10K_DBG_BOOT, "Check saving eeprom configAddr from board-data\n");*/ for (i = 0; ieeprom_configAddrs[i] = e32[offset + i]; + ar->eeprom_configAddrs[i] = le32_to_cpu(e32[offset + i]); if (ar->eeprom_configAddrs[i]) { ath10k_dbg(ar, ATH10K_DBG_BOOT, "saving eeprom configAddr[%i]: 0x%08x\n", i, ar->eeprom_configAddrs[i]); @@ -3395,6 +3395,10 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, ath10k_wmi_pdev_set_special(ar, SET_SPECIAL_ID_DISABLE_IBSS_CCA, ar->eeprom_overrides.disable_ibss_cca); + if (ar->eeprom_overrides.peer_stats_pn) + ath10k_wmi_pdev_set_special(ar, SET_SPECIAL_ID_PEER_STATS_PN, + ar->eeprom_overrides.peer_stats_pn); + if (ar->eeprom_overrides.su_sounding_timer_ms) ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->txbf_sound_period_cmdid, ar->eeprom_overrides.su_sounding_timer_ms); @@ -3409,15 +3413,29 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, ath10k_wmi_pdev_set_fwtest(ar, 20, ar->eeprom_overrides.rc_txbf_probe); - for (i = 0; ieeprom_configAddrs); i += 2) { + for (i = 0; ieeprom_configAddrs); ) { if (ar->eeprom_configAddrs[i]) { - ath10k_dbg(ar, ATH10K_DBG_BOOT, "Applying eeprom configAddr[%i]: 0x%08x 0x%08x\n", - i, ar->eeprom_configAddrs[i], ar->eeprom_configAddrs[i+1]); + #define CONFIG_ADDR_MODE_SHIFT 20 + int mode = (ar->eeprom_configAddrs[i] >> CONFIG_ADDR_MODE_SHIFT) & 0x3; + int count = 1; /* one value applied to both 2G and 5G modes */ + int q; + + if (mode == 2) /* 2G, 5G value tuple */ + count = 2; + else if (mode == 3) /* 2G_VHT20, 2G_VHT40, 5G_VHT20, 5G_VHT40, 5G_VHT80/160/80+80 */ + count = 5; + ath10k_dbg(ar, ATH10K_DBG_BOOT, "Applying eeprom configAddr[%i]: mode: %d count: %d 0x%08x 0x%08x 0x%08x\n", + i, mode, count, ar->eeprom_configAddrs[i], ar->eeprom_configAddrs[i+1], + (count >= 2) ? ar->eeprom_configAddrs[i+2] : 0); ath10k_wmi_pdev_set_special(ar, SET_SPECIAL_ID_EEPROM_CFG_ADDR_A, ar->eeprom_configAddrs[i]); - ath10k_wmi_pdev_set_special(ar, SET_SPECIAL_ID_EEPROM_CFG_ADDR_V, - ar->eeprom_configAddrs[i+1]); + for (q = 0; qeeprom_configAddrs[i + q + 1]); + } + + i += (count + 1); } else { break; @@ -3856,6 +3874,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, goto err_free_wq; mutex_init(&ar->conf_mutex); + mutex_init(&ar->dump_mutex); spin_lock_init(&ar->data_lock); INIT_LIST_HEAD(&ar->peers); diff --git a/ath10k-5.1/core.h b/ath10k-5.2/core.h similarity index 99% rename from ath10k-5.1/core.h rename to ath10k-5.2/core.h index 010d06c..c7c2cb3 100644 --- a/ath10k-5.1/core.h +++ b/ath10k-5.2/core.h @@ -1337,6 +1337,9 @@ struct ath10k { /* prevents concurrent FW reconfiguration */ struct mutex conf_mutex; + /* protects coredump data */ + struct mutex dump_mutex; + /* protects shared structure data */ spinlock_t data_lock; @@ -1500,6 +1503,7 @@ struct ath10k { bool rx_all_mgt; bool apply_board_power_ctl_table; u8 disable_ibss_cca; + u8 peer_stats_pn; u8 rc_txbf_probe; #define CT_DISABLE_20MHZ 0x1 #define CT_DISABLE_40MHZ 0x2 diff --git a/ath10k-5.1/coredump.c b/ath10k-5.2/coredump.c similarity index 99% rename from ath10k-5.1/coredump.c rename to ath10k-5.2/coredump.c index e304962..b3788b1 100644 --- a/ath10k-5.1/coredump.c +++ b/ath10k-5.2/coredump.c @@ -1102,7 +1102,7 @@ struct ath10k_fw_crash_data *ath10k_coredump_new(struct ath10k *ar) { struct ath10k_fw_crash_data *crash_data = ar->coredump.fw_crash_data; - lockdep_assert_held(&ar->data_lock); + lockdep_assert_held(&ar->dump_mutex); if (ath10k_coredump_mask == 0) /* coredump disabled */ @@ -1163,7 +1163,7 @@ static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar) if (!buf) return NULL; - spin_lock_bh(&ar->data_lock); + mutex_lock(&ar->dump_mutex); dump_data = (struct ath10k_dump_file_data *)(buf); strlcpy(dump_data->df_magic, "ATH10K-FW-DUMP", @@ -1290,7 +1290,8 @@ static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar) WARN_ON(sofar != len); - spin_unlock_bh(&ar->data_lock); + + mutex_unlock(&ar->dump_mutex); return dump_data; } diff --git a/ath10k-5.1/coredump.h b/ath10k-5.2/coredump.h similarity index 100% rename from ath10k-5.1/coredump.h rename to ath10k-5.2/coredump.h diff --git a/ath10k-5.1/debug.c b/ath10k-5.2/debug.c similarity index 99% rename from ath10k-5.1/debug.c rename to ath10k-5.2/debug.c index 118bdd7..be7f380 100644 --- a/ath10k-5.1/debug.c +++ b/ath10k-5.2/debug.c @@ -3393,6 +3393,11 @@ static ssize_t ath10k_write_ct_special(struct file *file, /* Not stored in driver, will not be restored upon FW crash/restart */ ath10k_warn(ar, "Adding EEPROM configAddr value setting 0x08%x.\n", val); } + else if (id == SET_SPECIAL_ID_PEER_STATS_PN) { + ar->eeprom_overrides.peer_stats_pn = val; + ath10k_warn(ar, "Setting peer-stats-pn to %d\n", + ar->eeprom_overrides.peer_stats_pn); + } /* Below here are local driver hacks, and not necessarily passed directly to firmware. */ else if (id == 0x1001) { /* Set station failed-transmit kickout threshold. */ @@ -3506,7 +3511,9 @@ static ssize_t ath10k_read_ct_special(struct file *file, "id: 0x11 allow tx-hang logic to try cold resets instead of just warm resets.\n" "id: 0x12 disable special CCA setting for IBSS queues.\n" "id: 0x13 set 5-bit antenna-mask for peer, format: (peer-id << 16) | ant_mask\n" - "id: 0x14 Add a 32-bit sticky register / value override to the eeprom." + "id: 0x14 Add a 32-bit sticky register address override to the eeprom." + "id: 0x15 Add a 32-bit sticky register value override to the eeprom." + "id: 0x16 Enable/Disable reporting PN in peer-stats." "\nBelow here should work with most firmware, including non-CT firmware.\n" "id: 0x1001 set sta-kickout threshold due to tx-failures (0 means disable. Default is 20 * 16.)\n" "id: 0x1002 set su-sounding-timer-ms (0 means use defaults next FW reload. Default is 100, max is 500)\n" diff --git a/ath10k-5.1/debug.h b/ath10k-5.2/debug.h similarity index 100% rename from ath10k-5.1/debug.h rename to ath10k-5.2/debug.h diff --git a/ath10k-5.1/debugfs_sta.c b/ath10k-5.2/debugfs_sta.c similarity index 100% rename from ath10k-5.1/debugfs_sta.c rename to ath10k-5.2/debugfs_sta.c diff --git a/ath10k-5.1/hif.h b/ath10k-5.2/hif.h similarity index 100% rename from ath10k-5.1/hif.h rename to ath10k-5.2/hif.h diff --git a/ath10k-5.1/htc.c b/ath10k-5.2/htc.c similarity index 100% rename from ath10k-5.1/htc.c rename to ath10k-5.2/htc.c diff --git a/ath10k-5.1/htc.h b/ath10k-5.2/htc.h similarity index 100% rename from ath10k-5.1/htc.h rename to ath10k-5.2/htc.h diff --git a/ath10k-5.1/htt.c b/ath10k-5.2/htt.c similarity index 100% rename from ath10k-5.1/htt.c rename to ath10k-5.2/htt.c diff --git a/ath10k-5.1/htt.h b/ath10k-5.2/htt.h similarity index 100% rename from ath10k-5.1/htt.h rename to ath10k-5.2/htt.h diff --git a/ath10k-5.1/htt_rx.c b/ath10k-5.2/htt_rx.c similarity index 100% rename from ath10k-5.1/htt_rx.c rename to ath10k-5.2/htt_rx.c diff --git a/ath10k-5.1/htt_tx.c b/ath10k-5.2/htt_tx.c similarity index 94% rename from ath10k-5.1/htt_tx.c rename to ath10k-5.2/htt_tx.c index 69a6ecf..7445231 100644 --- a/ath10k-5.1/htt_tx.c +++ b/ath10k-5.2/htt_tx.c @@ -1155,6 +1155,44 @@ static u8 ath10k_htt_tx_get_tid(struct sk_buff *skb, bool is_eth) return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST; } +/* Copied from ieee80211_is_robust_mgmt_frame, but disable the check for has_protected + * since we do tx hw crypt, and it won't actually be encrypted even when this flag is + * set. + */ +bool ieee80211_is_robust_mgmt_frame_tx(struct ieee80211_hdr *hdr) +{ + if (ieee80211_is_disassoc(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control)) + return true; + + if (ieee80211_is_action(hdr->frame_control)) { + u8 *category; + + /* + * Action frames, excluding Public Action frames, are Robust + * Management Frames. However, if we are looking at a Protected + * frame, skip the check since the data may be encrypted and + * the frame has already been found to be a Robust Management + * Frame (by the other end). + */ + /* + if (ieee80211_has_protected(hdr->frame_control)) + return true; + */ + category = ((u8 *) hdr) + 24; + return *category != WLAN_CATEGORY_PUBLIC && + *category != WLAN_CATEGORY_HT && + *category != WLAN_CATEGORY_WNM_UNPROTECTED && + *category != WLAN_CATEGORY_SELF_PROTECTED && + *category != WLAN_CATEGORY_UNPROT_DMG && + *category != WLAN_CATEGORY_VHT && + *category != WLAN_CATEGORY_VENDOR_SPECIFIC; + } + + return false; +} + + int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) { struct ath10k *ar = htt->ar; @@ -1414,21 +1452,23 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, /*ath10k_warn(ar, "qos-data: %d data: %d qos-nullfunc: %d nullfunc: %d\n", ieee80211_is_data_qos(fc), ieee80211_is_data(fc), ieee80211_is_qos_nullfunc(fc), ieee80211_is_nullfunc(fc));*/ - if ((ieee80211_is_data_qos(fc) || ieee80211_is_data(fc)) && + /* In order to allow ARP to work, don't mess with frames < 100 bytes in length, assume + * test frames are larger. + */ + if ((msdu->len >= 100) && + (ieee80211_is_data_qos(fc) || ieee80211_is_data(fc)) && (!(ieee80211_is_qos_nullfunc(fc) || ieee80211_is_nullfunc(fc)))) { - if (arvif && arvif->txo_active) { - tpc = arvif->txo_tpc; - sgi = arvif->txo_sgi; - mcs = arvif->txo_mcs; - nss = arvif->txo_nss; - pream_type = arvif->txo_pream; - num_retries = arvif->txo_retries; - dyn_bw = arvif->txo_dynbw; - bw = arvif->txo_bw; - rix = arvif->txo_rix; - /*ath10k_warn(ar, "gathering txrate info from arvif, tpc: %d mcs: %d nss: %d pream_type: %d num_retries: %d dyn_bw: %d bw: %d rix: %d\n", - tpc, mcs, nss, pream_type, num_retries, dyn_bw, bw, rix);*/ - } + tpc = arvif->txo_tpc; + sgi = arvif->txo_sgi; + mcs = arvif->txo_mcs; + nss = arvif->txo_nss; + pream_type = arvif->txo_pream; + num_retries = arvif->txo_retries; + dyn_bw = arvif->txo_dynbw; + bw = arvif->txo_bw; + rix = arvif->txo_rix; + /*ath10k_warn(ar, "gathering txrate info from arvif, tpc: %d mcs: %d nss: %d pream_type: %d num_retries: %d dyn_bw: %d bw: %d rix: %d\n", + tpc, mcs, nss, pream_type, num_retries, dyn_bw, bw, rix);*/ } else { if (!(info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT)) @@ -1492,15 +1532,22 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, txbuf_paddr = htt->txbuf.paddr + (sizeof(struct ath10k_htt_txbuf_32) * msdu_id); - if ((ieee80211_is_action(hdr->frame_control) || - ieee80211_is_deauth(hdr->frame_control) || - ieee80211_is_disassoc(hdr->frame_control)) && - ieee80211_has_protected(hdr->frame_control)) { - skb_put(msdu, IEEE80211_CCMP_MIC_LEN); - } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) && - txmode == ATH10K_HW_TXRX_RAW && - ieee80211_has_protected(hdr->frame_control)) { - skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + if (ar->eeprom_overrides.tx_debug & 0x3) { + ath10k_warn(ar, + "htt tx, is-action: %d deauth: %d disassoc: %d has-protected: %d nohwcrypt: %d txmode: %d data-qos: %d\n", + ieee80211_is_action(hdr->frame_control), ieee80211_is_deauth(hdr->frame_control), + ieee80211_is_disassoc(hdr->frame_control), ieee80211_has_protected(hdr->frame_control), + skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT, txmode, ieee80211_is_data_qos(hdr->frame_control)); + } + + if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT)) { + if (ieee80211_is_robust_mgmt_frame_tx(hdr) && + ieee80211_has_protected(hdr->frame_control)) { + skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + } else if (txmode == ATH10K_HW_TXRX_RAW && + ieee80211_has_protected(hdr->frame_control)) { + skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + } } /* NOTE: This writes over info->control.rates[0], at least. */ @@ -1613,19 +1660,26 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, skb_len = msdu->len; trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid); - if (ar->eeprom_overrides.tx_debug & 0x3) + if (ar->eeprom_overrides.tx_debug & 0x3) { ath10k_warn(ar, "htt tx flags0 %hhu flags1 %hu (noack: %d) len %d id %hu frags_paddr %pad, msdu_paddr %pad vdev %hhu tid %hhu freq %hu\n", flags0, flags1, (flags1 & HTT_DATA_TX_DESC_FLAGS1_NO_ACK_CT), skb_len, msdu_id, &frags_paddr, &skb_cb->paddr, vdev_id, tid, freq); - else + if (ar->eeprom_overrides.tx_debug & 0x10) { + ath10k_dbg_dump(ar, ATH10K_DBG_BOOT, NULL, "htt tx msdu: ", + msdu->data, skb_len); + } + } + else { ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %pad, msdu_paddr %pad vdev %hhu tid %hhu freq %hu\n", flags0, flags1, skb_len, msdu_id, &frags_paddr, &skb_cb->paddr, vdev_id, tid, freq); - ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ", - msdu->data, skb_len); + ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ", + msdu->data, skb_len); + } + trace_ath10k_tx_hdr(ar, msdu->data, msdu->len); trace_ath10k_tx_payload(ar, msdu->data, msdu->len); diff --git a/ath10k-5.1/hw.c b/ath10k-5.2/hw.c similarity index 100% rename from ath10k-5.1/hw.c rename to ath10k-5.2/hw.c diff --git a/ath10k-5.1/hw.h b/ath10k-5.2/hw.h similarity index 100% rename from ath10k-5.1/hw.h rename to ath10k-5.2/hw.h diff --git a/ath10k-5.1/mac.c b/ath10k-5.2/mac.c similarity index 99% rename from ath10k-5.1/mac.c rename to ath10k-5.2/mac.c index 6ff9350..6734925 100644 --- a/ath10k-5.1/mac.c +++ b/ath10k-5.2/mac.c @@ -1141,6 +1141,40 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar) return ar->last_wmi_vdev_start_status; } +static u32 ath10k_get_max_antenna_gain(struct ath10k *ar, + u32 ch_max_antenna_gain) +{ + u32 max_antenna_gain; + + if (ar->dfs_detector && ar->dfs_detector->region == NL80211_DFS_FCC) { + /* FCC allows maximum antenna gain of 6 dBi. 15.247(b)(4): + * + * > (4) The conducted output power limit + * > specified in paragraph (b) of this section + * > is based on the use of antennas + * > with directional gains that do not exceed + * > 6 dBi. Except as shown in paragraph + * > (c) of this section, if transmitting + * > antennas of directional gain greater + * > than 6 dBi are used, the conducted + * > output power from the intentional radiator + * > shall be reduced below the stated + * > values in paragraphs (b)(1), (b)(2), + * > and (b)(3) of this section, as appropriate, + * > by the amount in dB that the + * > directional gain of the antenna exceeds + * > 6 dBi. + * + * https://www.gpo.gov/fdsys/pkg/CFR-2013-title47-vol1/pdf/CFR-2013-title47-vol1-sec15-247.pdf + */ + max_antenna_gain = 6; + } else { + max_antenna_gain = 0; + } + + return max(ch_max_antenna_gain, max_antenna_gain); +} + static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) { struct cfg80211_chan_def *chandef = NULL; @@ -1173,7 +1207,8 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) arg.channel.min_power = 0; arg.channel.max_power = channel->max_power * 2; arg.channel.max_reg_power = channel->max_reg_power * 2; - arg.channel.max_antenna_gain = channel->max_antenna_gain * 2; + arg.channel.max_antenna_gain = ath10k_get_max_antenna_gain(ar, + channel->max_antenna_gain); reinit_completion(&ar->vdev_setup_done); @@ -1615,7 +1650,8 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif, arg.channel.min_power = 0; arg.channel.max_power = chandef->chan->max_power * 2; arg.channel.max_reg_power = chandef->chan->max_reg_power * 2; - arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain * 2; + arg.channel.max_antenna_gain = ath10k_get_max_antenna_gain(ar, + chandef->chan->max_antenna_gain); /* CT Firmware can support 32+ VDEVS, but can only support * beacon-ing devs with dev ids 0 - 31 due to firmware limitations. @@ -3787,7 +3823,8 @@ static int ath10k_update_channel_list(struct ath10k *ar) ch->min_power = 0; ch->max_power = channel->max_power * 2; ch->max_reg_power = channel->max_reg_power * 2; - ch->max_antenna_gain = channel->max_antenna_gain * 2; + ch->max_antenna_gain = ath10k_get_max_antenna_gain(ar, + channel->max_antenna_gain); ch->reg_class_id = 0; /* FIXME */ /* FIXME: why use only legacy modes, why not any @@ -4070,6 +4107,9 @@ void ath10k_mac_handle_tx_pause_vdev(struct ath10k *ar, u32 vdev_id, spin_unlock_bh(&ar->htt.tx_lock); } +static bool ath10k_tx_h_use_hwcrypto(struct ieee80211_vif *vif, + struct sk_buff *skb); + static enum ath10k_hw_txrx_mode ath10k_mac_tx_h_get_txmode(struct ath10k *ar, struct ieee80211_vif *vif, @@ -4086,8 +4126,23 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar, /* CT Firmware with HTT-TX support sends all frames, including * management frames, over HTT in NATIVE-WIFI format. */ - if (ar->ct_all_pkts_htt) + if (ar->ct_all_pkts_htt) { + if (ieee80211_has_protected(hdr->frame_control)) { + /* If data is protected, but we don't want HW to crypt it, then use raw mode. */ + if (!(ath10k_tx_h_use_hwcrypto(vif, skb))) + return ATH10K_HW_TXRX_RAW; + + /* If we are PMF/MFP, then packets are evidently not encrypted by the hardware + * unless we are in raw mode. Go figure. + * Set to raw mode for PMF frames. + */ + if ((ieee80211_is_action(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control) || + ieee80211_is_disassoc(hdr->frame_control))) + return ATH10K_HW_TXRX_RAW; + } goto do_native_mgt_ct; + } if (ieee80211_is_mgmt(fc)) return ATH10K_HW_TXRX_MGMT; @@ -6649,7 +6704,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_MCAST_RATE && - !WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def))) { + !ath10k_mac_vif_chan(arvif->vif, &def)) { band = def.chan->band; rateidx = vif->bss_conf.mcast_rate[band] - 1; @@ -6687,7 +6742,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_BASIC_RATES) { - if (WARN_ON(ath10k_mac_vif_chan(vif, &def))) { + if (ath10k_mac_vif_chan(vif, &def)) { mutex_unlock(&ar->conf_mutex); return; } diff --git a/ath10k-5.1/mac.h b/ath10k-5.2/mac.h similarity index 100% rename from ath10k-5.1/mac.h rename to ath10k-5.2/mac.h diff --git a/ath10k-5.1/p2p.c b/ath10k-5.2/p2p.c similarity index 100% rename from ath10k-5.1/p2p.c rename to ath10k-5.2/p2p.c diff --git a/ath10k-5.1/p2p.h b/ath10k-5.2/p2p.h similarity index 100% rename from ath10k-5.1/p2p.h rename to ath10k-5.2/p2p.h diff --git a/ath10k-5.1/pci.c b/ath10k-5.2/pci.c similarity index 99% rename from ath10k-5.1/pci.c rename to ath10k-5.2/pci.c index be35315..beb68f0 100644 --- a/ath10k-5.1/pci.c +++ b/ath10k-5.2/pci.c @@ -1593,7 +1593,7 @@ static void ath10k_pci_dump_registers(struct ath10k *ar, __le32 reg_dump_values[REG_DUMP_COUNT_QCA988X] = {}; int i, ret; - lockdep_assert_held(&ar->data_lock); + lockdep_assert_held(&ar->dump_mutex); ret = ath10k_pci_diag_read_hi(ar, ®_dump_values[0], hi_failure_state, @@ -1858,7 +1858,7 @@ static void ath10k_pci_dump_memory(struct ath10k *ar, int ret, i; u8 *buf; - lockdep_assert_held(&ar->data_lock); + lockdep_assert_held(&ar->dump_mutex); if (!crash_data) return; @@ -2033,14 +2033,19 @@ static void ath10k_pci_dump_dbglog(struct ath10k *ar) } /* While we have a debug buffer to read */ } -static void ath10k_pci_fw_crashed_dump(struct ath10k *ar) +static void ath10k_pci_fw_dump_work(struct work_struct *work) { + struct ath10k_pci *ar_pci = container_of(work, struct ath10k_pci, + dump_work); struct ath10k_fw_crash_data *crash_data; + struct ath10k *ar = ar_pci->ar; char guid[UUID_STRING_LEN + 1]; - spin_lock_bh(&ar->data_lock); + mutex_lock(&ar->dump_mutex); + spin_lock_bh(&ar->data_lock); ar->stats.fw_crash_counter++; + spin_unlock_bh(&ar->data_lock); crash_data = ath10k_coredump_new(ar); @@ -2060,11 +2065,18 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar) ath10k_pci_dump_bss_ram(ar, crash_data); ath10k_pci_dump_bss_rom(ar, crash_data); - spin_unlock_bh(&ar->data_lock); + mutex_unlock(&ar->dump_mutex); queue_work(ar->workqueue, &ar->restart_work); } +static void ath10k_pci_fw_crashed_dump(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + queue_work(ar->workqueue, &ar_pci->dump_work); +} + void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, int force) { @@ -3785,6 +3797,8 @@ int ath10k_pci_setup_resource(struct ath10k *ar) spin_lock_init(&ar_pci->ps_lock); mutex_init(&ar_pci->ce_diag_mutex); + INIT_WORK(&ar_pci->dump_work, ath10k_pci_fw_dump_work); + timer_setup(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, 0); if (QCA_REV_6174(ar) || QCA_REV_9377(ar)) diff --git a/ath10k-5.1/pci.h b/ath10k-5.2/pci.h similarity index 99% rename from ath10k-5.1/pci.h rename to ath10k-5.2/pci.h index 3773c79..4455ed6 100644 --- a/ath10k-5.1/pci.h +++ b/ath10k-5.2/pci.h @@ -121,6 +121,8 @@ struct ath10k_pci { /* For protecting ce_diag */ struct mutex ce_diag_mutex; + struct work_struct dump_work; + struct ath10k_ce ce; struct timer_list rx_post_retry; diff --git a/ath10k-5.1/qmi.c b/ath10k-5.2/qmi.c similarity index 100% rename from ath10k-5.1/qmi.c rename to ath10k-5.2/qmi.c diff --git a/ath10k-5.1/qmi.h b/ath10k-5.2/qmi.h similarity index 100% rename from ath10k-5.1/qmi.h rename to ath10k-5.2/qmi.h diff --git a/ath10k-5.1/qmi_wlfw_v01.c b/ath10k-5.2/qmi_wlfw_v01.c similarity index 100% rename from ath10k-5.1/qmi_wlfw_v01.c rename to ath10k-5.2/qmi_wlfw_v01.c diff --git a/ath10k-5.1/qmi_wlfw_v01.h b/ath10k-5.2/qmi_wlfw_v01.h similarity index 100% rename from ath10k-5.1/qmi_wlfw_v01.h rename to ath10k-5.2/qmi_wlfw_v01.h diff --git a/ath10k-5.1/rx_desc.h b/ath10k-5.2/rx_desc.h similarity index 100% rename from ath10k-5.1/rx_desc.h rename to ath10k-5.2/rx_desc.h diff --git a/ath10k-5.1/sdio.c b/ath10k-5.2/sdio.c similarity index 100% rename from ath10k-5.1/sdio.c rename to ath10k-5.2/sdio.c diff --git a/ath10k-5.1/sdio.h b/ath10k-5.2/sdio.h similarity index 100% rename from ath10k-5.1/sdio.h rename to ath10k-5.2/sdio.h diff --git a/ath10k-5.1/snoc.c b/ath10k-5.2/snoc.c similarity index 100% rename from ath10k-5.1/snoc.c rename to ath10k-5.2/snoc.c diff --git a/ath10k-5.1/snoc.h b/ath10k-5.2/snoc.h similarity index 100% rename from ath10k-5.1/snoc.h rename to ath10k-5.2/snoc.h diff --git a/ath10k-5.1/spectral.c b/ath10k-5.2/spectral.c similarity index 100% rename from ath10k-5.1/spectral.c rename to ath10k-5.2/spectral.c diff --git a/ath10k-5.1/spectral.h b/ath10k-5.2/spectral.h similarity index 100% rename from ath10k-5.1/spectral.h rename to ath10k-5.2/spectral.h diff --git a/ath10k-5.1/swap.c b/ath10k-5.2/swap.c similarity index 100% rename from ath10k-5.1/swap.c rename to ath10k-5.2/swap.c diff --git a/ath10k-5.1/swap.h b/ath10k-5.2/swap.h similarity index 100% rename from ath10k-5.1/swap.h rename to ath10k-5.2/swap.h diff --git a/ath10k-5.1/targaddrs.h b/ath10k-5.2/targaddrs.h similarity index 100% rename from ath10k-5.1/targaddrs.h rename to ath10k-5.2/targaddrs.h diff --git a/ath10k-5.1/testmode.c b/ath10k-5.2/testmode.c similarity index 99% rename from ath10k-5.1/testmode.c rename to ath10k-5.2/testmode.c index 6433ff1..a29cfb9 100644 --- a/ath10k-5.1/testmode.c +++ b/ath10k-5.2/testmode.c @@ -416,8 +416,8 @@ int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct nlattr *tb[ATH10K_TM_ATTR_MAX + 1]; int ret; - ret = nla_parse(tb, ATH10K_TM_ATTR_MAX, data, len, ath10k_tm_policy, - NULL); + ret = nla_parse_deprecated(tb, ATH10K_TM_ATTR_MAX, data, len, + ath10k_tm_policy, NULL); if (ret) return ret; diff --git a/ath10k-5.1/testmode.h b/ath10k-5.2/testmode.h similarity index 100% rename from ath10k-5.1/testmode.h rename to ath10k-5.2/testmode.h diff --git a/ath10k-5.1/testmode_i.h b/ath10k-5.2/testmode_i.h similarity index 100% rename from ath10k-5.1/testmode_i.h rename to ath10k-5.2/testmode_i.h diff --git a/ath10k-5.1/thermal.c b/ath10k-5.2/thermal.c similarity index 100% rename from ath10k-5.1/thermal.c rename to ath10k-5.2/thermal.c diff --git a/ath10k-5.1/thermal.h b/ath10k-5.2/thermal.h similarity index 100% rename from ath10k-5.1/thermal.h rename to ath10k-5.2/thermal.h diff --git a/ath10k-5.1/trace.c b/ath10k-5.2/trace.c similarity index 100% rename from ath10k-5.1/trace.c rename to ath10k-5.2/trace.c diff --git a/ath10k-5.1/trace.h b/ath10k-5.2/trace.h similarity index 100% rename from ath10k-5.1/trace.h rename to ath10k-5.2/trace.h diff --git a/ath10k-5.1/txrx.c b/ath10k-5.2/txrx.c similarity index 100% rename from ath10k-5.1/txrx.c rename to ath10k-5.2/txrx.c diff --git a/ath10k-5.1/txrx.h b/ath10k-5.2/txrx.h similarity index 100% rename from ath10k-5.1/txrx.h rename to ath10k-5.2/txrx.h diff --git a/ath10k-5.1/usb.c b/ath10k-5.2/usb.c similarity index 100% rename from ath10k-5.1/usb.c rename to ath10k-5.2/usb.c diff --git a/ath10k-5.1/usb.h b/ath10k-5.2/usb.h similarity index 100% rename from ath10k-5.1/usb.h rename to ath10k-5.2/usb.h diff --git a/ath10k-5.1/wmi-ops.h b/ath10k-5.2/wmi-ops.h similarity index 100% rename from ath10k-5.1/wmi-ops.h rename to ath10k-5.2/wmi-ops.h diff --git a/ath10k-5.1/wmi-tlv.c b/ath10k-5.2/wmi-tlv.c similarity index 100% rename from ath10k-5.1/wmi-tlv.c rename to ath10k-5.2/wmi-tlv.c diff --git a/ath10k-5.1/wmi-tlv.h b/ath10k-5.2/wmi-tlv.h similarity index 100% rename from ath10k-5.1/wmi-tlv.h rename to ath10k-5.2/wmi-tlv.h diff --git a/ath10k-5.1/wmi.c b/ath10k-5.2/wmi.c similarity index 99% rename from ath10k-5.1/wmi.c rename to ath10k-5.2/wmi.c index 5b8133f..aa99cc0 100644 --- a/ath10k-5.1/wmi.c +++ b/ath10k-5.2/wmi.c @@ -3220,12 +3220,12 @@ ath10k_wmi_10_4_pull_peer_stats(const struct wmi_10_4_peer_stats *src, dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); /* Firmware stores these internally as 16 bits. CT firmware may pack * peer's TX PN into top 16 bits if the user has previously set the - * PN when setting a key. + * PN when setting a key or used the ct-special API to enable reporting PN. */ - dst->pn = __le32_to_cpu(src->num_pkt_loss_overflow[2]) >> 16; + dst->pn = __le32_to_cpu(src->num_pkt_loss_excess_retry[2]) >> 16; dst->pn <<= 32; - dst->pn |= (__le32_to_cpu(src->num_pkt_loss_overflow[1]) & 0xFFFF0000); - dst->pn |= __le32_to_cpu(src->num_pkt_loss_overflow[0]) >> 16; + dst->pn |= (__le32_to_cpu(src->num_pkt_loss_excess_retry[1]) & 0xFFFF0000); + dst->pn |= __le32_to_cpu(src->num_pkt_loss_excess_retry[0]) >> 16; } static void diff --git a/ath10k-5.1/wmi.h b/ath10k-5.2/wmi.h similarity index 99% rename from ath10k-5.1/wmi.h rename to ath10k-5.2/wmi.h index de1ffb2..eb79b3b 100644 --- a/ath10k-5.1/wmi.h +++ b/ath10k-5.2/wmi.h @@ -2100,7 +2100,9 @@ struct wmi_channel { union { __le32 reginfo1; struct { + /* note: power unit is 1 dBm */ u8 antenna_max; + /* note: power unit is 0.5 dBm */ u8 max_tx_power; } __packed; } __packed; @@ -2120,6 +2122,7 @@ struct wmi_channel_arg { u32 min_power; u32 max_power; u32 max_reg_power; + /* note: power unit is 1 dBm */ u32 max_antenna_gain; u32 reg_class_id; enum wmi_phy_mode mode; @@ -7349,8 +7352,13 @@ struct wmi_pdev_set_special_cmd { * (see 'peers' debugfs for peer id listing) * val = peer_id << 16 | ant-mask-value */ -#define SET_SPECIAL_ID_EEPROM_CFG_ADDR_A 0x14 /* Append an address to the configAddr in the eeprom. */ -#define SET_SPECIAL_ID_EEPROM_CFG_ADDR_V 0x15 /* Append an value to the configAddr in the eeprom. */ +#define SET_SPECIAL_ID_EEPROM_CFG_ADDR_A 0x14 /* Append an address to the configAddr in the eeprom. + * The mode should normally be OR'd in to the address. + */ +#define SET_SPECIAL_ID_EEPROM_CFG_ADDR_V 0x15 /* Append an value to the configAddr in the eeprom. Multiple values may + * be appended if the mode supports it. + */ +#define SET_SPECIAL_ID_PEER_STATS_PN 0x16 /* Report PN in peer-stats object */ /* Requires specially compiled firmware (-T option) to have any useful effect. */ #define SET_SPECIAL_ID_TX_DBG 0x99 /* 0x1 == enable, 0x2 == pkt-dbg, 0x0 == disable (default). */ diff --git a/ath10k-5.1/wow.c b/ath10k-5.2/wow.c similarity index 100% rename from ath10k-5.1/wow.c rename to ath10k-5.2/wow.c diff --git a/ath10k-5.1/wow.h b/ath10k-5.2/wow.h similarity index 100% rename from ath10k-5.1/wow.h rename to ath10k-5.2/wow.h diff --git a/refresh.bash b/refresh.bash index 90e1692..f5d3899 100755 --- a/refresh.bash +++ b/refresh.bash @@ -32,8 +32,8 @@ KVER=4.20 mkdir -p ./ath10k-$KVER cp -ar ~/git/linux-$KVER.dev.y/drivers/net/wireless/ath/ath10k/* ./ath10k-$KVER -# And for 5.1 kernel -KVER=5.1 +# And for 5.2 kernel +KVER=5.2 mkdir -p ./ath10k-$KVER cp -ar ~/git/linux-$KVER.dev.y/drivers/net/wireless/ath/ath10k/* ./ath10k-$KVER