]>
Commit | Line | Data |
---|---|---|
a55360e4 TW |
1 | /****************************************************************************** |
2 | * | |
1f447808 | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
a55360e4 TW |
4 | * |
5 | * Portions of this file are derived from the ipw3945 project, as well | |
6 | * as portions of the ieee80211 subsystem header files. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify it | |
9 | * under the terms of version 2 of the GNU General Public License as | |
10 | * published by the Free Software Foundation. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
15 | * more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License along with | |
18 | * this program; if not, write to the Free Software Foundation, Inc., | |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | |
20 | * | |
21 | * The full GNU General Public License is included in this distribution in the | |
22 | * file called LICENSE. | |
23 | * | |
24 | * Contact Information: | |
759ef89f | 25 | * Intel Linux Wireless <ilw@linux.intel.com> |
a55360e4 TW |
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
27 | * | |
28 | *****************************************************************************/ | |
29 | ||
1781a07f | 30 | #include <linux/etherdevice.h> |
5a0e3ad6 | 31 | #include <linux/slab.h> |
a55360e4 | 32 | #include <net/mac80211.h> |
a05ffd39 | 33 | #include <asm/unaligned.h> |
a55360e4 TW |
34 | #include "iwl-eeprom.h" |
35 | #include "iwl-dev.h" | |
36 | #include "iwl-core.h" | |
37 | #include "iwl-sta.h" | |
38 | #include "iwl-io.h" | |
39 | #include "iwl-helpers.h" | |
40 | /************************** RX-FUNCTIONS ****************************/ | |
41 | /* | |
42 | * Rx theory of operation | |
43 | * | |
44 | * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs), | |
45 | * each of which point to Receive Buffers to be filled by the NIC. These get | |
46 | * used not only for Rx frames, but for any command response or notification | |
47 | * from the NIC. The driver and NIC manage the Rx buffers by means | |
48 | * of indexes into the circular buffer. | |
49 | * | |
50 | * Rx Queue Indexes | |
51 | * The host/firmware share two index registers for managing the Rx buffers. | |
52 | * | |
53 | * The READ index maps to the first position that the firmware may be writing | |
54 | * to -- the driver can read up to (but not including) this position and get | |
55 | * good data. | |
56 | * The READ index is managed by the firmware once the card is enabled. | |
57 | * | |
58 | * The WRITE index maps to the last position the driver has read from -- the | |
59 | * position preceding WRITE is the last slot the firmware can place a packet. | |
60 | * | |
61 | * The queue is empty (no good data) if WRITE = READ - 1, and is full if | |
62 | * WRITE = READ. | |
63 | * | |
64 | * During initialization, the host sets up the READ queue position to the first | |
65 | * INDEX position, and WRITE to the last (READ - 1 wrapped) | |
66 | * | |
67 | * When the firmware places a packet in a buffer, it will advance the READ index | |
68 | * and fire the RX interrupt. The driver can then query the READ index and | |
69 | * process as many packets as possible, moving the WRITE index forward as it | |
70 | * resets the Rx queue buffers with new memory. | |
71 | * | |
72 | * The management in the driver is as follows: | |
73 | * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When | |
74 | * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled | |
75 | * to replenish the iwl->rxq->rx_free. | |
76 | * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the | |
77 | * iwl->rxq is replenished and the READ INDEX is updated (updating the | |
78 | * 'processed' and 'read' driver indexes as well) | |
79 | * + A received packet is processed and handed to the kernel network stack, | |
80 | * detached from the iwl->rxq. The driver 'processed' index is updated. | |
81 | * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free | |
82 | * list. If there are no allocated buffers in iwl->rxq->rx_free, the READ | |
83 | * INDEX is not incremented and iwl->status(RX_STALLED) is set. If there | |
84 | * were enough free buffers and RX_STALLED is set it is cleared. | |
85 | * | |
86 | * | |
87 | * Driver sequence: | |
88 | * | |
89 | * iwl_rx_queue_alloc() Allocates rx_free | |
90 | * iwl_rx_replenish() Replenishes rx_free list from rx_used, and calls | |
91 | * iwl_rx_queue_restock | |
92 | * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx | |
93 | * queue, updates firmware pointers, and updates | |
94 | * the WRITE index. If insufficient rx_free buffers | |
95 | * are available, schedules iwl_rx_replenish | |
96 | * | |
97 | * -- enable interrupts -- | |
98 | * ISR - iwl_rx() Detach iwl_rx_mem_buffers from pool up to the | |
99 | * READ INDEX, detaching the SKB from the pool. | |
100 | * Moves the packet buffer from queue to rx_used. | |
101 | * Calls iwl_rx_queue_restock to refill any empty | |
102 | * slots. | |
103 | * ... | |
104 | * | |
105 | */ | |
106 | ||
107 | /** | |
108 | * iwl_rx_queue_space - Return number of free slots available in queue. | |
109 | */ | |
110 | int iwl_rx_queue_space(const struct iwl_rx_queue *q) | |
111 | { | |
112 | int s = q->read - q->write; | |
113 | if (s <= 0) | |
114 | s += RX_QUEUE_SIZE; | |
115 | /* keep some buffer to not confuse full and empty queue */ | |
116 | s -= 2; | |
117 | if (s < 0) | |
118 | s = 0; | |
119 | return s; | |
120 | } | |
121 | EXPORT_SYMBOL(iwl_rx_queue_space); | |
122 | ||
123 | /** | |
124 | * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue | |
125 | */ | |
7bfedc59 | 126 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) |
a55360e4 | 127 | { |
a55360e4 | 128 | unsigned long flags; |
141c43a3 WT |
129 | u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg; |
130 | u32 reg; | |
a55360e4 TW |
131 | |
132 | spin_lock_irqsave(&q->lock, flags); | |
133 | ||
134 | if (q->need_update == 0) | |
135 | goto exit_unlock; | |
136 | ||
137 | /* If power-saving is in use, make sure device is awake */ | |
138 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | |
139 | reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); | |
140 | ||
141 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | |
309e731a BC |
142 | IWL_DEBUG_INFO(priv, "Rx queue requesting wakeup, GP1 = 0x%x\n", |
143 | reg); | |
a55360e4 TW |
144 | iwl_set_bit(priv, CSR_GP_CNTRL, |
145 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | |
146 | goto exit_unlock; | |
147 | } | |
148 | ||
4752c93c MA |
149 | q->write_actual = (q->write & ~0x7); |
150 | iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual); | |
a55360e4 TW |
151 | |
152 | /* Else device is assumed to be awake */ | |
141c43a3 | 153 | } else { |
a55360e4 | 154 | /* Device expects a multiple of 8 */ |
4752c93c MA |
155 | q->write_actual = (q->write & ~0x7); |
156 | iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual); | |
141c43a3 | 157 | } |
a55360e4 TW |
158 | |
159 | q->need_update = 0; | |
160 | ||
161 | exit_unlock: | |
162 | spin_unlock_irqrestore(&q->lock, flags); | |
a55360e4 TW |
163 | } |
164 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); | |
a55360e4 TW |
165 | |
166 | int iwl_rx_queue_alloc(struct iwl_priv *priv) | |
167 | { | |
168 | struct iwl_rx_queue *rxq = &priv->rxq; | |
f36d04ab | 169 | struct device *dev = &priv->pci_dev->dev; |
a55360e4 TW |
170 | int i; |
171 | ||
172 | spin_lock_init(&rxq->lock); | |
173 | INIT_LIST_HEAD(&rxq->rx_free); | |
174 | INIT_LIST_HEAD(&rxq->rx_used); | |
175 | ||
176 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ | |
d5b25c90 | 177 | rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma, |
f36d04ab | 178 | GFP_KERNEL); |
a55360e4 | 179 | if (!rxq->bd) |
8d86422a WT |
180 | goto err_bd; |
181 | ||
f36d04ab SG |
182 | rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status), |
183 | &rxq->rb_stts_dma, GFP_KERNEL); | |
8d86422a WT |
184 | if (!rxq->rb_stts) |
185 | goto err_rb; | |
a55360e4 TW |
186 | |
187 | /* Fill the rx_used queue with _all_ of the Rx buffers */ | |
188 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) | |
189 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | |
190 | ||
191 | /* Set us so that we have processed and used all buffers, but have | |
192 | * not restocked the Rx queue with fresh buffers */ | |
193 | rxq->read = rxq->write = 0; | |
4752c93c | 194 | rxq->write_actual = 0; |
a55360e4 TW |
195 | rxq->free_count = 0; |
196 | rxq->need_update = 0; | |
197 | return 0; | |
8d86422a WT |
198 | |
199 | err_rb: | |
f36d04ab | 200 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
d5b25c90 | 201 | rxq->bd_dma); |
8d86422a WT |
202 | err_bd: |
203 | return -ENOMEM; | |
a55360e4 TW |
204 | } |
205 | EXPORT_SYMBOL(iwl_rx_queue_alloc); | |
206 | ||
8f91aecb | 207 | |
81963d68 RC |
208 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, |
209 | struct iwl_rx_mem_buffer *rxb) | |
210 | { | |
211 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | |
212 | struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); | |
213 | ||
214 | if (!report->state) { | |
215 | IWL_DEBUG_11H(priv, | |
216 | "Spectrum Measure Notification: Start\n"); | |
217 | return; | |
218 | } | |
219 | ||
220 | memcpy(&priv->measure_report, report, sizeof(*report)); | |
221 | priv->measurement_status |= MEASUREMENT_READY; | |
222 | } | |
223 | EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif); | |
224 | ||
a29576a7 | 225 | void iwl_recover_from_statistics(struct iwl_priv *priv, |
fa8f130c WYG |
226 | struct iwl_rx_packet *pkt) |
227 | { | |
228 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | |
229 | return; | |
246ed355 | 230 | if (iwl_is_any_associated(priv)) { |
fa8f130c WYG |
231 | if (priv->cfg->ops->lib->check_ack_health) { |
232 | if (!priv->cfg->ops->lib->check_ack_health( | |
233 | priv, pkt)) { | |
234 | /* | |
235 | * low ack count detected | |
236 | * restart Firmware | |
237 | */ | |
238 | IWL_ERR(priv, "low ack count detected, " | |
239 | "restart firmware\n"); | |
c04f9f22 | 240 | if (!iwl_force_reset(priv, IWL_FW_RESET, false)) |
3d38f173 | 241 | return; |
fa8f130c | 242 | } |
3d38f173 WYG |
243 | } |
244 | if (priv->cfg->ops->lib->check_plcp_health) { | |
fa8f130c WYG |
245 | if (!priv->cfg->ops->lib->check_plcp_health( |
246 | priv, pkt)) { | |
247 | /* | |
248 | * high plcp error detected | |
249 | * reset Radio | |
250 | */ | |
c04f9f22 | 251 | iwl_force_reset(priv, IWL_RF_RESET, false); |
fa8f130c | 252 | } |
3e4fb5fa TAN |
253 | } |
254 | } | |
beac5498 | 255 | } |
a29576a7 | 256 | EXPORT_SYMBOL(iwl_recover_from_statistics); |
beac5498 | 257 | |
1781a07f EG |
258 | /* |
259 | * returns non-zero if packet should be dropped | |
260 | */ | |
8ccde88a SO |
261 | int iwl_set_decrypted_flag(struct iwl_priv *priv, |
262 | struct ieee80211_hdr *hdr, | |
263 | u32 decrypt_res, | |
264 | struct ieee80211_rx_status *stats) | |
1781a07f EG |
265 | { |
266 | u16 fc = le16_to_cpu(hdr->frame_control); | |
267 | ||
246ed355 JB |
268 | /* |
269 | * All contexts have the same setting here due to it being | |
270 | * a module parameter, so OK to check any context. | |
271 | */ | |
272 | if (priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags & | |
273 | RXON_FILTER_DIS_DECRYPT_MSK) | |
1781a07f EG |
274 | return 0; |
275 | ||
276 | if (!(fc & IEEE80211_FCTL_PROTECTED)) | |
277 | return 0; | |
278 | ||
e1623446 | 279 | IWL_DEBUG_RX(priv, "decrypt_res:0x%x\n", decrypt_res); |
1781a07f EG |
280 | switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) { |
281 | case RX_RES_STATUS_SEC_TYPE_TKIP: | |
282 | /* The uCode has got a bad phase 1 Key, pushes the packet. | |
283 | * Decryption will be done in SW. */ | |
284 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | |
285 | RX_RES_STATUS_BAD_KEY_TTAK) | |
286 | break; | |
287 | ||
288 | case RX_RES_STATUS_SEC_TYPE_WEP: | |
289 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | |
290 | RX_RES_STATUS_BAD_ICV_MIC) { | |
291 | /* bad ICV, the packet is destroyed since the | |
292 | * decryption is inplace, drop it */ | |
e1623446 | 293 | IWL_DEBUG_RX(priv, "Packet destroyed\n"); |
1781a07f EG |
294 | return -1; |
295 | } | |
296 | case RX_RES_STATUS_SEC_TYPE_CCMP: | |
297 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | |
298 | RX_RES_STATUS_DECRYPT_OK) { | |
e1623446 | 299 | IWL_DEBUG_RX(priv, "hw decrypt successfully!!!\n"); |
1781a07f EG |
300 | stats->flag |= RX_FLAG_DECRYPTED; |
301 | } | |
302 | break; | |
303 | ||
304 | default: | |
305 | break; | |
306 | } | |
307 | return 0; | |
308 | } | |
8ccde88a | 309 | EXPORT_SYMBOL(iwl_set_decrypted_flag); |