Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 265883
b: refs/heads/master
c: 464021f
h: refs/heads/master
i:
  265881: 206eef9
  265879: 77a4b12
v: v3
  • Loading branch information
Emmanuel Grumbach authored and John W. Linville committed Aug 29, 2011
1 parent bc07508 commit 9c98713
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 82 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 288712a6ccf47b9df104f800616f6659ecadc940
refs/heads/master: 464021ffc1c080283e67729d966d76612728a08c
65 changes: 4 additions & 61 deletions trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,43 +477,6 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
return 0;
}

static int iwlagn_txq_check_empty(struct iwl_priv *priv,
int sta_id, u8 tid, int txq_id)
{
struct iwl_queue *q = &priv->txq[txq_id].q;
u8 *addr = priv->stations[sta_id].sta.sta.addr;
struct iwl_tid_data *tid_data = &priv->shrd->tid_data[sta_id][tid];
struct iwl_rxon_context *ctx;

ctx = &priv->contexts[priv->stations[sta_id].ctxid];

lockdep_assert_held(&priv->shrd->sta_lock);

switch (priv->shrd->tid_data[sta_id][tid].agg.state) {
case IWL_EMPTYING_HW_QUEUE_DELBA:
/* We are reclaiming the last packet of the */
/* aggregated HW queue */
if ((txq_id == tid_data->agg.txq_id) &&
(q->read_ptr == q->write_ptr)) {
IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n");
iwl_trans_txq_agg_disable(trans(priv), txq_id);
tid_data->agg.state = IWL_AGG_OFF;
ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
}
break;
case IWL_EMPTYING_HW_QUEUE_ADDBA:
/* We are reclaiming the last packet of the queue */
if (tid_data->tfds_in_queue == 0) {
IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n");
tid_data->agg.state = IWL_AGG_ON;
ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
}
break;
}

return 0;
}

static void iwlagn_non_agg_tx_status(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
const u8 *addr1)
Expand Down Expand Up @@ -724,21 +687,6 @@ static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp)
tx_resp->frame_count) & MAX_SN;
}

static void iwl_free_tfds_in_queue(struct iwl_priv *priv,
int sta_id, int tid, int freed)
{
lockdep_assert_held(&priv->shrd->sta_lock);

if (priv->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed)
priv->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed;
else {
IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n",
priv->shrd->tid_data[sta_id][tid].tfds_in_queue,
freed);
priv->shrd->tid_data[sta_id][tid].tfds_in_queue = 0;
}
}

static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status)
{
status &= TX_STATUS_MSK;
Expand Down Expand Up @@ -889,7 +837,8 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)

__skb_queue_head_init(&skbs);
/*we can free until ssn % q.n_bd not inclusive */
iwl_trans_reclaim(trans(priv), txq_id, ssn, status, &skbs);
iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
ssn, status, &skbs);
freed = 0;
while (!skb_queue_empty(&skbs)) {
skb = __skb_dequeue(&skbs);
Expand Down Expand Up @@ -939,9 +888,6 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
}

WARN_ON(!is_agg && freed != 1);

iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
}

iwl_check_abort_status(priv, tx_resp->frame_count, status);
Expand Down Expand Up @@ -1050,8 +996,8 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
/* Release all TFDs before the SSN, i.e. all TFDs in front of
* block-ack window (we assume that they've been successfully
* transmitted ... if not, it's too late anyway). */
iwl_trans_reclaim(trans(priv), scd_flow, ba_resp_scd_ssn, 0,
&reclaimed_skbs);
iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow, ba_resp_scd_ssn,
0, &reclaimed_skbs);
freed = 0;
while (!skb_queue_empty(&reclaimed_skbs)) {

Expand Down Expand Up @@ -1082,8 +1028,5 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
ieee80211_tx_status_irqsafe(priv->hw, skb);
}

iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow);

spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
}
21 changes: 20 additions & 1 deletion trunk/drivers/net/wireless/iwlwifi/iwl-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1858,11 +1858,30 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
return cpu_to_le32(res);
}

void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, u8 ctx,
void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
enum iwl_rxon_context_id ctx,
u8 sta_id, u8 tid)
{
struct ieee80211_vif *vif = priv->contexts[ctx].vif;
u8 *addr = priv->stations[sta_id].sta.sta.addr;

if (ctx == NUM_IWL_RXON_CTX)
ctx = priv->stations[sta_id].ctxid;
vif = priv->contexts[ctx].vif;

ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
}

void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
enum iwl_rxon_context_id ctx,
u8 sta_id, u8 tid)
{
struct ieee80211_vif *vif;
u8 *addr = priv->stations[sta_id].sta.sta.addr;

if (ctx == NUM_IWL_RXON_CTX)
ctx = priv->stations[sta_id].ctxid;
vif = priv->contexts[ctx].vif;

ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid);
}
6 changes: 5 additions & 1 deletion trunk/drivers/net/wireless/iwlwifi/iwl-shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,12 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
struct iwl_cfg *cfg);
void __devexit iwl_remove(struct iwl_priv * priv);

void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, u8 ctx,
void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
enum iwl_rxon_context_id ctx,
u8 sta_id, u8 tid);
void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
enum iwl_rxon_context_id ctx,
u8 sta_id, u8 tid);

/*****************************************************
* DRIVER STATUS FUNCTIONS
Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv,
int sta_id, int tid, int frame_limit);
void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
int index);
void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
struct sk_buff_head *skbs);
int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
struct sk_buff_head *skbs);

/*****************************************************
* Error handling
Expand Down
11 changes: 7 additions & 4 deletions trunk/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c
Original file line number Diff line number Diff line change
Expand Up @@ -1118,12 +1118,13 @@ int iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags,
}

/* Frees buffers until index _not_ inclusive */
void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
struct sk_buff_head *skbs)
int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
struct sk_buff_head *skbs)
{
struct iwl_tx_queue *txq = &priv(trans)->txq[txq_id];
struct iwl_queue *q = &txq->q;
int last_to_free;
int freed = 0;

/*Since we free until index _not_ inclusive, the one before index is
* the last we will free. This one must be used */
Expand All @@ -1135,14 +1136,14 @@ void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
"last_to_free %d is out of range [0-%d] %d %d.\n",
__func__, txq_id, last_to_free, q->n_bd,
q->write_ptr, q->read_ptr);
return;
return 0;
}

IWL_DEBUG_TX_REPLY(trans, "reclaim: [%d, %d, %d]\n", txq_id,
q->read_ptr, index);

if (WARN_ON(!skb_queue_empty(skbs)))
return;
return 0;

for (;
q->read_ptr != index;
Expand All @@ -1158,5 +1159,7 @@ void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
iwlagn_txq_inval_byte_cnt_tbl(trans, txq);

iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr);
freed++;
}
return freed;
}
73 changes: 66 additions & 7 deletions trunk/drivers/net/wireless/iwlwifi/iwl-trans.c
Original file line number Diff line number Diff line change
Expand Up @@ -1265,19 +1265,75 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans)
return 0;
}

static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id,
int ssn, u32 status, struct sk_buff_head *skbs)
static int iwlagn_txq_check_empty(struct iwl_trans *trans,
int sta_id, u8 tid, int txq_id)
{
struct iwl_priv *priv = priv(trans);
struct iwl_tx_queue *txq = &priv->txq[txq_id];
struct iwl_queue *q = &priv(trans)->txq[txq_id].q;
struct iwl_tid_data *tid_data = &trans->shrd->tid_data[sta_id][tid];

lockdep_assert_held(&trans->shrd->sta_lock);

switch (trans->shrd->tid_data[sta_id][tid].agg.state) {
case IWL_EMPTYING_HW_QUEUE_DELBA:
/* We are reclaiming the last packet of the */
/* aggregated HW queue */
if ((txq_id == tid_data->agg.txq_id) &&
(q->read_ptr == q->write_ptr)) {
IWL_DEBUG_HT(trans,
"HW queue empty: continue DELBA flow\n");
iwl_trans_pcie_txq_agg_disable(priv(trans), txq_id);
tid_data->agg.state = IWL_AGG_OFF;
iwl_stop_tx_ba_trans_ready(priv(trans),
NUM_IWL_RXON_CTX,
sta_id, tid);
iwl_wake_queue(priv(trans), &priv(trans)->txq[txq_id]);
}
break;
case IWL_EMPTYING_HW_QUEUE_ADDBA:
/* We are reclaiming the last packet of the queue */
if (tid_data->tfds_in_queue == 0) {
IWL_DEBUG_HT(trans,
"HW queue empty: continue ADDBA flow\n");
tid_data->agg.state = IWL_AGG_ON;
iwl_start_tx_ba_trans_ready(priv(trans),
NUM_IWL_RXON_CTX,
sta_id, tid);
}
break;
}

return 0;
}

static void iwl_free_tfds_in_queue(struct iwl_trans *trans,
int sta_id, int tid, int freed)
{
lockdep_assert_held(&trans->shrd->sta_lock);

if (trans->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed)
trans->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed;
else {
IWL_DEBUG_TX(trans, "free more than tfds_in_queue (%u:%d)\n",
trans->shrd->tid_data[sta_id][tid].tfds_in_queue,
freed);
trans->shrd->tid_data[sta_id][tid].tfds_in_queue = 0;
}
}

static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
int txq_id, int ssn, u32 status,
struct sk_buff_head *skbs)
{
struct iwl_tx_queue *txq = &priv(trans)->txq[txq_id];
/* n_bd is usually 256 => n_bd - 1 = 0xff */
int tfd_num = ssn & (txq->q.n_bd - 1);
int freed = 0;
u8 agg_state;
bool cond;

if (txq->sched_retry) {
agg_state =
priv->shrd->tid_data[txq->sta_id][txq->tid].agg.state;
trans->shrd->tid_data[txq->sta_id][txq->tid].agg.state;
cond = (agg_state != IWL_EMPTYING_HW_QUEUE_DELBA);
} else {
cond = (status != TX_STATUS_FAIL_PASSIVE_NO_RX);
Expand All @@ -1287,10 +1343,13 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id,
IWL_DEBUG_TX_REPLY(trans, "Retry scheduler reclaim "
"scd_ssn=%d idx=%d txq=%d swq=%d\n",
ssn , tfd_num, txq_id, txq->swq_id);
iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond)
iwl_wake_queue(priv, txq);
iwl_wake_queue(priv(trans), txq);
}

iwl_free_tfds_in_queue(trans, sta_id, tid, freed);
iwlagn_txq_check_empty(trans, sta_id, tid, txq_id);
}

static void iwl_trans_pcie_free(struct iwl_trans *trans)
Expand Down
11 changes: 6 additions & 5 deletions trunk/drivers/net/wireless/iwlwifi/iwl-trans.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,9 @@ struct iwl_trans_ops {
const void *data);
int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id);
void (*reclaim)(struct iwl_trans *trans, int txq_id, int ssn,
u32 status, struct sk_buff_head *skbs);
void (*reclaim)(struct iwl_trans *trans, int sta_id, int tid,
int txq_id, int ssn, u32 status,
struct sk_buff_head *skbs);

int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id);
int (*tx_agg_alloc)(struct iwl_trans *trans,
Expand Down Expand Up @@ -208,11 +209,11 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id);
}

static inline void iwl_trans_reclaim(struct iwl_trans *trans, int txq_id,
int ssn, u32 status,
static inline void iwl_trans_reclaim(struct iwl_trans *trans, int sta_id,
int tid, int txq_id, int ssn, u32 status,
struct sk_buff_head *skbs)
{
trans->ops->reclaim(trans, txq_id, ssn, status, skbs);
trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, status, skbs);
}

static inline int iwl_trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id)
Expand Down

0 comments on commit 9c98713

Please sign in to comment.