summaryrefslogtreecommitdiff
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorKalle Valo <kvalo@codeaurora.org>2018-03-29 15:55:28 +0300
committerKalle Valo <kvalo@codeaurora.org>2018-03-29 15:55:28 +0300
commit14c99949a3398a655c47b262ca8e2e83edfae7fd (patch)
tree769385b16a9b3a3057afaca2bc195120cc8a2bb6 /drivers/net/wireless
parent63f5be0a81e0c607255e8debab16e62670305fee (diff)
parenta72c92629108bb8ad756f31b74791c51e1de2af4 (diff)
downloadlinux-14c99949a3398a655c47b262ca8e2e83edfae7fd.tar.xz
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for 4.17. Major changes: ath10k * enable chip temperature measurement for QCA6174/QCA9377 * add firmware memory dump for QCA9984 * enable buffer STA on TDLS link for QCA6174 * support different beacon internals in multiple interface scenario for QCA988X/QCA99X0/QCA9984/QCA4019
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath.h2
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c6
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h21
-rw-r--r--drivers/net/wireless/ath/ath10k/coredump.c90
-rw-r--r--drivers/net/wireless/ath/ath10k/coredump.h2
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c42
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c16
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c99
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c94
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.h18
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c152
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h28
-rw-r--r--drivers/net/wireless/ath/ath5k/attach.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c11
-rw-r--r--drivers/net/wireless/ath/wcn36xx/dxe.c13
-rw-r--r--drivers/net/wireless/ath/wcn36xx/dxe.h3
-rw-r--r--drivers/net/wireless/ath/wcn36xx/main.c2
-rw-r--r--drivers/net/wireless/ath/wcn36xx/smd.c95
-rw-r--r--drivers/net/wireless/ath/wcn36xx/txrx.c32
20 files changed, 580 insertions, 150 deletions
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index f3f2784f6ebd..7a364eca46d6 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -33,8 +33,6 @@
*/
#define ATH_KEYMAX 128 /* max key cache size we handle */
-static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
struct ath_ani {
bool caldone;
unsigned int longcal_timer;
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 830b7fe466f3..8a3020dbd4cf 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2041,7 +2041,8 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS;
ar->num_tids = TARGET_10_4_TGT_NUM_TIDS;
ar->fw_stats_req_mask = WMI_10_4_STAT_PEER |
- WMI_10_4_STAT_PEER_EXTD;
+ WMI_10_4_STAT_PEER_EXTD |
+ WMI_10_4_STAT_VDEV_EXTD;
ar->max_spatial_stream = ar->hw_params.max_spatial_stream;
ar->max_num_tdls_vdevs = TARGET_10_4_NUM_TDLS_VDEVS;
@@ -2282,6 +2283,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
if (ath10k_peer_stats_enabled(ar))
val = WMI_10_4_PEER_STATS;
+ /* Enable vdev stats by default */
+ val |= WMI_10_4_VDEV_STATS;
+
if (test_bit(WMI_SERVICE_BSS_CHANNEL_INFO_64, ar->wmi.svc_map))
val |= WMI_10_4_BSS_CHANNEL_INFO_64;
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 73712c830be7..c17d805d68cc 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -222,6 +222,27 @@ struct ath10k_fw_stats_vdev {
u32 beacon_rssi_history[10];
};
+struct ath10k_fw_stats_vdev_extd {
+ struct list_head list;
+
+ u32 vdev_id;
+ u32 ppdu_aggr_cnt;
+ u32 ppdu_noack;
+ u32 mpdu_queued;
+ u32 ppdu_nonaggr_cnt;
+ u32 mpdu_sw_requeued;
+ u32 mpdu_suc_retry;
+ u32 mpdu_suc_multitry;
+ u32 mpdu_fail_retry;
+ u32 tx_ftm_suc;
+ u32 tx_ftm_suc_retry;
+ u32 tx_ftm_fail;
+ u32 rx_ftmr_cnt;
+ u32 rx_ftmr_dup_cnt;
+ u32 rx_iftmr_cnt;
+ u32 rx_iftmr_dup_cnt;
+};
+
struct ath10k_fw_stats_pdev {
struct list_head list;
diff --git a/drivers/net/wireless/ath/ath10k/coredump.c b/drivers/net/wireless/ath/ath10k/coredump.c
index 7173b3743b43..f90cec0ebb1c 100644
--- a/drivers/net/wireless/ath/ath10k/coredump.c
+++ b/drivers/net/wireless/ath/ath10k/coredump.c
@@ -701,6 +701,89 @@ static const struct ath10k_mem_region qca988x_hw20_mem_regions[] = {
},
};
+static const struct ath10k_mem_region qca9984_hw10_mem_regions[] = {
+ {
+ .type = ATH10K_MEM_REGION_TYPE_DRAM,
+ .start = 0x400000,
+ .len = 0x80000,
+ .name = "DRAM",
+ .section_table = {
+ .sections = NULL,
+ .size = 0,
+ },
+ },
+ {
+ .type = ATH10K_MEM_REGION_TYPE_REG,
+ .start = 0x98000,
+ .len = 0x50000,
+ .name = "IRAM",
+ .section_table = {
+ .sections = NULL,
+ .size = 0,
+ },
+ },
+ {
+ .type = ATH10K_MEM_REGION_TYPE_IOSRAM,
+ .start = 0xC0000,
+ .len = 0x40000,
+ .name = "SRAM",
+ .section_table = {
+ .sections = NULL,
+ .size = 0,
+ },
+ },
+ {
+ .type = ATH10K_MEM_REGION_TYPE_IOREG,
+ .start = 0x30000,
+ .len = 0x7000,
+ .name = "APB REG 1",
+ .section_table = {
+ .sections = NULL,
+ .size = 0,
+ },
+ },
+ {
+ .type = ATH10K_MEM_REGION_TYPE_IOREG,
+ .start = 0x3f000,
+ .len = 0x3000,
+ .name = "APB REG 2",
+ .section_table = {
+ .sections = NULL,
+ .size = 0,
+ },
+ },
+ {
+ .type = ATH10K_MEM_REGION_TYPE_IOREG,
+ .start = 0x43000,
+ .len = 0x3000,
+ .name = "WIFI REG",
+ .section_table = {
+ .sections = NULL,
+ .size = 0,
+ },
+ },
+ {
+ .type = ATH10K_MEM_REGION_TYPE_IOREG,
+ .start = 0x4A000,
+ .len = 0x5000,
+ .name = "CE REG",
+ .section_table = {
+ .sections = NULL,
+ .size = 0,
+ },
+ },
+ {
+ .type = ATH10K_MEM_REGION_TYPE_IOREG,
+ .start = 0x80000,
+ .len = 0x6000,
+ .name = "SOC REG",
+ .section_table = {
+ .sections = NULL,
+ .size = 0,
+ },
+ },
+};
+
static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
{
.hw_id = QCA6174_HW_1_0_VERSION,
@@ -758,6 +841,13 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
.size = ARRAY_SIZE(qca988x_hw20_mem_regions),
},
},
+ {
+ .hw_id = QCA9984_HW_1_0_DEV_VERSION,
+ .region_table = {
+ .regions = qca9984_hw10_mem_regions,
+ .size = ARRAY_SIZE(qca9984_hw10_mem_regions),
+ },
+ },
};
static u32 ath10k_coredump_get_ramdump_size(struct ath10k *ar)
diff --git a/drivers/net/wireless/ath/ath10k/coredump.h b/drivers/net/wireless/ath/ath10k/coredump.h
index bfee13038e59..3baaf9d2cbcd 100644
--- a/drivers/net/wireless/ath/ath10k/coredump.h
+++ b/drivers/net/wireless/ath/ath10k/coredump.h
@@ -124,6 +124,8 @@ enum ath10k_mem_region_type {
ATH10K_MEM_REGION_TYPE_AXI = 3,
ATH10K_MEM_REGION_TYPE_IRAM1 = 4,
ATH10K_MEM_REGION_TYPE_IRAM2 = 5,
+ ATH10K_MEM_REGION_TYPE_IOSRAM = 6,
+ ATH10K_MEM_REGION_TYPE_IOREG = 7,
};
/* Define a section of the region which should be copied. As not all parts
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 64996aba1485..5e02e26158f6 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -724,6 +724,28 @@ struct amsdu_subframe_hdr {
#define GROUP_ID_IS_SU_MIMO(x) ((x) == 0 || (x) == 63)
+static inline u8 ath10k_bw_to_mac80211_bw(u8 bw)
+{
+ u8 ret = 0;
+
+ switch (bw) {
+ case 0:
+ ret = RATE_INFO_BW_20;
+ break;
+ case 1:
+ ret = RATE_INFO_BW_40;
+ break;
+ case 2:
+ ret = RATE_INFO_BW_80;
+ break;
+ case 3:
+ ret = RATE_INFO_BW_160;
+ break;
+ }
+
+ return ret;
+}
+
static void ath10k_htt_rx_h_rates(struct ath10k *ar,
struct ieee80211_rx_status *status,
struct htt_rx_desc *rxd)
@@ -826,23 +848,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
if (sgi)
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
- switch (bw) {
- /* 20MHZ */
- case 0:
- break;
- /* 40MHZ */
- case 1:
- status->bw = RATE_INFO_BW_40;
- break;
- /* 80MHZ */
- case 2:
- status->bw = RATE_INFO_BW_80;
- break;
- case 3:
- status->bw = RATE_INFO_BW_160;
- break;
- }
-
+ status->bw = ath10k_bw_to_mac80211_bw(bw);
status->encoding = RX_ENC_VHT;
break;
default:
@@ -2550,7 +2556,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
arsta->txrate.nss = txrate.nss;
- arsta->txrate.bw = txrate.bw + RATE_INFO_BW_20;
+ arsta->txrate.bw = ath10k_bw_to_mac80211_bw(txrate.bw);
}
static void ath10k_htt_fetch_peer_stats(struct ath10k *ar,
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 02674ee04435..bf05a3689558 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2977,7 +2977,7 @@ static int ath10k_station_assoc(struct ath10k *ar,
}
/* Plumb cached keys only for static WEP */
- if (arvif->def_wep_key_idx != -1) {
+ if ((arvif->def_wep_key_idx != -1) && (!sta->tdls)) {
ret = ath10k_install_peer_wep_keys(arvif, sta->addr);
if (ret) {
ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n",
@@ -5932,6 +5932,10 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
ath10k_warn(ar, "Peer %pM disappeared!\n", peer_addr);
spin_unlock_bh(&ar->data_lock);
+ if (sta && sta->tdls)
+ ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
+ WMI_PEER_AUTHORIZE, 1);
+
exit:
mutex_unlock(&ar->conf_mutex);
return ret;
@@ -6046,9 +6050,8 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
sta->addr, smps, err);
}
- if (changed & IEEE80211_RC_SUPP_RATES_CHANGED ||
- changed & IEEE80211_RC_NSS_CHANGED) {
- ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates/nss\n",
+ if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
+ ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates\n",
sta->addr);
err = ath10k_station_assoc(ar, arvif->vif, sta, true);
@@ -7902,6 +7905,7 @@ static const struct ieee80211_iface_combination ath10k_10x_if_comb[] = {
.max_interfaces = 8,
.num_different_channels = 1,
.beacon_int_infra_match = true,
+ .beacon_int_min_gcd = 1,
#ifdef CONFIG_ATH10K_DFS_CERTIFIED
.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
BIT(NL80211_CHAN_WIDTH_20) |
@@ -8025,6 +8029,7 @@ static const struct ieee80211_iface_combination ath10k_10_4_if_comb[] = {
.max_interfaces = 16,
.num_different_channels = 1,
.beacon_int_infra_match = true,
+ .beacon_int_min_gcd = 1,
#ifdef CONFIG_ATH10K_DFS_CERTIFIED
.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
BIT(NL80211_CHAN_WIDTH_20) |
@@ -8326,6 +8331,9 @@ int ath10k_mac_register(struct ath10k *ar)
ieee80211_hw_set(ar->hw, TDLS_WIDER_BW);
}
+ if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map))
+ ieee80211_hw_set(ar->hw, SUPPORTS_TDLS_BUFFER_STA);
+
ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
ar->hw->wiphy->max_remain_on_channel_duration = 5000;
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 808f3d67ba90..fd1566cd7d2b 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -57,6 +57,10 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)");
*/
#define ATH10K_DIAG_TRANSFER_LIMIT 0x5000
+#define QCA99X0_PCIE_BAR0_START_REG 0x81030
+#define QCA99X0_CPU_MEM_ADDR_REG 0x4d00c
+#define QCA99X0_CPU_MEM_DATA_REG 0x4d010
+
static const struct pci_device_id ath10k_pci_id_table[] = {
/* PCI-E QCA988X V2 (Ubiquiti branded) */
{ PCI_VDEVICE(UBIQUITI, QCA988X_2_0_DEVICE_ID_UBNT) },
@@ -1584,6 +1588,69 @@ static int ath10k_pci_set_ram_config(struct ath10k *ar, u32 config)
return 0;
}
+/* if an error happened returns < 0, otherwise the length */
+static int ath10k_pci_dump_memory_sram(struct ath10k *ar,
+ const struct ath10k_mem_region *region,
+ u8 *buf)
+{
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+ u32 base_addr, i;
+
+ base_addr = ioread32(ar_pci->mem + QCA99X0_PCIE_BAR0_START_REG);
+ base_addr += region->start;
+
+ for (i = 0; i < region->len; i += 4) {
+ iowrite32(base_addr + i, ar_pci->mem + QCA99X0_CPU_MEM_ADDR_REG);
+ *(u32 *)(buf + i) = ioread32(ar_pci->mem + QCA99X0_CPU_MEM_DATA_REG);
+ }
+
+ return region->len;
+}
+
+/* if an error happened returns < 0, otherwise the length */
+static int ath10k_pci_dump_memory_reg(struct ath10k *ar,
+ const struct ath10k_mem_region *region,
+ u8 *buf)
+{
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+ u32 i;
+
+ for (i = 0; i < region->len; i += 4)
+ *(u32 *)(buf + i) = ioread32(ar_pci->mem + region->start + i);
+
+ return region->len;
+}
+
+/* if an error happened returns < 0, otherwise the length */
+static int ath10k_pci_dump_memory_generic(struct ath10k *ar,
+ const struct ath10k_mem_region *current_region,
+ u8 *buf)
+{
+ int ret;
+
+ if (current_region->section_table.size > 0)
+ /* Copy each section individually. */
+ return ath10k_pci_dump_memory_section(ar,
+ current_region,
+ buf,
+ current_region->len);
+
+ /* No individiual memory sections defined so we can
+ * copy the entire memory region.
+ */
+ ret = ath10k_pci_diag_read_mem(ar,
+ current_region->start,
+ buf,
+ current_region->len);
+ if (ret) {
+ ath10k_warn(ar, "failed to copy ramdump region %s: %d\n",
+ current_region->name, ret);
+ return ret;
+ }
+
+ return current_region->len;
+}
+
static void ath10k_pci_dump_memory(struct ath10k *ar,
struct ath10k_fw_crash_data *crash_data)
{
@@ -1642,27 +1709,20 @@ static void ath10k_pci_dump_memory(struct ath10k *ar,
buf += sizeof(*hdr);
buf_len -= sizeof(*hdr);
- if (current_region->section_table.size > 0) {
- /* Copy each section individually. */
- count = ath10k_pci_dump_memory_section(ar,
- current_region,
- buf,
- current_region->len);
- } else {
- /* No individiual memory sections defined so we can
- * copy the entire memory region.
- */
- ret = ath10k_pci_diag_read_mem(ar,
- current_region->start,
- buf,
- current_region->len);
- if (ret) {
- ath10k_warn(ar, "failed to copy ramdump region %s: %d\n",
- current_region->name, ret);
+ switch (current_region->type) {
+ case ATH10K_MEM_REGION_TYPE_IOSRAM:
+ count = ath10k_pci_dump_memory_sram(ar, current_region, buf);
+ break;
+ case ATH10K_MEM_REGION_TYPE_IOREG:
+ count = ath10k_pci_dump_memory_reg(ar, current_region, buf);
+ break;
+ default:
+ ret = ath10k_pci_dump_memory_generic(ar, current_region, buf);
+ if (ret < 0)
break;
- }
- count = current_region->len;
+ count = ret;
+ break;
}
hdr->region_type = cpu_to_le32(current_region->type);
@@ -3718,5 +3778,6 @@ MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" QCA6174_HW_3_0_BOARD_DATA_FILE);
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_BOARD_API2_FILE);
/* QCA9377 1.0 firmware files */
+MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" ATH10K_FW_API6_FILE);
MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" ATH10K_FW_API5_FILE);
MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" QCA9377_HW_1_0_BOARD_DATA_FILE);
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index 523af3f8bb62..9d1b0a459069 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -413,6 +413,62 @@ static int ath10k_wmi_tlv_event_tx_pause(struct ath10k *ar,
return 0;
}
+static int ath10k_wmi_tlv_event_temperature(struct ath10k *ar,
+ struct sk_buff *skb)
+{
+ const struct wmi_tlv_pdev_temperature_event *ev;
+
+ ev = (struct wmi_tlv_pdev_temperature_event *)skb->data;
+ if (WARN_ON(skb->len < sizeof(*ev)))
+ return -EPROTO;
+
+ ath10k_thermal_event_temperature(ar, __le32_to_cpu(ev->temperature));
+ return 0;
+}
+
+static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb)
+{
+ struct ieee80211_sta *station;
+ const struct wmi_tlv_tdls_peer_event *ev;
+ const void **tb;
+ struct ath10k_vif *arvif;
+
+ tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
+ if (IS_ERR(tb)) {
+ ath10k_warn(ar, "tdls peer failed to parse tlv");
+ return;
+ }
+ ev = tb[WMI_TLV_TAG_STRUCT_TDLS_PEER_EVENT];
+ if (!ev) {
+ kfree(tb);
+ ath10k_warn(ar, "tdls peer NULL event");
+ return;
+ }
+
+ switch (__le32_to_cpu(ev->peer_reason)) {
+ case WMI_TDLS_TEARDOWN_REASON_TX:
+ case WMI_TDLS_TEARDOWN_REASON_RSSI:
+ case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
+ station = ieee80211_find_sta_by_ifaddr(ar->hw,
+ ev->peer_macaddr.addr,
+ NULL);
+ if (!station) {
+ ath10k_warn(ar, "did not find station from tdls peer event");
+ kfree(tb);
+ return;
+ }
+ arvif = ath10k_get_arvif(ar, __le32_to_cpu(ev->vdev_id));
+ ieee80211_tdls_oper_request(
+ arvif->vif, station->addr,
+ NL80211_TDLS_TEARDOWN,
+ WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE,
+ GFP_ATOMIC
+ );
+ break;
+ }
+ kfree(tb);
+}
+
/***********/
/* TLV ops */
/***********/
@@ -553,6 +609,12 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
case WMI_TLV_TX_PAUSE_EVENTID:
ath10k_wmi_tlv_event_tx_pause(ar, skb);
break;
+ case WMI_TLV_PDEV_TEMPERATURE_EVENTID:
+ ath10k_wmi_tlv_event_temperature(ar, skb);
+ break;
+ case WMI_TLV_TDLS_PEER_EVENTID:
+ ath10k_wmi_event_tdls_peer(ar, skb);
+ break;
default:
ath10k_warn(ar, "Unknown eventid: %d\n", id);
break;
@@ -2658,6 +2720,25 @@ ath10k_wmi_tlv_op_gen_pktlog_enable(struct ath10k *ar, u32 filter)
}
static struct sk_buff *
+ath10k_wmi_tlv_op_gen_pdev_get_temperature(struct ath10k *ar)
+{
+ struct wmi_tlv_pdev_get_temp_cmd *cmd;
+ struct wmi_tlv *tlv;
+ struct sk_buff *skb;
+
+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
+ if (!skb)
+ return ERR_PTR(-ENOMEM);
+
+ tlv = (void *)skb->data;
+ tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_GET_TEMPERATURE_CMD);
+ tlv->len = __cpu_to_le16(sizeof(*cmd));
+ cmd = (void *)tlv->value;
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi pdev get temperature tlv\n");
+ return skb;
+}
+
+static struct sk_buff *
ath10k_wmi_tlv_op_gen_pktlog_disable(struct ath10k *ar)
{
struct wmi_tlv_pktlog_disable *cmd;
@@ -2851,6 +2932,15 @@ ath10k_wmi_tlv_op_gen_update_fw_tdls_state(struct ath10k *ar, u32 vdev_id,
*/
u32 options = 0;
+ if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map))
+ options |= WMI_TLV_TDLS_BUFFER_STA_EN;
+
+ /* WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL means firm will handle TDLS
+ * link inactivity detecting logic.
+ */
+ if (state == WMI_TDLS_ENABLE_ACTIVE)
+ state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
+
len = sizeof(*tlv) + sizeof(*cmd);
skb = ath10k_wmi_alloc_skb(ar, len);
if (!skb)
@@ -3439,7 +3529,7 @@ static struct wmi_cmd_map wmi_tlv_cmd_map = {
.force_fw_hang_cmdid = WMI_TLV_FORCE_FW_HANG_CMDID,
.gpio_config_cmdid = WMI_TLV_GPIO_CONFIG_CMDID,
.gpio_output_cmdid = WMI_TLV_GPIO_OUTPUT_CMDID,
- .pdev_get_temperature_cmdid = WMI_TLV_CMD_UNSUPPORTED,
+ .pdev_get_temperature_cmdid = WMI_TLV_PDEV_GET_TEMPERATURE_CMDID,
.vdev_set_wmm_params_cmdid = WMI_TLV_VDEV_SET_WMM_PARAMS_CMDID,
.tdls_set_state_cmdid = WMI_TLV_TDLS_SET_STATE_CMDID,
.tdls_peer_update_cmdid = WMI_TLV_TDLS_PEER_UPDATE_CMDID,
@@ -3702,7 +3792,7 @@ static const struct wmi_ops wmi_tlv_ops = {
.gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable,
.gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable,
/* .gen_pdev_set_quiet_mode not implemented */
- /* .gen_pdev_get_temperature not implemented */
+ .gen_pdev_get_temperature = ath10k_wmi_tlv_op_gen_pdev_get_temperature,
/* .gen_addba_clear_resp not implemented */
/* .gen_addba_send not implemented */
/* .gen_addba_set_resp not implemented */
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
index da89128e8dd6..fa3773ec7c68 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -1340,6 +1340,17 @@ struct wmi_tlv_init_cmd {
__le32 num_host_mem_chunks;
} __packed;
+struct wmi_tlv_pdev_get_temp_cmd {
+ __le32 pdev_id; /* not used */
+} __packed;
+
+struct wmi_tlv_pdev_temperature_event {
+ __le32 tlv_hdr;
+ /* temperature value in Celcius degree */
+ __le32 temperature;
+ __le32 pdev_id;
+} __packed;
+
struct wmi_tlv_pdev_set_param_cmd {
__le32 pdev_id; /* not used yet */
__le32 param_id;
@@ -1746,6 +1757,13 @@ struct wmi_tlv_tx_pause_ev {
__le32 tid_map;
} __packed;
+struct wmi_tlv_tdls_peer_event {
+ struct wmi_mac_addr peer_macaddr;
+ __le32 peer_status;
+ __le32 peer_reason;
+ __le32 vdev_id;
+} __packed;
+
void ath10k_wmi_tlv_attach(struct ath10k *ar);
struct wmi_tlv_mgmt_tx_cmd {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 9649bb752bbd..c5e1ca5945db 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2708,6 +2708,28 @@ 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);
}
+static void
+ath10k_wmi_10_4_pull_vdev_stats(const struct wmi_vdev_stats_extd *src,
+ struct ath10k_fw_stats_vdev_extd *dst)
+{
+ dst->vdev_id = __le32_to_cpu(src->vdev_id);
+ dst->ppdu_aggr_cnt = __le32_to_cpu(src->ppdu_aggr_cnt);
+ dst->ppdu_noack = __le32_to_cpu(src->ppdu_noack);
+ dst->mpdu_queued = __le32_to_cpu(src->mpdu_queued);
+ dst->ppdu_nonaggr_cnt = __le32_to_cpu(src->ppdu_nonaggr_cnt);
+ dst->mpdu_sw_requeued = __le32_to_cpu(src->mpdu_sw_requeued);
+ dst->mpdu_suc_retry = __le32_to_cpu(src->mpdu_suc_retry);
+ dst->mpdu_suc_multitry = __le32_to_cpu(src->mpdu_suc_multitry);
+ dst->mpdu_fail_retry = __le32_to_cpu(src->mpdu_fail_retry);
+ dst->tx_ftm_suc = __le32_to_cpu(src->tx_ftm_suc);
+ dst->tx_ftm_suc_retry = __le32_to_cpu(src->tx_ftm_suc_retry);
+ dst->tx_ftm_fail = __le32_to_cpu(src->tx_ftm_fail);
+ dst->rx_ftmr_cnt = __le32_to_cpu(src->rx_ftmr_cnt);
+ dst->rx_ftmr_dup_cnt = __le32_to_cpu(src->rx_ftmr_dup_cnt);
+ dst->rx_iftmr_cnt = __le32_to_cpu(src->rx_iftmr_cnt);
+ dst->rx_iftmr_dup_cnt = __le32_to_cpu(src->rx_iftmr_dup_cnt);
+}
+
static int ath10k_wmi_main_op_pull_fw_stats(struct ath10k *ar,
struct sk_buff *skb,
struct ath10k_fw_stats *stats)
@@ -3047,7 +3069,16 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
*/
}
- /* fw doesn't implement vdev stats */
+ for (i = 0; i < num_vdev_stats; i++) {
+ const struct wmi_vdev_stats *src;
+
+ /* Ignore vdev stats here as it has only vdev id. Actual vdev
+ * stats will be retrieved from vdev extended stats.
+ */
+ src = (void *)skb->data;
+ if (!skb_pull(skb, sizeof(*src)))
+ return -EPROTO;
+ }
for (i = 0; i < num_peer_stats; i++) {
const struct wmi_10_4_peer_stats *src;
@@ -3079,26 +3110,43 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
*/
}
- if ((stats_id & WMI_10_4_STAT_PEER_EXTD) == 0)
- return 0;
+ if (stats_id & WMI_10_4_STAT_PEER_EXTD) {
+ stats->extended = true;
- stats->extended = true;
+ for (i = 0; i < num_peer_stats; i++) {
+ const struct wmi_10_4_peer_extd_stats *src;
+ struct ath10k_fw_extd_stats_peer *dst;
- for (i = 0; i < num_peer_stats; i++) {
- const struct wmi_10_4_peer_extd_stats *src;
- struct ath10k_fw_extd_stats_peer *dst;
+ src = (void *)skb->data;
+ if (!skb_pull(skb, sizeof(*src)))
+ return -EPROTO;
- src = (void *)skb->data;
- if (!skb_pull(skb, sizeof(*src)))
- return -EPROTO;
+ dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ if (!dst)
+ continue;
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
- if (!dst)
- continue;
+ ether_addr_copy(dst->peer_macaddr,
+ src->peer_macaddr.addr);
+ dst->rx_duration = __le32_to_cpu(src->rx_duration);
+ list_add_tail(&dst->list, &stats->peers_extd);
+ }
+ }
- ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
- dst->rx_duration = __le32_to_cpu(src->rx_duration);
- list_add_tail(&dst->list, &stats->peers_extd);
+ if (stats_id & WMI_10_4_STAT_VDEV_EXTD) {
+ for (i = 0; i < num_vdev_stats; i++) {
+ const struct wmi_vdev_stats_extd *src;
+ struct ath10k_fw_stats_vdev_extd *dst;
+
+ src = (void *)skb->data;
+ if (!skb_pull(skb, sizeof(*src)))
+ return -EPROTO;
+
+ dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ if (!dst)
+ continue;
+ ath10k_wmi_10_4_pull_vdev_stats(src, dst);
+ list_add_tail(&dst->list, &stats->vdevs);
+ }
}
return 0;
@@ -5786,6 +5834,7 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
case WMI_10_4_WOW_WAKEUP_HOST_EVENTID:
case WMI_10_4_PEER_RATECODE_LIST_EVENTID:
case WMI_10_4_WDS_PEER_EVENTID:
+ case WMI_10_4_DEBUG_FATAL_CONDITION_EVENTID:
ath10k_dbg(ar, ATH10K_DBG_WMI,
"received event id %d not implemented\n", id);
break;
@@ -8003,6 +8052,72 @@ ath10k_wmi_op_gen_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable,
return skb;
}
+static void
+ath10k_wmi_fw_vdev_stats_extd_fill(const struct ath10k_fw_stats_vdev_extd *vdev,
+ char *buf, u32 *length)
+{
+ u32 len = *length;
+ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
+ u32 val;
+
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "vdev id", vdev->vdev_id);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "ppdu aggr count", vdev->ppdu_aggr_cnt);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "ppdu noack", vdev->ppdu_noack);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "mpdu queued", vdev->mpdu_queued);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "ppdu nonaggr count", vdev->ppdu_nonaggr_cnt);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "mpdu sw requeued", vdev->mpdu_sw_requeued);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "mpdu success retry", vdev->mpdu_suc_retry);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "mpdu success multitry", vdev->mpdu_suc_multitry);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "mpdu fail retry", vdev->mpdu_fail_retry);
+ val = vdev->tx_ftm_suc;
+ if (val & WMI_VDEV_STATS_FTM_COUNT_VALID)
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "tx ftm success",
+ MS(val, WMI_VDEV_STATS_FTM_COUNT));
+ val = vdev->tx_ftm_suc_retry;
+ if (val & WMI_VDEV_STATS_FTM_COUNT_VALID)
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "tx ftm success retry",
+ MS(val, WMI_VDEV_STATS_FTM_COUNT));
+ val = vdev->tx_ftm_fail;
+ if (val & WMI_VDEV_STATS_FTM_COUNT_VALID)
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "tx ftm fail",
+ MS(val, WMI_VDEV_STATS_FTM_COUNT));
+ val = vdev->rx_ftmr_cnt;
+ if (val & WMI_VDEV_STATS_FTM_COUNT_VALID)
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "rx ftm request count",
+ MS(val, WMI_VDEV_STATS_FTM_COUNT));
+ val = vdev->rx_ftmr_dup_cnt;
+ if (val & WMI_VDEV_STATS_FTM_COUNT_VALID)
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "rx ftm request dup count",
+ MS(val, WMI_VDEV_STATS_FTM_COUNT));
+ val = vdev->rx_iftmr_cnt;
+ if (val & WMI_VDEV_STATS_FTM_COUNT_VALID)
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "rx initial ftm req count",
+ MS(val, WMI_VDEV_STATS_FTM_COUNT));
+ val = vdev->rx_iftmr_dup_cnt;
+ if (val & WMI_VDEV_STATS_FTM_COUNT_VALID)
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "rx initial ftm req dup cnt",
+ MS(val, WMI_VDEV_STATS_FTM_COUNT));
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ *length = len;
+}
+
void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
struct ath10k_fw_stats *fw_stats,
char *buf)
@@ -8010,7 +8125,7 @@ void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
u32 len = 0;
u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
const struct ath10k_fw_stats_pdev *pdev;
- const struct ath10k_fw_stats_vdev *vdev;
+ const struct ath10k_fw_stats_vdev_extd *vdev;
const struct ath10k_fw_stats_peer *peer;
size_t num_peers;
size_t num_vdevs;
@@ -8063,9 +8178,8 @@ void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
"ath10k VDEV stats", num_vdevs);
len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
"=================");
-
list_for_each_entry(vdev, &fw_stats->vdevs, list) {
- ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len);
+ ath10k_wmi_fw_vdev_stats_extd_fill(vdev, buf, &len);
}
len += scnprintf(buf + len, buf_len - len, "\n");
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index c8fc45d8090e..6fbc84c29521 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -4413,6 +4413,7 @@ enum wmi_10_4_stats_id {
WMI_10_4_STAT_AP = BIT(1),
WMI_10_4_STAT_INST = BIT(2),
WMI_10_4_STAT_PEER_EXTD = BIT(3),
+ WMI_10_4_STAT_VDEV_EXTD = BIT(4),
};
struct wlan_inst_rssi_args {
@@ -4552,12 +4553,36 @@ struct wmi_10_4_pdev_stats {
/*
* VDEV statistics
- * TODO: add all VDEV stats here
*/
+
+#define WMI_VDEV_STATS_FTM_COUNT_VALID BIT(31)
+#define WMI_VDEV_STATS_FTM_COUNT_LSB 0
+#define WMI_VDEV_STATS_FTM_COUNT_MASK 0x7fffffff
+
struct wmi_vdev_stats {
__le32 vdev_id;
} __packed;
+struct wmi_vdev_stats_extd {
+ __le32 vdev_id;
+ __le32 ppdu_aggr_cnt;
+ __le32 ppdu_noack;
+ __le32 mpdu_queued;
+ __le32 ppdu_nonaggr_cnt;
+ __le32 mpdu_sw_requeued;
+ __le32 mpdu_suc_retry;
+ __le32 mpdu_suc_multitry;
+ __le32 mpdu_fail_retry;
+ __le32 tx_ftm_suc;
+ __le32 tx_ftm_suc_retry;
+ __le32 tx_ftm_fail;
+ __le32 rx_ftmr_cnt;
+ __le32 rx_ftmr_dup_cnt;
+ __le32 rx_iftmr_cnt;
+ __le32 rx_iftmr_dup_cnt;
+ __le32 reserved[6];
+} __packed;
+
/*
* peer statistics.
* TODO: add more stats
@@ -6792,6 +6817,7 @@ enum wmi_tdls_state {
WMI_TDLS_DISABLE,
WMI_TDLS_ENABLE_PASSIVE,
WMI_TDLS_ENABLE_ACTIVE,
+ WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL,
};
enum wmi_tdls_peer_state {
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index 233054bd6b52..12d3a6c92ba4 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -327,7 +327,7 @@ int ath5k_hw_init(struct ath5k_hw *ah)
ath5k_hw_set_lladdr(ah, zero_mac);
/* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
- memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN);
+ eth_broadcast_addr(common->curbssid);
ath5k_hw_set_bssid(ah);
ath5k_hw_set_opmode(ah, ah->opmode);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index f246e9ed4a81..214c68269a69 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -591,7 +591,7 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv)
{
struct ath_common *common = ath9k_hw_common(priv->ah);
- memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
+ eth_broadcast_addr(common->bssidmask);
common->last_rssi = ATH_RSSI_DUMMY_MARKER;
priv->ah->opmode = NL80211_IFTYPE_STATION;
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index e479fae5aab9..c070a9e51ebf 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -257,6 +257,11 @@ static void ath9k_reg_notifier(struct wiphy *wiphy,
ath_reg_notifier_apply(wiphy, request, reg);
+ /* synchronize DFS detector if regulatory domain changed */
+ if (sc->dfs_detector != NULL)
+ sc->dfs_detector->set_dfs_domain(sc->dfs_detector,
+ request->dfs_region);
+
/* Set tx power */
if (!ah->curchan)
return;
@@ -267,10 +272,6 @@ static void ath9k_reg_notifier(struct wiphy *wiphy,
ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower,
sc->cur_chan->txpower,
&sc->cur_chan->cur_txpower);
- /* synchronize DFS detector if regulatory domain changed */
- if (sc->dfs_detector != NULL)
- sc->dfs_detector->set_dfs_domain(sc->dfs_detector,
- request->dfs_region);
ath9k_ps_restore(sc);
}
@@ -427,7 +428,7 @@ static void ath9k_init_misc(struct ath_softc *sc)
timer_setup(&common->ani.timer, ath_ani_calibrate, 0);
common->last_rssi = ATH_RSSI_DUMMY_MARKER;
- memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
+ eth_broadcast_addr(common->bssidmask);
sc->beacon.slottime = 9;
for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c
index 7d5ecaf02288..2c3b899a88fa 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -27,15 +27,6 @@
#include "wcn36xx.h"
#include "txrx.h"
-void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low)
-{
- struct wcn36xx_dxe_ch *ch = is_low ?
- &wcn->dxe_tx_l_ch :
- &wcn->dxe_tx_h_ch;
-
- return ch->head_blk_ctl->bd_cpu_addr;
-}
-
static void wcn36xx_ccu_write_register(struct wcn36xx *wcn, int addr, int data)
{
wcn36xx_dbg(WCN36XX_DBG_DXE,
@@ -648,6 +639,7 @@ void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn)
int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
struct wcn36xx_vif *vif_priv,
+ struct wcn36xx_tx_bd *bd,
struct sk_buff *skb,
bool is_low)
{
@@ -681,6 +673,9 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
ctl->skb = NULL;
desc = ctl->desc;
+ /* write buffer descriptor */
+ memcpy(ctl->bd_cpu_addr, bd, sizeof(*bd));
+
/* Set source address of the BD we send */
desc->src_addr_l = ctl->bd_phy_addr;
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h
index 2bc376c5391b..ce580960d109 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.h
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.h
@@ -452,6 +452,7 @@ struct wcn36xx_dxe_mem_pool {
dma_addr_t phy_addr;
};
+struct wcn36xx_tx_bd;
struct wcn36xx_vif;
int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn);
void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn);
@@ -463,8 +464,8 @@ void wcn36xx_dxe_deinit(struct wcn36xx *wcn);
int wcn36xx_dxe_init_channels(struct wcn36xx *wcn);
int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
struct wcn36xx_vif *vif_priv,
+ struct wcn36xx_tx_bd *bd,
struct sk_buff *skb,
bool is_low);
void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status);
-void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low);
#endif /* _DXE_H_ */
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 621e72b6ec99..69d6be59d97f 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -1152,8 +1152,6 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
wcn->hw->wiphy->cipher_suites = cipher_suites;
wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
- wcn->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
-
#ifdef CONFIG_PM
wcn->hw->wiphy->wowlan = &wowlan_support;
#endif
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index def6b23b777f..8932af5e4d8d 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2411,54 +2411,63 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
{
struct wcn36xx *wcn =
container_of(work, struct wcn36xx, hal_ind_work);
- struct wcn36xx_hal_msg_header *msg_header;
- struct wcn36xx_hal_ind_msg *hal_ind_msg;
- unsigned long flags;
- spin_lock_irqsave(&wcn->hal_ind_lock, flags);
+ for (;;) {
+ struct wcn36xx_hal_msg_header *msg_header;
+ struct wcn36xx_hal_ind_msg *hal_ind_msg;
+ unsigned long flags;
- hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
- struct wcn36xx_hal_ind_msg,
- list);
- list_del(wcn->hal_ind_queue.next);
- spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
+ spin_lock_irqsave(&wcn->hal_ind_lock, flags);
- msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
+ if (list_empty(&wcn->hal_ind_queue)) {
+ spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
+ return;
+ }
- switch (msg_header->msg_type) {
- case WCN36XX_HAL_COEX_IND:
- case WCN36XX_HAL_DEL_BA_IND:
- case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
- break;
- case WCN36XX_HAL_OTA_TX_COMPL_IND:
- wcn36xx_smd_tx_compl_ind(wcn,
- hal_ind_msg->msg,
- hal_ind_msg->msg_len);
- break;
- case WCN36XX_HAL_MISSED_BEACON_IND:
- wcn36xx_smd_missed_beacon_ind(wcn,
- hal_ind_msg->msg,
- hal_ind_msg->msg_len);
- break;
- case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
- wcn36xx_smd_delete_sta_context_ind(wcn,
- hal_ind_msg->msg,
- hal_ind_msg->msg_len);
- break;
- case WCN36XX_HAL_PRINT_REG_INFO_IND:
- wcn36xx_smd_print_reg_info_ind(wcn,
- hal_ind_msg->msg,
- hal_ind_msg->msg_len);
- break;
- case WCN36XX_HAL_SCAN_OFFLOAD_IND:
- wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg,
- hal_ind_msg->msg_len);
- break;
- default:
- wcn36xx_err("SMD_EVENT (%d) not supported\n",
- msg_header->msg_type);
+ hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
+ struct wcn36xx_hal_ind_msg,
+ list);
+ list_del(&hal_ind_msg->list);
+ spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
+
+ msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
+
+ switch (msg_header->msg_type) {
+ case WCN36XX_HAL_COEX_IND:
+ case WCN36XX_HAL_DEL_BA_IND:
+ case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
+ break;
+ case WCN36XX_HAL_OTA_TX_COMPL_IND:
+ wcn36xx_smd_tx_compl_ind(wcn,
+ hal_ind_msg->msg,
+ hal_ind_msg->msg_len);
+ break;
+ case WCN36XX_HAL_MISSED_BEACON_IND:
+ wcn36xx_smd_missed_beacon_ind(wcn,
+ hal_ind_msg->msg,
+ hal_ind_msg->msg_len);
+ break;
+ case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
+ wcn36xx_smd_delete_sta_context_ind(wcn,
+ hal_ind_msg->msg,
+ hal_ind_msg->msg_len);
+ break;
+ case WCN36XX_HAL_PRINT_REG_INFO_IND:
+ wcn36xx_smd_print_reg_info_ind(wcn,
+ hal_ind_msg->msg,
+ hal_ind_msg->msg_len);
+ break;
+ case WCN36XX_HAL_SCAN_OFFLOAD_IND:
+ wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg,
+ hal_ind_msg->msg_len);
+ break;
+ default:
+ wcn36xx_err("SMD_EVENT (%d) not supported\n",
+ msg_header->msg_type);
+ }
+
+ kfree(hal_ind_msg);
}
- kfree(hal_ind_msg);
}
int wcn36xx_smd_open(struct wcn36xx *wcn)
{
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c
index 22304edc5948..b1768ed6b0be 100644
--- a/drivers/net/wireless/ath/wcn36xx/txrx.c
+++ b/drivers/net/wireless/ath/wcn36xx/txrx.c
@@ -272,21 +272,9 @@ int wcn36xx_start_tx(struct wcn36xx *wcn,
bool is_low = ieee80211_is_data(hdr->frame_control);
bool bcast = is_broadcast_ether_addr(hdr->addr1) ||
is_multicast_ether_addr(hdr->addr1);
- struct wcn36xx_tx_bd *bd = wcn36xx_dxe_get_next_bd(wcn, is_low);
-
- if (!bd) {
- /*
- * TX DXE are used in pairs. One for the BD and one for the
- * actual frame. The BD DXE's has a preallocated buffer while
- * the skb ones does not. If this isn't true something is really
- * wierd. TODO: Recover from this situation
- */
-
- wcn36xx_err("bd address may not be NULL for BD DXE\n");
- return -EINVAL;
- }
+ struct wcn36xx_tx_bd bd;
- memset(bd, 0, sizeof(*bd));
+ memset(&bd, 0, sizeof(bd));
wcn36xx_dbg(WCN36XX_DBG_TX,
"tx skb %p len %d fc %04x sn %d %s %s\n",
@@ -296,10 +284,10 @@ int wcn36xx_start_tx(struct wcn36xx *wcn,
wcn36xx_dbg_dump(WCN36XX_DBG_TX_DUMP, "", skb->data, skb->len);
- bd->dpu_rf = WCN36XX_BMU_WQ_TX;
+ bd.dpu_rf = WCN36XX_BMU_WQ_TX;
- bd->tx_comp = !!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS);
- if (bd->tx_comp) {
+ bd.tx_comp = !!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS);
+ if (bd.tx_comp) {
wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n");
spin_lock_irqsave(&wcn->dxe_lock, flags);
if (wcn->tx_ack_skb) {
@@ -321,13 +309,13 @@ int wcn36xx_start_tx(struct wcn36xx *wcn,
/* Data frames served first*/
if (is_low)
- wcn36xx_set_tx_data(bd, wcn, &vif_priv, sta_priv, skb, bcast);
+ wcn36xx_set_tx_data(&bd, wcn, &vif_priv, sta_priv, skb, bcast);
else
/* MGMT and CTRL frames are handeld here*/
- wcn36xx_set_tx_mgmt(bd, wcn, &vif_priv, skb, bcast);
+ wcn36xx_set_tx_mgmt(&bd, wcn, &vif_priv, skb, bcast);
- buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32));
- bd->tx_bd_sign = 0xbdbdbdbd;
+ buff_to_be((u32 *)&bd, sizeof(bd)/sizeof(u32));
+ bd.tx_bd_sign = 0xbdbdbdbd;
- return wcn36xx_dxe_tx_frame(wcn, vif_priv, skb, is_low);
+ return wcn36xx_dxe_tx_frame(wcn, vif_priv, &bd, skb, is_low);
}