Commit 9e4b4269 authored by John W. Linville's avatar John W. Linville

Merge branch 'for-linville' of git://github.com/kvalo/ath

parents 161d7855 9797febc
...@@ -63,7 +63,7 @@ enum ath_bus_type { ...@@ -63,7 +63,7 @@ enum ath_bus_type {
}; };
struct reg_dmn_pair_mapping { struct reg_dmn_pair_mapping {
u16 regDmnEnum; u16 reg_domain;
u16 reg_5ghz_ctl; u16 reg_5ghz_ctl;
u16 reg_2ghz_ctl; u16 reg_2ghz_ctl;
}; };
......
...@@ -55,8 +55,7 @@ static void ath10k_send_suspend_complete(struct ath10k *ar) ...@@ -55,8 +55,7 @@ static void ath10k_send_suspend_complete(struct ath10k *ar)
{ {
ath10k_dbg(ATH10K_DBG_BOOT, "boot suspend complete\n"); ath10k_dbg(ATH10K_DBG_BOOT, "boot suspend complete\n");
ar->is_target_paused = true; complete(&ar->target_suspend);
wake_up(&ar->event_queue);
} }
static int ath10k_init_connect_htc(struct ath10k *ar) static int ath10k_init_connect_htc(struct ath10k *ar)
...@@ -470,8 +469,12 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) ...@@ -470,8 +469,12 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
if (index == ie_len) if (index == ie_len)
break; break;
if (data[index] & (1 << bit)) if (data[index] & (1 << bit)) {
ath10k_dbg(ATH10K_DBG_BOOT,
"Enabling feature bit: %i\n",
i);
__set_bit(i, ar->fw_features); __set_bit(i, ar->fw_features);
}
} }
ath10k_dbg_dump(ATH10K_DBG_BOOT, "features", "", ath10k_dbg_dump(ATH10K_DBG_BOOT, "features", "",
...@@ -699,6 +702,7 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev, ...@@ -699,6 +702,7 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
init_completion(&ar->scan.started); init_completion(&ar->scan.started);
init_completion(&ar->scan.completed); init_completion(&ar->scan.completed);
init_completion(&ar->scan.on_channel); init_completion(&ar->scan.on_channel);
init_completion(&ar->target_suspend);
init_completion(&ar->install_key_done); init_completion(&ar->install_key_done);
init_completion(&ar->vdev_setup_done); init_completion(&ar->vdev_setup_done);
...@@ -722,8 +726,6 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev, ...@@ -722,8 +726,6 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
INIT_WORK(&ar->wmi_mgmt_tx_work, ath10k_mgmt_over_wmi_tx_work); INIT_WORK(&ar->wmi_mgmt_tx_work, ath10k_mgmt_over_wmi_tx_work);
skb_queue_head_init(&ar->wmi_mgmt_tx_queue); skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
init_waitqueue_head(&ar->event_queue);
INIT_WORK(&ar->restart_work, ath10k_core_restart); INIT_WORK(&ar->restart_work, ath10k_core_restart);
return ar; return ar;
...@@ -856,10 +858,34 @@ int ath10k_core_start(struct ath10k *ar) ...@@ -856,10 +858,34 @@ int ath10k_core_start(struct ath10k *ar)
} }
EXPORT_SYMBOL(ath10k_core_start); EXPORT_SYMBOL(ath10k_core_start);
int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt)
{
int ret;
reinit_completion(&ar->target_suspend);
ret = ath10k_wmi_pdev_suspend_target(ar, suspend_opt);
if (ret) {
ath10k_warn("could not suspend target (%d)\n", ret);
return ret;
}
ret = wait_for_completion_timeout(&ar->target_suspend, 1 * HZ);
if (ret == 0) {
ath10k_warn("suspend timed out - target pause event never came\n");
return -ETIMEDOUT;
}
return 0;
}
void ath10k_core_stop(struct ath10k *ar) void ath10k_core_stop(struct ath10k *ar)
{ {
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
/* try to suspend target */
ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);
ath10k_debug_stop(ar); ath10k_debug_stop(ar);
ath10k_htc_stop(&ar->htc); ath10k_htc_stop(&ar->htc);
ath10k_htt_detach(&ar->htt); ath10k_htt_detach(&ar->htt);
......
...@@ -46,6 +46,18 @@ ...@@ -46,6 +46,18 @@
#define ATH10K_MAX_NUM_MGMT_PENDING 128 #define ATH10K_MAX_NUM_MGMT_PENDING 128
/* number of failed packets */
#define ATH10K_KICKOUT_THRESHOLD 50
/*
* Use insanely high numbers to make sure that the firmware implementation
* won't start, we have the same functionality already in hostapd. Unit
* is seconds.
*/
#define ATH10K_KEEPALIVE_MIN_IDLE 3747
#define ATH10K_KEEPALIVE_MAX_IDLE 3895
#define ATH10K_KEEPALIVE_MAX_UNRESPONSIVE 3900
struct ath10k; struct ath10k;
struct ath10k_skb_cb { struct ath10k_skb_cb {
...@@ -61,6 +73,11 @@ struct ath10k_skb_cb { ...@@ -61,6 +73,11 @@ struct ath10k_skb_cb {
u8 frag_len; u8 frag_len;
u8 pad_len; u8 pad_len;
} __packed htt; } __packed htt;
struct {
bool dtim_zero;
bool deliver_cab;
} bcn;
} __packed; } __packed;
static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb) static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb)
...@@ -211,6 +228,18 @@ struct ath10k_peer { ...@@ -211,6 +228,18 @@ struct ath10k_peer {
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
}; };
struct ath10k_sta {
struct ath10k_vif *arvif;
/* the following are protected by ar->data_lock */
u32 changed; /* IEEE80211_RC_* */
u32 bw;
u32 nss;
u32 smps;
struct work_struct update_wk;
};
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ) #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ)
struct ath10k_vif { struct ath10k_vif {
...@@ -222,10 +251,17 @@ struct ath10k_vif { ...@@ -222,10 +251,17 @@ struct ath10k_vif {
u32 beacon_interval; u32 beacon_interval;
u32 dtim_period; u32 dtim_period;
struct sk_buff *beacon; struct sk_buff *beacon;
/* protected by data_lock */
bool beacon_sent;
struct ath10k *ar; struct ath10k *ar;
struct ieee80211_vif *vif; struct ieee80211_vif *vif;
bool is_started;
bool is_up;
u32 aid;
u8 bssid[ETH_ALEN];
struct work_struct wep_key_work; struct work_struct wep_key_work;
struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1]; struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1];
u8 def_wep_key_idx; u8 def_wep_key_idx;
...@@ -235,7 +271,6 @@ struct ath10k_vif { ...@@ -235,7 +271,6 @@ struct ath10k_vif {
union { union {
struct { struct {
u8 bssid[ETH_ALEN];
u32 uapsd; u32 uapsd;
} sta; } sta;
struct { struct {
...@@ -249,9 +284,6 @@ struct ath10k_vif { ...@@ -249,9 +284,6 @@ struct ath10k_vif {
u32 noa_len; u32 noa_len;
u8 *noa_data; u8 *noa_data;
} ap; } ap;
struct {
u8 bssid[ETH_ALEN];
} ibss;
} u; } u;
u8 fixed_rate; u8 fixed_rate;
...@@ -355,8 +387,7 @@ struct ath10k { ...@@ -355,8 +387,7 @@ struct ath10k {
const struct ath10k_hif_ops *ops; const struct ath10k_hif_ops *ops;
} hif; } hif;
wait_queue_head_t event_queue; struct completion target_suspend;
bool is_target_paused;
struct ath10k_bmi bmi; struct ath10k_bmi bmi;
struct ath10k_wmi wmi; struct ath10k_wmi wmi;
...@@ -412,6 +443,9 @@ struct ath10k { ...@@ -412,6 +443,9 @@ struct ath10k {
/* valid during scan; needed for mgmt rx during scan */ /* valid during scan; needed for mgmt rx during scan */
struct ieee80211_channel *scan_channel; struct ieee80211_channel *scan_channel;
/* current operating channel definition */
struct cfg80211_chan_def chandef;
int free_vdev_map; int free_vdev_map;
int monitor_vdev_id; int monitor_vdev_id;
bool monitor_enabled; bool monitor_enabled;
...@@ -470,6 +504,7 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev, ...@@ -470,6 +504,7 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
void ath10k_core_destroy(struct ath10k *ar); void ath10k_core_destroy(struct ath10k *ar);
int ath10k_core_start(struct ath10k *ar); int ath10k_core_start(struct ath10k *ar);
int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt);
void ath10k_core_stop(struct ath10k *ar); void ath10k_core_stop(struct ath10k *ar);
int ath10k_core_register(struct ath10k *ar, u32 chip_id); int ath10k_core_register(struct ath10k *ar, u32 chip_id);
void ath10k_core_unregister(struct ath10k *ar); void ath10k_core_unregister(struct ath10k *ar);
......
...@@ -92,7 +92,7 @@ static inline void ath10k_debug_read_target_stats(struct ath10k *ar, ...@@ -92,7 +92,7 @@ static inline void ath10k_debug_read_target_stats(struct ath10k *ar,
#ifdef CONFIG_ATH10K_DEBUG #ifdef CONFIG_ATH10K_DEBUG
__printf(2, 3) void ath10k_dbg(enum ath10k_debug_mask mask, __printf(2, 3) void ath10k_dbg(enum ath10k_debug_mask mask,
const char *fmt, ...); const char *fmt, ...);
void ath10k_dbg_dump(enum ath10k_debug_mask mask, void ath10k_dbg_dump(enum ath10k_debug_mask mask,
const char *msg, const char *prefix, const char *msg, const char *prefix,
const void *buf, size_t len); const void *buf, size_t len);
......
...@@ -324,7 +324,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -324,7 +324,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
msdu->len + skb_tailroom(msdu), msdu->len + skb_tailroom(msdu),
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt rx: ", ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt rx pop: ",
msdu->data, msdu->len + skb_tailroom(msdu)); msdu->data, msdu->len + skb_tailroom(msdu));
rx_desc = (struct htt_rx_desc *)msdu->data; rx_desc = (struct htt_rx_desc *)msdu->data;
...@@ -417,8 +417,8 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -417,8 +417,8 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
next->len + skb_tailroom(next), next->len + skb_tailroom(next),
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt rx: ", ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL,
next->data, "htt rx chained: ", next->data,
next->len + skb_tailroom(next)); next->len + skb_tailroom(next));
skb_trim(next, 0); skb_trim(next, 0);
...@@ -430,12 +430,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -430,12 +430,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
msdu_chaining = 1; msdu_chaining = 1;
} }
if (msdu_len > 0) {
/* This may suggest FW bug? */
ath10k_warn("htt rx msdu len not consumed (%d)\n",
msdu_len);
}
last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) & last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) &
RX_MSDU_END_INFO0_LAST_MSDU; RX_MSDU_END_INFO0_LAST_MSDU;
...@@ -751,7 +745,7 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt, struct htt_rx_info *info) ...@@ -751,7 +745,7 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt, struct htt_rx_info *info)
/* This shouldn't happen. If it does than it may be a FW bug. */ /* This shouldn't happen. If it does than it may be a FW bug. */
if (skb->next) { if (skb->next) {
ath10k_warn("received chained non A-MSDU frame\n"); ath10k_warn("htt rx received chained non A-MSDU frame\n");
ath10k_htt_rx_free_msdu_chain(skb->next); ath10k_htt_rx_free_msdu_chain(skb->next);
skb->next = NULL; skb->next = NULL;
} }
...@@ -937,6 +931,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ...@@ -937,6 +931,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
} }
if (ath10k_htt_rx_has_decrypt_err(msdu_head)) { if (ath10k_htt_rx_has_decrypt_err(msdu_head)) {
ath10k_dbg(ATH10K_DBG_HTT,
"htt rx dropping due to decrypt-err\n");
ath10k_htt_rx_free_msdu_chain(msdu_head); ath10k_htt_rx_free_msdu_chain(msdu_head);
continue; continue;
} }
...@@ -945,12 +941,14 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ...@@ -945,12 +941,14 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
/* Skip mgmt frames while we handle this in WMI */ /* Skip mgmt frames while we handle this in WMI */
if (status == HTT_RX_IND_MPDU_STATUS_MGMT_CTRL) { if (status == HTT_RX_IND_MPDU_STATUS_MGMT_CTRL) {
ath10k_dbg(ATH10K_DBG_HTT, "htt rx mgmt ctrl\n");
ath10k_htt_rx_free_msdu_chain(msdu_head); ath10k_htt_rx_free_msdu_chain(msdu_head);
continue; continue;
} }
if (status != HTT_RX_IND_MPDU_STATUS_OK && if (status != HTT_RX_IND_MPDU_STATUS_OK &&
status != HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR && status != HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR &&
status != HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER &&
!htt->ar->monitor_enabled) { !htt->ar->monitor_enabled) {
ath10k_dbg(ATH10K_DBG_HTT, ath10k_dbg(ATH10K_DBG_HTT,
"htt rx ignoring frame w/ status %d\n", "htt rx ignoring frame w/ status %d\n",
...@@ -960,6 +958,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ...@@ -960,6 +958,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
} }
if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) { if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) {
ath10k_dbg(ATH10K_DBG_HTT,
"htt rx CAC running\n");
ath10k_htt_rx_free_msdu_chain(msdu_head); ath10k_htt_rx_free_msdu_chain(msdu_head);
continue; continue;
} }
...@@ -967,7 +967,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ...@@ -967,7 +967,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
/* FIXME: we do not support chaining yet. /* FIXME: we do not support chaining yet.
* this needs investigation */ * this needs investigation */
if (msdu_chaining) { if (msdu_chaining) {
ath10k_warn("msdu_chaining is true\n"); ath10k_warn("htt rx msdu_chaining is true\n");
ath10k_htt_rx_free_msdu_chain(msdu_head); ath10k_htt_rx_free_msdu_chain(msdu_head);
continue; continue;
} }
...@@ -975,6 +975,15 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ...@@ -975,6 +975,15 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
info.skb = msdu_head; info.skb = msdu_head;
info.fcs_err = ath10k_htt_rx_has_fcs_err(msdu_head); info.fcs_err = ath10k_htt_rx_has_fcs_err(msdu_head);
info.mic_err = ath10k_htt_rx_has_mic_err(msdu_head); info.mic_err = ath10k_htt_rx_has_mic_err(msdu_head);
if (info.fcs_err)
ath10k_dbg(ATH10K_DBG_HTT,
"htt rx has FCS err\n");
if (info.mic_err)
ath10k_dbg(ATH10K_DBG_HTT,
"htt rx has MIC err\n");
info.signal = ATH10K_DEFAULT_NOISE_FLOOR; info.signal = ATH10K_DEFAULT_NOISE_FLOOR;
info.signal += rx->ppdu.combined_rssi; info.signal += rx->ppdu.combined_rssi;
...@@ -1095,7 +1104,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ...@@ -1095,7 +1104,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
skb_trim(info.skb, info.skb->len - trim); skb_trim(info.skb, info.skb->len - trim);
ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt frag mpdu: ", ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt rx frag mpdu: ",
info.skb->data, info.skb->len); info.skb->data, info.skb->len);
ath10k_process_rx(htt->ar, &info); ath10k_process_rx(htt->ar, &info);
...@@ -1116,7 +1125,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) ...@@ -1116,7 +1125,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
if (!IS_ALIGNED((unsigned long)skb->data, 4)) if (!IS_ALIGNED((unsigned long)skb->data, 4))
ath10k_warn("unaligned htt message, expect trouble\n"); ath10k_warn("unaligned htt message, expect trouble\n");
ath10k_dbg(ATH10K_DBG_HTT, "HTT RX, msg_type: 0x%0X\n", ath10k_dbg(ATH10K_DBG_HTT, "htt rx, msg_type: 0x%0X\n",
resp->hdr.msg_type); resp->hdr.msg_type);
switch (resp->hdr.msg_type) { switch (resp->hdr.msg_type) {
case HTT_T2H_MSG_TYPE_VERSION_CONF: { case HTT_T2H_MSG_TYPE_VERSION_CONF: {
......
...@@ -460,9 +460,9 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ...@@ -460,9 +460,9 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
DMA_TO_DEVICE); DMA_TO_DEVICE);
} }
ath10k_dbg(ATH10K_DBG_HTT, "msdu 0x%llx\n", ath10k_dbg(ATH10K_DBG_HTT, "tx-msdu 0x%llx\n",
(unsigned long long) ATH10K_SKB_CB(msdu)->paddr); (unsigned long long) ATH10K_SKB_CB(msdu)->paddr);
ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "msdu: ", ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "tx-msdu: ",
msdu->data, msdu->len); msdu->data, msdu->len);
skb_put(txdesc, desc_len); skb_put(txdesc, desc_len);
......
...@@ -205,8 +205,11 @@ enum ath10k_mcast2ucast_mode { ...@@ -205,8 +205,11 @@ enum ath10k_mcast2ucast_mode {
#define WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x0006c000 #define WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x0006c000
#define PCIE_LOCAL_BASE_ADDRESS 0x00080000 #define PCIE_LOCAL_BASE_ADDRESS 0x00080000
#define SOC_RESET_CONTROL_ADDRESS 0x00000000
#define SOC_RESET_CONTROL_OFFSET 0x00000000 #define SOC_RESET_CONTROL_OFFSET 0x00000000
#define SOC_RESET_CONTROL_SI0_RST_MASK 0x00000001 #define SOC_RESET_CONTROL_SI0_RST_MASK 0x00000001
#define SOC_RESET_CONTROL_CE_RST_MASK 0x00040000
#define SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040
#define SOC_CPU_CLOCK_OFFSET 0x00000020 #define SOC_CPU_CLOCK_OFFSET 0x00000020
#define SOC_CPU_CLOCK_STANDARD_LSB 0 #define SOC_CPU_CLOCK_STANDARD_LSB 0
#define SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 #define SOC_CPU_CLOCK_STANDARD_MASK 0x00000003
...@@ -216,6 +219,8 @@ enum ath10k_mcast2ucast_mode { ...@@ -216,6 +219,8 @@ enum ath10k_mcast2ucast_mode {
#define SOC_LPO_CAL_OFFSET 0x000000e0 #define SOC_LPO_CAL_OFFSET 0x000000e0
#define SOC_LPO_CAL_ENABLE_LSB 20 #define SOC_LPO_CAL_ENABLE_LSB 20
#define SOC_LPO_CAL_ENABLE_MASK 0x00100000 #define SOC_LPO_CAL_ENABLE_MASK 0x00100000
#define SOC_LF_TIMER_CONTROL0_ADDRESS 0x00000050
#define SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0x00000004
#define SOC_CHIP_ID_ADDRESS 0x000000ec #define SOC_CHIP_ID_ADDRESS 0x000000ec
#define SOC_CHIP_ID_REV_LSB 8 #define SOC_CHIP_ID_REV_LSB 8
...@@ -273,6 +278,7 @@ enum ath10k_mcast2ucast_mode { ...@@ -273,6 +278,7 @@ enum ath10k_mcast2ucast_mode {
#define PCIE_INTR_CAUSE_ADDRESS 0x000c #define PCIE_INTR_CAUSE_ADDRESS 0x000c
#define PCIE_INTR_CLR_ADDRESS 0x0014 #define PCIE_INTR_CLR_ADDRESS 0x0014
#define SCRATCH_3_ADDRESS 0x0030 #define SCRATCH_3_ADDRESS 0x0030
#define CPU_INTR_ADDRESS 0x0010
/* Firmware indications to the Host via SCRATCH_3 register. */ /* Firmware indications to the Host via SCRATCH_3 register. */
#define FW_INDICATOR_ADDRESS (SOC_CORE_BASE_ADDRESS + SCRATCH_3_ADDRESS) #define FW_INDICATOR_ADDRESS (SOC_CORE_BASE_ADDRESS + SCRATCH_3_ADDRESS)
......
This diff is collapsed.
...@@ -64,7 +64,8 @@ static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info, ...@@ -64,7 +64,8 @@ static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info,
int num); int num);
static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info); static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info);
static void ath10k_pci_stop_ce(struct ath10k *ar); static void ath10k_pci_stop_ce(struct ath10k *ar);
static int ath10k_pci_device_reset(struct ath10k *ar); static int ath10k_pci_cold_reset(struct ath10k *ar);
static int ath10k_pci_warm_reset(struct ath10k *ar);
static int ath10k_pci_wait_for_target_init(struct ath10k *ar); static int ath10k_pci_wait_for_target_init(struct ath10k *ar);
static int ath10k_pci_init_irq(struct ath10k *ar); static int ath10k_pci_init_irq(struct ath10k *ar);
static int ath10k_pci_deinit_irq(struct ath10k *ar); static int ath10k_pci_deinit_irq(struct ath10k *ar);
...@@ -833,9 +834,7 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar) ...@@ -833,9 +834,7 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
ath10k_err("firmware crashed!\n"); ath10k_err("firmware crashed!\n");
ath10k_err("hardware name %s version 0x%x\n", ath10k_err("hardware name %s version 0x%x\n",
ar->hw_params.name, ar->target_version); ar->hw_params.name, ar->target_version);
ath10k_err("firmware version: %u.%u.%u.%u\n", ar->fw_version_major, ath10k_err("firmware version: %s\n", ar->hw->wiphy->fw_version);
ar->fw_version_minor, ar->fw_version_release,
ar->fw_version_build);
host_addr = host_interest_item_address(HI_ITEM(hi_failure_state)); host_addr = host_interest_item_address(HI_ITEM(hi_failure_state));
ret = ath10k_pci_diag_read_mem(ar, host_addr, ret = ath10k_pci_diag_read_mem(ar, host_addr,
...@@ -1502,7 +1501,7 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) ...@@ -1502,7 +1501,7 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
* configuration during init. If ringbuffers are freed and the device * configuration during init. If ringbuffers are freed and the device
* were to access them this could lead to memory corruption on the * were to access them this could lead to memory corruption on the
* host. */ * host. */
ath10k_pci_device_reset(ar); ath10k_pci_warm_reset(ar);
ar_pci->started = 0; ar_pci->started = 0;
} }
...@@ -1993,7 +1992,94 @@ static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar) ...@@ -1993,7 +1992,94 @@ static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar)
ath10k_pci_sleep(ar); ath10k_pci_sleep(ar);
} }
static int ath10k_pci_hif_power_up(struct ath10k *ar) static int ath10k_pci_warm_reset(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ret = 0;
u32 val;
ath10k_dbg(ATH10K_DBG_BOOT, "boot performing warm chip reset\n");
ret = ath10k_do_pci_wake(ar);
if (ret) {
ath10k_err("failed to wake up target: %d\n", ret);
return ret;
}
/* debug */
val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
PCIE_INTR_CAUSE_ADDRESS);
ath10k_dbg(ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n", val);
val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
CPU_INTR_ADDRESS);
ath10k_dbg(ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n",
val);
/* disable pending irqs */
ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
PCIE_INTR_ENABLE_ADDRESS, 0);
ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
PCIE_INTR_CLR_ADDRESS, ~0);
msleep(100);
/* clear fw indicator */
ath10k_pci_write32(ar, ar_pci->fw_indicator_address, 0);
/* clear target LF timer interrupts */
val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
SOC_LF_TIMER_CONTROL0_ADDRESS);
ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS +
SOC_LF_TIMER_CONTROL0_ADDRESS,
val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK);
/* reset CE */
val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
SOC_RESET_CONTROL_ADDRESS);
ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
val | SOC_RESET_CONTROL_CE_RST_MASK);
val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
SOC_RESET_CONTROL_ADDRESS);
msleep(10);
/* unreset CE */
ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
val & ~SOC_RESET_CONTROL_CE_RST_MASK);
val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
SOC_RESET_CONTROL_ADDRESS);
msleep(10);
/* debug */
val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
PCIE_INTR_CAUSE_ADDRESS);
ath10k_dbg(ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n", val);
val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
CPU_INTR_ADDRESS);
ath10k_dbg(ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n",
val);
/* CPU warm reset */
val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
SOC_RESET_CONTROL_ADDRESS);
ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK);
val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
SOC_RESET_CONTROL_ADDRESS);
ath10k_dbg(ATH10K_DBG_BOOT, "boot target reset state: 0x%08x\n", val);
msleep(100);
ath10k_dbg(ATH10K_DBG_BOOT, "boot warm reset complete\n");
ath10k_do_pci_sleep(ar);
return ret;
}
static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset)
{ {
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
const char *irq_mode; const char *irq_mode;
...@@ -2009,7 +2095,11 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) ...@@ -2009,7 +2095,11 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
* is in an unexpected state. We try to catch that here in order to * is in an unexpected state. We try to catch that here in order to
* reset the Target and retry the probe. * reset the Target and retry the probe.
*/ */
ret = ath10k_pci_device_reset(ar); if (cold_reset)
ret = ath10k_pci_cold_reset(ar);
else
ret = ath10k_pci_warm_reset(ar);
if (ret) { if (ret) {
ath10k_err("failed to reset target: %d\n", ret); ath10k_err("failed to reset target: %d\n", ret);
goto err; goto err;
...@@ -2079,7 +2169,7 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) ...@@ -2079,7 +2169,7 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
ath10k_pci_deinit_irq(ar); ath10k_pci_deinit_irq(ar);
err_ce: err_ce:
ath10k_pci_ce_deinit(ar); ath10k_pci_ce_deinit(ar);
ath10k_pci_device_reset(ar); ath10k_pci_warm_reset(ar);
err_ps: err_ps:
if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features)) if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
ath10k_do_pci_sleep(ar); ath10k_do_pci_sleep(ar);
...@@ -2087,6 +2177,34 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) ...@@ -2087,6 +2177,34 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
return ret; return ret;
} }
static int ath10k_pci_hif_power_up(struct ath10k *ar)
{
int ret;
/*
* Hardware CUS232 version 2 has some issues with cold reset and the
* preferred (and safer) way to perform a device reset is through a
* warm reset.
*
* Warm reset doesn't always work though (notably after a firmware
* crash) so fall back to cold reset if necessary.
*/
ret = __ath10k_pci_hif_power_up(ar, false);
if (ret) {
ath10k_warn("failed to power up target using warm reset (%d), trying cold reset\n",
ret);
ret = __ath10k_pci_hif_power_up(ar, true);
if (ret) {
ath10k_err("failed to power up target using cold reset too (%d)\n",
ret);
return ret;
}
}
return 0;
}
static void ath10k_pci_hif_power_down(struct ath10k *ar) static void ath10k_pci_hif_power_down(struct ath10k *ar)
{ {
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
...@@ -2094,7 +2212,7 @@ static void ath10k_pci_hif_power_down(struct ath10k *ar) ...@@ -2094,7 +2212,7 @@ static void ath10k_pci_hif_power_down(struct ath10k *ar)
ath10k_pci_free_early_irq(ar); ath10k_pci_free_early_irq(ar);
ath10k_pci_kill_tasklet(ar); ath10k_pci_kill_tasklet(ar);
ath10k_pci_deinit_irq(ar); ath10k_pci_deinit_irq(ar);
ath10k_pci_device_reset(ar); ath10k_pci_warm_reset(ar);
ath10k_pci_ce_deinit(ar); ath10k_pci_ce_deinit(ar);
if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features)) if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
...@@ -2411,11 +2529,10 @@ static int ath10k_pci_init_irq(struct ath10k *ar) ...@@ -2411,11 +2529,10 @@ static int ath10k_pci_init_irq(struct ath10k *ar)
/* Try MSI-X */ /* Try MSI-X */
if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO && msix_supported) { if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO && msix_supported) {
ar_pci->num_msi_intrs = MSI_NUM_REQUEST; ar_pci->num_msi_intrs = MSI_NUM_REQUEST;
ret = pci_enable_msi_block(ar_pci->pdev, ar_pci->num_msi_intrs); ret = pci_enable_msi_range(ar_pci->pdev, ar_pci->num_msi_intrs,
if (ret == 0) ar_pci->num_msi_intrs);
return 0;
if (ret > 0) if (ret > 0)
pci_disable_msi(ar_pci->pdev); return 0;
/* fall-through */ /* fall-through */
} }
...@@ -2482,6 +2599,8 @@ static int ath10k_pci_deinit_irq(struct ath10k *ar) ...@@ -2482,6 +2599,8 @@ static int ath10k_pci_deinit_irq(struct ath10k *ar)
case MSI_NUM_REQUEST: case MSI_NUM_REQUEST:
pci_disable_msi(ar_pci->pdev); pci_disable_msi(ar_pci->pdev);
return 0; return 0;
default:
pci_disable_msi(ar_pci->pdev);
} }
ath10k_warn("unknown irq configuration upon deinit\n"); ath10k_warn("unknown irq configuration upon deinit\n");
...@@ -2523,7 +2642,7 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar) ...@@ -2523,7 +2642,7 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar)
return ret; return ret;
} }
static int ath10k_pci_device_reset(struct ath10k *ar) static int ath10k_pci_cold_reset(struct ath10k *ar)
{ {
int i, ret; int i, ret;
u32 val; u32 val;
......
...@@ -259,7 +259,7 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info) ...@@ -259,7 +259,7 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info)
status->freq = ch->center_freq; status->freq = ch->center_freq;
ath10k_dbg(ATH10K_DBG_DATA, ath10k_dbg(ATH10K_DBG_DATA,
"rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u\n", "rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i\n",
info->skb, info->skb,
info->skb->len, info->skb->len,
status->flag == 0 ? "legacy" : "", status->flag == 0 ? "legacy" : "",
...@@ -271,7 +271,7 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info) ...@@ -271,7 +271,7 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info)
status->rate_idx, status->rate_idx,
status->vht_nss, status->vht_nss,
status->freq, status->freq,
status->band); status->band, status->flag, info->fcs_err);
ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ", ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ",
info->skb->data, info->skb->len); info->skb->data, info->skb->len);
......
...@@ -213,7 +213,7 @@ static struct wmi_cmd_map wmi_10x_cmd_map = { ...@@ -213,7 +213,7 @@ static struct wmi_cmd_map wmi_10x_cmd_map = {
.p2p_go_set_beacon_ie = WMI_10X_P2P_GO_SET_BEACON_IE, .p2p_go_set_beacon_ie = WMI_10X_P2P_GO_SET_BEACON_IE,
.p2p_go_set_probe_resp_ie = WMI_10X_P2P_GO_SET_PROBE_RESP_IE, .p2p_go_set_probe_resp_ie = WMI_10X_P2P_GO_SET_PROBE_RESP_IE,
.p2p_set_vendor_ie_data_cmdid = WMI_CMD_UNSUPPORTED, .p2p_set_vendor_ie_data_cmdid = WMI_CMD_UNSUPPORTED,
.ap_ps_peer_param_cmdid = WMI_CMD_UNSUPPORTED, .ap_ps_peer_param_cmdid = WMI_10X_AP_PS_PEER_PARAM_CMDID,
.ap_ps_peer_uapsd_coex_cmdid = WMI_CMD_UNSUPPORTED, .ap_ps_peer_uapsd_coex_cmdid = WMI_CMD_UNSUPPORTED,
.peer_rate_retry_sched_cmdid = WMI_10X_PEER_RATE_RETRY_SCHED_CMDID, .peer_rate_retry_sched_cmdid = WMI_10X_PEER_RATE_RETRY_SCHED_CMDID,
.wlan_profile_trigger_cmdid = WMI_10X_WLAN_PROFILE_TRIGGER_CMDID, .wlan_profile_trigger_cmdid = WMI_10X_WLAN_PROFILE_TRIGGER_CMDID,
...@@ -420,7 +420,6 @@ static struct wmi_pdev_param_map wmi_pdev_param_map = { ...@@ -420,7 +420,6 @@ static struct wmi_pdev_param_map wmi_pdev_param_map = {
.bcnflt_stats_update_period = WMI_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, .bcnflt_stats_update_period = WMI_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD,
.pmf_qos = WMI_PDEV_PARAM_PMF_QOS, .pmf_qos = WMI_PDEV_PARAM_PMF_QOS,
.arp_ac_override = WMI_PDEV_PARAM_ARP_AC_OVERRIDE, .arp_ac_override = WMI_PDEV_PARAM_ARP_AC_OVERRIDE,
.arpdhcp_ac_override = WMI_PDEV_PARAM_UNSUPPORTED,
.dcs = WMI_PDEV_PARAM_DCS, .dcs = WMI_PDEV_PARAM_DCS,
.ani_enable = WMI_PDEV_PARAM_ANI_ENABLE, .ani_enable = WMI_PDEV_PARAM_ANI_ENABLE,
.ani_poll_period = WMI_PDEV_PARAM_ANI_POLL_PERIOD, .ani_poll_period = WMI_PDEV_PARAM_ANI_POLL_PERIOD,
...@@ -472,8 +471,7 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = { ...@@ -472,8 +471,7 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
.bcnflt_stats_update_period = .bcnflt_stats_update_period =
WMI_10X_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, WMI_10X_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD,
.pmf_qos = WMI_10X_PDEV_PARAM_PMF_QOS, .pmf_qos = WMI_10X_PDEV_PARAM_PMF_QOS,
.arp_ac_override = WMI_PDEV_PARAM_UNSUPPORTED, .arp_ac_override = WMI_10X_PDEV_PARAM_ARPDHCP_AC_OVERRIDE,
.arpdhcp_ac_override = WMI_10X_PDEV_PARAM_ARPDHCP_AC_OVERRIDE,
.dcs = WMI_10X_PDEV_PARAM_DCS, .dcs = WMI_10X_PDEV_PARAM_DCS,
.ani_enable = WMI_10X_PDEV_PARAM_ANI_ENABLE, .ani_enable = WMI_10X_PDEV_PARAM_ANI_ENABLE,
.ani_poll_period = WMI_10X_PDEV_PARAM_ANI_POLL_PERIOD, .ani_poll_period = WMI_10X_PDEV_PARAM_ANI_POLL_PERIOD,
...@@ -561,7 +559,6 @@ static int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb, ...@@ -561,7 +559,6 @@ static int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb,
static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif) static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
{ {
struct wmi_bcn_tx_arg arg = {0};
int ret; int ret;
lockdep_assert_held(&arvif->ar->data_lock); lockdep_assert_held(&arvif->ar->data_lock);
...@@ -569,18 +566,16 @@ static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif) ...@@ -569,18 +566,16 @@ static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
if (arvif->beacon == NULL) if (arvif->beacon == NULL)
return; return;
arg.vdev_id = arvif->vdev_id; if (arvif->beacon_sent)
arg.tx_rate = 0; return;
arg.tx_power = 0;
arg.bcn = arvif->beacon->data;
arg.bcn_len = arvif->beacon->len;
ret = ath10k_wmi_beacon_send_nowait(arvif->ar, &arg); ret = ath10k_wmi_beacon_send_ref_nowait(arvif);
if (ret) if (ret)
return; return;
dev_kfree_skb_any(arvif->beacon); /* We need to retain the arvif->beacon reference for DMA unmapping and
arvif->beacon = NULL; * freeing the skbuff later. */
arvif->beacon_sent = true;
} }
static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac, static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac,
...@@ -1116,7 +1111,27 @@ static void ath10k_wmi_event_vdev_stopped(struct ath10k *ar, ...@@ -1116,7 +1111,27 @@ static void ath10k_wmi_event_vdev_stopped(struct ath10k *ar,
static void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar, static void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar,
struct sk_buff *skb) struct sk_buff *skb)
{ {
ath10k_dbg(ATH10K_DBG_WMI, "WMI_PEER_STA_KICKOUT_EVENTID\n"); struct wmi_peer_sta_kickout_event *ev;
struct ieee80211_sta *sta;
ev = (struct wmi_peer_sta_kickout_event *)skb->data;
ath10k_dbg(ATH10K_DBG_WMI, "wmi event peer sta kickout %pM\n",
ev->peer_macaddr.addr);
rcu_read_lock();
sta = ieee80211_find_sta_by_ifaddr(ar->hw, ev->peer_macaddr.addr, NULL);
if (!sta) {
ath10k_warn("Spurious quick kickout for STA %pM\n",
ev->peer_macaddr.addr);
goto exit;
}
ieee80211_report_low_ack(sta, 10);
exit:
rcu_read_unlock();
} }
/* /*
...@@ -1217,6 +1232,13 @@ static void ath10k_wmi_update_tim(struct ath10k *ar, ...@@ -1217,6 +1232,13 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
tim->bitmap_ctrl = !!__le32_to_cpu(bcn_info->tim_info.tim_mcast); tim->bitmap_ctrl = !!__le32_to_cpu(bcn_info->tim_info.tim_mcast);
memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len); memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len);
if (tim->dtim_count == 0) {
ATH10K_SKB_CB(bcn)->bcn.dtim_zero = true;
if (__le32_to_cpu(bcn_info->tim_info.tim_mcast) == 1)
ATH10K_SKB_CB(bcn)->bcn.deliver_cab = true;
}
ath10k_dbg(ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n", ath10k_dbg(ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n",
tim->dtim_count, tim->dtim_period, tim->dtim_count, tim->dtim_period,
tim->bitmap_ctrl, pvm_len); tim->bitmap_ctrl, pvm_len);
...@@ -1385,6 +1407,17 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) ...@@ -1385,6 +1407,17 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
continue; continue;
} }
/* There are no completions for beacons so wait for next SWBA
* before telling mac80211 to decrement CSA counter
*
* Once CSA counter is completed stop sending beacons until
* actual channel switch is done */
if (arvif->vif->csa_active &&
ieee80211_csa_is_complete(arvif->vif)) {
ieee80211_csa_finish(arvif->vif);
continue;
}
bcn = ieee80211_beacon_get(ar->hw, arvif->vif); bcn = ieee80211_beacon_get(ar->hw, arvif->vif);
if (!bcn) { if (!bcn) {
ath10k_warn("could not get mac80211 beacon\n"); ath10k_warn("could not get mac80211 beacon\n");
...@@ -1396,13 +1429,20 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) ...@@ -1396,13 +1429,20 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info); ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info);
spin_lock_bh(&ar->data_lock); spin_lock_bh(&ar->data_lock);
if (arvif->beacon) { if (arvif->beacon) {
ath10k_warn("SWBA overrun on vdev %d\n", if (!arvif->beacon_sent)
arvif->vdev_id); ath10k_warn("SWBA overrun on vdev %d\n",
arvif->vdev_id);
ath10k_skb_unmap(ar->dev, arvif->beacon);
dev_kfree_skb_any(arvif->beacon); dev_kfree_skb_any(arvif->beacon);
} }
ath10k_skb_map(ar->dev, bcn);
arvif->beacon = bcn; arvif->beacon = bcn;
arvif->beacon_sent = false;
ath10k_wmi_tx_beacon_nowait(arvif); ath10k_wmi_tx_beacon_nowait(arvif);
spin_unlock_bh(&ar->data_lock); spin_unlock_bh(&ar->data_lock);
...@@ -2031,11 +2071,11 @@ static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -2031,11 +2071,11 @@ static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb)
memcpy(ar->mac_addr, ev->mac_addr.addr, ETH_ALEN); memcpy(ar->mac_addr, ev->mac_addr.addr, ETH_ALEN);
ath10k_dbg(ATH10K_DBG_WMI, ath10k_dbg(ATH10K_DBG_WMI,
"wmi event ready sw_version %u abi_version %u mac_addr %pM status %d\n", "wmi event ready sw_version %u abi_version %u mac_addr %pM status %d skb->len %i ev-sz %zu\n",
__le32_to_cpu(ev->sw_version), __le32_to_cpu(ev->sw_version),
__le32_to_cpu(ev->abi_version), __le32_to_cpu(ev->abi_version),
ev->mac_addr.addr, ev->mac_addr.addr,
__le32_to_cpu(ev->status)); __le32_to_cpu(ev->status), skb->len, sizeof(*ev));
complete(&ar->wmi.unified_ready); complete(&ar->wmi.unified_ready);
return 0; return 0;
...@@ -2403,7 +2443,7 @@ int ath10k_wmi_pdev_set_channel(struct ath10k *ar, ...@@ -2403,7 +2443,7 @@ int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
ar->wmi.cmd->pdev_set_channel_cmdid); ar->wmi.cmd->pdev_set_channel_cmdid);
} }
int ath10k_wmi_pdev_suspend_target(struct ath10k *ar) int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt)
{ {
struct wmi_pdev_suspend_cmd *cmd; struct wmi_pdev_suspend_cmd *cmd;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -2413,7 +2453,7 @@ int ath10k_wmi_pdev_suspend_target(struct ath10k *ar) ...@@ -2413,7 +2453,7 @@ int ath10k_wmi_pdev_suspend_target(struct ath10k *ar)
return -ENOMEM; return -ENOMEM;
cmd = (struct wmi_pdev_suspend_cmd *)skb->data; cmd = (struct wmi_pdev_suspend_cmd *)skb->data;
cmd->suspend_opt = WMI_PDEV_SUSPEND; cmd->suspend_opt = __cpu_to_le32(suspend_opt);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_suspend_cmdid); return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_suspend_cmdid);
} }
...@@ -3411,25 +3451,41 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar, ...@@ -3411,25 +3451,41 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar,
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_assoc_cmdid); return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_assoc_cmdid);
} }
int ath10k_wmi_beacon_send_nowait(struct ath10k *ar, /* This function assumes the beacon is already DMA mapped */
const struct wmi_bcn_tx_arg *arg) int ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif)
{ {
struct wmi_bcn_tx_cmd *cmd; struct wmi_bcn_tx_ref_cmd *cmd;
struct sk_buff *skb; struct sk_buff *skb;
struct sk_buff *beacon = arvif->beacon;
struct ath10k *ar = arvif->ar;
struct ieee80211_hdr *hdr;
int ret; int ret;
u16 fc;
skb = ath10k_wmi_alloc_skb(sizeof(*cmd) + arg->bcn_len); skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
if (!skb) if (!skb)
return -ENOMEM; return -ENOMEM;
cmd = (struct wmi_bcn_tx_cmd *)skb->data; hdr = (struct ieee80211_hdr *)beacon->data;
cmd->hdr.vdev_id = __cpu_to_le32(arg->vdev_id); fc = le16_to_cpu(hdr->frame_control);
cmd->hdr.tx_rate = __cpu_to_le32(arg->tx_rate);
cmd->hdr.tx_power = __cpu_to_le32(arg->tx_power); cmd = (struct wmi_bcn_tx_ref_cmd *)skb->data;
cmd->hdr.bcn_len = __cpu_to_le32(arg->bcn_len); cmd->vdev_id = __cpu_to_le32(arvif->vdev_id);
memcpy(cmd->bcn, arg->bcn, arg->bcn_len); cmd->data_len = __cpu_to_le32(beacon->len);
cmd->data_ptr = __cpu_to_le32(ATH10K_SKB_CB(beacon)->paddr);
cmd->msdu_id = 0;
cmd->frame_control = __cpu_to_le32(fc);
cmd->flags = 0;
if (ATH10K_SKB_CB(beacon)->bcn.dtim_zero)
cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO);
if (ATH10K_SKB_CB(beacon)->bcn.deliver_cab)
cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB);
ret = ath10k_wmi_cmd_send_nowait(ar, skb,
ar->wmi.cmd->pdev_send_bcn_cmdid);
ret = ath10k_wmi_cmd_send_nowait(ar, skb, ar->wmi.cmd->bcn_tx_cmdid);
if (ret) if (ret)
dev_kfree_skb(skb); dev_kfree_skb(skb);
......
...@@ -2277,7 +2277,6 @@ struct wmi_pdev_param_map { ...@@ -2277,7 +2277,6 @@ struct wmi_pdev_param_map {
u32 bcnflt_stats_update_period; u32 bcnflt_stats_update_period;
u32 pmf_qos; u32 pmf_qos;
u32 arp_ac_override; u32 arp_ac_override;
u32 arpdhcp_ac_override;
u32 dcs; u32 dcs;
u32 ani_enable; u32 ani_enable;
u32 ani_poll_period; u32 ani_poll_period;
...@@ -3403,6 +3402,24 @@ struct wmi_bcn_tx_arg { ...@@ -3403,6 +3402,24 @@ struct wmi_bcn_tx_arg {
const void *bcn; const void *bcn;
}; };
enum wmi_bcn_tx_ref_flags {
WMI_BCN_TX_REF_FLAG_DTIM_ZERO = 0x1,
WMI_BCN_TX_REF_FLAG_DELIVER_CAB = 0x2,
};
struct wmi_bcn_tx_ref_cmd {
__le32 vdev_id;
__le32 data_len;
/* physical address of the frame - dma pointer */
__le32 data_ptr;
/* id for host to track */
__le32 msdu_id;
/* frame ctrl to setup PPDU desc */
__le32 frame_control;
/* to control CABQ traffic: WMI_BCN_TX_REF_FLAG_ */
__le32 flags;
} __packed;
/* Beacon filter */ /* Beacon filter */
#define WMI_BCN_FILTER_ALL 0 /* Filter all beacons */ #define WMI_BCN_FILTER_ALL 0 /* Filter all beacons */
#define WMI_BCN_FILTER_NONE 1 /* Pass all beacons */ #define WMI_BCN_FILTER_NONE 1 /* Pass all beacons */
...@@ -3859,6 +3876,12 @@ enum wmi_peer_smps_state { ...@@ -3859,6 +3876,12 @@ enum wmi_peer_smps_state {
WMI_PEER_SMPS_DYNAMIC = 0x2 WMI_PEER_SMPS_DYNAMIC = 0x2
}; };
enum wmi_peer_chwidth {
WMI_PEER_CHWIDTH_20MHZ = 0,
WMI_PEER_CHWIDTH_40MHZ = 1,
WMI_PEER_CHWIDTH_80MHZ = 2,
};
enum wmi_peer_param { enum wmi_peer_param {
WMI_PEER_SMPS_STATE = 0x1, /* see %wmi_peer_smps_state */ WMI_PEER_SMPS_STATE = 0x1, /* see %wmi_peer_smps_state */
WMI_PEER_AMPDU = 0x2, WMI_PEER_AMPDU = 0x2,
...@@ -4039,6 +4062,10 @@ struct wmi_chan_info_event { ...@@ -4039,6 +4062,10 @@ struct wmi_chan_info_event {
__le32 cycle_count; __le32 cycle_count;
} __packed; } __packed;
struct wmi_peer_sta_kickout_event {
struct wmi_mac_addr peer_macaddr;
} __packed;
#define WMI_CHAN_INFO_FLAG_COMPLETE BIT(0) #define WMI_CHAN_INFO_FLAG_COMPLETE BIT(0)
/* FIXME: empirically extrapolated */ /* FIXME: empirically extrapolated */
...@@ -4172,7 +4199,7 @@ int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar); ...@@ -4172,7 +4199,7 @@ int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar);
int ath10k_wmi_connect_htc_service(struct ath10k *ar); int ath10k_wmi_connect_htc_service(struct ath10k *ar);
int ath10k_wmi_pdev_set_channel(struct ath10k *ar, int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
const struct wmi_channel_arg *); const struct wmi_channel_arg *);
int ath10k_wmi_pdev_suspend_target(struct ath10k *ar); int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt);
int ath10k_wmi_pdev_resume_target(struct ath10k *ar); int ath10k_wmi_pdev_resume_target(struct ath10k *ar);
int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g,
u16 rd5g, u16 ctl2g, u16 ctl5g); u16 rd5g, u16 ctl2g, u16 ctl5g);
...@@ -4219,8 +4246,7 @@ int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac, ...@@ -4219,8 +4246,7 @@ int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac,
enum wmi_ap_ps_peer_param param_id, u32 value); enum wmi_ap_ps_peer_param param_id, u32 value);
int ath10k_wmi_scan_chan_list(struct ath10k *ar, int ath10k_wmi_scan_chan_list(struct ath10k *ar,
const struct wmi_scan_chan_list_arg *arg); const struct wmi_scan_chan_list_arg *arg);
int ath10k_wmi_beacon_send_nowait(struct ath10k *ar, int ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif);
const struct wmi_bcn_tx_arg *arg);
int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
const struct wmi_pdev_set_wmm_params_arg *arg); const struct wmi_pdev_set_wmm_params_arg *arg);
int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id); int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id);
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
/* constants */ /* constants */
#define TX_URB_COUNT 32 #define TX_URB_COUNT 32
#define RX_URB_COUNT 32 #define RX_URB_COUNT 32
#define ATH6KL_USB_RX_BUFFER_SIZE 1700 #define ATH6KL_USB_RX_BUFFER_SIZE 4096
/* tx/rx pipes for usb */ /* tx/rx pipes for usb */
enum ATH6KL_USB_PIPE_ID { enum ATH6KL_USB_PIPE_ID {
...@@ -481,8 +481,8 @@ static void ath6kl_usb_start_recv_pipes(struct ath6kl_usb *ar_usb) ...@@ -481,8 +481,8 @@ static void ath6kl_usb_start_recv_pipes(struct ath6kl_usb *ar_usb)
* ATH6KL_USB_RX_BUFFER_SIZE); * ATH6KL_USB_RX_BUFFER_SIZE);
*/ */
ar_usb->pipes[ATH6KL_USB_PIPE_RX_DATA].urb_cnt_thresh = ar_usb->pipes[ATH6KL_USB_PIPE_RX_DATA].urb_cnt_thresh = 1;
ar_usb->pipes[ATH6KL_USB_PIPE_RX_DATA].urb_alloc / 2;
ath6kl_usb_post_recv_transfers(&ar_usb->pipes[ATH6KL_USB_PIPE_RX_DATA], ath6kl_usb_post_recv_transfers(&ar_usb->pipes[ATH6KL_USB_PIPE_RX_DATA],
ATH6KL_USB_RX_BUFFER_SIZE); ATH6KL_USB_RX_BUFFER_SIZE);
} }
......
...@@ -914,7 +914,7 @@ ath6kl_get_regpair(u16 regdmn) ...@@ -914,7 +914,7 @@ ath6kl_get_regpair(u16 regdmn)
return NULL; return NULL;
for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) { for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
if (regDomainPairs[i].regDmnEnum == regdmn) if (regDomainPairs[i].reg_domain == regdmn)
return &regDomainPairs[i]; return &regDomainPairs[i];
} }
...@@ -954,7 +954,7 @@ static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len) ...@@ -954,7 +954,7 @@ static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len)
country = ath6kl_regd_find_country_by_rd((u16) reg_code); country = ath6kl_regd_find_country_by_rd((u16) reg_code);
if (regpair) if (regpair)
ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n", ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n",
regpair->regDmnEnum); regpair->reg_domain);
else else
ath6kl_warn("Regpair not found reg_code 0x%0x\n", ath6kl_warn("Regpair not found reg_code 0x%0x\n",
reg_code); reg_code);
......
...@@ -222,7 +222,7 @@ static const struct ieee80211_regdomain *ath_default_world_regdomain(void) ...@@ -222,7 +222,7 @@ static const struct ieee80211_regdomain *ath_default_world_regdomain(void)
static const struct static const struct
ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg) ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg)
{ {
switch (reg->regpair->regDmnEnum) { switch (reg->regpair->reg_domain) {
case 0x60: case 0x60:
case 0x61: case 0x61:
case 0x62: case 0x62:
...@@ -431,7 +431,7 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy, ...@@ -431,7 +431,7 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy,
enum nl80211_reg_initiator initiator, enum nl80211_reg_initiator initiator,
struct ath_regulatory *reg) struct ath_regulatory *reg)
{ {
switch (reg->regpair->regDmnEnum) { switch (reg->regpair->reg_domain) {
case 0x60: case 0x60:
case 0x63: case 0x63:
case 0x66: case 0x66:
...@@ -560,7 +560,7 @@ static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg) ...@@ -560,7 +560,7 @@ static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg)
printk(KERN_DEBUG "ath: EEPROM indicates we " printk(KERN_DEBUG "ath: EEPROM indicates we "
"should expect a direct regpair map\n"); "should expect a direct regpair map\n");
for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
if (regDomainPairs[i].regDmnEnum == rd) if (regDomainPairs[i].reg_domain == rd)
return true; return true;
} }
printk(KERN_DEBUG printk(KERN_DEBUG
...@@ -617,7 +617,7 @@ ath_get_regpair(int regdmn) ...@@ -617,7 +617,7 @@ ath_get_regpair(int regdmn)
if (regdmn == NO_ENUMRD) if (regdmn == NO_ENUMRD)
return NULL; return NULL;
for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) { for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
if (regDomainPairs[i].regDmnEnum == regdmn) if (regDomainPairs[i].reg_domain == regdmn)
return &regDomainPairs[i]; return &regDomainPairs[i];
} }
return NULL; return NULL;
...@@ -741,7 +741,7 @@ static int __ath_regd_init(struct ath_regulatory *reg) ...@@ -741,7 +741,7 @@ static int __ath_regd_init(struct ath_regulatory *reg)
printk(KERN_DEBUG "ath: Country alpha2 being used: %c%c\n", printk(KERN_DEBUG "ath: Country alpha2 being used: %c%c\n",
reg->alpha2[0], reg->alpha2[1]); reg->alpha2[0], reg->alpha2[1]);
printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n", printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n",
reg->regpair->regDmnEnum); reg->regpair->reg_domain);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment