diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 112 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl4965-base.c | 19 |
3 files changed, 55 insertions, 82 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index a94578889e17..e6a0397266fc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -2673,19 +2673,23 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv, | |||
2673 | struct ieee80211_hdr *hdr, int sta_id, | 2673 | struct ieee80211_hdr *hdr, int sta_id, |
2674 | int is_hcca) | 2674 | int is_hcca) |
2675 | { | 2675 | { |
2676 | u8 rate; | 2676 | struct iwl4965_tx_cmd *tx = &cmd->cmd.tx; |
2677 | u8 rts_retry_limit = 0; | 2677 | u8 rts_retry_limit = 0; |
2678 | u8 data_retry_limit = 0; | 2678 | u8 data_retry_limit = 0; |
2679 | __le32 tx_flags; | ||
2680 | u16 fc = le16_to_cpu(hdr->frame_control); | 2679 | u16 fc = le16_to_cpu(hdr->frame_control); |
2680 | u8 rate_plcp; | ||
2681 | u16 rate_flags = 0; | ||
2682 | int rate_idx = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1); | ||
2681 | 2683 | ||
2682 | tx_flags = cmd->cmd.tx.tx_flags; | 2684 | rate_plcp = iwl4965_rates[rate_idx].plcp; |
2683 | |||
2684 | rate = iwl4965_rates[ctrl->tx_rate].plcp; | ||
2685 | 2685 | ||
2686 | rts_retry_limit = (is_hcca) ? | 2686 | rts_retry_limit = (is_hcca) ? |
2687 | RTS_HCCA_RETRY_LIMIT : RTS_DFAULT_RETRY_LIMIT; | 2687 | RTS_HCCA_RETRY_LIMIT : RTS_DFAULT_RETRY_LIMIT; |
2688 | 2688 | ||
2689 | if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) | ||
2690 | rate_flags |= RATE_MCS_CCK_MSK; | ||
2691 | |||
2692 | |||
2689 | if (ieee80211_is_probe_response(fc)) { | 2693 | if (ieee80211_is_probe_response(fc)) { |
2690 | data_retry_limit = 3; | 2694 | data_retry_limit = 3; |
2691 | if (data_retry_limit < rts_retry_limit) | 2695 | if (data_retry_limit < rts_retry_limit) |
@@ -2696,26 +2700,38 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv, | |||
2696 | if (priv->data_retry_limit != -1) | 2700 | if (priv->data_retry_limit != -1) |
2697 | data_retry_limit = priv->data_retry_limit; | 2701 | data_retry_limit = priv->data_retry_limit; |
2698 | 2702 | ||
2699 | if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) { | 2703 | |
2704 | if (ieee80211_is_data(fc)) { | ||
2705 | tx->initial_rate_index = 0; | ||
2706 | tx->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; | ||
2707 | } else { | ||
2700 | switch (fc & IEEE80211_FCTL_STYPE) { | 2708 | switch (fc & IEEE80211_FCTL_STYPE) { |
2701 | case IEEE80211_STYPE_AUTH: | 2709 | case IEEE80211_STYPE_AUTH: |
2702 | case IEEE80211_STYPE_DEAUTH: | 2710 | case IEEE80211_STYPE_DEAUTH: |
2703 | case IEEE80211_STYPE_ASSOC_REQ: | 2711 | case IEEE80211_STYPE_ASSOC_REQ: |
2704 | case IEEE80211_STYPE_REASSOC_REQ: | 2712 | case IEEE80211_STYPE_REASSOC_REQ: |
2705 | if (tx_flags & TX_CMD_FLG_RTS_MSK) { | 2713 | if (tx->tx_flags & TX_CMD_FLG_RTS_MSK) { |
2706 | tx_flags &= ~TX_CMD_FLG_RTS_MSK; | 2714 | tx->tx_flags &= ~TX_CMD_FLG_RTS_MSK; |
2707 | tx_flags |= TX_CMD_FLG_CTS_MSK; | 2715 | tx->tx_flags |= TX_CMD_FLG_CTS_MSK; |
2708 | } | 2716 | } |
2709 | break; | 2717 | break; |
2710 | default: | 2718 | default: |
2711 | break; | 2719 | break; |
2712 | } | 2720 | } |
2721 | |||
2722 | /* Alternate between antenna A and B for successive frames */ | ||
2723 | if (priv->use_ant_b_for_management_frame) { | ||
2724 | priv->use_ant_b_for_management_frame = 0; | ||
2725 | rate_flags |= RATE_MCS_ANT_B_MSK; | ||
2726 | } else { | ||
2727 | priv->use_ant_b_for_management_frame = 1; | ||
2728 | rate_flags |= RATE_MCS_ANT_A_MSK; | ||
2729 | } | ||
2713 | } | 2730 | } |
2714 | 2731 | ||
2715 | cmd->cmd.tx.rts_retry_limit = rts_retry_limit; | 2732 | tx->rts_retry_limit = rts_retry_limit; |
2716 | cmd->cmd.tx.data_retry_limit = data_retry_limit; | 2733 | tx->data_retry_limit = data_retry_limit; |
2717 | cmd->cmd.tx.rate_n_flags = iwl4965_hw_set_rate_n_flags(rate, 0); | 2734 | tx->rate_n_flags = iwl4965_hw_set_rate_n_flags(rate_plcp, rate_flags); |
2718 | cmd->cmd.tx.tx_flags = tx_flags; | ||
2719 | } | 2735 | } |
2720 | 2736 | ||
2721 | int iwl4965_hw_get_rx_read(struct iwl4965_priv *priv) | 2737 | int iwl4965_hw_get_rx_read(struct iwl4965_priv *priv) |
@@ -3254,69 +3270,13 @@ static void iwl4965_bg_agg_work(struct work_struct *work) | |||
3254 | spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); | 3270 | spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); |
3255 | return; | 3271 | return; |
3256 | } | 3272 | } |
3257 | #endif /*CONFIG_IWL4965_HT_AGG */ | ||
3258 | #endif /* CONFIG_IWL4965_HT */ | ||
3259 | 3273 | ||
3260 | int iwl4965_tx_cmd(struct iwl4965_priv *priv, struct iwl4965_cmd *out_cmd, | 3274 | /* TODO: move this functionality to rate scaling */ |
3261 | u8 sta_id, dma_addr_t txcmd_phys, | 3275 | void iwl4965_tl_get_stats(struct iwl4965_priv *priv, |
3262 | struct ieee80211_hdr *hdr, u8 hdr_len, | 3276 | struct ieee80211_hdr *hdr) |
3263 | struct ieee80211_tx_control *ctrl, void *sta_in) | ||
3264 | { | 3277 | { |
3265 | struct iwl4965_tx_cmd *tx = &out_cmd->cmd.tx; | 3278 | __le16 *qc = ieee80211_get_qos_ctrl(hdr); |
3266 | dma_addr_t scratch_phys; | ||
3267 | u8 unicast = 0; | ||
3268 | u8 is_data = 1; | ||
3269 | u16 fc; | ||
3270 | u16 rate_flags; | ||
3271 | int rate_index = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1); | ||
3272 | #ifdef CONFIG_IWL4965_HT | ||
3273 | #ifdef CONFIG_IWL4965_HT_AGG | ||
3274 | __le16 *qc; | ||
3275 | #endif /*CONFIG_IWL4965_HT_AGG */ | ||
3276 | #endif /* CONFIG_IWL4965_HT */ | ||
3277 | |||
3278 | unicast = !is_multicast_ether_addr(hdr->addr1); | ||
3279 | |||
3280 | fc = le16_to_cpu(hdr->frame_control); | ||
3281 | if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) | ||
3282 | is_data = 0; | ||
3283 | 3279 | ||
3284 | scratch_phys = txcmd_phys + sizeof(struct iwl4965_cmd_header) + | ||
3285 | offsetof(struct iwl4965_tx_cmd, scratch); | ||
3286 | tx->dram_lsb_ptr = cpu_to_le32(scratch_phys); | ||
3287 | tx->dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys); | ||
3288 | |||
3289 | /* Hard coded to start at the highest retry fallback position | ||
3290 | * until the 4965 specific rate control algorithm is tied in */ | ||
3291 | tx->initial_rate_index = LINK_QUAL_MAX_RETRY_NUM - 1; | ||
3292 | |||
3293 | /* Alternate between antenna A and B for successive frames */ | ||
3294 | if (priv->use_ant_b_for_management_frame) { | ||
3295 | priv->use_ant_b_for_management_frame = 0; | ||
3296 | rate_flags = RATE_MCS_ANT_B_MSK; | ||
3297 | } else { | ||
3298 | priv->use_ant_b_for_management_frame = 1; | ||
3299 | rate_flags = RATE_MCS_ANT_A_MSK; | ||
3300 | } | ||
3301 | |||
3302 | if (!unicast || !is_data) { | ||
3303 | if ((rate_index >= IWL_FIRST_CCK_RATE) && | ||
3304 | (rate_index <= IWL_LAST_CCK_RATE)) | ||
3305 | rate_flags |= RATE_MCS_CCK_MSK; | ||
3306 | } else { | ||
3307 | tx->initial_rate_index = 0; | ||
3308 | tx->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; | ||
3309 | } | ||
3310 | |||
3311 | tx->rate_n_flags = iwl4965_hw_set_rate_n_flags(iwl4965_rates[rate_index].plcp, | ||
3312 | rate_flags); | ||
3313 | |||
3314 | if (ieee80211_is_back_request(fc)) | ||
3315 | tx->tx_flags |= TX_CMD_FLG_ACK_MSK | | ||
3316 | TX_CMD_FLG_IMM_BA_RSP_MASK; | ||
3317 | #ifdef CONFIG_IWL4965_HT | ||
3318 | #ifdef CONFIG_IWL4965_HT_AGG | ||
3319 | qc = ieee80211_get_qos_ctrl(hdr); | ||
3320 | if (qc && | 3280 | if (qc && |
3321 | (priv->iw_mode != IEEE80211_IF_TYPE_IBSS)) { | 3281 | (priv->iw_mode != IEEE80211_IF_TYPE_IBSS)) { |
3322 | u8 tid = 0; | 3282 | u8 tid = 0; |
@@ -3334,11 +3294,11 @@ int iwl4965_tx_cmd(struct iwl4965_priv *priv, struct iwl4965_cmd *out_cmd, | |||
3334 | spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); | 3294 | spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); |
3335 | schedule_work(&priv->agg_work); | 3295 | schedule_work(&priv->agg_work); |
3336 | } | 3296 | } |
3337 | #endif | ||
3338 | #endif | ||
3339 | return 0; | ||
3340 | } | 3297 | } |
3341 | 3298 | ||
3299 | #endif /*CONFIG_IWL4965_HT_AGG */ | ||
3300 | #endif /* CONFIG_IWL4965_HT */ | ||
3301 | |||
3342 | /** | 3302 | /** |
3343 | * sign_extend - Sign extend a value using specified bit as sign-bit | 3303 | * sign_extend - Sign extend a value using specified bit as sign-bit |
3344 | * | 3304 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index c38648216dc4..78bc148c9f7f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h | |||
@@ -758,10 +758,6 @@ extern int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv, | |||
758 | extern void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, | 758 | extern void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, |
759 | int is_ap); | 759 | int is_ap); |
760 | extern void iwl4965_set_rxon_chain(struct iwl4965_priv *priv); | 760 | extern void iwl4965_set_rxon_chain(struct iwl4965_priv *priv); |
761 | extern int iwl4965_tx_cmd(struct iwl4965_priv *priv, struct iwl4965_cmd *out_cmd, | ||
762 | u8 sta_id, dma_addr_t txcmd_phys, | ||
763 | struct ieee80211_hdr *hdr, u8 hdr_len, | ||
764 | struct ieee80211_tx_control *ctrl, void *sta_in); | ||
765 | extern int iwl4965_alive_notify(struct iwl4965_priv *priv); | 761 | extern int iwl4965_alive_notify(struct iwl4965_priv *priv); |
766 | extern void iwl4965_update_rate_scaling(struct iwl4965_priv *priv, u8 mode); | 762 | extern void iwl4965_update_rate_scaling(struct iwl4965_priv *priv, u8 mode); |
767 | extern void iwl4965_chain_noise_reset(struct iwl4965_priv *priv); | 763 | extern void iwl4965_chain_noise_reset(struct iwl4965_priv *priv); |
@@ -789,6 +785,8 @@ extern int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da, | |||
789 | extern int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, | 785 | extern int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, |
790 | u16 tid, int generator); | 786 | u16 tid, int generator); |
791 | extern void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid); | 787 | extern void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid); |
788 | extern void iwl4965_tl_get_stats(struct iwl4965_priv *priv, | ||
789 | struct ieee80211_hdr *hdr); | ||
792 | #endif /* CONFIG_IWL4965_HT_AGG */ | 790 | #endif /* CONFIG_IWL4965_HT_AGG */ |
793 | #endif /*CONFIG_IWL4965_HT */ | 791 | #endif /*CONFIG_IWL4965_HT */ |
794 | /* Structures, enum, and defines specific to the 4965 */ | 792 | /* Structures, enum, and defines specific to the 4965 */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 2597c08a2395..ad824c607f36 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -2772,6 +2772,10 @@ static void iwl4965_build_tx_cmd_basic(struct iwl4965_priv *priv, | |||
2772 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | 2772 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; |
2773 | } | 2773 | } |
2774 | 2774 | ||
2775 | if (ieee80211_is_back_request(fc)) | ||
2776 | tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; | ||
2777 | |||
2778 | |||
2775 | cmd->cmd.tx.sta_id = std_id; | 2779 | cmd->cmd.tx.sta_id = std_id; |
2776 | if (ieee80211_get_morefrag(hdr)) | 2780 | if (ieee80211_get_morefrag(hdr)) |
2777 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; | 2781 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; |
@@ -2880,6 +2884,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, | |||
2880 | struct iwl4965_queue *q = NULL; | 2884 | struct iwl4965_queue *q = NULL; |
2881 | dma_addr_t phys_addr; | 2885 | dma_addr_t phys_addr; |
2882 | dma_addr_t txcmd_phys; | 2886 | dma_addr_t txcmd_phys; |
2887 | dma_addr_t scratch_phys; | ||
2883 | struct iwl4965_cmd *out_cmd = NULL; | 2888 | struct iwl4965_cmd *out_cmd = NULL; |
2884 | u16 len, idx, len_org; | 2889 | u16 len, idx, len_org; |
2885 | u8 id, hdr_len, unicast; | 2890 | u8 id, hdr_len, unicast; |
@@ -3053,8 +3058,18 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, | |||
3053 | /* set is_hcca to 0; it probably will never be implemented */ | 3058 | /* set is_hcca to 0; it probably will never be implemented */ |
3054 | iwl4965_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0); | 3059 | iwl4965_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0); |
3055 | 3060 | ||
3056 | iwl4965_tx_cmd(priv, out_cmd, sta_id, txcmd_phys, | 3061 | scratch_phys = txcmd_phys + sizeof(struct iwl4965_cmd_header) + |
3057 | hdr, hdr_len, ctl, NULL); | 3062 | offsetof(struct iwl4965_tx_cmd, scratch); |
3063 | out_cmd->cmd.tx.dram_lsb_ptr = cpu_to_le32(scratch_phys); | ||
3064 | out_cmd->cmd.tx.dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys); | ||
3065 | |||
3066 | #ifdef CONFIG_IWL4965_HT_AGG | ||
3067 | #ifdef CONFIG_IWL4965_HT | ||
3068 | /* TODO: move this functionality to rate scaling */ | ||
3069 | iwl4965_tl_get_stats(priv, hdr); | ||
3070 | #endif /* CONFIG_IWL4965_HT_AGG */ | ||
3071 | #endif /*CONFIG_IWL4965_HT */ | ||
3072 | |||
3058 | 3073 | ||
3059 | if (!ieee80211_get_morefrag(hdr)) { | 3074 | if (!ieee80211_get_morefrag(hdr)) { |
3060 | txq->need_update = 1; | 3075 | txq->need_update = 1; |