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
This commit is contained in:
commit
14c99949a3
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -2657,6 +2719,25 @@ ath10k_wmi_tlv_op_gen_pktlog_enable(struct ath10k *ar, u32 filter)
|
|||
return skb;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
struct wcn36xx_tx_bd bd;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue