Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca...
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / iwl-trans.c
1 /******************************************************************************
2  *
3  * This file is provided under a dual BSD/GPLv2 license.  When using or
4  * redistributing this file, you may do so under either license.
5  *
6  * GPL LICENSE SUMMARY
7  *
8  * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of version 2 of the GNU General Public License as
12  * published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
22  * USA
23  *
24  * The full GNU General Public License is included in this distribution
25  * in the file called LICENSE.GPL.
26  *
27  * Contact Information:
28  *  Intel Linux Wireless <ilw@linux.intel.com>
29  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30  *
31  * BSD LICENSE
32  *
33  * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
34  * All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  *
40  *  * Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  *  * Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in
44  *    the documentation and/or other materials provided with the
45  *    distribution.
46  *  * Neither the name Intel Corporation nor the names of its
47  *    contributors may be used to endorse or promote products derived
48  *    from this software without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61  *
62  *****************************************************************************/
63 #include "iwl-dev.h"
64 #include "iwl-trans.h"
65 #include "iwl-core.h"
66 #include "iwl-helpers.h"
67 /*TODO remove uneeded includes when the transport layer tx_free will be here */
68 #include "iwl-agn.h"
69
70 static int iwl_trans_rx_alloc(struct iwl_priv *priv)
71 {
72         struct iwl_rx_queue *rxq = &priv->rxq;
73         struct device *dev = priv->bus.dev;
74
75         memset(&priv->rxq, 0, sizeof(priv->rxq));
76
77         spin_lock_init(&rxq->lock);
78         INIT_LIST_HEAD(&rxq->rx_free);
79         INIT_LIST_HEAD(&rxq->rx_used);
80
81         if (WARN_ON(rxq->bd || rxq->rb_stts))
82                 return -EINVAL;
83
84         /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */
85         rxq->bd = dma_alloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
86                                      &rxq->bd_dma, GFP_KERNEL);
87         if (!rxq->bd)
88                 goto err_bd;
89         memset(rxq->bd, 0, sizeof(__le32) * RX_QUEUE_SIZE);
90
91         /*Allocate the driver's pointer to receive buffer status */
92         rxq->rb_stts = dma_alloc_coherent(dev, sizeof(*rxq->rb_stts),
93                                           &rxq->rb_stts_dma, GFP_KERNEL);
94         if (!rxq->rb_stts)
95                 goto err_rb_stts;
96         memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts));
97
98         return 0;
99
100 err_rb_stts:
101         dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
102                         rxq->bd, rxq->bd_dma);
103         memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
104         rxq->bd = NULL;
105 err_bd:
106         return -ENOMEM;
107 }
108
109 static void iwl_trans_rxq_free_rx_bufs(struct iwl_priv *priv)
110 {
111         struct iwl_rx_queue *rxq = &priv->rxq;
112         int i;
113
114         /* Fill the rx_used queue with _all_ of the Rx buffers */
115         for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
116                 /* In the reset function, these buffers may have been allocated
117                  * to an SKB, so we need to unmap and free potential storage */
118                 if (rxq->pool[i].page != NULL) {
119                         dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma,
120                                 PAGE_SIZE << priv->hw_params.rx_page_order,
121                                 DMA_FROM_DEVICE);
122                         __iwl_free_pages(priv, rxq->pool[i].page);
123                         rxq->pool[i].page = NULL;
124                 }
125                 list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
126         }
127 }
128
129 static int iwl_trans_rx_init(struct iwl_priv *priv)
130 {
131         struct iwl_rx_queue *rxq = &priv->rxq;
132         int i, err;
133         unsigned long flags;
134
135         if (!rxq->bd) {
136                 err = iwl_trans_rx_alloc(priv);
137                 if (err)
138                         return err;
139         }
140
141         spin_lock_irqsave(&rxq->lock, flags);
142         INIT_LIST_HEAD(&rxq->rx_free);
143         INIT_LIST_HEAD(&rxq->rx_used);
144
145         iwl_trans_rxq_free_rx_bufs(priv);
146
147         for (i = 0; i < RX_QUEUE_SIZE; i++)
148                 rxq->queue[i] = NULL;
149
150         /* Set us so that we have processed and used all buffers, but have
151          * not restocked the Rx queue with fresh buffers */
152         rxq->read = rxq->write = 0;
153         rxq->write_actual = 0;
154         rxq->free_count = 0;
155         spin_unlock_irqrestore(&rxq->lock, flags);
156
157         return 0;
158 }
159
160 static void iwl_trans_rx_free(struct iwl_priv *priv)
161 {
162         struct iwl_rx_queue *rxq = &priv->rxq;
163         unsigned long flags;
164
165         /*if rxq->bd is NULL, it means that nothing has been allocated,
166          * exit now */
167         if (!rxq->bd) {
168                 IWL_DEBUG_INFO(priv, "Free NULL rx context\n");
169                 return;
170         }
171
172         spin_lock_irqsave(&rxq->lock, flags);
173         iwl_trans_rxq_free_rx_bufs(priv);
174         spin_unlock_irqrestore(&rxq->lock, flags);
175
176         dma_free_coherent(priv->bus.dev, sizeof(__le32) * RX_QUEUE_SIZE,
177                           rxq->bd, rxq->bd_dma);
178         memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
179         rxq->bd = NULL;
180
181         if (rxq->rb_stts)
182                 dma_free_coherent(priv->bus.dev,
183                                   sizeof(struct iwl_rb_status),
184                                   rxq->rb_stts, rxq->rb_stts_dma);
185         else
186                 IWL_DEBUG_INFO(priv, "Free rxq->rb_stts which is NULL\n");
187         memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma));
188         rxq->rb_stts = NULL;
189 }
190
191 /* TODO:remove this code duplication */
192 static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv,
193                                     struct iwl_dma_ptr *ptr, size_t size)
194 {
195         if (WARN_ON(ptr->addr))
196                 return -EINVAL;
197
198         ptr->addr = dma_alloc_coherent(priv->bus.dev, size,
199                                        &ptr->dma, GFP_KERNEL);
200         if (!ptr->addr)
201                 return -ENOMEM;
202         ptr->size = size;
203         return 0;
204 }
205
206 static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq,
207                       int slots_num, u32 txq_id)
208 {
209         size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
210         int i;
211
212         if (WARN_ON(txq->meta || txq->cmd || txq->txb || txq->tfds))
213                 return -EINVAL;
214
215         txq->meta = kzalloc(sizeof(txq->meta[0]) * slots_num,
216                             GFP_KERNEL);
217         txq->cmd = kzalloc(sizeof(txq->cmd[0]) * slots_num,
218                            GFP_KERNEL);
219
220         if (!txq->meta || !txq->cmd)
221                 goto error;
222
223         for (i = 0; i < slots_num; i++) {
224                 txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd),
225                                         GFP_KERNEL);
226                 if (!txq->cmd[i])
227                         goto error;
228         }
229
230         /* Alloc driver data array and TFD circular buffer */
231         /* Driver private data, only for Tx (not command) queues,
232          * not shared with device. */
233         if (txq_id != priv->cmd_queue) {
234                 txq->txb = kzalloc(sizeof(txq->txb[0]) *
235                                    TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
236                 if (!txq->txb) {
237                         IWL_ERR(priv, "kmalloc for auxiliary BD "
238                                   "structures failed\n");
239                         goto error;
240                 }
241         } else {
242                 txq->txb = NULL;
243         }
244
245         /* Circular buffer of transmit frame descriptors (TFDs),
246          * shared with device */
247         txq->tfds = dma_alloc_coherent(priv->bus.dev, tfd_sz, &txq->q.dma_addr,
248                                        GFP_KERNEL);
249         if (!txq->tfds) {
250                 IWL_ERR(priv, "dma_alloc_coherent(%zd) failed\n", tfd_sz);
251                 goto error;
252         }
253         txq->q.id = txq_id;
254
255         return 0;
256 error:
257         kfree(txq->txb);
258         txq->txb = NULL;
259         /* since txq->cmd has been zeroed,
260          * all non allocated cmd[i] will be NULL */
261         if (txq->cmd)
262                 for (i = 0; i < slots_num; i++)
263                         kfree(txq->cmd[i]);
264         kfree(txq->meta);
265         kfree(txq->cmd);
266         txq->meta = NULL;
267         txq->cmd = NULL;
268
269         return -ENOMEM;
270
271 }
272
273 static int iwl_trans_txq_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
274                       int slots_num, u32 txq_id)
275 {
276         int ret;
277
278         txq->need_update = 0;
279         memset(txq->meta, 0, sizeof(txq->meta[0]) * slots_num);
280
281         /*
282          * For the default queues 0-3, set up the swq_id
283          * already -- all others need to get one later
284          * (if they need one at all).
285          */
286         if (txq_id < 4)
287                 iwl_set_swq_id(txq, txq_id, txq_id);
288
289         /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
290          * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
291         BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
292
293         /* Initialize queue's high/low-water marks, and head/tail indexes */
294         ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num,
295                         txq_id);
296         if (ret)
297                 return ret;
298
299         /*
300          * Tell nic where to find circular buffer of Tx Frame Descriptors for
301          * given Tx queue, and enable the DMA channel used for that queue.
302          * Circular buffer (TFD queue in DRAM) physical base address */
303         iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
304                              txq->q.dma_addr >> 8);
305
306         return 0;
307 }
308
309 /**
310  * iwl_trans_tx_alloc - allocate TX context
311  * Allocate all Tx DMA structures and initialize them
312  *
313  * @param priv
314  * @return error code
315  */
316 static int iwl_trans_tx_alloc(struct iwl_priv *priv)
317 {
318         int ret;
319         int txq_id, slots_num;
320
321         /*It is not allowed to alloc twice, so warn when this happens.
322          * We cannot rely on the previous allocation, so free and fail */
323         if (WARN_ON(priv->txq)) {
324                 ret = -EINVAL;
325                 goto error;
326         }
327
328         ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls,
329                                 priv->hw_params.scd_bc_tbls_size);
330         if (ret) {
331                 IWL_ERR(priv, "Scheduler BC Table allocation failed\n");
332                 goto error;
333         }
334
335         /* Alloc keep-warm buffer */
336         ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE);
337         if (ret) {
338                 IWL_ERR(priv, "Keep Warm allocation failed\n");
339                 goto error;
340         }
341
342         priv->txq = kzalloc(sizeof(struct iwl_tx_queue) *
343                         priv->cfg->base_params->num_of_queues, GFP_KERNEL);
344         if (!priv->txq) {
345                 IWL_ERR(priv, "Not enough memory for txq\n");
346                 ret = ENOMEM;
347                 goto error;
348         }
349
350         /* Alloc and init all Tx queues, including the command queue (#4/#9) */
351         for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
352                 slots_num = (txq_id == priv->cmd_queue) ?
353                                         TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
354                 ret = iwl_trans_txq_alloc(priv, &priv->txq[txq_id], slots_num,
355                                        txq_id);
356                 if (ret) {
357                         IWL_ERR(priv, "Tx %d queue alloc failed\n", txq_id);
358                         goto error;
359                 }
360         }
361
362         return 0;
363
364 error:
365         iwlagn_hw_txq_ctx_free(priv);
366
367         return ret;
368 }
369 static int iwl_trans_tx_init(struct iwl_priv *priv)
370 {
371         int ret;
372         int txq_id, slots_num;
373         unsigned long flags;
374         bool alloc = false;
375
376         if (!priv->txq) {
377                 ret = iwl_trans_tx_alloc(priv);
378                 if (ret)
379                         goto error;
380                 alloc = true;
381         }
382
383         spin_lock_irqsave(&priv->lock, flags);
384
385         /* Turn off all Tx DMA fifos */
386         iwl_write_prph(priv, IWLAGN_SCD_TXFACT, 0);
387
388         /* Tell NIC where to find the "keep warm" buffer */
389         iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
390
391         spin_unlock_irqrestore(&priv->lock, flags);
392
393         /* Alloc and init all Tx queues, including the command queue (#4/#9) */
394         for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
395                 slots_num = (txq_id == priv->cmd_queue) ?
396                                         TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
397                 ret = iwl_trans_txq_init(priv, &priv->txq[txq_id], slots_num,
398                                        txq_id);
399                 if (ret) {
400                         IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
401                         goto error;
402                 }
403         }
404
405         return 0;
406 error:
407         /*Upon error, free only if we allocated something */
408         if (alloc)
409                 iwlagn_hw_txq_ctx_free(priv);
410         return ret;
411 }
412
413 static const struct iwl_trans_ops trans_ops = {
414         .rx_init = iwl_trans_rx_init,
415         .rx_free = iwl_trans_rx_free,
416
417         .tx_init = iwl_trans_tx_init,
418 };
419
420 void iwl_trans_register(struct iwl_trans *trans)
421 {
422         trans->ops = &trans_ops;
423 }