aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl4965-base.c
diff options
context:
space:
mode:
authorRon Rindjunsky <ron.rindjunsky@intel.com>2008-01-28 07:07:24 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-02-29 15:19:18 -0500
commitfe01b477bbd23e69c3bdc6bce5be510ddad8297d (patch)
tree353471f96adb7580b7940c3b7cf6df4f8f0044a2 /drivers/net/wireless/iwlwifi/iwl4965-base.c
parent8114fcf185c58b23dc9fcaf4944b59b4c1407b39 (diff)
iwlwifi: A-MPDU Tx conform flows to mac80211
This patch alters the current iwlwifi behavior to fit the flows introduced by the mac80211, mainly queues handling and start/stop call backs flows Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl4965-base.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c121
1 files changed, 65 insertions, 56 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 3f5114f5fe16..16cb990e06fa 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -205,7 +205,7 @@ static void iwl4965_print_hex_dump(int level, void *p, u32 len)
205 * See more detailed info in iwl-4965-hw.h. 205 * See more detailed info in iwl-4965-hw.h.
206 ***************************************************/ 206 ***************************************************/
207 207
208static int iwl4965_queue_space(const struct iwl4965_queue *q) 208int iwl4965_queue_space(const struct iwl4965_queue *q)
209{ 209{
210 int s = q->read_ptr - q->write_ptr; 210 int s = q->read_ptr - q->write_ptr;
211 211
@@ -2972,11 +2972,10 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
2972 __constant_cpu_to_le16(IEEE80211_SCTL_FRAG)); 2972 __constant_cpu_to_le16(IEEE80211_SCTL_FRAG));
2973 seq_number += 0x10; 2973 seq_number += 0x10;
2974#ifdef CONFIG_IWL4965_HT 2974#ifdef CONFIG_IWL4965_HT
2975#ifdef CONFIG_IWL4965_HT_AGG
2976 /* aggregation is on for this <sta,tid> */ 2975 /* aggregation is on for this <sta,tid> */
2977 if (ctl->flags & IEEE80211_TXCTL_HT_MPDU_AGG) 2976 if (ctl->flags & IEEE80211_TXCTL_AMPDU)
2978 txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; 2977 txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
2979#endif /* CONFIG_IWL4965_HT_AGG */ 2978 priv->stations[sta_id].tid[tid].tfds_in_queue++;
2980#endif /* CONFIG_IWL4965_HT */ 2979#endif /* CONFIG_IWL4965_HT */
2981 } 2980 }
2982 2981
@@ -3528,10 +3527,10 @@ int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index)
3528 nfreed++; 3527 nfreed++;
3529 } 3528 }
3530 3529
3531 if (iwl4965_queue_space(q) > q->low_mark && (txq_id >= 0) && 3530/* if (iwl4965_queue_space(q) > q->low_mark && (txq_id >= 0) &&
3532 (txq_id != IWL_CMD_QUEUE_NUM) && 3531 (txq_id != IWL_CMD_QUEUE_NUM) &&
3533 priv->mac80211_registered) 3532 priv->mac80211_registered)
3534 ieee80211_wake_queue(priv->hw, txq_id); 3533 ieee80211_wake_queue(priv->hw, txq_id); */
3535 3534
3536 3535
3537 return nfreed; 3536 return nfreed;
@@ -3550,7 +3549,6 @@ static int iwl4965_is_tx_success(u32 status)
3550 * 3549 *
3551 ******************************************************************************/ 3550 ******************************************************************************/
3552#ifdef CONFIG_IWL4965_HT 3551#ifdef CONFIG_IWL4965_HT
3553#ifdef CONFIG_IWL4965_HT_AGG
3554 3552
3555static inline int iwl4965_get_ra_sta_id(struct iwl4965_priv *priv, 3553static inline int iwl4965_get_ra_sta_id(struct iwl4965_priv *priv,
3556 struct ieee80211_hdr *hdr) 3554 struct ieee80211_hdr *hdr)
@@ -3585,11 +3583,11 @@ static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
3585 */ 3583 */
3586static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, 3584static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
3587 struct iwl4965_ht_agg *agg, 3585 struct iwl4965_ht_agg *agg,
3588 struct iwl4965_tx_resp *tx_resp, 3586 struct iwl4965_tx_resp_agg *tx_resp,
3589 u16 start_idx) 3587 u16 start_idx)
3590{ 3588{
3591 u32 status; 3589 u16 status;
3592 __le32 *frame_status = &tx_resp->status; 3590 struct agg_tx_status *frame_status = &tx_resp->status;
3593 struct ieee80211_tx_status *tx_status = NULL; 3591 struct ieee80211_tx_status *tx_status = NULL;
3594 struct ieee80211_hdr *hdr = NULL; 3592 struct ieee80211_hdr *hdr = NULL;
3595 int i, sh; 3593 int i, sh;
@@ -3602,26 +3600,25 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
3602 agg->frame_count = tx_resp->frame_count; 3600 agg->frame_count = tx_resp->frame_count;
3603 agg->start_idx = start_idx; 3601 agg->start_idx = start_idx;
3604 agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); 3602 agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
3605 agg->bitmap0 = agg->bitmap1 = 0; 3603 agg->bitmap = 0;
3606 3604
3607 /* # frames attempted by Tx command */ 3605 /* # frames attempted by Tx command */
3608 if (agg->frame_count == 1) { 3606 if (agg->frame_count == 1) {
3609 /* Only one frame was attempted; no block-ack will arrive */ 3607 /* Only one frame was attempted; no block-ack will arrive */
3610 struct iwl4965_tx_queue *txq ; 3608 status = le16_to_cpu(frame_status[0].status);
3611 status = le32_to_cpu(frame_status[0]); 3609 seq = le16_to_cpu(frame_status[0].sequence);
3610 idx = SEQ_TO_INDEX(seq);
3611 txq_id = SEQ_TO_QUEUE(seq);
3612 3612
3613 txq_id = agg->txq_id;
3614 txq = &priv->txq[txq_id];
3615 /* FIXME: code repetition */ 3613 /* FIXME: code repetition */
3616 IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d \n", 3614 IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n",
3617 agg->frame_count, agg->start_idx); 3615 agg->frame_count, agg->start_idx, idx);
3618 3616
3619 tx_status = &(priv->txq[txq_id].txb[txq->q.read_ptr].status); 3617 tx_status = &(priv->txq[txq_id].txb[idx].status);
3620 tx_status->retry_count = tx_resp->failure_frame; 3618 tx_status->retry_count = tx_resp->failure_frame;
3621 tx_status->queue_number = status & 0xff; 3619 tx_status->queue_number = status & 0xff;
3622 tx_status->queue_length = tx_resp->bt_kill_count; 3620 tx_status->queue_length = tx_resp->failure_rts;
3623 tx_status->queue_length |= tx_resp->failure_rts; 3621 tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU;
3624
3625 tx_status->flags = iwl4965_is_tx_success(status)? 3622 tx_status->flags = iwl4965_is_tx_success(status)?
3626 IEEE80211_TX_STATUS_ACK : 0; 3623 IEEE80211_TX_STATUS_ACK : 0;
3627 tx_status->control.tx_rate = 3624 tx_status->control.tx_rate =
@@ -3642,8 +3639,8 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
3642 /* Construct bit-map of pending frames within Tx window */ 3639 /* Construct bit-map of pending frames within Tx window */
3643 for (i = 0; i < agg->frame_count; i++) { 3640 for (i = 0; i < agg->frame_count; i++) {
3644 u16 sc; 3641 u16 sc;
3645 status = le32_to_cpu(frame_status[i]); 3642 status = le16_to_cpu(frame_status[i].status);
3646 seq = status >> 16; 3643 seq = le16_to_cpu(frame_status[i].sequence);
3647 idx = SEQ_TO_INDEX(seq); 3644 idx = SEQ_TO_INDEX(seq);
3648 txq_id = SEQ_TO_QUEUE(seq); 3645 txq_id = SEQ_TO_QUEUE(seq);
3649 3646
@@ -3687,13 +3684,12 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
3687 start, (u32)(bitmap & 0xFFFFFFFF)); 3684 start, (u32)(bitmap & 0xFFFFFFFF));
3688 } 3685 }
3689 3686
3690 agg->bitmap0 = bitmap & 0xFFFFFFFF; 3687 agg->bitmap = bitmap;
3691 agg->bitmap1 = bitmap >> 32;
3692 agg->start_idx = start; 3688 agg->start_idx = start;
3693 agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); 3689 agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
3694 IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%x\n", 3690 IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n",
3695 agg->frame_count, agg->start_idx, 3691 agg->frame_count, agg->start_idx,
3696 agg->bitmap0); 3692 agg->bitmap);
3697 3693
3698 if (bitmap) 3694 if (bitmap)
3699 agg->wait_for_ba = 1; 3695 agg->wait_for_ba = 1;
@@ -3701,7 +3697,6 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
3701 return 0; 3697 return 0;
3702} 3698}
3703#endif 3699#endif
3704#endif
3705 3700
3706/** 3701/**
3707 * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response 3702 * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
@@ -3718,9 +3713,9 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
3718 struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; 3713 struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
3719 u32 status = le32_to_cpu(tx_resp->status); 3714 u32 status = le32_to_cpu(tx_resp->status);
3720#ifdef CONFIG_IWL4965_HT 3715#ifdef CONFIG_IWL4965_HT
3721#ifdef CONFIG_IWL4965_HT_AGG 3716 int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION;
3722 int tid, sta_id; 3717 struct ieee80211_hdr *hdr;
3723#endif 3718 __le16 *qc;
3724#endif 3719#endif
3725 3720
3726 if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) { 3721 if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) {
@@ -3732,44 +3727,51 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
3732 } 3727 }
3733 3728
3734#ifdef CONFIG_IWL4965_HT 3729#ifdef CONFIG_IWL4965_HT
3735#ifdef CONFIG_IWL4965_HT_AGG 3730 hdr = iwl4965_tx_queue_get_hdr(priv, txq_id, index);
3731 qc = ieee80211_get_qos_ctrl(hdr);
3732
3733 if (qc)
3734 tid = le16_to_cpu(*qc) & 0xf;
3735
3736 sta_id = iwl4965_get_ra_sta_id(priv, hdr);
3737 if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
3738 IWL_ERROR("Station not known\n");
3739 return;
3740 }
3741
3736 if (txq->sched_retry) { 3742 if (txq->sched_retry) {
3737 const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp); 3743 const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
3738 struct ieee80211_hdr *hdr =
3739 iwl4965_tx_queue_get_hdr(priv, txq_id, index);
3740 struct iwl4965_ht_agg *agg = NULL; 3744 struct iwl4965_ht_agg *agg = NULL;
3741 __le16 *qc = ieee80211_get_qos_ctrl(hdr);
3742 3745
3743 if (qc == NULL) { 3746 if (!qc)
3744 IWL_ERROR("BUG_ON qc is null!!!!\n");
3745 return; 3747 return;
3746 }
3747
3748 tid = le16_to_cpu(*qc) & 0xf;
3749
3750 sta_id = iwl4965_get_ra_sta_id(priv, hdr);
3751 if (unlikely(sta_id == IWL_INVALID_STATION)) {
3752 IWL_ERROR("Station not known for\n");
3753 return;
3754 }
3755 3748
3756 agg = &priv->stations[sta_id].tid[tid].agg; 3749 agg = &priv->stations[sta_id].tid[tid].agg;
3757 3750
3758 iwl4965_tx_status_reply_tx(priv, agg, tx_resp, index); 3751 iwl4965_tx_status_reply_tx(priv, agg,
3752 (struct iwl4965_tx_resp_agg *)tx_resp, index);
3759 3753
3760 if ((tx_resp->frame_count == 1) && 3754 if ((tx_resp->frame_count == 1) &&
3761 !iwl4965_is_tx_success(status)) { 3755 !iwl4965_is_tx_success(status)) {
3762 /* TODO: send BAR */ 3756 /* TODO: send BAR */
3763 } 3757 }
3764 3758
3765 if ((txq->q.read_ptr != (scd_ssn & 0xff))) { 3759 if (txq->q.read_ptr != (scd_ssn & 0xff)) {
3760 int freed;
3766 index = iwl4965_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); 3761 index = iwl4965_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
3767 IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn " 3762 IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
3768 "%d index %d\n", scd_ssn , index); 3763 "%d index %d\n", scd_ssn , index);
3769 iwl4965_tx_queue_reclaim(priv, txq_id, index); 3764 freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
3765 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
3766
3767 if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
3768 txq_id >= 0 && priv->mac80211_registered &&
3769 agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
3770 ieee80211_wake_queue(priv->hw, txq_id);
3771
3772 iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
3770 } 3773 }
3771 } else { 3774 } else {
3772#endif /* CONFIG_IWL4965_HT_AGG */
3773#endif /* CONFIG_IWL4965_HT */ 3775#endif /* CONFIG_IWL4965_HT */
3774 tx_status = &(txq->txb[txq->q.read_ptr].status); 3776 tx_status = &(txq->txb[txq->q.read_ptr].status);
3775 3777
@@ -3790,12 +3792,21 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
3790 tx_resp->failure_frame); 3792 tx_resp->failure_frame);
3791 3793
3792 IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); 3794 IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
3793 if (index != -1) 3795 if (index != -1) {
3794 iwl4965_tx_queue_reclaim(priv, txq_id, index); 3796 int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
3797#ifdef CONFIG_IWL4965_HT
3798 if (tid != MAX_TID_COUNT)
3799 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
3800 if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
3801 (txq_id >= 0) &&
3802 priv->mac80211_registered)
3803 ieee80211_wake_queue(priv->hw, txq_id);
3804 if (tid != MAX_TID_COUNT)
3805 iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
3806#endif
3807 }
3795#ifdef CONFIG_IWL4965_HT 3808#ifdef CONFIG_IWL4965_HT
3796#ifdef CONFIG_IWL4965_HT_AGG
3797 } 3809 }
3798#endif /* CONFIG_IWL4965_HT_AGG */
3799#endif /* CONFIG_IWL4965_HT */ 3810#endif /* CONFIG_IWL4965_HT */
3800 3811
3801 if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) 3812 if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
@@ -9089,10 +9100,8 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
9089 /* Default value; 4 EDCA QOS priorities */ 9100 /* Default value; 4 EDCA QOS priorities */
9090 hw->queues = 4; 9101 hw->queues = 4;
9091#ifdef CONFIG_IWL4965_HT 9102#ifdef CONFIG_IWL4965_HT
9092#ifdef CONFIG_IWL4965_HT_AGG
9093 /* Enhanced value; more queues, to support 11n aggregation */ 9103 /* Enhanced value; more queues, to support 11n aggregation */
9094 hw->queues = 16; 9104 hw->queues = 16;
9095#endif /* CONFIG_IWL4965_HT_AGG */
9096#endif /* CONFIG_IWL4965_HT */ 9105#endif /* CONFIG_IWL4965_HT */
9097 9106
9098 spin_lock_init(&priv->lock); 9107 spin_lock_init(&priv->lock);