carl9170: refactor carl9170_update_beacon
This patch moves parts of carl9170_update_beacon into separate subroutines, so the parts become more manageable. Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
558925f313
commit
1f1d9654e1
1 changed files with 81 additions and 54 deletions
|
@ -1520,36 +1520,93 @@ void carl9170_tx_scheduler(struct ar9170 *ar)
|
|||
carl9170_tx(ar);
|
||||
}
|
||||
|
||||
/* caller has to take rcu_read_lock */
|
||||
static struct carl9170_vif_info *carl9170_pick_beaconing_vif(struct ar9170 *ar)
|
||||
{
|
||||
struct carl9170_vif_info *cvif;
|
||||
int i = 1;
|
||||
|
||||
/* The AR9170 hardware has no fancy beacon queue or some
|
||||
* other scheduling mechanism. So, the driver has to make
|
||||
* due by setting the two beacon timers (pretbtt and tbtt)
|
||||
* once and then swapping the beacon address in the HW's
|
||||
* register file each time the pretbtt fires.
|
||||
*/
|
||||
|
||||
cvif = rcu_dereference(ar->beacon_iter);
|
||||
if (ar->vifs > 0 && cvif) {
|
||||
do {
|
||||
list_for_each_entry_continue_rcu(cvif, &ar->vif_list,
|
||||
list) {
|
||||
if (cvif->active && cvif->enable_beacon)
|
||||
goto out;
|
||||
}
|
||||
} while (ar->beacon_enabled && i--);
|
||||
}
|
||||
|
||||
out:
|
||||
rcu_assign_pointer(ar->beacon_iter, cvif);
|
||||
return cvif;
|
||||
}
|
||||
|
||||
static bool carl9170_tx_beacon_physet(struct ar9170 *ar, struct sk_buff *skb,
|
||||
u32 *ht1, u32 *plcp)
|
||||
{
|
||||
struct ieee80211_tx_info *txinfo;
|
||||
struct ieee80211_tx_rate *rate;
|
||||
unsigned int power, chains;
|
||||
bool ht_rate;
|
||||
|
||||
txinfo = IEEE80211_SKB_CB(skb);
|
||||
rate = &txinfo->control.rates[0];
|
||||
ht_rate = !!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS);
|
||||
carl9170_tx_rate_tpc_chains(ar, txinfo, rate, plcp, &power, &chains);
|
||||
|
||||
*ht1 = AR9170_MAC_BCN_HT1_TX_ANT0;
|
||||
if (chains == AR9170_TX_PHY_TXCHAIN_2)
|
||||
*ht1 |= AR9170_MAC_BCN_HT1_TX_ANT1;
|
||||
SET_VAL(AR9170_MAC_BCN_HT1_PWR_CTRL, *ht1, 7);
|
||||
SET_VAL(AR9170_MAC_BCN_HT1_TPC, *ht1, power);
|
||||
SET_VAL(AR9170_MAC_BCN_HT1_CHAIN_MASK, *ht1, chains);
|
||||
|
||||
if (ht_rate) {
|
||||
*ht1 |= AR9170_MAC_BCN_HT1_HT_EN;
|
||||
if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
|
||||
*plcp |= AR9170_MAC_BCN_HT2_SGI;
|
||||
|
||||
if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
|
||||
*ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED;
|
||||
*plcp |= AR9170_MAC_BCN_HT2_BW40;
|
||||
} else if (rate->flags & IEEE80211_TX_RC_DUP_DATA) {
|
||||
*ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_DUP;
|
||||
*plcp |= AR9170_MAC_BCN_HT2_BW40;
|
||||
}
|
||||
|
||||
SET_VAL(AR9170_MAC_BCN_HT2_LEN, *plcp, skb->len + FCS_LEN);
|
||||
} else {
|
||||
if (*plcp <= AR9170_TX_PHY_RATE_CCK_11M)
|
||||
*plcp |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
|
||||
else
|
||||
*plcp |= ((skb->len + FCS_LEN) << 16) + 0x0010;
|
||||
}
|
||||
|
||||
return ht_rate;
|
||||
}
|
||||
|
||||
int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
struct carl9170_vif_info *cvif;
|
||||
struct ieee80211_tx_info *txinfo;
|
||||
struct ieee80211_tx_rate *rate;
|
||||
__le32 *data, *old = NULL;
|
||||
unsigned int plcp, power, chains;
|
||||
u32 word, ht1, off, addr, len;
|
||||
u32 word, ht1, plcp, off, addr, len;
|
||||
int i = 0, err = 0;
|
||||
bool ht_rate;
|
||||
|
||||
rcu_read_lock();
|
||||
cvif = rcu_dereference(ar->beacon_iter);
|
||||
retry:
|
||||
if (ar->vifs == 0 || !cvif)
|
||||
cvif = carl9170_pick_beaconing_vif(ar);
|
||||
if (!cvif)
|
||||
goto out_unlock;
|
||||
|
||||
list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) {
|
||||
if (cvif->active && cvif->enable_beacon)
|
||||
goto found;
|
||||
}
|
||||
|
||||
if (!ar->beacon_enabled || i++)
|
||||
goto out_unlock;
|
||||
|
||||
goto retry;
|
||||
|
||||
found:
|
||||
rcu_assign_pointer(ar->beacon_iter, cvif);
|
||||
|
||||
skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif),
|
||||
NULL, NULL);
|
||||
|
||||
|
@ -1558,7 +1615,6 @@ int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
|
|||
goto err_free;
|
||||
}
|
||||
|
||||
txinfo = IEEE80211_SKB_CB(skb);
|
||||
spin_lock_bh(&ar->beacon_lock);
|
||||
data = (__le32 *)skb->data;
|
||||
if (cvif->beacon)
|
||||
|
@ -1588,43 +1644,14 @@ int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
|
|||
goto err_unlock;
|
||||
}
|
||||
|
||||
ht1 = AR9170_MAC_BCN_HT1_TX_ANT0;
|
||||
rate = &txinfo->control.rates[0];
|
||||
carl9170_tx_rate_tpc_chains(ar, txinfo, rate, &plcp, &power, &chains);
|
||||
if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS)) {
|
||||
if (plcp <= AR9170_TX_PHY_RATE_CCK_11M)
|
||||
plcp |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
|
||||
else
|
||||
plcp |= ((skb->len + FCS_LEN) << 16) + 0x0010;
|
||||
} else {
|
||||
ht1 |= AR9170_MAC_BCN_HT1_HT_EN;
|
||||
if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
|
||||
plcp |= AR9170_MAC_BCN_HT2_SGI;
|
||||
|
||||
if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
|
||||
ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED;
|
||||
plcp |= AR9170_MAC_BCN_HT2_BW40;
|
||||
}
|
||||
if (rate->flags & IEEE80211_TX_RC_DUP_DATA) {
|
||||
ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_DUP;
|
||||
plcp |= AR9170_MAC_BCN_HT2_BW40;
|
||||
}
|
||||
|
||||
SET_VAL(AR9170_MAC_BCN_HT2_LEN, plcp, skb->len + FCS_LEN);
|
||||
}
|
||||
|
||||
SET_VAL(AR9170_MAC_BCN_HT1_PWR_CTRL, ht1, 7);
|
||||
SET_VAL(AR9170_MAC_BCN_HT1_TPC, ht1, power);
|
||||
SET_VAL(AR9170_MAC_BCN_HT1_CHAIN_MASK, ht1, chains);
|
||||
if (chains == AR9170_TX_PHY_TXCHAIN_2)
|
||||
ht1 |= AR9170_MAC_BCN_HT1_TX_ANT1;
|
||||
ht_rate = carl9170_tx_beacon_physet(ar, skb, &ht1, &plcp);
|
||||
|
||||
carl9170_async_regwrite_begin(ar);
|
||||
carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT1, ht1);
|
||||
if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS))
|
||||
carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, plcp);
|
||||
else
|
||||
if (ht_rate)
|
||||
carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT2, plcp);
|
||||
else
|
||||
carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, plcp);
|
||||
|
||||
for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue