Commit 500ff9f9 authored by Michal Kazior's avatar Michal Kazior Committed by Kalle Valo
Browse files

ath10k: implement chanctx API



The chanctx API will allow ath10k to support
multi-channel operation.
Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 0a27347e
......@@ -284,6 +284,15 @@ struct ath10k_sta {
#endif
};
struct ath10k_chanctx {
/* Used to story copy of chanctx_conf to avoid inconsistencies. Ideally
* mac80211 should allow some sort of explicit locking to guarantee
* that the publicly available chanctx_conf can be accessed safely at
* all times.
*/
struct ieee80211_chanctx_conf conf;
};
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ)
enum ath10k_beacon_state {
......@@ -607,6 +616,7 @@ struct ath10k {
struct cfg80211_chan_def chandef;
unsigned long long free_vdev_map;
struct ath10k_vif *monitor_arvif;
bool monitor;
int monitor_vdev_id;
bool monitor_started;
......
......@@ -723,8 +723,87 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
}
}
static struct ieee80211_channel *
ath10k_htt_rx_h_peer_channel(struct ath10k *ar, struct htt_rx_desc *rxd)
{
struct ath10k_peer *peer;
struct ath10k_vif *arvif;
struct cfg80211_chan_def def;
u16 peer_id;
lockdep_assert_held(&ar->data_lock);
if (!rxd)
return NULL;
if (rxd->attention.flags &
__cpu_to_le32(RX_ATTENTION_FLAGS_PEER_IDX_INVALID))
return NULL;
if (!(rxd->msdu_end.info0 &
__cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU)))
return NULL;
peer_id = MS(__le32_to_cpu(rxd->mpdu_start.info0),
RX_MPDU_START_INFO0_PEER_IDX);
peer = ath10k_peer_find_by_id(ar, peer_id);
if (!peer)
return NULL;
arvif = ath10k_get_arvif(ar, peer->vdev_id);
if (WARN_ON_ONCE(!arvif))
return NULL;
if (WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def)))
return NULL;
return def.chan;
}
static struct ieee80211_channel *
ath10k_htt_rx_h_vdev_channel(struct ath10k *ar, u32 vdev_id)
{
struct ath10k_vif *arvif;
struct cfg80211_chan_def def;
lockdep_assert_held(&ar->data_lock);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (arvif->vdev_id == vdev_id &&
ath10k_mac_vif_chan(arvif->vif, &def) == 0)
return def.chan;
}
return NULL;
}
static void
ath10k_htt_rx_h_any_chan_iter(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *conf,
void *data)
{
struct cfg80211_chan_def *def = data;
*def = conf->def;
}
static struct ieee80211_channel *
ath10k_htt_rx_h_any_channel(struct ath10k *ar)
{
struct cfg80211_chan_def def = {};
ieee80211_iter_chan_contexts_atomic(ar->hw,
ath10k_htt_rx_h_any_chan_iter,
&def);
return def.chan;
}
static bool ath10k_htt_rx_h_channel(struct ath10k *ar,
struct ieee80211_rx_status *status)
struct ieee80211_rx_status *status,
struct htt_rx_desc *rxd,
u32 vdev_id)
{
struct ieee80211_channel *ch;
......@@ -732,6 +811,12 @@ static bool ath10k_htt_rx_h_channel(struct ath10k *ar,
ch = ar->scan_channel;
if (!ch)
ch = ar->rx_channel;
if (!ch)
ch = ath10k_htt_rx_h_peer_channel(ar, rxd);
if (!ch)
ch = ath10k_htt_rx_h_vdev_channel(ar, vdev_id);
if (!ch)
ch = ath10k_htt_rx_h_any_channel(ar);
spin_unlock_bh(&ar->data_lock);
if (!ch)
......@@ -769,7 +854,8 @@ static void ath10k_htt_rx_h_mactime(struct ath10k *ar,
static void ath10k_htt_rx_h_ppdu(struct ath10k *ar,
struct sk_buff_head *amsdu,
struct ieee80211_rx_status *status)
struct ieee80211_rx_status *status,
u32 vdev_id)
{
struct sk_buff *first;
struct htt_rx_desc *rxd;
......@@ -801,7 +887,7 @@ static void ath10k_htt_rx_h_ppdu(struct ath10k *ar,
status->flag |= RX_FLAG_NO_SIGNAL_VAL;
ath10k_htt_rx_h_signal(ar, status, rxd);
ath10k_htt_rx_h_channel(ar, status);
ath10k_htt_rx_h_channel(ar, status, rxd, vdev_id);
ath10k_htt_rx_h_rates(ar, status, rxd);
}
......@@ -1472,7 +1558,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
break;
}
ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status);
ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff);
ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0);
ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
......@@ -1519,7 +1605,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
return;
}
ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status);
ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff);
ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
......@@ -1746,7 +1832,7 @@ static void ath10k_htt_rx_h_rx_offload(struct ath10k *ar,
status->flag |= RX_FLAG_NO_SIGNAL_VAL;
ath10k_htt_rx_h_rx_offload_prot(status, msdu);
ath10k_htt_rx_h_channel(ar, status);
ath10k_htt_rx_h_channel(ar, status, NULL, rx->vdev_id);
ath10k_process_rx(ar, status, msdu);
}
}
......@@ -1819,7 +1905,7 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
* better to report something than nothing though. This
* should still give an idea about rx rate to the user.
*/
ath10k_htt_rx_h_ppdu(ar, &amsdu, status);
ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id);
ath10k_htt_rx_h_filter(ar, &amsdu, status);
ath10k_htt_rx_h_mpdu(ar, &amsdu, status);
ath10k_htt_rx_h_deliver(ar, &amsdu, status);
......
This diff is collapsed.
......@@ -53,6 +53,8 @@ void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif);
void ath10k_drain_tx(struct ath10k *ar);
bool ath10k_mac_is_peer_wep_key_set(struct ath10k *ar, const u8 *addr,
u8 keyidx);
int ath10k_mac_vif_chan(struct ieee80211_vif *vif,
struct cfg80211_chan_def *def);
void ath10k_mac_handle_beacon(struct ath10k *ar, struct sk_buff *skb);
void ath10k_mac_handle_beacon_miss(struct ath10k *ar, u32 vdev_id);
......
......@@ -2425,6 +2425,7 @@ static void ath10k_dfs_radar_report(struct ath10k *ar,
u64 tsf)
{
u32 reg0, reg1, tsf32l;
struct ieee80211_channel *ch;
struct pulse_event pe;
u64 tsf64;
u8 rssi, width;
......@@ -2453,6 +2454,15 @@ static void ath10k_dfs_radar_report(struct ath10k *ar,
if (!ar->dfs_detector)
return;
spin_lock_bh(&ar->data_lock);
ch = ar->rx_channel;
spin_unlock_bh(&ar->data_lock);
if (!ch) {
ath10k_warn(ar, "failed to derive channel for radar pulse, treating as radar\n");
goto radar_detected;
}
/* report event to DFS pattern detector */
tsf32l = __le32_to_cpu(phyerr->tsf_timestamp);
tsf64 = tsf & (~0xFFFFFFFFULL);
......@@ -2468,7 +2478,7 @@ static void ath10k_dfs_radar_report(struct ath10k *ar,
rssi = 0;
pe.ts = tsf64;
pe.freq = ar->hw->conf.chandef.chan->center_freq;
pe.freq = ch->center_freq;
pe.width = width;
pe.rssi = rssi;
pe.chirp = (MS(reg0, RADAR_REPORT_REG0_PULSE_IS_CHIRP) != 0);
......@@ -2484,6 +2494,7 @@ static void ath10k_dfs_radar_report(struct ath10k *ar,
return;
}
radar_detected:
ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs radar detected\n");
ATH10K_DFS_STAT_INC(ar, radar_detected);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment