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:
Kalle Valo 2018-03-29 15:55:28 +03:00
commit 14c99949a3
20 changed files with 580 additions and 150 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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);

View 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 */

View File

@ -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 {

View File

@ -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");

View File

@ -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 {

View File

@ -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);

View File

@ -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;

View File

@ -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++)

View File

@ -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;

View File

@ -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_ */

View File

@ -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

View File

@ -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)
{

View File

@ -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);
}