Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4be43770fd | |||
| 3dbabf3092 | |||
| 44b296647b | |||
| 25c0ed8c57 |
+17
-9
@@ -353,15 +353,23 @@ struct bes2600_common {
|
|||||||
* Keeping in common structure for the time being. Will be moved to VIFF
|
* Keeping in common structure for the time being. Will be moved to VIFF
|
||||||
* after the mechanism is clear */
|
* after the mechanism is clear */
|
||||||
u8 ba_tid_mask;
|
u8 ba_tid_mask;
|
||||||
int ba_acc; /*TODO: Same as above */
|
/*
|
||||||
int ba_cnt; /*TODO: Same as above */
|
* Patch D: ba_lock removed. Per-frame TX/RX hot-path bumped these
|
||||||
int ba_cnt_rx; /*TODO: Same as above */
|
* counters under spin_lock_bh; the lock did not protect any
|
||||||
int ba_acc_rx; /*TODO: Same as above */
|
* compound invariant that atomic ops can't satisfy. Counters are
|
||||||
int ba_hist; /*TODO: Same as above */
|
* now atomic_t; ba_armed gates the once-per-window mod_timer
|
||||||
struct timer_list ba_timer;/*TODO: Same as above */
|
* arm via cmpxchg so concurrent TX/RX at a fresh window each
|
||||||
spinlock_t ba_lock; /*TODO: Same as above */
|
* try to claim the arm and exactly one succeeds.
|
||||||
bool ba_ena; /*TODO: Same as above */
|
*/
|
||||||
struct work_struct ba_work; /*TODO: Same as above */
|
atomic_t ba_acc;
|
||||||
|
atomic_t ba_cnt;
|
||||||
|
atomic_t ba_cnt_rx;
|
||||||
|
atomic_t ba_acc_rx;
|
||||||
|
atomic_t ba_armed;
|
||||||
|
int ba_hist;
|
||||||
|
struct timer_list ba_timer;
|
||||||
|
atomic_t ba_ena;
|
||||||
|
struct work_struct ba_work;
|
||||||
bool is_BT_Present;
|
bool is_BT_Present;
|
||||||
bool is_go_thru_go_neg;
|
bool is_go_thru_go_neg;
|
||||||
u8 conf_listen_interval;
|
u8 conf_listen_interval;
|
||||||
|
|||||||
+8
-5
@@ -110,17 +110,20 @@ static int bes2600_status_show_common(struct seq_file *seq, void *v)
|
|||||||
int ba_cnt, ba_acc, ba_cnt_rx, ba_acc_rx, ba_avg = 0, ba_avg_rx = 0;
|
int ba_cnt, ba_acc, ba_cnt_rx, ba_acc_rx, ba_avg = 0, ba_avg_rx = 0;
|
||||||
bool ba_ena;
|
bool ba_ena;
|
||||||
|
|
||||||
spin_lock_bh(&hw_priv->ba_lock);
|
/*
|
||||||
ba_cnt = hw_priv->debug->ba_cnt;
|
* Patch D: ba_lock removed. hw_priv->debug->ba_* are written only
|
||||||
ba_acc = hw_priv->debug->ba_acc;
|
* by the timer callback (single writer); reading without a lock is
|
||||||
|
* fine for stats. ba_ena is atomic_t.
|
||||||
|
*/
|
||||||
|
ba_cnt = hw_priv->debug->ba_cnt;
|
||||||
|
ba_acc = hw_priv->debug->ba_acc;
|
||||||
ba_cnt_rx = hw_priv->debug->ba_cnt_rx;
|
ba_cnt_rx = hw_priv->debug->ba_cnt_rx;
|
||||||
ba_acc_rx = hw_priv->debug->ba_acc_rx;
|
ba_acc_rx = hw_priv->debug->ba_acc_rx;
|
||||||
ba_ena = hw_priv->ba_ena;
|
ba_ena = !!atomic_read(&hw_priv->ba_ena);
|
||||||
if (ba_cnt)
|
if (ba_cnt)
|
||||||
ba_avg = ba_acc / ba_cnt;
|
ba_avg = ba_acc / ba_cnt;
|
||||||
if (ba_cnt_rx)
|
if (ba_cnt_rx)
|
||||||
ba_avg_rx = ba_acc_rx / ba_cnt_rx;
|
ba_avg_rx = ba_acc_rx / ba_cnt_rx;
|
||||||
spin_unlock_bh(&hw_priv->ba_lock);
|
|
||||||
|
|
||||||
seq_puts(seq, "BES2600 Wireless LAN driver status\n");
|
seq_puts(seq, "BES2600 Wireless LAN driver status\n");
|
||||||
seq_printf(seq, "Hardware: %d.%d\n",
|
seq_printf(seq, "Hardware: %d.%d\n",
|
||||||
|
|||||||
+1
-1
@@ -496,7 +496,7 @@ static struct ieee80211_hw *bes2600_init_common(size_t hw_priv_data_len)
|
|||||||
INIT_LIST_HEAD(&hw_priv->event_queue);
|
INIT_LIST_HEAD(&hw_priv->event_queue);
|
||||||
INIT_WORK(&hw_priv->event_handler, bes2600_event_handler);
|
INIT_WORK(&hw_priv->event_handler, bes2600_event_handler);
|
||||||
INIT_WORK(&hw_priv->ba_work, bes2600_ba_work);
|
INIT_WORK(&hw_priv->ba_work, bes2600_ba_work);
|
||||||
spin_lock_init(&hw_priv->ba_lock);
|
/* Patch D: ba_lock removed; ba_acc/ba_cnt/etc are atomic_t. */
|
||||||
timer_setup(&hw_priv->ba_timer, bes2600_ba_timer, 0);
|
timer_setup(&hw_priv->ba_timer, bes2600_ba_timer, 0);
|
||||||
|
|
||||||
if (unlikely(bes2600_queue_stats_init(&hw_priv->tx_queue_stats,
|
if (unlikely(bes2600_queue_stats_init(&hw_priv->tx_queue_stats,
|
||||||
|
|||||||
+46
-31
@@ -2342,14 +2342,19 @@ void bes2600_join_work(struct work_struct *work)
|
|||||||
//WARN_ON(wsm_reset(hw_priv, &reset, priv->if_id));
|
//WARN_ON(wsm_reset(hw_priv, &reset, priv->if_id));
|
||||||
WARN_ON(wsm_set_block_ack_policy(hw_priv,
|
WARN_ON(wsm_set_block_ack_policy(hw_priv,
|
||||||
0, hw_priv->ba_tid_mask, priv->if_id));
|
0, hw_priv->ba_tid_mask, priv->if_id));
|
||||||
spin_lock_bh(&hw_priv->ba_lock);
|
/*
|
||||||
hw_priv->ba_ena = false;
|
* Patch D: ba_lock removed. Disconnect-reset clears the
|
||||||
hw_priv->ba_cnt = 0;
|
* counters and the arm flag; producers racing here cannot
|
||||||
hw_priv->ba_acc = 0;
|
* cause harm — at worst they re-arm the timer and bump
|
||||||
|
* counters that will be cleared on the next timer tick.
|
||||||
|
*/
|
||||||
|
atomic_set(&hw_priv->ba_ena, 0);
|
||||||
|
atomic_set(&hw_priv->ba_cnt, 0);
|
||||||
|
atomic_set(&hw_priv->ba_acc, 0);
|
||||||
hw_priv->ba_hist = 0;
|
hw_priv->ba_hist = 0;
|
||||||
hw_priv->ba_cnt_rx = 0;
|
atomic_set(&hw_priv->ba_cnt_rx, 0);
|
||||||
hw_priv->ba_acc_rx = 0;
|
atomic_set(&hw_priv->ba_acc_rx, 0);
|
||||||
spin_unlock_bh(&hw_priv->ba_lock);
|
atomic_set(&hw_priv->ba_armed, 0);
|
||||||
|
|
||||||
mgmt_policy.protectedMgmtEnable = 0;
|
mgmt_policy.protectedMgmtEnable = 0;
|
||||||
mgmt_policy.unprotectedMgmtFramesAllowed = 1;
|
mgmt_policy.unprotectedMgmtFramesAllowed = 1;
|
||||||
@@ -2629,10 +2634,11 @@ void bes2600_ba_work(struct work_struct *work)
|
|||||||
return;*/
|
return;*/
|
||||||
|
|
||||||
bes_devel("BA work****\n");
|
bes_devel("BA work****\n");
|
||||||
spin_lock_bh(&hw_priv->ba_lock);
|
/*
|
||||||
// tx_ba_tid_mask = hw_priv->ba_ena ? hw_priv->ba_tid_mask : 0;
|
* Patch D: ba_lock removed. ba_tid_mask is u8 set once at init
|
||||||
|
* (main.c); reading it without a lock is fine.
|
||||||
|
*/
|
||||||
tx_ba_tid_mask = hw_priv->ba_tid_mask;
|
tx_ba_tid_mask = hw_priv->ba_tid_mask;
|
||||||
spin_unlock_bh(&hw_priv->ba_lock);
|
|
||||||
|
|
||||||
wsm_lock_tx(hw_priv);
|
wsm_lock_tx(hw_priv);
|
||||||
|
|
||||||
@@ -2645,37 +2651,49 @@ void bes2600_ba_work(struct work_struct *work)
|
|||||||
void bes2600_ba_timer(struct timer_list *t)
|
void bes2600_ba_timer(struct timer_list *t)
|
||||||
{
|
{
|
||||||
bool ba_ena;
|
bool ba_ena;
|
||||||
|
int cnt, acc, cnt_rx, acc_rx;
|
||||||
struct bes2600_common *hw_priv = from_timer(hw_priv, t, ba_timer);
|
struct bes2600_common *hw_priv = from_timer(hw_priv, t, ba_timer);
|
||||||
|
|
||||||
spin_lock_bh(&hw_priv->ba_lock);
|
/*
|
||||||
bes2600_debug_ba(hw_priv, hw_priv->ba_cnt, hw_priv->ba_acc,
|
* Patch D: ba_lock removed. Snapshot atomic counters into locals
|
||||||
hw_priv->ba_cnt_rx, hw_priv->ba_acc_rx);
|
* for the predicate evaluation; producers may race incrementing
|
||||||
|
* after the snapshot but the resulting decision is approximate
|
||||||
|
* which the policy already tolerates (next timer tick re-evaluates).
|
||||||
|
*/
|
||||||
|
cnt = atomic_read(&hw_priv->ba_cnt);
|
||||||
|
acc = atomic_read(&hw_priv->ba_acc);
|
||||||
|
cnt_rx = atomic_read(&hw_priv->ba_cnt_rx);
|
||||||
|
acc_rx = atomic_read(&hw_priv->ba_acc_rx);
|
||||||
|
|
||||||
|
bes2600_debug_ba(hw_priv, cnt, acc, cnt_rx, acc_rx);
|
||||||
|
|
||||||
if (atomic_read(&hw_priv->scan.in_progress)) {
|
if (atomic_read(&hw_priv->scan.in_progress)) {
|
||||||
hw_priv->ba_cnt = 0;
|
atomic_set(&hw_priv->ba_cnt, 0);
|
||||||
hw_priv->ba_acc = 0;
|
atomic_set(&hw_priv->ba_acc, 0);
|
||||||
hw_priv->ba_cnt_rx = 0;
|
atomic_set(&hw_priv->ba_cnt_rx, 0);
|
||||||
hw_priv->ba_acc_rx = 0;
|
atomic_set(&hw_priv->ba_acc_rx, 0);
|
||||||
goto skip_statistic_update;
|
atomic_set(&hw_priv->ba_armed, 0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hw_priv->ba_cnt >= BES2600_BLOCK_ACK_CNT &&
|
if (cnt >= BES2600_BLOCK_ACK_CNT &&
|
||||||
(hw_priv->ba_acc / hw_priv->ba_cnt >= BES2600_BLOCK_ACK_THLD ||
|
(acc / cnt >= BES2600_BLOCK_ACK_THLD ||
|
||||||
(hw_priv->ba_cnt_rx >= BES2600_BLOCK_ACK_CNT &&
|
(cnt_rx >= BES2600_BLOCK_ACK_CNT &&
|
||||||
hw_priv->ba_acc_rx / hw_priv->ba_cnt_rx >=
|
acc_rx / cnt_rx >=
|
||||||
BES2600_BLOCK_ACK_THLD)))
|
BES2600_BLOCK_ACK_THLD)))
|
||||||
ba_ena = true;
|
ba_ena = true;
|
||||||
else
|
else
|
||||||
ba_ena = false;
|
ba_ena = false;
|
||||||
|
|
||||||
hw_priv->ba_cnt = 0;
|
atomic_set(&hw_priv->ba_cnt, 0);
|
||||||
hw_priv->ba_acc = 0;
|
atomic_set(&hw_priv->ba_acc, 0);
|
||||||
hw_priv->ba_cnt_rx = 0;
|
atomic_set(&hw_priv->ba_cnt_rx, 0);
|
||||||
hw_priv->ba_acc_rx = 0;
|
atomic_set(&hw_priv->ba_acc_rx, 0);
|
||||||
|
atomic_set(&hw_priv->ba_armed, 0);
|
||||||
|
|
||||||
if (ba_ena != hw_priv->ba_ena) {
|
if (ba_ena != !!atomic_read(&hw_priv->ba_ena)) {
|
||||||
if (ba_ena || ++hw_priv->ba_hist >= BES2600_BLOCK_ACK_HIST) {
|
if (ba_ena || ++hw_priv->ba_hist >= BES2600_BLOCK_ACK_HIST) {
|
||||||
hw_priv->ba_ena = ba_ena;
|
atomic_set(&hw_priv->ba_ena, ba_ena ? 1 : 0);
|
||||||
hw_priv->ba_hist = 0;
|
hw_priv->ba_hist = 0;
|
||||||
#if 0
|
#if 0
|
||||||
bes_devel("[STA] %s block ACK:\n",
|
bes_devel("[STA] %s block ACK:\n",
|
||||||
@@ -2685,9 +2703,6 @@ void bes2600_ba_timer(struct timer_list *t)
|
|||||||
}
|
}
|
||||||
} else if (hw_priv->ba_hist)
|
} else if (hw_priv->ba_hist)
|
||||||
--hw_priv->ba_hist;
|
--hw_priv->ba_hist;
|
||||||
|
|
||||||
skip_statistic_update:
|
|
||||||
spin_unlock_bh(&hw_priv->ba_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int bes2600_vif_setup(struct bes2600_vif *priv)
|
int bes2600_vif_setup(struct bes2600_vif *priv)
|
||||||
|
|||||||
+37
-16
@@ -995,14 +995,18 @@ bes2600_tx_h_ba_stat(struct bes2600_vif *priv,
|
|||||||
if (!ieee80211_is_data(t->hdr->frame_control))
|
if (!ieee80211_is_data(t->hdr->frame_control))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock_bh(&hw_priv->ba_lock);
|
/*
|
||||||
hw_priv->ba_acc += t->skb->len - t->hdrlen;
|
* Patch D: lock-free hot-path BA accounting. atomic_inc + atomic_add
|
||||||
if (!(hw_priv->ba_cnt_rx || hw_priv->ba_cnt)) {
|
* each per-frame; the once-per-window timer-arm uses cmpxchg on
|
||||||
|
* ba_armed so concurrent TX/RX can't both try to set the timer and
|
||||||
|
* we don't need cross-counter coherency on the ba_cnt/ba_cnt_rx pair.
|
||||||
|
*/
|
||||||
|
atomic_add(t->skb->len - t->hdrlen, &hw_priv->ba_acc);
|
||||||
|
atomic_inc(&hw_priv->ba_cnt);
|
||||||
|
if (atomic_cmpxchg(&hw_priv->ba_armed, 0, 1) == 0) {
|
||||||
mod_timer(&hw_priv->ba_timer,
|
mod_timer(&hw_priv->ba_timer,
|
||||||
jiffies + BES2600_BLOCK_ACK_INTERVAL);
|
jiffies + BES2600_BLOCK_ACK_INTERVAL);
|
||||||
}
|
}
|
||||||
hw_priv->ba_cnt++;
|
|
||||||
spin_unlock_bh(&hw_priv->ba_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -1629,14 +1633,13 @@ bes2600_rx_h_ba_stat(struct bes2600_vif *priv,
|
|||||||
if (!priv->setbssparams_done)
|
if (!priv->setbssparams_done)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock_bh(&hw_priv->ba_lock);
|
/* Patch D: lock-free hot-path BA accounting; see TX side comment. */
|
||||||
hw_priv->ba_acc_rx += skb_len - hdrlen;
|
atomic_add(skb_len - hdrlen, &hw_priv->ba_acc_rx);
|
||||||
if (!(hw_priv->ba_cnt_rx || hw_priv->ba_cnt)) {
|
atomic_inc(&hw_priv->ba_cnt_rx);
|
||||||
|
if (atomic_cmpxchg(&hw_priv->ba_armed, 0, 1) == 0) {
|
||||||
mod_timer(&hw_priv->ba_timer,
|
mod_timer(&hw_priv->ba_timer,
|
||||||
jiffies + BES2600_BLOCK_ACK_INTERVAL);
|
jiffies + BES2600_BLOCK_ACK_INTERVAL);
|
||||||
}
|
}
|
||||||
hw_priv->ba_cnt_rx++;
|
|
||||||
spin_unlock_bh(&hw_priv->ba_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bes2600_rx_cb(struct bes2600_vif *priv,
|
void bes2600_rx_cb(struct bes2600_vif *priv,
|
||||||
@@ -1939,13 +1942,31 @@ void bes2600_rx_cb(struct bes2600_vif *priv,
|
|||||||
if (unlikely(bes2600_itp_rxed(hw_priv, skb)))
|
if (unlikely(bes2600_itp_rxed(hw_priv, skb)))
|
||||||
consume_skb(skb);
|
consume_skb(skb);
|
||||||
else if (unlikely(early_data)) {
|
else if (unlikely(early_data)) {
|
||||||
spin_lock_bh(&priv->ps_state_lock);
|
/*
|
||||||
/* Double-check status with lock held */
|
* Patch E: when c7 has latched pm_unsupported (firmware
|
||||||
if (entry->status == BES2600_LINK_SOFT)
|
* doesn't honour PSM, see feedback_bes2600_firmware_no_psm),
|
||||||
skb_queue_tail(&entry->rx_queue, skb);
|
* AP-side power-save state machine is dead and link entries
|
||||||
else
|
* never transition to BES2600_LINK_SOFT. The double-check
|
||||||
|
* branch under ps_state_lock is unreachable in that case,
|
||||||
|
* so skip the per-frame lock acquisition entirely and
|
||||||
|
* deliver to mac80211 directly.
|
||||||
|
*
|
||||||
|
* On firmware that does honour PSM (the latch self-clears
|
||||||
|
* if a real PM_INDICATION ever arrives — see c7), this
|
||||||
|
* predicate flips back to false and the original locked
|
||||||
|
* path is taken.
|
||||||
|
*/
|
||||||
|
if (hw_priv->bes_power.pm_unsupported) {
|
||||||
ieee80211_rx_irqsafe(priv->hw, skb);
|
ieee80211_rx_irqsafe(priv->hw, skb);
|
||||||
spin_unlock_bh(&priv->ps_state_lock);
|
} else {
|
||||||
|
spin_lock_bh(&priv->ps_state_lock);
|
||||||
|
/* Double-check status with lock held */
|
||||||
|
if (entry->status == BES2600_LINK_SOFT)
|
||||||
|
skb_queue_tail(&entry->rx_queue, skb);
|
||||||
|
else
|
||||||
|
ieee80211_rx_irqsafe(priv->hw, skb);
|
||||||
|
spin_unlock_bh(&priv->ps_state_lock);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ieee80211_rx_irqsafe(priv->hw, skb);
|
ieee80211_rx_irqsafe(priv->hw, skb);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user