2 * carl9170 firmware - used by the ar9170 wireless device
4 * WLAN receive routines
6 * Copyright (c) 2000-2005 ZyDAS Technology Corporation
7 * Copyright (c) 2007-2009 Atheros Communications, Inc.
8 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
9 * Copyright 2009-2012 Christian Lamparter <chunkeey@googlemail.com>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; If not, see <http://www.gnu.org/licenses/>.
26 #include "shared/phy.h"
32 #include "linux/ieee80211.h"
35 static struct carl9170_bar_ctx *wlan_get_bar_cache_buffer(void)
37 struct carl9170_bar_ctx *tmp;
39 tmp = &fw.wlan.ba_cache[fw.wlan.ba_tail_idx];
40 fw.wlan.ba_tail_idx++;
41 fw.wlan.ba_tail_idx %= CONFIG_CARL9170FW_BACK_REQS_NUM;
42 if (fw.wlan.queued_ba < CONFIG_CARL9170FW_BACK_REQS_NUM)
48 static void handle_bar(struct dma_desc *desc __unused, struct ieee80211_hdr *hdr,
49 unsigned int len, unsigned int mac_err)
51 struct ieee80211_bar *bar;
52 struct carl9170_bar_ctx *ctx;
54 if (unlikely(mac_err)) {
56 * This check does a number of things:
57 * 1. checks if the frame is in good nick
58 * 2. checks if the RA (MAC) matches
63 if (unlikely(len < (sizeof(struct ieee80211_bar) + FCS_LEN))) {
65 * Sneaky, corrupted BARs... but not with us!
73 if ((bar->control & cpu_to_le16(IEEE80211_BAR_CTRL_MULTI_TID)) ||
74 !(bar->control & cpu_to_le16(IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA))) {
75 /* not implemented yet */
80 ctx = wlan_get_bar_cache_buffer();
82 memcpy(ctx->ra, bar->ra, 6);
83 memcpy(ctx->ta, bar->ta, 6);
84 ctx->control = bar->control;
85 ctx->start_seq_num = bar->start_seq_num;
88 static unsigned int wlan_rx_filter(struct dma_desc *desc)
90 struct ieee80211_hdr *hdr;
91 unsigned int data_len;
92 unsigned int rx_filter;
95 data_len = ar9170_get_rx_mpdu_len(desc);
96 mac_err = ar9170_get_rx_macstatus_error(desc);
98 #define AR9170_RX_ERROR_BAD (AR9170_RX_ERROR_FCS | AR9170_RX_ERROR_PLCP)
100 if (unlikely(data_len < (4 + 6 + FCS_LEN) ||
101 desc->totalLen > CONFIG_CARL9170FW_RX_FRAME_LEN) ||
102 mac_err & AR9170_RX_ERROR_BAD) {
104 * This frame is too damaged to do anything
108 return CARL9170_RX_FILTER_BAD;
112 if (mac_err & AR9170_RX_ERROR_WRONG_RA)
113 rx_filter |= CARL9170_RX_FILTER_OTHER_RA;
115 if (mac_err & AR9170_RX_ERROR_DECRYPT)
116 rx_filter |= CARL9170_RX_FILTER_DECRY_FAIL;
118 hdr = ar9170_get_rx_i3e(desc);
119 if (likely(ieee80211_is_data(hdr->frame_control))) {
120 rx_filter |= CARL9170_RX_FILTER_DATA;
121 } else if (ieee80211_is_ctl(hdr->frame_control)) {
122 switch (le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE) {
123 case IEEE80211_STYPE_BACK_REQ:
124 handle_bar(desc, hdr, data_len, mac_err);
125 rx_filter |= CARL9170_RX_FILTER_CTL_BACKR;
127 case IEEE80211_STYPE_PSPOLL:
128 rx_filter |= CARL9170_RX_FILTER_CTL_PSPOLL;
130 case IEEE80211_STYPE_BACK:
131 if (fw.wlan.queued_bar) {
133 * Don't filter block acks when the application
134 * has queued BARs. This is because the firmware
135 * can't do the accouting and the application
136 * has to sort out if the BA belongs to any BARs.
142 rx_filter |= CARL9170_RX_FILTER_CTL_OTHER;
146 /* ieee80211_is_mgmt */
147 rx_filter |= CARL9170_RX_FILTER_MGMT;
150 if (unlikely(fw.suspend_mode == CARL9170_HOST_SUSPENDED)) {
151 wol_rx(rx_filter, hdr, min(data_len,
152 (unsigned int)AR9170_BLOCK_SIZE));
155 #undef AR9170_RX_ERROR_BAD
160 void handle_wlan_rx(void)
162 struct dma_desc *desc;
164 for_each_desc_not_bits(desc, &fw.wlan.rx_queue, AR9170_OWN_BITS_HW) {
165 if (!(wlan_rx_filter(desc) & fw.wlan.rx_filter)) {
166 dma_put(&fw.pta.up_queue, desc);
169 dma_reclaim(&fw.wlan.rx_queue, desc);
170 wlan_trigger(AR9170_DMA_TRIGGER_RXQ);