Skip to content

Commit

Permalink
carl9170: refactor carl9170_update_beacon
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
chunkeey authored and linvjw committed Jan 7, 2013
1 parent 558925f commit 1f1d965
Showing 1 changed file with 80 additions and 53 deletions.
133 changes: 80 additions & 53 deletions drivers/net/wireless/ath/carl9170/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1520,35 +1520,92 @@ void carl9170_tx_scheduler(struct ar9170 *ar)
carl9170_tx(ar);
}

int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
/* caller has to take rcu_read_lock */
static struct carl9170_vif_info *carl9170_pick_beaconing_vif(struct ar9170 *ar)
{
struct sk_buff *skb = NULL;
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;
__le32 *data, *old = NULL;
unsigned int plcp, power, chains;
u32 word, ht1, off, addr, len;
int i = 0, err = 0;
unsigned int power, chains;
bool ht_rate;

rcu_read_lock();
cvif = rcu_dereference(ar->beacon_iter);
retry:
if (ar->vifs == 0 || !cvif)
goto out_unlock;
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);

list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) {
if (cvif->active && cvif->enable_beacon)
goto found;
*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;
}

if (!ar->beacon_enabled || i++)
goto out_unlock;
return ht_rate;
}

goto retry;
int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
{
struct sk_buff *skb = NULL;
struct carl9170_vif_info *cvif;
__le32 *data, *old = NULL;
u32 word, ht1, plcp, off, addr, len;
int i = 0, err = 0;
bool ht_rate;

found:
rcu_assign_pointer(ar->beacon_iter, cvif);
rcu_read_lock();
cvif = carl9170_pick_beaconing_vif(ar);
if (!cvif)
goto out_unlock;

skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif),
NULL, NULL);
Expand All @@ -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)
Expand Down Expand Up @@ -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++) {
/*
Expand Down

0 comments on commit 1f1d965

Please sign in to comment.