mirror of https://gitee.com/openkylin/linux.git
Merge branch 'for-linville' of git://github.com/kvalo/ath
This commit is contained in:
commit
9e4b4269ec
|
@ -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)
|
||||||
{
|
{
|
||||||
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,9 +469,13 @@ 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", "",
|
||||||
ar->fw_features,
|
ar->fw_features,
|
||||||
|
@ -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,
|
||||||
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)
|
||||||
}
|
}
|
||||||
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 @@
|
||||||
|
|
||||||
#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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
u8 bssid[ETH_ALEN];
|
|
||||||
u32 uapsd;
|
u32 uapsd;
|
||||||
} sta;
|
} sta;
|
||||||
struct {
|
struct {
|
||||||
|
@ -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 {
|
||||||
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 {
|
||||||
/* 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,
|
||||||
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);
|
||||||
|
|
|
@ -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,
|
||||||
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,
|
||||||
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)
|
||||||
|
|
||||||
/* 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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
|
|
||||||
/* 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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
/* 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,
|
||||||
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,
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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 {
|
||||||
#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 {
|
||||||
#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 {
|
||||||
#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)
|
||||||
|
|
|
@ -339,6 +339,50 @@ static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ath10k_mac_set_kickout(struct ath10k_vif *arvif)
|
||||||
|
{
|
||||||
|
struct ath10k *ar = arvif->ar;
|
||||||
|
u32 param;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
param = ar->wmi.pdev_param->sta_kickout_th;
|
||||||
|
ret = ath10k_wmi_pdev_set_param(ar, param,
|
||||||
|
ATH10K_KICKOUT_THRESHOLD);
|
||||||
|
if (ret) {
|
||||||
|
ath10k_warn("Failed to set kickout threshold: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
param = ar->wmi.vdev_param->ap_keepalive_min_idle_inactive_time_secs;
|
||||||
|
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param,
|
||||||
|
ATH10K_KEEPALIVE_MIN_IDLE);
|
||||||
|
if (ret) {
|
||||||
|
ath10k_warn("Failed to set keepalive minimum idle time : %d\n",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
param = ar->wmi.vdev_param->ap_keepalive_max_idle_inactive_time_secs;
|
||||||
|
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param,
|
||||||
|
ATH10K_KEEPALIVE_MAX_IDLE);
|
||||||
|
if (ret) {
|
||||||
|
ath10k_warn("Failed to set keepalive maximum idle time: %d\n",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
param = ar->wmi.vdev_param->ap_keepalive_max_unresponsive_time_secs;
|
||||||
|
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param,
|
||||||
|
ATH10K_KEEPALIVE_MAX_UNRESPONSIVE);
|
||||||
|
if (ret) {
|
||||||
|
ath10k_warn("Failed to set keepalive maximum unresponsive time: %d\n",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value)
|
static int ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value)
|
||||||
{
|
{
|
||||||
struct ath10k *ar = arvif->ar;
|
struct ath10k *ar = arvif->ar;
|
||||||
|
@ -444,8 +488,7 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
|
||||||
static int ath10k_vdev_start(struct ath10k_vif *arvif)
|
static int ath10k_vdev_start(struct ath10k_vif *arvif)
|
||||||
{
|
{
|
||||||
struct ath10k *ar = arvif->ar;
|
struct ath10k *ar = arvif->ar;
|
||||||
struct ieee80211_conf *conf = &ar->hw->conf;
|
struct cfg80211_chan_def *chandef = &ar->chandef;
|
||||||
struct ieee80211_channel *channel = conf->chandef.chan;
|
|
||||||
struct wmi_vdev_start_request_arg arg = {};
|
struct wmi_vdev_start_request_arg arg = {};
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -457,16 +500,14 @@ static int ath10k_vdev_start(struct ath10k_vif *arvif)
|
||||||
arg.dtim_period = arvif->dtim_period;
|
arg.dtim_period = arvif->dtim_period;
|
||||||
arg.bcn_intval = arvif->beacon_interval;
|
arg.bcn_intval = arvif->beacon_interval;
|
||||||
|
|
||||||
arg.channel.freq = channel->center_freq;
|
arg.channel.freq = chandef->chan->center_freq;
|
||||||
|
arg.channel.band_center_freq1 = chandef->center_freq1;
|
||||||
arg.channel.band_center_freq1 = conf->chandef.center_freq1;
|
arg.channel.mode = chan_to_phymode(chandef);
|
||||||
|
|
||||||
arg.channel.mode = chan_to_phymode(&conf->chandef);
|
|
||||||
|
|
||||||
arg.channel.min_power = 0;
|
arg.channel.min_power = 0;
|
||||||
arg.channel.max_power = channel->max_power * 2;
|
arg.channel.max_power = chandef->chan->max_power * 2;
|
||||||
arg.channel.max_reg_power = channel->max_reg_power * 2;
|
arg.channel.max_reg_power = chandef->chan->max_reg_power * 2;
|
||||||
arg.channel.max_antenna_gain = channel->max_antenna_gain * 2;
|
arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain * 2;
|
||||||
|
|
||||||
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
|
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
|
||||||
arg.ssid = arvif->u.ap.ssid;
|
arg.ssid = arvif->u.ap.ssid;
|
||||||
|
@ -475,7 +516,7 @@ static int ath10k_vdev_start(struct ath10k_vif *arvif)
|
||||||
|
|
||||||
/* For now allow DFS for AP mode */
|
/* For now allow DFS for AP mode */
|
||||||
arg.channel.chan_radar =
|
arg.channel.chan_radar =
|
||||||
!!(channel->flags & IEEE80211_CHAN_RADAR);
|
!!(chandef->chan->flags & IEEE80211_CHAN_RADAR);
|
||||||
} else if (arvif->vdev_type == WMI_VDEV_TYPE_IBSS) {
|
} else if (arvif->vdev_type == WMI_VDEV_TYPE_IBSS) {
|
||||||
arg.ssid = arvif->vif->bss_conf.ssid;
|
arg.ssid = arvif->vif->bss_conf.ssid;
|
||||||
arg.ssid_len = arvif->vif->bss_conf.ssid_len;
|
arg.ssid_len = arvif->vif->bss_conf.ssid_len;
|
||||||
|
@ -527,7 +568,8 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif)
|
||||||
|
|
||||||
static int ath10k_monitor_start(struct ath10k *ar, int vdev_id)
|
static int ath10k_monitor_start(struct ath10k *ar, int vdev_id)
|
||||||
{
|
{
|
||||||
struct ieee80211_channel *channel = ar->hw->conf.chandef.chan;
|
struct cfg80211_chan_def *chandef = &ar->chandef;
|
||||||
|
struct ieee80211_channel *channel = chandef->chan;
|
||||||
struct wmi_vdev_start_request_arg arg = {};
|
struct wmi_vdev_start_request_arg arg = {};
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -540,11 +582,11 @@ static int ath10k_monitor_start(struct ath10k *ar, int vdev_id)
|
||||||
|
|
||||||
arg.vdev_id = vdev_id;
|
arg.vdev_id = vdev_id;
|
||||||
arg.channel.freq = channel->center_freq;
|
arg.channel.freq = channel->center_freq;
|
||||||
arg.channel.band_center_freq1 = ar->hw->conf.chandef.center_freq1;
|
arg.channel.band_center_freq1 = chandef->center_freq1;
|
||||||
|
|
||||||
/* TODO setup this dynamically, what in case we
|
/* TODO setup this dynamically, what in case we
|
||||||
don't have any vifs? */
|
don't have any vifs? */
|
||||||
arg.channel.mode = chan_to_phymode(&ar->hw->conf.chandef);
|
arg.channel.mode = chan_to_phymode(chandef);
|
||||||
arg.channel.chan_radar =
|
arg.channel.chan_radar =
|
||||||
!!(channel->flags & IEEE80211_CHAN_RADAR);
|
!!(channel->flags & IEEE80211_CHAN_RADAR);
|
||||||
|
|
||||||
|
@ -791,6 +833,20 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif,
|
||||||
|
|
||||||
if (!info->enable_beacon) {
|
if (!info->enable_beacon) {
|
||||||
ath10k_vdev_stop(arvif);
|
ath10k_vdev_stop(arvif);
|
||||||
|
|
||||||
|
arvif->is_started = false;
|
||||||
|
arvif->is_up = false;
|
||||||
|
|
||||||
|
spin_lock_bh(&arvif->ar->data_lock);
|
||||||
|
if (arvif->beacon) {
|
||||||
|
ath10k_skb_unmap(arvif->ar->dev, arvif->beacon);
|
||||||
|
dev_kfree_skb_any(arvif->beacon);
|
||||||
|
|
||||||
|
arvif->beacon = NULL;
|
||||||
|
arvif->beacon_sent = false;
|
||||||
|
}
|
||||||
|
spin_unlock_bh(&arvif->ar->data_lock);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -800,12 +856,21 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif,
|
||||||
if (ret)
|
if (ret)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, 0, info->bssid);
|
arvif->aid = 0;
|
||||||
|
memcpy(arvif->bssid, info->bssid, ETH_ALEN);
|
||||||
|
|
||||||
|
ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
|
||||||
|
arvif->bssid);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ath10k_warn("Failed to bring up VDEV: %d\n",
|
ath10k_warn("Failed to bring up VDEV: %d\n",
|
||||||
arvif->vdev_id);
|
arvif->vdev_id);
|
||||||
|
ath10k_vdev_stop(arvif);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arvif->is_started = true;
|
||||||
|
arvif->is_up = true;
|
||||||
|
|
||||||
ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d up\n", arvif->vdev_id);
|
ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d up\n", arvif->vdev_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -824,18 +889,18 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif,
|
||||||
ath10k_warn("Failed to delete IBSS self peer:%pM for VDEV:%d ret:%d\n",
|
ath10k_warn("Failed to delete IBSS self peer:%pM for VDEV:%d ret:%d\n",
|
||||||
self_peer, arvif->vdev_id, ret);
|
self_peer, arvif->vdev_id, ret);
|
||||||
|
|
||||||
if (is_zero_ether_addr(arvif->u.ibss.bssid))
|
if (is_zero_ether_addr(arvif->bssid))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id,
|
ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id,
|
||||||
arvif->u.ibss.bssid);
|
arvif->bssid);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ath10k_warn("Failed to delete IBSS BSSID peer:%pM for VDEV:%d ret:%d\n",
|
ath10k_warn("Failed to delete IBSS BSSID peer:%pM for VDEV:%d ret:%d\n",
|
||||||
arvif->u.ibss.bssid, arvif->vdev_id, ret);
|
arvif->bssid, arvif->vdev_id, ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(arvif->u.ibss.bssid, 0, ETH_ALEN);
|
memset(arvif->bssid, 0, ETH_ALEN);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1017,7 +1082,6 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
|
||||||
struct wmi_peer_assoc_complete_arg *arg)
|
struct wmi_peer_assoc_complete_arg *arg)
|
||||||
{
|
{
|
||||||
const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
|
const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
|
||||||
int smps;
|
|
||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
lockdep_assert_held(&ar->conf_mutex);
|
lockdep_assert_held(&ar->conf_mutex);
|
||||||
|
@ -1063,17 +1127,6 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
|
||||||
arg->peer_flags |= WMI_PEER_STBC;
|
arg->peer_flags |= WMI_PEER_STBC;
|
||||||
}
|
}
|
||||||
|
|
||||||
smps = ht_cap->cap & IEEE80211_HT_CAP_SM_PS;
|
|
||||||
smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT;
|
|
||||||
|
|
||||||
if (smps == WLAN_HT_CAP_SM_PS_STATIC) {
|
|
||||||
arg->peer_flags |= WMI_PEER_SPATIAL_MUX;
|
|
||||||
arg->peer_flags |= WMI_PEER_STATIC_MIMOPS;
|
|
||||||
} else if (smps == WLAN_HT_CAP_SM_PS_DYNAMIC) {
|
|
||||||
arg->peer_flags |= WMI_PEER_SPATIAL_MUX;
|
|
||||||
arg->peer_flags |= WMI_PEER_DYN_MIMOPS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ht_cap->mcs.rx_mask[1] && ht_cap->mcs.rx_mask[2])
|
if (ht_cap->mcs.rx_mask[1] && ht_cap->mcs.rx_mask[2])
|
||||||
arg->peer_rate_caps |= WMI_RC_TS_FLAG;
|
arg->peer_rate_caps |= WMI_RC_TS_FLAG;
|
||||||
else if (ht_cap->mcs.rx_mask[1])
|
else if (ht_cap->mcs.rx_mask[1])
|
||||||
|
@ -1083,8 +1136,23 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
|
||||||
if (ht_cap->mcs.rx_mask[i/8] & (1 << i%8))
|
if (ht_cap->mcs.rx_mask[i/8] & (1 << i%8))
|
||||||
arg->peer_ht_rates.rates[n++] = i;
|
arg->peer_ht_rates.rates[n++] = i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a workaround for HT-enabled STAs which break the spec
|
||||||
|
* and have no HT capabilities RX mask (no HT RX MCS map).
|
||||||
|
*
|
||||||
|
* As per spec, in section 20.3.5 Modulation and coding scheme (MCS),
|
||||||
|
* MCS 0 through 7 are mandatory in 20MHz with 800 ns GI at all STAs.
|
||||||
|
*
|
||||||
|
* Firmware asserts if such situation occurs.
|
||||||
|
*/
|
||||||
|
if (n == 0) {
|
||||||
|
arg->peer_ht_rates.num_rates = 8;
|
||||||
|
for (i = 0; i < arg->peer_ht_rates.num_rates; i++)
|
||||||
|
arg->peer_ht_rates.rates[i] = i;
|
||||||
|
} else {
|
||||||
arg->peer_ht_rates.num_rates = n;
|
arg->peer_ht_rates.num_rates = n;
|
||||||
arg->peer_num_spatial_streams = max((n+7) / 8, 1);
|
arg->peer_num_spatial_streams = sta->rx_nss;
|
||||||
|
}
|
||||||
|
|
||||||
ath10k_dbg(ATH10K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n",
|
ath10k_dbg(ATH10K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n",
|
||||||
arg->addr,
|
arg->addr,
|
||||||
|
@ -1092,27 +1160,20 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
|
||||||
arg->peer_num_spatial_streams);
|
arg->peer_num_spatial_streams);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath10k_peer_assoc_h_qos_ap(struct ath10k *ar,
|
static int ath10k_peer_assoc_qos_ap(struct ath10k *ar,
|
||||||
struct ath10k_vif *arvif,
|
struct ath10k_vif *arvif,
|
||||||
struct ieee80211_sta *sta,
|
struct ieee80211_sta *sta)
|
||||||
struct ieee80211_bss_conf *bss_conf,
|
|
||||||
struct wmi_peer_assoc_complete_arg *arg)
|
|
||||||
{
|
{
|
||||||
u32 uapsd = 0;
|
u32 uapsd = 0;
|
||||||
u32 max_sp = 0;
|
u32 max_sp = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
lockdep_assert_held(&ar->conf_mutex);
|
lockdep_assert_held(&ar->conf_mutex);
|
||||||
|
|
||||||
if (sta->wme)
|
|
||||||
arg->peer_flags |= WMI_PEER_QOS;
|
|
||||||
|
|
||||||
if (sta->wme && sta->uapsd_queues) {
|
if (sta->wme && sta->uapsd_queues) {
|
||||||
ath10k_dbg(ATH10K_DBG_MAC, "mac uapsd_queues 0x%x max_sp %d\n",
|
ath10k_dbg(ATH10K_DBG_MAC, "mac uapsd_queues 0x%x max_sp %d\n",
|
||||||
sta->uapsd_queues, sta->max_sp);
|
sta->uapsd_queues, sta->max_sp);
|
||||||
|
|
||||||
arg->peer_flags |= WMI_PEER_APSD;
|
|
||||||
arg->peer_rate_caps |= WMI_RC_UAPSD_FLAG;
|
|
||||||
|
|
||||||
if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
|
if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
|
||||||
uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN |
|
uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN |
|
||||||
WMI_AP_PS_UAPSD_AC3_TRIGGER_EN;
|
WMI_AP_PS_UAPSD_AC3_TRIGGER_EN;
|
||||||
|
@ -1130,35 +1191,40 @@ static void ath10k_peer_assoc_h_qos_ap(struct ath10k *ar,
|
||||||
if (sta->max_sp < MAX_WMI_AP_PS_PEER_PARAM_MAX_SP)
|
if (sta->max_sp < MAX_WMI_AP_PS_PEER_PARAM_MAX_SP)
|
||||||
max_sp = sta->max_sp;
|
max_sp = sta->max_sp;
|
||||||
|
|
||||||
ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id,
|
ret = ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id,
|
||||||
sta->addr,
|
sta->addr,
|
||||||
WMI_AP_PS_PEER_PARAM_UAPSD,
|
WMI_AP_PS_PEER_PARAM_UAPSD,
|
||||||
uapsd);
|
uapsd);
|
||||||
|
if (ret) {
|
||||||
|
ath10k_warn("failed to set ap ps peer param uapsd: %d\n",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id,
|
ret = ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id,
|
||||||
sta->addr,
|
sta->addr,
|
||||||
WMI_AP_PS_PEER_PARAM_MAX_SP,
|
WMI_AP_PS_PEER_PARAM_MAX_SP,
|
||||||
max_sp);
|
max_sp);
|
||||||
|
if (ret) {
|
||||||
|
ath10k_warn("failed to set ap ps peer param max sp: %d\n",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO setup this based on STA listen interval and
|
/* TODO setup this based on STA listen interval and
|
||||||
beacon interval. Currently we don't know
|
beacon interval. Currently we don't know
|
||||||
sta->listen_interval - mac80211 patch required.
|
sta->listen_interval - mac80211 patch required.
|
||||||
Currently use 10 seconds */
|
Currently use 10 seconds */
|
||||||
ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id,
|
ret = ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id, sta->addr,
|
||||||
sta->addr,
|
WMI_AP_PS_PEER_PARAM_AGEOUT_TIME, 10);
|
||||||
WMI_AP_PS_PEER_PARAM_AGEOUT_TIME,
|
if (ret) {
|
||||||
10);
|
ath10k_warn("failed to set ap ps peer param ageout time: %d\n",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath10k_peer_assoc_h_qos_sta(struct ath10k *ar,
|
return 0;
|
||||||
struct ath10k_vif *arvif,
|
|
||||||
struct ieee80211_sta *sta,
|
|
||||||
struct ieee80211_bss_conf *bss_conf,
|
|
||||||
struct wmi_peer_assoc_complete_arg *arg)
|
|
||||||
{
|
|
||||||
if (bss_conf->qos)
|
|
||||||
arg->peer_flags |= WMI_PEER_QOS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
|
static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
|
||||||
|
@ -1211,10 +1277,17 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
|
||||||
{
|
{
|
||||||
switch (arvif->vdev_type) {
|
switch (arvif->vdev_type) {
|
||||||
case WMI_VDEV_TYPE_AP:
|
case WMI_VDEV_TYPE_AP:
|
||||||
ath10k_peer_assoc_h_qos_ap(ar, arvif, sta, bss_conf, arg);
|
if (sta->wme)
|
||||||
|
arg->peer_flags |= WMI_PEER_QOS;
|
||||||
|
|
||||||
|
if (sta->wme && sta->uapsd_queues) {
|
||||||
|
arg->peer_flags |= WMI_PEER_APSD;
|
||||||
|
arg->peer_rate_caps |= WMI_RC_UAPSD_FLAG;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case WMI_VDEV_TYPE_STA:
|
case WMI_VDEV_TYPE_STA:
|
||||||
ath10k_peer_assoc_h_qos_sta(ar, arvif, sta, bss_conf, arg);
|
if (bss_conf->qos)
|
||||||
|
arg->peer_flags |= WMI_PEER_QOS;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1293,6 +1366,33 @@ static int ath10k_peer_assoc_prepare(struct ath10k *ar,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const u32 ath10k_smps_map[] = {
|
||||||
|
[WLAN_HT_CAP_SM_PS_STATIC] = WMI_PEER_SMPS_STATIC,
|
||||||
|
[WLAN_HT_CAP_SM_PS_DYNAMIC] = WMI_PEER_SMPS_DYNAMIC,
|
||||||
|
[WLAN_HT_CAP_SM_PS_INVALID] = WMI_PEER_SMPS_PS_NONE,
|
||||||
|
[WLAN_HT_CAP_SM_PS_DISABLED] = WMI_PEER_SMPS_PS_NONE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ath10k_setup_peer_smps(struct ath10k *ar, struct ath10k_vif *arvif,
|
||||||
|
const u8 *addr,
|
||||||
|
const struct ieee80211_sta_ht_cap *ht_cap)
|
||||||
|
{
|
||||||
|
int smps;
|
||||||
|
|
||||||
|
if (!ht_cap->ht_supported)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
smps = ht_cap->cap & IEEE80211_HT_CAP_SM_PS;
|
||||||
|
smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT;
|
||||||
|
|
||||||
|
if (smps >= ARRAY_SIZE(ath10k_smps_map))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return ath10k_wmi_peer_set_param(ar, arvif->vdev_id, addr,
|
||||||
|
WMI_PEER_SMPS_STATE,
|
||||||
|
ath10k_smps_map[smps]);
|
||||||
|
}
|
||||||
|
|
||||||
/* can be called only in mac80211 callbacks due to `key_count` usage */
|
/* can be called only in mac80211 callbacks due to `key_count` usage */
|
||||||
static void ath10k_bss_assoc(struct ieee80211_hw *hw,
|
static void ath10k_bss_assoc(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
|
@ -1300,6 +1400,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
|
||||||
{
|
{
|
||||||
struct ath10k *ar = hw->priv;
|
struct ath10k *ar = hw->priv;
|
||||||
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
|
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
|
||||||
|
struct ieee80211_sta_ht_cap ht_cap;
|
||||||
struct wmi_peer_assoc_complete_arg peer_arg;
|
struct wmi_peer_assoc_complete_arg peer_arg;
|
||||||
struct ieee80211_sta *ap_sta;
|
struct ieee80211_sta *ap_sta;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1316,6 +1417,10 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ap_sta must be accessed only within rcu section which must be left
|
||||||
|
* before calling ath10k_setup_peer_smps() which might sleep. */
|
||||||
|
ht_cap = ap_sta->ht_cap;
|
||||||
|
|
||||||
ret = ath10k_peer_assoc_prepare(ar, arvif, ap_sta,
|
ret = ath10k_peer_assoc_prepare(ar, arvif, ap_sta,
|
||||||
bss_conf, &peer_arg);
|
bss_conf, &peer_arg);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -1334,15 +1439,27 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = ath10k_setup_peer_smps(ar, arvif, bss_conf->bssid, &ht_cap);
|
||||||
|
if (ret) {
|
||||||
|
ath10k_warn("failed to setup peer SMPS: %d\n", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ath10k_dbg(ATH10K_DBG_MAC,
|
ath10k_dbg(ATH10K_DBG_MAC,
|
||||||
"mac vdev %d up (associated) bssid %pM aid %d\n",
|
"mac vdev %d up (associated) bssid %pM aid %d\n",
|
||||||
arvif->vdev_id, bss_conf->bssid, bss_conf->aid);
|
arvif->vdev_id, bss_conf->bssid, bss_conf->aid);
|
||||||
|
|
||||||
ret = ath10k_wmi_vdev_up(ar, arvif->vdev_id, bss_conf->aid,
|
arvif->aid = bss_conf->aid;
|
||||||
bss_conf->bssid);
|
memcpy(arvif->bssid, bss_conf->bssid, ETH_ALEN);
|
||||||
if (ret)
|
|
||||||
|
ret = ath10k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid);
|
||||||
|
if (ret) {
|
||||||
ath10k_warn("VDEV: %d up failed: ret %d\n",
|
ath10k_warn("VDEV: %d up failed: ret %d\n",
|
||||||
arvif->vdev_id, ret);
|
arvif->vdev_id, ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
arvif->is_up = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1382,6 +1499,9 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
|
||||||
ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
|
ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
|
||||||
|
|
||||||
arvif->def_wep_key_idx = 0;
|
arvif->def_wep_key_idx = 0;
|
||||||
|
|
||||||
|
arvif->is_started = false;
|
||||||
|
arvif->is_up = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif,
|
static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif,
|
||||||
|
@ -1406,12 +1526,25 @@ static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = ath10k_setup_peer_smps(ar, arvif, sta->addr, &sta->ht_cap);
|
||||||
|
if (ret) {
|
||||||
|
ath10k_warn("failed to setup peer SMPS: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = ath10k_install_peer_wep_keys(arvif, sta->addr);
|
ret = ath10k_install_peer_wep_keys(arvif, sta->addr);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ath10k_warn("could not install peer wep keys (%d)\n", ret);
|
ath10k_warn("could not install peer wep keys (%d)\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta);
|
||||||
|
if (ret) {
|
||||||
|
ath10k_warn("could not set qos params for STA %pM, %d\n",
|
||||||
|
sta->addr, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1547,9 +1680,9 @@ static void ath10k_regd_update(struct ath10k *ar)
|
||||||
/* Target allows setting up per-band regdomain but ath_common provides
|
/* Target allows setting up per-band regdomain but ath_common provides
|
||||||
* a combined one only */
|
* a combined one only */
|
||||||
ret = ath10k_wmi_pdev_set_regdomain(ar,
|
ret = ath10k_wmi_pdev_set_regdomain(ar,
|
||||||
regpair->regDmnEnum,
|
regpair->reg_domain,
|
||||||
regpair->regDmnEnum, /* 2ghz */
|
regpair->reg_domain, /* 2ghz */
|
||||||
regpair->regDmnEnum, /* 5ghz */
|
regpair->reg_domain, /* 5ghz */
|
||||||
regpair->reg_2ghz_ctl,
|
regpair->reg_2ghz_ctl,
|
||||||
regpair->reg_5ghz_ctl);
|
regpair->reg_5ghz_ctl);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -2100,11 +2233,29 @@ static int ath10k_start(struct ieee80211_hw *hw)
|
||||||
ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n",
|
ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n",
|
||||||
ret);
|
ret);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* By default FW set ARP frames ac to voice (6). In that case ARP
|
||||||
|
* exchange is not working properly for UAPSD enabled AP. ARP requests
|
||||||
|
* which arrives with access category 0 are processed by network stack
|
||||||
|
* and send back with access category 0, but FW changes access category
|
||||||
|
* to 6. Set ARP frames access category to best effort (0) solves
|
||||||
|
* this problem.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = ath10k_wmi_pdev_set_param(ar,
|
||||||
|
ar->wmi.pdev_param->arp_ac_override, 0);
|
||||||
|
if (ret) {
|
||||||
|
ath10k_warn("could not set arp ac override parameter: %d\n",
|
||||||
|
ret);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
ath10k_regd_update(ar);
|
ath10k_regd_update(ar);
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
mutex_unlock(&ar->conf_mutex);
|
mutex_unlock(&ar->conf_mutex);
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath10k_stop(struct ieee80211_hw *hw)
|
static void ath10k_stop(struct ieee80211_hw *hw)
|
||||||
|
@ -2145,6 +2296,98 @@ static int ath10k_config_ps(struct ath10k *ar)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *chandef_get_width(enum nl80211_chan_width width)
|
||||||
|
{
|
||||||
|
switch (width) {
|
||||||
|
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||||
|
return "20 (noht)";
|
||||||
|
case NL80211_CHAN_WIDTH_20:
|
||||||
|
return "20";
|
||||||
|
case NL80211_CHAN_WIDTH_40:
|
||||||
|
return "40";
|
||||||
|
case NL80211_CHAN_WIDTH_80:
|
||||||
|
return "80";
|
||||||
|
case NL80211_CHAN_WIDTH_80P80:
|
||||||
|
return "80+80";
|
||||||
|
case NL80211_CHAN_WIDTH_160:
|
||||||
|
return "160";
|
||||||
|
case NL80211_CHAN_WIDTH_5:
|
||||||
|
return "5";
|
||||||
|
case NL80211_CHAN_WIDTH_10:
|
||||||
|
return "10";
|
||||||
|
}
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ath10k_config_chan(struct ath10k *ar)
|
||||||
|
{
|
||||||
|
struct ath10k_vif *arvif;
|
||||||
|
bool monitor_was_enabled;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
lockdep_assert_held(&ar->conf_mutex);
|
||||||
|
|
||||||
|
ath10k_dbg(ATH10K_DBG_MAC,
|
||||||
|
"mac config channel to %dMHz (cf1 %dMHz cf2 %dMHz width %s)\n",
|
||||||
|
ar->chandef.chan->center_freq,
|
||||||
|
ar->chandef.center_freq1,
|
||||||
|
ar->chandef.center_freq2,
|
||||||
|
chandef_get_width(ar->chandef.width));
|
||||||
|
|
||||||
|
/* First stop monitor interface. Some FW versions crash if there's a
|
||||||
|
* lone monitor interface. */
|
||||||
|
monitor_was_enabled = ar->monitor_enabled;
|
||||||
|
|
||||||
|
if (ar->monitor_enabled)
|
||||||
|
ath10k_monitor_stop(ar);
|
||||||
|
|
||||||
|
list_for_each_entry(arvif, &ar->arvifs, list) {
|
||||||
|
if (!arvif->is_started)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = ath10k_vdev_stop(arvif);
|
||||||
|
if (ret) {
|
||||||
|
ath10k_warn("could not stop vdev %d (%d)\n",
|
||||||
|
arvif->vdev_id, ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* all vdevs are now stopped - now attempt to restart them */
|
||||||
|
|
||||||
|
list_for_each_entry(arvif, &ar->arvifs, list) {
|
||||||
|
if (!arvif->is_started)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = ath10k_vdev_start(arvif);
|
||||||
|
if (ret) {
|
||||||
|
ath10k_warn("could not start vdev %d (%d)\n",
|
||||||
|
arvif->vdev_id, ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!arvif->is_up)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
|
||||||
|
arvif->bssid);
|
||||||
|
if (ret) {
|
||||||
|
ath10k_warn("could not bring vdev up %d (%d)\n",
|
||||||
|
arvif->vdev_id, ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (monitor_was_enabled)
|
||||||
|
ath10k_monitor_start(ar, ar->monitor_vdev_id);
|
||||||
|
}
|
||||||
|
|
||||||
static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
|
static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
|
||||||
{
|
{
|
||||||
struct ath10k *ar = hw->priv;
|
struct ath10k *ar = hw->priv;
|
||||||
|
@ -2165,6 +2408,11 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
|
||||||
spin_unlock_bh(&ar->data_lock);
|
spin_unlock_bh(&ar->data_lock);
|
||||||
|
|
||||||
ath10k_config_radar_detection(ar);
|
ath10k_config_radar_detection(ar);
|
||||||
|
|
||||||
|
if (!cfg80211_chandef_identical(&ar->chandef, &conf->chandef)) {
|
||||||
|
ar->chandef = conf->chandef;
|
||||||
|
ath10k_config_chan(ar);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed & IEEE80211_CONF_CHANGE_POWER) {
|
if (changed & IEEE80211_CONF_CHANGE_POWER) {
|
||||||
|
@ -2214,7 +2462,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
||||||
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
|
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
|
||||||
enum wmi_sta_powersave_param param;
|
enum wmi_sta_powersave_param param;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
u32 value, param_id;
|
u32 value;
|
||||||
int bit;
|
int bit;
|
||||||
u32 vdev_param;
|
u32 vdev_param;
|
||||||
|
|
||||||
|
@ -2307,12 +2555,12 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
||||||
goto err_vdev_delete;
|
goto err_vdev_delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
param_id = ar->wmi.pdev_param->sta_kickout_th;
|
ret = ath10k_mac_set_kickout(arvif);
|
||||||
|
if (ret) {
|
||||||
/* Disable STA KICKOUT functionality in FW */
|
ath10k_warn("Failed to set kickout parameters: %d\n",
|
||||||
ret = ath10k_wmi_pdev_set_param(ar, param_id, 0);
|
ret);
|
||||||
if (ret)
|
goto err_peer_delete;
|
||||||
ath10k_warn("Failed to disable STA KICKOUT\n");
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arvif->vdev_type == WMI_VDEV_TYPE_STA) {
|
if (arvif->vdev_type == WMI_VDEV_TYPE_STA) {
|
||||||
|
@ -2559,15 +2807,20 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
|
||||||
* this is never erased as we it for crypto key
|
* this is never erased as we it for crypto key
|
||||||
* clearing; this is FW requirement
|
* clearing; this is FW requirement
|
||||||
*/
|
*/
|
||||||
memcpy(arvif->u.sta.bssid, info->bssid,
|
memcpy(arvif->bssid, info->bssid, ETH_ALEN);
|
||||||
ETH_ALEN);
|
|
||||||
|
|
||||||
ath10k_dbg(ATH10K_DBG_MAC,
|
ath10k_dbg(ATH10K_DBG_MAC,
|
||||||
"mac vdev %d start %pM\n",
|
"mac vdev %d start %pM\n",
|
||||||
arvif->vdev_id, info->bssid);
|
arvif->vdev_id, info->bssid);
|
||||||
|
|
||||||
/* FIXME: check return value */
|
|
||||||
ret = ath10k_vdev_start(arvif);
|
ret = ath10k_vdev_start(arvif);
|
||||||
|
if (ret) {
|
||||||
|
ath10k_warn("failed to start vdev: %d\n",
|
||||||
|
ret);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
arvif->is_started = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2576,7 +2829,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
|
||||||
* IBSS in order to remove BSSID peer.
|
* IBSS in order to remove BSSID peer.
|
||||||
*/
|
*/
|
||||||
if (vif->type == NL80211_IFTYPE_ADHOC)
|
if (vif->type == NL80211_IFTYPE_ADHOC)
|
||||||
memcpy(arvif->u.ibss.bssid, info->bssid,
|
memcpy(arvif->bssid, info->bssid,
|
||||||
ETH_ALEN);
|
ETH_ALEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2645,6 +2898,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
|
||||||
ath10k_bss_assoc(hw, vif, info);
|
ath10k_bss_assoc(hw, vif, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
mutex_unlock(&ar->conf_mutex);
|
mutex_unlock(&ar->conf_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2850,6 +3104,69 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ath10k_sta_rc_update_wk(struct work_struct *wk)
|
||||||
|
{
|
||||||
|
struct ath10k *ar;
|
||||||
|
struct ath10k_vif *arvif;
|
||||||
|
struct ath10k_sta *arsta;
|
||||||
|
struct ieee80211_sta *sta;
|
||||||
|
u32 changed, bw, nss, smps;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
arsta = container_of(wk, struct ath10k_sta, update_wk);
|
||||||
|
sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
|
||||||
|
arvif = arsta->arvif;
|
||||||
|
ar = arvif->ar;
|
||||||
|
|
||||||
|
spin_lock_bh(&ar->data_lock);
|
||||||
|
|
||||||
|
changed = arsta->changed;
|
||||||
|
arsta->changed = 0;
|
||||||
|
|
||||||
|
bw = arsta->bw;
|
||||||
|
nss = arsta->nss;
|
||||||
|
smps = arsta->smps;
|
||||||
|
|
||||||
|
spin_unlock_bh(&ar->data_lock);
|
||||||
|
|
||||||
|
mutex_lock(&ar->conf_mutex);
|
||||||
|
|
||||||
|
if (changed & IEEE80211_RC_BW_CHANGED) {
|
||||||
|
ath10k_dbg(ATH10K_DBG_MAC, "mac update sta %pM peer bw %d\n",
|
||||||
|
sta->addr, bw);
|
||||||
|
|
||||||
|
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||||
|
WMI_PEER_CHAN_WIDTH, bw);
|
||||||
|
if (err)
|
||||||
|
ath10k_warn("failed to update STA %pM peer bw %d: %d\n",
|
||||||
|
sta->addr, bw, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed & IEEE80211_RC_NSS_CHANGED) {
|
||||||
|
ath10k_dbg(ATH10K_DBG_MAC, "mac update sta %pM nss %d\n",
|
||||||
|
sta->addr, nss);
|
||||||
|
|
||||||
|
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||||
|
WMI_PEER_NSS, nss);
|
||||||
|
if (err)
|
||||||
|
ath10k_warn("failed to update STA %pM nss %d: %d\n",
|
||||||
|
sta->addr, nss, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed & IEEE80211_RC_SMPS_CHANGED) {
|
||||||
|
ath10k_dbg(ATH10K_DBG_MAC, "mac update sta %pM smps %d\n",
|
||||||
|
sta->addr, smps);
|
||||||
|
|
||||||
|
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||||
|
WMI_PEER_SMPS_STATE, smps);
|
||||||
|
if (err)
|
||||||
|
ath10k_warn("failed to update STA %pM smps %d: %d\n",
|
||||||
|
sta->addr, smps, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&ar->conf_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
static int ath10k_sta_state(struct ieee80211_hw *hw,
|
static int ath10k_sta_state(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta,
|
struct ieee80211_sta *sta,
|
||||||
|
@ -2858,9 +3175,15 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
|
||||||
{
|
{
|
||||||
struct ath10k *ar = hw->priv;
|
struct ath10k *ar = hw->priv;
|
||||||
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
|
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
|
||||||
|
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
|
||||||
int max_num_peers;
|
int max_num_peers;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
/* cancel must be done outside the mutex to avoid deadlock */
|
||||||
|
if ((old_state == IEEE80211_STA_NONE &&
|
||||||
|
new_state == IEEE80211_STA_NOTEXIST))
|
||||||
|
cancel_work_sync(&arsta->update_wk);
|
||||||
|
|
||||||
mutex_lock(&ar->conf_mutex);
|
mutex_lock(&ar->conf_mutex);
|
||||||
|
|
||||||
if (old_state == IEEE80211_STA_NOTEXIST &&
|
if (old_state == IEEE80211_STA_NOTEXIST &&
|
||||||
|
@ -2885,6 +3208,10 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
|
||||||
"mac vdev %d peer create %pM (new sta) num_peers %d\n",
|
"mac vdev %d peer create %pM (new sta) num_peers %d\n",
|
||||||
arvif->vdev_id, sta->addr, ar->num_peers);
|
arvif->vdev_id, sta->addr, ar->num_peers);
|
||||||
|
|
||||||
|
memset(arsta, 0, sizeof(*arsta));
|
||||||
|
arsta->arvif = arvif;
|
||||||
|
INIT_WORK(&arsta->update_wk, ath10k_sta_rc_update_wk);
|
||||||
|
|
||||||
ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr);
|
ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr);
|
||||||
if (ret)
|
if (ret)
|
||||||
ath10k_warn("Failed to add peer %pM for vdev %d when adding a new sta: %i\n",
|
ath10k_warn("Failed to add peer %pM for vdev %d when adding a new sta: %i\n",
|
||||||
|
@ -3234,23 +3561,14 @@ static int ath10k_suspend(struct ieee80211_hw *hw,
|
||||||
struct ath10k *ar = hw->priv;
|
struct ath10k *ar = hw->priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ar->is_target_paused = false;
|
mutex_lock(&ar->conf_mutex);
|
||||||
|
|
||||||
ret = ath10k_wmi_pdev_suspend_target(ar);
|
ret = ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ath10k_warn("could not suspend target (%d)\n", ret);
|
if (ret == -ETIMEDOUT)
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = wait_event_interruptible_timeout(ar->event_queue,
|
|
||||||
ar->is_target_paused == true,
|
|
||||||
1 * HZ);
|
|
||||||
if (ret < 0) {
|
|
||||||
ath10k_warn("suspend interrupted (%d)\n", ret);
|
|
||||||
goto resume;
|
|
||||||
} else if (ret == 0) {
|
|
||||||
ath10k_warn("suspend timed out - target pause event never came\n");
|
|
||||||
goto resume;
|
goto resume;
|
||||||
|
ret = 1;
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ath10k_hif_suspend(ar);
|
ret = ath10k_hif_suspend(ar);
|
||||||
|
@ -3259,12 +3577,17 @@ static int ath10k_suspend(struct ieee80211_hw *hw,
|
||||||
goto resume;
|
goto resume;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
ret = 0;
|
||||||
|
goto exit;
|
||||||
resume:
|
resume:
|
||||||
ret = ath10k_wmi_pdev_resume_target(ar);
|
ret = ath10k_wmi_pdev_resume_target(ar);
|
||||||
if (ret)
|
if (ret)
|
||||||
ath10k_warn("could not resume target (%d)\n", ret);
|
ath10k_warn("could not resume target (%d)\n", ret);
|
||||||
return 1;
|
|
||||||
|
ret = 1;
|
||||||
|
exit:
|
||||||
|
mutex_unlock(&ar->conf_mutex);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ath10k_resume(struct ieee80211_hw *hw)
|
static int ath10k_resume(struct ieee80211_hw *hw)
|
||||||
|
@ -3272,19 +3595,26 @@ static int ath10k_resume(struct ieee80211_hw *hw)
|
||||||
struct ath10k *ar = hw->priv;
|
struct ath10k *ar = hw->priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&ar->conf_mutex);
|
||||||
|
|
||||||
ret = ath10k_hif_resume(ar);
|
ret = ath10k_hif_resume(ar);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ath10k_warn("could not resume hif (%d)\n", ret);
|
ath10k_warn("could not resume hif (%d)\n", ret);
|
||||||
return 1;
|
ret = 1;
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ath10k_wmi_pdev_resume_target(ar);
|
ret = ath10k_wmi_pdev_resume_target(ar);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ath10k_warn("could not resume target (%d)\n", ret);
|
ath10k_warn("could not resume target (%d)\n", ret);
|
||||||
return 1;
|
ret = 1;
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
ret = 0;
|
||||||
|
exit:
|
||||||
|
mutex_unlock(&ar->conf_mutex);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3640,6 +3970,96 @@ static int ath10k_set_bitrate_mask(struct ieee80211_hw *hw,
|
||||||
return ath10k_set_fixed_rate_param(arvif, fixed_rate, fixed_nss);
|
return ath10k_set_fixed_rate_param(arvif, fixed_rate, fixed_nss);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ath10k_channel_switch_beacon(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct cfg80211_chan_def *chandef)
|
||||||
|
{
|
||||||
|
/* there's no need to do anything here. vif->csa_active is enough */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_sta *sta,
|
||||||
|
u32 changed)
|
||||||
|
{
|
||||||
|
struct ath10k *ar = hw->priv;
|
||||||
|
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
|
||||||
|
u32 bw, smps;
|
||||||
|
|
||||||
|
spin_lock_bh(&ar->data_lock);
|
||||||
|
|
||||||
|
ath10k_dbg(ATH10K_DBG_MAC,
|
||||||
|
"mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
|
||||||
|
sta->addr, changed, sta->bandwidth, sta->rx_nss,
|
||||||
|
sta->smps_mode);
|
||||||
|
|
||||||
|
if (changed & IEEE80211_RC_BW_CHANGED) {
|
||||||
|
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||||
|
|
||||||
|
switch (sta->bandwidth) {
|
||||||
|
case IEEE80211_STA_RX_BW_20:
|
||||||
|
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||||
|
break;
|
||||||
|
case IEEE80211_STA_RX_BW_40:
|
||||||
|
bw = WMI_PEER_CHWIDTH_40MHZ;
|
||||||
|
break;
|
||||||
|
case IEEE80211_STA_RX_BW_80:
|
||||||
|
bw = WMI_PEER_CHWIDTH_80MHZ;
|
||||||
|
break;
|
||||||
|
case IEEE80211_STA_RX_BW_160:
|
||||||
|
ath10k_warn("mac sta rc update for %pM: invalid bw %d\n",
|
||||||
|
sta->addr, sta->bandwidth);
|
||||||
|
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
arsta->bw = bw;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed & IEEE80211_RC_NSS_CHANGED)
|
||||||
|
arsta->nss = sta->rx_nss;
|
||||||
|
|
||||||
|
if (changed & IEEE80211_RC_SMPS_CHANGED) {
|
||||||
|
smps = WMI_PEER_SMPS_PS_NONE;
|
||||||
|
|
||||||
|
switch (sta->smps_mode) {
|
||||||
|
case IEEE80211_SMPS_AUTOMATIC:
|
||||||
|
case IEEE80211_SMPS_OFF:
|
||||||
|
smps = WMI_PEER_SMPS_PS_NONE;
|
||||||
|
break;
|
||||||
|
case IEEE80211_SMPS_STATIC:
|
||||||
|
smps = WMI_PEER_SMPS_STATIC;
|
||||||
|
break;
|
||||||
|
case IEEE80211_SMPS_DYNAMIC:
|
||||||
|
smps = WMI_PEER_SMPS_DYNAMIC;
|
||||||
|
break;
|
||||||
|
case IEEE80211_SMPS_NUM_MODES:
|
||||||
|
ath10k_warn("mac sta rc update for %pM: invalid smps: %d\n",
|
||||||
|
sta->addr, sta->smps_mode);
|
||||||
|
smps = WMI_PEER_SMPS_PS_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
arsta->smps = smps;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
|
||||||
|
/* FIXME: Not implemented. Probably the only way to do it would
|
||||||
|
* be to re-assoc the peer. */
|
||||||
|
changed &= ~IEEE80211_RC_SUPP_RATES_CHANGED;
|
||||||
|
ath10k_dbg(ATH10K_DBG_MAC,
|
||||||
|
"mac sta rc update for %pM: changing supported rates not implemented\n",
|
||||||
|
sta->addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
arsta->changed |= changed;
|
||||||
|
|
||||||
|
spin_unlock_bh(&ar->data_lock);
|
||||||
|
|
||||||
|
ieee80211_queue_work(hw, &arsta->update_wk);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct ieee80211_ops ath10k_ops = {
|
static const struct ieee80211_ops ath10k_ops = {
|
||||||
.tx = ath10k_tx,
|
.tx = ath10k_tx,
|
||||||
.start = ath10k_start,
|
.start = ath10k_start,
|
||||||
|
@ -3663,6 +4083,8 @@ static const struct ieee80211_ops ath10k_ops = {
|
||||||
.restart_complete = ath10k_restart_complete,
|
.restart_complete = ath10k_restart_complete,
|
||||||
.get_survey = ath10k_get_survey,
|
.get_survey = ath10k_get_survey,
|
||||||
.set_bitrate_mask = ath10k_set_bitrate_mask,
|
.set_bitrate_mask = ath10k_set_bitrate_mask,
|
||||||
|
.channel_switch_beacon = ath10k_channel_switch_beacon,
|
||||||
|
.sta_rc_update = ath10k_sta_rc_update,
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
.suspend = ath10k_suspend,
|
.suspend = ath10k_suspend,
|
||||||
.resume = ath10k_resume,
|
.resume = ath10k_resume,
|
||||||
|
@ -4038,10 +4460,12 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||||
ar->hw->wiphy->max_scan_ie_len = WLAN_SCAN_PARAMS_MAX_IE_LEN;
|
ar->hw->wiphy->max_scan_ie_len = WLAN_SCAN_PARAMS_MAX_IE_LEN;
|
||||||
|
|
||||||
ar->hw->vif_data_size = sizeof(struct ath10k_vif);
|
ar->hw->vif_data_size = sizeof(struct ath10k_vif);
|
||||||
|
ar->hw->sta_data_size = sizeof(struct ath10k_sta);
|
||||||
|
|
||||||
ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL;
|
ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL;
|
||||||
|
|
||||||
ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
|
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;
|
ar->hw->wiphy->max_remain_on_channel_duration = 5000;
|
||||||
|
|
||||||
ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
|
ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
|
||||||
|
|
|
@ -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)
|
||||||
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)
|
||||||
* 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)
|
||||||
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)
|
||||||
* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
/* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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 = {
|
||||||
.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 = {
|
||||||
.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 = {
|
||||||
.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,
|
||||||
|
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
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) {
|
||||||
|
if (!arvif->beacon_sent)
|
||||||
ath10k_warn("SWBA overrun on vdev %d\n",
|
ath10k_warn("SWBA overrun on vdev %d\n",
|
||||||
arvif->vdev_id);
|
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)
|
||||||
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,
|
||||||
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)
|
||||||
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,
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
__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);
|
||||||
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,
|
||||||
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 @@
|
||||||
/* 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)
|
||||||
* 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)
|
||||||
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 ®DomainPairs[i];
|
return ®DomainPairs[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
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 ®DomainPairs[i];
|
return ®DomainPairs[i];
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue