mirror of https://gitee.com/openkylin/linux.git
ath9k_htc: Add beacon slots
Beacon transmission is now handled through a slot mechanism. This allows multiple beaconing interfaces to be be present. Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
1c165c972b
commit
832f6a18fc
|
@ -244,6 +244,7 @@ struct ath9k_htc_vif {
|
|||
u8 index;
|
||||
u16 seq_no;
|
||||
bool beacon_configured;
|
||||
int bslot;
|
||||
};
|
||||
|
||||
struct ath9k_vif_iter_data {
|
||||
|
@ -351,10 +352,14 @@ struct ath_led {
|
|||
int brightness;
|
||||
};
|
||||
|
||||
#define BSTUCK_THRESHOLD 10
|
||||
|
||||
struct htc_beacon_config {
|
||||
struct ieee80211_vif *bslot[ATH9K_HTC_MAX_BCN_VIF];
|
||||
u16 beacon_interval;
|
||||
u16 dtim_period;
|
||||
u16 bmiss_timeout;
|
||||
u32 bmiss_cnt;
|
||||
};
|
||||
|
||||
struct ath_btcoex {
|
||||
|
@ -414,7 +419,6 @@ struct ath9k_htc_priv {
|
|||
u16 txpowlimit;
|
||||
u16 nvifs;
|
||||
u16 nstations;
|
||||
u32 bmiss_cnt;
|
||||
bool rearm_ani;
|
||||
bool reconfig_beacon;
|
||||
|
||||
|
@ -425,7 +429,6 @@ struct ath9k_htc_priv {
|
|||
bool tx_queues_stop;
|
||||
spinlock_t tx_lock;
|
||||
|
||||
struct ieee80211_vif *vif;
|
||||
struct htc_beacon_config cur_beacon_conf;
|
||||
unsigned int rxfilter;
|
||||
struct tasklet_struct swba_tasklet;
|
||||
|
@ -473,11 +476,15 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
|
|||
|
||||
void ath9k_htc_reset(struct ath9k_htc_priv *priv);
|
||||
|
||||
void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_vif *vif);
|
||||
void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_vif *vif);
|
||||
void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv);
|
||||
void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_vif *vif);
|
||||
void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv);
|
||||
void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending);
|
||||
void ath9k_htc_swba(struct ath9k_htc_priv *priv);
|
||||
|
||||
void ath9k_htc_rxep(void *priv, struct sk_buff *skb,
|
||||
enum htc_endpoint_id ep_id);
|
||||
|
|
|
@ -172,12 +172,13 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
|
|||
imask |= ATH9K_INT_SWBA;
|
||||
|
||||
ath_dbg(common, ATH_DBG_CONFIG,
|
||||
"AP Beacon config, intval: %d, nexttbtt: %u imask: 0x%x\n",
|
||||
"AP Beacon config, intval: %d, nexttbtt: %u "
|
||||
"imask: 0x%x\n",
|
||||
bss_conf->beacon_interval, nexttbtt, imask);
|
||||
|
||||
WMI_CMD(WMI_DISABLE_INTR_CMDID);
|
||||
ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval));
|
||||
priv->bmiss_cnt = 0;
|
||||
priv->cur_beacon_conf.bmiss_cnt = 0;
|
||||
htc_imask = cpu_to_be32(imask);
|
||||
WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
|
||||
}
|
||||
|
@ -214,7 +215,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
|
|||
|
||||
WMI_CMD(WMI_DISABLE_INTR_CMDID);
|
||||
ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval));
|
||||
priv->bmiss_cnt = 0;
|
||||
priv->cur_beacon_conf.bmiss_cnt = 0;
|
||||
htc_imask = cpu_to_be32(imask);
|
||||
WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
|
||||
}
|
||||
|
@ -225,9 +226,11 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,
|
|||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending)
|
||||
static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
|
||||
int slot)
|
||||
{
|
||||
struct ath9k_htc_vif *avp = (void *)priv->vif->drv_priv;
|
||||
struct ieee80211_vif *vif;
|
||||
struct ath9k_htc_vif *avp;
|
||||
struct tx_beacon_header beacon_hdr;
|
||||
struct ath9k_htc_tx_ctl tx_ctl;
|
||||
struct ieee80211_tx_info *info;
|
||||
|
@ -237,21 +240,18 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending)
|
|||
memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header));
|
||||
memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl));
|
||||
|
||||
/* FIXME: Handle BMISS */
|
||||
if (beacon_pending != 0) {
|
||||
priv->bmiss_cnt++;
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_bh(&priv->beacon_lock);
|
||||
|
||||
vif = priv->cur_beacon_conf.bslot[slot];
|
||||
avp = (struct ath9k_htc_vif *)vif->drv_priv;
|
||||
|
||||
if (unlikely(priv->op_flags & OP_SCANNING)) {
|
||||
spin_unlock_bh(&priv->beacon_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get a new beacon */
|
||||
beacon = ieee80211_beacon_get(priv->hw, priv->vif);
|
||||
beacon = ieee80211_beacon_get(priv->hw, vif);
|
||||
if (!beacon) {
|
||||
spin_unlock_bh(&priv->beacon_lock);
|
||||
return;
|
||||
|
@ -276,6 +276,69 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending)
|
|||
spin_unlock_bh(&priv->beacon_lock);
|
||||
}
|
||||
|
||||
static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
unsigned long flags;
|
||||
u64 tsf;
|
||||
u32 tsftu;
|
||||
u16 intval;
|
||||
int slot;
|
||||
|
||||
intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD;
|
||||
|
||||
spin_lock_irqsave(&priv->wmi->wmi_lock, flags);
|
||||
tsf = priv->wmi->tsf;
|
||||
spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags);
|
||||
|
||||
tsftu = TSF_TO_TU(tsf >> 32, tsf);
|
||||
slot = ((tsftu % intval) * ATH9K_HTC_MAX_BCN_VIF) / intval;
|
||||
slot = ATH9K_HTC_MAX_BCN_VIF - slot - 1;
|
||||
|
||||
ath_dbg(common, ATH_DBG_BEACON,
|
||||
"Choose slot: %d, tsf: %llu, tsftu: %u, intval: %u\n",
|
||||
slot, tsf, tsftu, intval);
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
void ath9k_htc_swba(struct ath9k_htc_priv *priv)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
unsigned long flags;
|
||||
int slot;
|
||||
|
||||
spin_lock_irqsave(&priv->wmi->wmi_lock, flags);
|
||||
if (priv->wmi->beacon_pending != 0) {
|
||||
spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags);
|
||||
priv->cur_beacon_conf.bmiss_cnt++;
|
||||
if (priv->cur_beacon_conf.bmiss_cnt > BSTUCK_THRESHOLD) {
|
||||
ath_dbg(common, ATH_DBG_BEACON,
|
||||
"Beacon stuck, HW reset\n");
|
||||
ath9k_htc_reset(priv);
|
||||
}
|
||||
return;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags);
|
||||
|
||||
if (priv->cur_beacon_conf.bmiss_cnt) {
|
||||
ath_dbg(common, ATH_DBG_BEACON,
|
||||
"Resuming beacon xmit after %u misses\n",
|
||||
priv->cur_beacon_conf.bmiss_cnt);
|
||||
priv->cur_beacon_conf.bmiss_cnt = 0;
|
||||
}
|
||||
|
||||
slot = ath9k_htc_choose_bslot(priv);
|
||||
spin_lock_bh(&priv->beacon_lock);
|
||||
if (priv->cur_beacon_conf.bslot[slot] == NULL) {
|
||||
spin_unlock_bh(&priv->beacon_lock);
|
||||
return;
|
||||
}
|
||||
spin_unlock_bh(&priv->beacon_lock);
|
||||
|
||||
ath9k_htc_send_beacon(priv, slot);
|
||||
}
|
||||
|
||||
/* Currently, only for IBSS */
|
||||
void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
|
||||
{
|
||||
|
@ -307,6 +370,42 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
|
|||
}
|
||||
}
|
||||
|
||||
void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv;
|
||||
int i = 0;
|
||||
|
||||
spin_lock_bh(&priv->beacon_lock);
|
||||
for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) {
|
||||
if (priv->cur_beacon_conf.bslot[i] == NULL) {
|
||||
avp->bslot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
priv->cur_beacon_conf.bslot[avp->bslot] = vif;
|
||||
spin_unlock_bh(&priv->beacon_lock);
|
||||
|
||||
ath_dbg(common, ATH_DBG_CONFIG,
|
||||
"Added interface at beacon slot: %d\n", avp->bslot);
|
||||
}
|
||||
|
||||
void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv;
|
||||
|
||||
spin_lock_bh(&priv->beacon_lock);
|
||||
priv->cur_beacon_conf.bslot[avp->bslot] = NULL;
|
||||
spin_unlock_bh(&priv->beacon_lock);
|
||||
|
||||
ath_dbg(common, ATH_DBG_CONFIG,
|
||||
"Removed interface at beacon slot: %d\n", avp->bslot);
|
||||
}
|
||||
|
||||
static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
bool *beacon_configured = (bool *)data;
|
||||
|
|
|
@ -643,7 +643,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
|
|||
{
|
||||
struct ath_hw *ah = NULL;
|
||||
struct ath_common *common;
|
||||
int ret = 0, csz = 0;
|
||||
int i, ret = 0, csz = 0;
|
||||
|
||||
priv->op_flags |= OP_INVALID;
|
||||
|
||||
|
@ -711,6 +711,9 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
|
|||
if (ret)
|
||||
goto err_queues;
|
||||
|
||||
for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)
|
||||
priv->cur_beacon_conf.bslot[i] = NULL;
|
||||
|
||||
ath9k_init_crypto(priv);
|
||||
ath9k_init_channels_rates(priv);
|
||||
ath9k_init_misc(priv);
|
||||
|
|
|
@ -1281,9 +1281,13 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
|
|||
|
||||
priv->vif_slot |= (1 << avp->index);
|
||||
priv->nvifs++;
|
||||
priv->vif = vif;
|
||||
|
||||
INC_VIF(priv, vif->type);
|
||||
|
||||
if ((vif->type == NL80211_IFTYPE_AP) ||
|
||||
(vif->type == NL80211_IFTYPE_ADHOC))
|
||||
ath9k_htc_assign_bslot(priv, vif);
|
||||
|
||||
ath9k_htc_set_opmode(priv);
|
||||
|
||||
if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
|
||||
|
@ -1321,9 +1325,13 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
|
|||
priv->vif_slot &= ~(1 << avp->index);
|
||||
|
||||
ath9k_htc_remove_station(priv, vif, NULL);
|
||||
priv->vif = NULL;
|
||||
|
||||
DEC_VIF(priv, vif->type);
|
||||
|
||||
if ((vif->type == NL80211_IFTYPE_AP) ||
|
||||
(vif->type == NL80211_IFTYPE_ADHOC))
|
||||
ath9k_htc_remove_bslot(priv, vif);
|
||||
|
||||
ath9k_htc_set_opmode(priv);
|
||||
|
||||
/*
|
||||
|
|
|
@ -126,7 +126,7 @@ void ath9k_swba_tasklet(unsigned long data)
|
|||
{
|
||||
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
|
||||
|
||||
ath9k_htc_swba(priv, priv->wmi->beacon_pending);
|
||||
ath9k_htc_swba(priv);
|
||||
}
|
||||
|
||||
void ath9k_fatal_work(struct work_struct *work)
|
||||
|
@ -173,8 +173,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
|
|||
case WMI_SWBA_EVENTID:
|
||||
swba = (struct wmi_event_swba *) wmi_event;
|
||||
|
||||
spin_lock(&wmi->wmi_lock);
|
||||
wmi->tsf = be64_to_cpu(swba->tsf);
|
||||
wmi->beacon_pending = swba->beacon_pending;
|
||||
spin_unlock(&wmi->wmi_lock);
|
||||
|
||||
tasklet_schedule(&wmi->drv_priv->swba_tasklet);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue