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, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "shared/phy.h"
33 #include "linux/ieee80211.h"
36 static struct carl9170_bar_ctx *wlan_get_bar_cache_buffer(void)
38 struct carl9170_bar_ctx *tmp;
40 tmp = &fw.wlan.ba_cache[fw.wlan.ba_tail_idx];
41 fw.wlan.ba_tail_idx++;
42 fw.wlan.ba_tail_idx %= CONFIG_CARL9170FW_BACK_REQS_NUM;
43 if (fw.wlan.queued_ba < CONFIG_CARL9170FW_BACK_REQS_NUM)
49 static void handle_bar(struct dma_desc *desc __unused, struct ieee80211_hdr *hdr,
50 unsigned int len, unsigned int mac_err)
52 struct ieee80211_bar *bar;
53 struct carl9170_bar_ctx *ctx;
55 if (unlikely(mac_err)) {
57 * This check does a number of things:
58 * 1. checks if the frame is in good nick
59 * 2. checks if the RA (MAC) matches
64 if (unlikely(len < (sizeof(struct ieee80211_bar) + FCS_LEN))) {
66 * Sneaky, corrupted BARs... but not with us!
74 if ((bar->control & cpu_to_le16(IEEE80211_BAR_CTRL_MULTI_TID)) ||
75 !(bar->control & cpu_to_le16(IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA))) {
76 /* not implemented yet */
81 ctx = wlan_get_bar_cache_buffer();
83 memcpy(ctx->ra, bar->ra, 6);
84 memcpy(ctx->ta, bar->ta, 6);
85 ctx->control = bar->control;
86 ctx->start_seq_num = bar->start_seq_num;
89 static unsigned int wlan_rx_filter(struct dma_desc *desc)
91 struct ieee80211_hdr *hdr;
92 unsigned int data_len;
93 unsigned int rx_filter;
96 data_len = ar9170_get_rx_mpdu_len(desc);
97 mac_err = ar9170_get_rx_macstatus_error(desc);
99 #define AR9170_RX_ERROR_BAD (AR9170_RX_ERROR_FCS | AR9170_RX_ERROR_PLCP)
101 if (unlikely(data_len < (4 + 6 + FCS_LEN) ||
102 desc->totalLen > CONFIG_CARL9170FW_RX_FRAME_LEN) ||
103 mac_err & AR9170_RX_ERROR_BAD) {
105 * This frame is too damaged to do anything
109 return CARL9170_RX_FILTER_BAD;
113 if (mac_err & AR9170_RX_ERROR_WRONG_RA)
114 rx_filter |= CARL9170_RX_FILTER_OTHER_RA;
116 if (mac_err & AR9170_RX_ERROR_DECRYPT)
117 rx_filter |= CARL9170_RX_FILTER_DECRY_FAIL;
119 hdr = ar9170_get_rx_i3e(desc);
120 if (likely(ieee80211_is_data(hdr->frame_control))) {
121 rx_filter |= CARL9170_RX_FILTER_DATA;
122 } else if (ieee80211_is_ctl(hdr->frame_control)) {
123 switch (le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE) {
124 case IEEE80211_STYPE_BACK_REQ:
125 handle_bar(desc, hdr, data_len, mac_err);
126 rx_filter |= CARL9170_RX_FILTER_CTL_BACKR;
128 case IEEE80211_STYPE_PSPOLL:
129 rx_filter |= CARL9170_RX_FILTER_CTL_PSPOLL;
131 case IEEE80211_STYPE_BACK:
132 if (fw.wlan.queued_bar) {
134 * Don't filter block acks when the application
135 * has queued BARs. This is because the firmware
136 * can't do the accouting and the application
137 * has to sort out if the BA belongs to any BARs.
141 /* otherwise fall through */
143 rx_filter |= CARL9170_RX_FILTER_CTL_OTHER;
147 /* ieee80211_is_mgmt */
148 rx_filter |= CARL9170_RX_FILTER_MGMT;
151 if (unlikely(fw.suspend_mode == CARL9170_HOST_SUSPENDED)) {
152 wol_rx(rx_filter, hdr, min(data_len,
153 (unsigned int)AR9170_BLOCK_SIZE));
156 #undef AR9170_RX_ERROR_BAD
161 void handle_wlan_rx(void)
163 struct dma_desc *desc;
165 for_each_desc_not_bits(desc, &fw.wlan.rx_queue, AR9170_OWN_BITS_HW) {
166 if (!(wlan_rx_filter(desc) & fw.wlan.rx_filter)) {
167 dma_put(&fw.pta.up_queue, desc);
170 dma_reclaim(&fw.wlan.rx_queue, desc);
171 wlan_trigger(AR9170_DMA_TRIGGER_RXQ);