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