blob: 3df990c7306abe116936c08528e561ccb0e858de [file] [log] [blame]
Henk de Groot68c0bdf2009-09-27 11:12:52 +02001/*******************************************************************************
2 * Agere Systems Inc.
3 * Wireless device driver for Linux (wlags49).
4 *
5 * Copyright (c) 1998-2003 Agere Systems Inc.
6 * All rights reserved.
7 * http://www.agere.com
8 *
9 * Initially developed by TriplePoint, Inc.
10 * http://www.triplepoint.com
11 *
12 *------------------------------------------------------------------------------
13 *
14 * This file contains processing and initialization specific to PCI/miniPCI
15 * devices.
16 *
17 *------------------------------------------------------------------------------
18 *
19 * SOFTWARE LICENSE
20 *
21 * This software is provided subject to the following terms and conditions,
22 * which you should read carefully before using the software. Using this
23 * software indicates your acceptance of these terms and conditions. If you do
24 * not agree with these terms and conditions, do not use the software.
25 *
Al Virod36b6912011-12-29 17:09:01 -050026 * Copyright © 2003 Agere Systems Inc.
Henk de Groot68c0bdf2009-09-27 11:12:52 +020027 * All rights reserved.
28 *
29 * Redistribution and use in source or binary forms, with or without
30 * modifications, are permitted provided that the following conditions are met:
31 *
32 * . Redistributions of source code must retain the above copyright notice, this
33 * list of conditions and the following Disclaimer as comments in the code as
34 * well as in the documentation and/or other materials provided with the
35 * distribution.
36 *
37 * . Redistributions in binary form must reproduce the above copyright notice,
38 * this list of conditions and the following Disclaimer in the documentation
39 * and/or other materials provided with the distribution.
40 *
41 * . Neither the name of Agere Systems Inc. nor the names of the contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
44 *
45 * Disclaimer
46 *
Al Virod36b6912011-12-29 17:09:01 -050047 * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
Henk de Groot68c0bdf2009-09-27 11:12:52 +020048 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
49 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
50 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
51 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
52 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
53 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
54 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
55 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
57 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
58 * DAMAGE.
59 *
60 ******************************************************************************/
61
Henk de Groot68c0bdf2009-09-27 11:12:52 +020062/*******************************************************************************
63 * include files
64 ******************************************************************************/
65#include <wireless/wl_version.h>
66
67#include <linux/module.h>
68#include <linux/kernel.h>
69#include <linux/errno.h>
70#include <linux/pci.h>
71#include <linux/init.h>
72#include <linux/sched.h>
73#include <linux/ptrace.h>
Henk de Groot68c0bdf2009-09-27 11:12:52 +020074#include <linux/ctype.h>
75#include <linux/string.h>
76//#include <linux/timer.h>
77#include <linux/interrupt.h>
78#include <linux/in.h>
79#include <linux/delay.h>
Henk de Groot68c0bdf2009-09-27 11:12:52 +020080#include <asm/io.h>
81#include <asm/irq.h>
Henk de Groot68c0bdf2009-09-27 11:12:52 +020082#include <asm/bitops.h>
83#include <asm/uaccess.h>
84
85#include <linux/ethtool.h>
86#include <linux/netdevice.h>
87#include <linux/etherdevice.h>
88#include <linux/skbuff.h>
89#include <linux/if_arp.h>
90#include <linux/ioport.h>
91
92#include <hcf/debug.h>
93
94#include <hcf.h>
95#include <dhf.h>
96#include <hcfdef.h>
97
98#include <wireless/wl_if.h>
99#include <wireless/wl_internal.h>
100#include <wireless/wl_util.h>
101#include <wireless/wl_main.h>
102#include <wireless/wl_netdev.h>
103#include <wireless/wl_pci.h>
104
105
106/*******************************************************************************
107 * global variables
108 ******************************************************************************/
109#if DBG
110extern dbg_info_t *DbgInfo;
111#endif // DBG
112
113/* define the PCI device Table Cardname and id tables */
Henk de Groot68c0bdf2009-09-27 11:12:52 +0200114static struct pci_device_id wl_pci_tbl[] __devinitdata = {
Peter Huewe5fef30b2011-11-27 15:13:51 +0100115 { PCI_DEVICE(PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_0), },
116 { PCI_DEVICE(PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_1), },
117 { PCI_DEVICE(PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_2), },
Javier Martinez Canillas100ca122010-08-02 00:43:13 -0400118
Henk de Groot68c0bdf2009-09-27 11:12:52 +0200119 { } /* Terminating entry */
120};
121
122MODULE_DEVICE_TABLE(pci, wl_pci_tbl);
123
124/*******************************************************************************
125 * function prototypes
126 ******************************************************************************/
127int __devinit wl_pci_probe( struct pci_dev *pdev,
128 const struct pci_device_id *ent );
129void __devexit wl_pci_remove(struct pci_dev *pdev);
130int wl_pci_setup( struct pci_dev *pdev );
131void wl_pci_enable_cardbus_interrupts( struct pci_dev *pdev );
132
133#ifdef ENABLE_DMA
134int wl_pci_dma_alloc( struct pci_dev *pdev, struct wl_private *lp );
135int wl_pci_dma_free( struct pci_dev *pdev, struct wl_private *lp );
136int wl_pci_dma_alloc_tx_packet( struct pci_dev *pdev, struct wl_private *lp,
137 DESC_STRCT **desc );
138int wl_pci_dma_free_tx_packet( struct pci_dev *pdev, struct wl_private *lp,
139 DESC_STRCT **desc );
140int wl_pci_dma_alloc_rx_packet( struct pci_dev *pdev, struct wl_private *lp,
141 DESC_STRCT **desc );
142int wl_pci_dma_free_rx_packet( struct pci_dev *pdev, struct wl_private *lp,
143 DESC_STRCT **desc );
144int wl_pci_dma_alloc_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp,
145 DESC_STRCT **desc, int size );
146int wl_pci_dma_free_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp,
147 DESC_STRCT **desc );
148int wl_pci_dma_alloc_desc( struct pci_dev *pdev, struct wl_private *lp,
149 DESC_STRCT **desc );
150int wl_pci_dma_free_desc( struct pci_dev *pdev, struct wl_private *lp,
151 DESC_STRCT **desc );
152int wl_pci_dma_alloc_buf( struct pci_dev *pdev, struct wl_private *lp,
153 DESC_STRCT *desc, int size );
154int wl_pci_dma_free_buf( struct pci_dev *pdev, struct wl_private *lp,
155 DESC_STRCT *desc );
156
157void wl_pci_dma_hcf_reclaim_rx( struct wl_private *lp );
158#endif // ENABLE_DMA
159
160/*******************************************************************************
161 * PCI module function registration
162 ******************************************************************************/
163static struct pci_driver wl_driver =
164{
165 name: MODULE_NAME,
166 id_table: wl_pci_tbl,
167 probe: wl_pci_probe,
168 remove: __devexit_p(wl_pci_remove),
169 suspend: NULL,
170 resume: NULL,
171};
172
173/*******************************************************************************
174 * wl_adapter_init_module()
175 *******************************************************************************
176 *
177 * DESCRIPTION:
178 *
179 * Called by init_module() to perform PCI-specific driver initialization.
180 *
181 * PARAMETERS:
182 *
183 * N/A
184 *
185 * RETURNS:
186 *
187 * 0
188 *
189 ******************************************************************************/
190int wl_adapter_init_module( void )
191{
192 int result;
193 /*------------------------------------------------------------------------*/
194
195 DBG_FUNC( "wl_adapter_init_module()" );
196 DBG_ENTER( DbgInfo );
197 DBG_TRACE( DbgInfo, "wl_adapter_init_module() -- PCI\n" );
198
199 result = pci_register_driver( &wl_driver ); //;?replace with pci_module_init, Rubini pg 490
200 //;? why not do something with the result
201
202 DBG_LEAVE( DbgInfo );
203 return 0;
204} // wl_adapter_init_module
205/*============================================================================*/
206
207/*******************************************************************************
208 * wl_adapter_cleanup_module()
209 *******************************************************************************
210 *
211 * DESCRIPTION:
212 *
213 * Called by cleanup_module() to perform PCI-specific driver cleanup.
214 *
215 * PARAMETERS:
216 *
217 * N/A
218 *
219 * RETURNS:
220 *
221 * N/A
222 *
223 ******************************************************************************/
224void wl_adapter_cleanup_module( void )
225{
226 //;?how comes wl_adapter_cleanup_module is located in a seemingly pci specific module
227 DBG_FUNC( "wl_adapter_cleanup_module" );
228 DBG_ENTER( DbgInfo );
229
230 //;?DBG_TRACE below feels like nearly redundant in the light of DBG_ENTER above
231 DBG_TRACE( DbgInfo, "wl_adapter_cleanup_module() -- PCI\n" );
232
233 pci_unregister_driver( &wl_driver );
234
235 DBG_LEAVE( DbgInfo );
236 return;
237} // wl_adapter_cleanup_module
238/*============================================================================*/
239
240/*******************************************************************************
241 * wl_adapter_insert()
242 *******************************************************************************
243 *
244 * DESCRIPTION:
245 *
246 * Called by wl_pci_probe() to continue the process of device insertion.
247 *
248 * PARAMETERS:
249 *
250 * dev - a pointer to the device's net_device structure
251 *
252 * RETURNS:
253 *
254 * TRUE or FALSE
255 *
256 ******************************************************************************/
257int wl_adapter_insert( struct net_device *dev )
258{
259 int result = FALSE;
260 /*------------------------------------------------------------------------*/
261
262 DBG_FUNC( "wl_adapter_insert" );
263 DBG_ENTER( DbgInfo );
264
265 DBG_TRACE( DbgInfo, "wl_adapter_insert() -- PCI\n" );
266
267 if( dev == NULL ) {
268 DBG_ERROR( DbgInfo, "net_device pointer is NULL!!!\n" );
269 } else if( dev->priv == NULL ) {
270 DBG_ERROR( DbgInfo, "wl_private pointer is NULL!!!\n" );
271 } else if( wl_insert( dev ) ) { /* Perform remaining device initialization */
272 result = TRUE;
273 } else {
274 DBG_TRACE( DbgInfo, "wl_insert() FAILED\n" );
275 }
276 DBG_LEAVE( DbgInfo );
277 return result;
278} // wl_adapter_insert
279/*============================================================================*/
280
281/*******************************************************************************
282 * wl_adapter_open()
283 *******************************************************************************
284 *
285 * DESCRIPTION:
286 *
287 * Open the device.
288 *
289 * PARAMETERS:
290 *
291 * dev - a pointer to the device's net_device structure
292 *
293 * RETURNS:
294 *
295 * an HCF status code
296 *
297 ******************************************************************************/
298int wl_adapter_open( struct net_device *dev )
299{
300 int result = 0;
301 int hcf_status = HCF_SUCCESS;
302 /*------------------------------------------------------------------------*/
303
304 DBG_FUNC( "wl_adapter_open" );
305 DBG_ENTER( DbgInfo );
306
307 DBG_TRACE( DbgInfo, "wl_adapter_open() -- PCI\n" );
308
309 hcf_status = wl_open( dev );
310
311 if( hcf_status != HCF_SUCCESS ) {
312 result = -ENODEV;
313 }
314
315 DBG_LEAVE( DbgInfo );
316 return result;
317} // wl_adapter_open
318/*============================================================================*/
319
320/*******************************************************************************
321 * wl_adapter_close()
322 *******************************************************************************
323 *
324 * DESCRIPTION:
325 *
326 * Close the device
327 *
328 * PARAMETERS:
329 *
330 * dev - a pointer to the device's net_device structure
331 *
332 * RETURNS:
333 *
334 * 0
335 *
336 ******************************************************************************/
337int wl_adapter_close( struct net_device *dev )
338{
339 DBG_FUNC( "wl_adapter_close" );
340 DBG_ENTER( DbgInfo );
341
342 DBG_TRACE( DbgInfo, "wl_adapter_close() -- PCI\n" );
343 DBG_TRACE( DbgInfo, "%s: Shutting down adapter.\n", dev->name );
344
345 wl_close( dev );
346
347 DBG_LEAVE( DbgInfo );
348 return 0;
349} // wl_adapter_close
350/*============================================================================*/
351
352/*******************************************************************************
353 * wl_adapter_is_open()
354 *******************************************************************************
355 *
356 * DESCRIPTION:
357 *
358 * Check whether this device is open. Returns
359 *
360 * PARAMETERS:
361 *
362 * dev - a pointer to the device's net_device structure
363 *
364 * RETURNS:
365 *
366 * nonzero if device is open.
367 *
368 ******************************************************************************/
369int wl_adapter_is_open( struct net_device *dev )
370{
371 /* This function is used in PCMCIA to check the status of the 'open' field
372 in the dev_link_t structure associated with a network device. There
373 doesn't seem to be an analog to this for PCI, and checking the status
374 contained in the net_device structure doesn't have the same effect.
375 For now, return TRUE, but find out if this is necessary for PCI. */
376
377 return TRUE;
378} // wl_adapter_is_open
379/*============================================================================*/
380
381/*******************************************************************************
382 * wl_pci_probe()
383 *******************************************************************************
384 *
385 * DESCRIPTION:
386 *
387 * Registered in the pci_driver structure, this function is called when the
388 * PCI subsystem finds a new PCI device which matches the infomation contained
389 * in the pci_device_id table.
390 *
391 * PARAMETERS:
392 *
393 * pdev - a pointer to the device's pci_dev structure
394 * ent - this device's entry in the pci_device_id table
395 *
396 * RETURNS:
397 *
398 * 0 on success
399 * errno value otherwise
400 *
401 ******************************************************************************/
402int __devinit wl_pci_probe( struct pci_dev *pdev,
403 const struct pci_device_id *ent )
404{
405 int result;
406 /*------------------------------------------------------------------------*/
407
408 DBG_FUNC( "wl_pci_probe" );
409 DBG_ENTER( DbgInfo );
410 DBG_PRINT( "%s\n", VERSION_INFO );
411
412 result = wl_pci_setup( pdev );
413
414 DBG_LEAVE( DbgInfo );
415
416 return result;
417} // wl_pci_probe
418/*============================================================================*/
419
420/*******************************************************************************
421 * wl_pci_remove()
422 *******************************************************************************
423 *
424 * DESCRIPTION:
425 *
426 * Registered in the pci_driver structure, this function is called when the
427 * PCI subsystem detects that a PCI device which matches the infomation
428 * contained in the pci_device_id table has been removed.
429 *
430 * PARAMETERS:
431 *
432 * pdev - a pointer to the device's pci_dev structure
433 *
434 * RETURNS:
435 *
436 * N/A
437 *
438 ******************************************************************************/
439void __devexit wl_pci_remove(struct pci_dev *pdev)
440{
441 struct net_device *dev = NULL;
442 /*------------------------------------------------------------------------*/
443
444 DBG_FUNC( "wl_pci_remove" );
445 DBG_ENTER( DbgInfo );
446
447 /* Make sure the pci_dev pointer passed in is valid */
448 if( pdev == NULL ) {
449 DBG_ERROR( DbgInfo, "PCI subsys passed in an invalid pci_dev pointer\n" );
450 return;
451 }
452
Joe Perches345594d2010-11-15 12:14:00 -0800453 dev = pci_get_drvdata( pdev );
Henk de Groot68c0bdf2009-09-27 11:12:52 +0200454 if( dev == NULL ) {
455 DBG_ERROR( DbgInfo, "Could not retrieve net_device structure\n" );
456 return;
457 }
458
459 /* Perform device cleanup */
460 wl_remove( dev );
461 free_irq( dev->irq, dev );
462
463#ifdef ENABLE_DMA
Kulikov Vasiliy2f72aee2010-06-29 14:16:29 +0400464 wl_pci_dma_free( pdev, dev->priv );
Henk de Groot68c0bdf2009-09-27 11:12:52 +0200465#endif
466
467 wl_device_dealloc( dev );
468
469 DBG_LEAVE( DbgInfo );
470 return;
471} // wl_pci_remove
472/*============================================================================*/
473
474/*******************************************************************************
475 * wl_pci_setup()
476 *******************************************************************************
477 *
478 * DESCRIPTION:
479 *
480 * Called by wl_pci_probe() to begin a device's initialization process.
481 *
482 * PARAMETERS:
483 *
484 * pdev - a pointer to the device's pci_dev structure
485 *
486 * RETURNS:
487 *
488 * 0 on success
489 * errno value otherwise
490 *
491 ******************************************************************************/
492int wl_pci_setup( struct pci_dev *pdev )
493{
494 int result = 0;
495 struct net_device *dev = NULL;
496 struct wl_private *lp = NULL;
497 /*------------------------------------------------------------------------*/
498
499 DBG_FUNC( "wl_pci_setup" );
500 DBG_ENTER( DbgInfo );
501
502 /* Make sure the pci_dev pointer passed in is valid */
503 if( pdev == NULL ) {
504 DBG_ERROR( DbgInfo, "PCI subsys passed in an invalid pci_dev pointer\n" );
505 return -ENODEV;
506 }
507
508 result = pci_enable_device( pdev );
509 if( result != 0 ) {
510 DBG_ERROR( DbgInfo, "pci_enable_device() failed\n" );
511 DBG_LEAVE( DbgInfo );
512 return result;
513 }
514
515 /* We found our device! Let's register it with the system */
516 DBG_TRACE( DbgInfo, "Found our device, now registering\n" );
517 dev = wl_device_alloc( );
518 if( dev == NULL ) {
519 DBG_ERROR( DbgInfo, "Could not register device!!!\n" );
520 DBG_LEAVE( DbgInfo );
521 return -ENOMEM;
522 }
523
524 /* Make sure that space was allocated for our private adapter struct */
525 if( dev->priv == NULL ) {
526 DBG_ERROR( DbgInfo, "Private adapter struct was not allocated!!!\n" );
527 DBG_LEAVE( DbgInfo );
528 return -ENOMEM;
529 }
530
531#ifdef ENABLE_DMA
532 /* Allocate DMA Descriptors */
Kulikov Vasiliy2f72aee2010-06-29 14:16:29 +0400533 if( wl_pci_dma_alloc( pdev, dev->priv ) < 0 ) {
Henk de Groot68c0bdf2009-09-27 11:12:52 +0200534 DBG_ERROR( DbgInfo, "Could not allocate DMA descriptor memory!!!\n" );
535 DBG_LEAVE( DbgInfo );
536 return -ENOMEM;
537 }
538#endif
539
540 /* Register our private adapter structure with PCI */
541 pci_set_drvdata( pdev, dev );
542
543 /* Fill out bus specific information in the net_device struct */
544 dev->irq = pdev->irq;
545 SET_MODULE_OWNER( dev );
546
547 DBG_TRACE( DbgInfo, "Device Base Address: %#03lx\n", pdev->resource[0].start );
548 dev->base_addr = pdev->resource[0].start;
549
550 /* Initialize our device here */
551 if( !wl_adapter_insert( dev )) {
552 DBG_ERROR( DbgInfo, "wl_adapter_insert() FAILED!!!\n" );
553 wl_device_dealloc( dev );
554 DBG_LEAVE( DbgInfo );
555 return -EINVAL;
556 }
557
558 /* Register our ISR */
559 DBG_TRACE( DbgInfo, "Registering ISR...\n" );
560
561 result = request_irq(dev->irq, wl_isr, SA_SHIRQ, dev->name, dev);
562 if( result ) {
563 DBG_WARNING( DbgInfo, "Could not register ISR!!!\n" );
564 DBG_LEAVE( DbgInfo );
565 return result;
566 }
567
568 /* Make sure interrupts are enabled properly for CardBus */
Kulikov Vasiliy2f72aee2010-06-29 14:16:29 +0400569 lp = dev->priv;
Henk de Groot68c0bdf2009-09-27 11:12:52 +0200570
571 if( lp->hcfCtx.IFB_BusType == CFG_NIC_BUS_TYPE_CARDBUS ||
572 lp->hcfCtx.IFB_BusType == CFG_NIC_BUS_TYPE_PCI ) {
573 DBG_TRACE( DbgInfo, "This is a PCI/CardBus card, enable interrupts\n" );
574 wl_pci_enable_cardbus_interrupts( pdev );
575 }
576
577 /* Enable bus mastering */
578 pci_set_master( pdev );
579
580 DBG_LEAVE( DbgInfo );
581 return 0;
582} // wl_pci_setup
583/*============================================================================*/
584
585/*******************************************************************************
586 * wl_pci_enable_cardbus_interrupts()
587 *******************************************************************************
588 *
589 * DESCRIPTION:
590 *
591 * Called by wl_pci_setup() to enable interrupts on a CardBus device. This
592 * is done by writing bit 15 to the function event mask register. This
593 * CardBus-specific register is located in BAR2 (counting from BAR0), in memory
594 * space at byte offset 1f4 (7f4 for WARP).
595 *
596 * PARAMETERS:
597 *
598 * pdev - a pointer to the device's pci_dev structure
599 *
600 * RETURNS:
601 *
602 * N/A
603 *
604 ******************************************************************************/
605void wl_pci_enable_cardbus_interrupts( struct pci_dev *pdev )
606{
607 u32 bar2_reg;
608 u32 mem_addr_bus;
609 u32 func_evt_mask_reg;
610 void *mem_addr_kern = NULL;
611 /*------------------------------------------------------------------------*/
612
613 DBG_FUNC( "wl_pci_enable_cardbus_interrupts" );
614 DBG_ENTER( DbgInfo );
615
616 /* Initialize to known bad values */
617 bar2_reg = 0xdeadbeef;
618 mem_addr_bus = 0xdeadbeef;
619
620 /* Read the BAR2 register; this register contains the base address of the
621 memory region where the function event mask register lives */
622 pci_read_config_dword( pdev, PCI_BASE_ADDRESS_2, &bar2_reg );
623 mem_addr_bus = bar2_reg & PCI_BASE_ADDRESS_MEM_MASK;
624
625 /* Once the base address is obtained, remap the memory region to kernel
626 space so we can retrieve the register */
627 mem_addr_kern = ioremap( mem_addr_bus, 0x200 );
628
629#ifdef HERMES25
630#define REG_OFFSET 0x07F4
631#else
632#define REG_OFFSET 0x01F4
633#endif // HERMES25
634
635#define BIT15 0x8000
636
637 /* Retrieve the functional event mask register, enable interrupts by
638 setting Bit 15, and write back the value */
639 func_evt_mask_reg = *(u32 *)( mem_addr_kern + REG_OFFSET );
640 func_evt_mask_reg |= BIT15;
641 *(u32 *)( mem_addr_kern + REG_OFFSET ) = func_evt_mask_reg;
642
643 /* Once complete, unmap the region and exit */
644 iounmap( mem_addr_kern );
645
646 DBG_LEAVE( DbgInfo );
647 return;
648} // wl_pci_enable_cardbus_interrupts
649/*============================================================================*/
650
651#ifdef ENABLE_DMA
652/*******************************************************************************
653 * wl_pci_dma_alloc()
654 *******************************************************************************
655 *
656 * DESCRIPTION:
657 *
658 * Allocates all resources needed for PCI/CardBus DMA operation
659 *
660 * PARAMETERS:
661 *
662 * pdev - a pointer to the device's pci_dev structure
663 * lp - the device's private adapter structure
664 *
665 * RETURNS:
666 *
667 * 0 on success
668 * errno value otherwise
669 *
670 ******************************************************************************/
671int wl_pci_dma_alloc( struct pci_dev *pdev, struct wl_private *lp )
672{
673 int i;
674 int status = 0;
675 /*------------------------------------------------------------------------*/
676
677 DBG_FUNC( "wl_pci_dma_alloc" );
678 DBG_ENTER( DbgInfo );
679
680// lp->dma.tx_rsc_ind = lp->dma.rx_rsc_ind = 0;
681//
682// /* Alloc for the Tx chain and its reclaim descriptor */
683// for( i = 0; i < NUM_TX_DESC; i++ ) {
684// status = wl_pci_dma_alloc_tx_packet( pdev, lp, &lp->dma.tx_packet[i] );
685// if( status == 0 ) {
686// DBG_PRINT( "lp->dma.tx_packet[%d] : 0x%p\n", i, lp->dma.tx_packet[i] );
687// DBG_PRINT( "lp->dma.tx_packet[%d]->next_desc_addr : 0x%p\n", i, lp->dma.tx_packet[i]->next_desc_addr );
688// lp->dma.tx_rsc_ind++;
689// } else {
690// DBG_ERROR( DbgInfo, "Could not alloc DMA Tx Packet\n" );
691// break;
692// }
693// }
694// if( status == 0 ) {
695// status = wl_pci_dma_alloc_desc( pdev, lp, &lp->dma.tx_reclaim_desc );
696// DBG_PRINT( "lp->dma.tx_reclaim_desc: 0x%p\n", lp->dma.tx_reclaim_desc );
697// }
698// /* Alloc for the Rx chain and its reclaim descriptor */
699// if( status == 0 ) {
700// for( i = 0; i < NUM_RX_DESC; i++ ) {
701// status = wl_pci_dma_alloc_rx_packet( pdev, lp, &lp->dma.rx_packet[i] );
702// if( status == 0 ) {
703// DBG_PRINT( "lp->dma.rx_packet[%d] : 0x%p\n", i, lp->dma.rx_packet[i] );
704// DBG_PRINT( "lp->dma.rx_packet[%d]->next_desc_addr : 0x%p\n", i, lp->dma.rx_packet[i]->next_desc_addr );
705// lp->dma.rx_rsc_ind++;
706// } else {
707// DBG_ERROR( DbgInfo, "Could not alloc DMA Rx Packet\n" );
708// break;
709// }
710// }
711// }
712// if( status == 0 ) {
713// status = wl_pci_dma_alloc_desc( pdev, lp, &lp->dma.rx_reclaim_desc );
714// DBG_PRINT( "lp->dma.rx_reclaim_desc: 0x%p\n", lp->dma.rx_reclaim_desc );
715// }
716// /* Store status, as host should not call HCF functions if this fails */
717// lp->dma.status = status; //;?all useages of dma.status have been commented out
718// DBG_LEAVE( DbgInfo );
719 return status;
720} // wl_pci_dma_alloc
721/*============================================================================*/
722
723/*******************************************************************************
724 * wl_pci_dma_free()
725 *******************************************************************************
726 *
727 * DESCRIPTION:
728 *
729 * Deallocated all resources needed for PCI/CardBus DMA operation
730 *
731 * PARAMETERS:
732 *
733 * pdev - a pointer to the device's pci_dev structure
734 * lp - the device's private adapter structure
735 *
736 * RETURNS:
737 *
738 * 0 on success
739 * errno value otherwise
740 *
741 ******************************************************************************/
742int wl_pci_dma_free( struct pci_dev *pdev, struct wl_private *lp )
743{
744 int i;
745 int status = 0;
746 /*------------------------------------------------------------------------*/
747
748 DBG_FUNC( "wl_pci_dma_free" );
749 DBG_ENTER( DbgInfo );
750
751 /* Reclaim all Rx packets that were handed over to the HCF */
752 /* Do I need to do this? Before this free is called, I've already disabled
753 the port which will call wl_pci_dma_hcf_reclaim */
754 //if( lp->dma.status == 0 )
755 //{
756 // wl_pci_dma_hcf_reclaim( lp );
757 //}
758
759 /* Free everything needed for DMA Rx */
760 for( i = 0; i < NUM_RX_DESC; i++ ) {
761 if( lp->dma.rx_packet[i] ) {
762 status = wl_pci_dma_free_rx_packet( pdev, lp, &lp->dma.rx_packet[i] );
763 if( status != 0 ) {
764 DBG_WARNING( DbgInfo, "Problem freeing Rx packet\n" );
765 }
766 }
767 }
768 lp->dma.rx_rsc_ind = 0;
769
770 if( lp->dma.rx_reclaim_desc ) {
771 status = wl_pci_dma_free_desc( pdev, lp, &lp->dma.rx_reclaim_desc );
772 if( status != 0 ) {
773 DBG_WARNING( DbgInfo, "Problem freeing Rx reclaim descriptor\n" );
774 }
775 }
776
777 /* Free everything needed for DMA Tx */
778 for( i = 0; i < NUM_TX_DESC; i++ ) {
779 if( lp->dma.tx_packet[i] ) {
780 status = wl_pci_dma_free_tx_packet( pdev, lp, &lp->dma.tx_packet[i] );
781 if( status != 0 ) {
782 DBG_WARNING( DbgInfo, "Problem freeing Tx packet\n" );
783 }
784 }
785 }
786 lp->dma.tx_rsc_ind = 0;
787
788 if( lp->dma.tx_reclaim_desc ) {
789 status = wl_pci_dma_free_desc( pdev, lp, &lp->dma.tx_reclaim_desc );
790 if( status != 0 ) {
791 DBG_WARNING( DbgInfo, "Problem freeing Tx reclaim descriptor\n" );
792 }
793 }
794
795 DBG_LEAVE( DbgInfo );
796 return status;
797} // wl_pci_dma_free
798
799/*============================================================================*/
800
801/*******************************************************************************
802 * wl_pci_dma_alloc_tx_packet()
803 *******************************************************************************
804 *
805 * DESCRIPTION:
806 *
807 * Allocates a single Tx packet, consisting of several descriptors and
808 * buffers. Data to transmit is first copied into the 'payload' buffer
809 * before being transmitted.
810 *
811 * PARAMETERS:
812 *
813 * pdev - a pointer to the device's pci_dev structure
814 * lp - the device's private adapter structure
815 * desc - a pointer which will reference the descriptor to be alloc'd.
816 *
817 * RETURNS:
818 *
819 * 0 on success
820 * errno value otherwise
821 *
822 ******************************************************************************/
823int wl_pci_dma_alloc_tx_packet( struct pci_dev *pdev, struct wl_private *lp,
824 DESC_STRCT **desc )
825{
826// int status = 0;
827// /*------------------------------------------------------------------------*/
828//
829// if( desc == NULL ) {
830// status = -EFAULT;
831// }
832// if( status == 0 ) {
833// status = wl_pci_dma_alloc_desc_and_buf( pdev, lp, desc,
834// HCF_DMA_TX_BUF1_SIZE );
835//
836// if( status == 0 ) {
837// status = wl_pci_dma_alloc_desc_and_buf( pdev, lp,
838// &( (*desc)->next_desc_addr ),
839// HCF_MAX_PACKET_SIZE );
840// }
841// }
842// if( status == 0 ) {
843// (*desc)->next_desc_phys_addr = (*desc)->next_desc_addr->desc_phys_addr;
844// }
845// return status;
846} // wl_pci_dma_alloc_tx_packet
847/*============================================================================*/
848
849/*******************************************************************************
850 * wl_pci_dma_free_tx_packet()
851 *******************************************************************************
852 *
853 * DESCRIPTION:
854 *
855 * Frees a single Tx packet, described in the corresponding alloc function.
856 *
857 * PARAMETERS:
858 *
859 * pdev - a pointer to the device's pci_dev structure
860 * lp - the device's private adapter structure
861 * desc - a pointer which will reference the descriptor to be alloc'd.
862 *
863 * RETURNS:
864 *
865 * 0 on success
866 * errno value otherwise
867 *
868 ******************************************************************************/
869int wl_pci_dma_free_tx_packet( struct pci_dev *pdev, struct wl_private *lp,
870 DESC_STRCT **desc )
871{
872 int status = 0;
873 /*------------------------------------------------------------------------*/
874
875 if( *desc == NULL ) {
876 DBG_PRINT( "Null descriptor\n" );
877 status = -EFAULT;
878 }
879 //;?the "limited" NDIS strategy, assuming a frame consists ALWAYS out of 2
880 //descriptors, make this robust
881 if( status == 0 && (*desc)->next_desc_addr ) {
882 status = wl_pci_dma_free_desc_and_buf( pdev, lp, &(*desc)->next_desc_addr );
883 }
884 if( status == 0 ) {
885 status = wl_pci_dma_free_desc_and_buf( pdev, lp, desc );
886 }
887 return status;
888} // wl_pci_dma_free_tx_packet
889/*============================================================================*/
890
891/*******************************************************************************
892 * wl_pci_dma_alloc_rx_packet()
893 *******************************************************************************
894 *
895 * DESCRIPTION:
896 *
897 * Allocates a single Rx packet, consisting of two descriptors and one
898 * contiguous buffer. THe buffer starts with the hermes-specific header.
899 * One descriptor points at the start, the other at offset 0x3a of the
900 * buffer.
901 *
902 * PARAMETERS:
903 *
904 * pdev - a pointer to the device's pci_dev structure
905 * lp - the device's private adapter structure
906 * desc - a pointer which will reference the descriptor to be alloc'd.
907 *
908 * RETURNS:
909 *
910 * 0 on success
911 * errno value otherwise
912 *
913 ******************************************************************************/
914int wl_pci_dma_alloc_rx_packet( struct pci_dev *pdev, struct wl_private *lp,
915 DESC_STRCT **desc )
916{
917 int status = 0;
918 DESC_STRCT *p;
919 /*------------------------------------------------------------------------*/
920
921// if( desc == NULL ) {
922// status = -EFAULT;
923// }
924// //;?the "limited" NDIS strategy, assuming a frame consists ALWAYS out of 2
925// //descriptors, make this robust
926// if( status == 0 ) {
927// status = wl_pci_dma_alloc_desc( pdev, lp, desc );
928// }
929// if( status == 0 ) {
930// status = wl_pci_dma_alloc_buf( pdev, lp, *desc, HCF_MAX_PACKET_SIZE );
931// }
932// if( status == 0 ) {
933// status = wl_pci_dma_alloc_desc( pdev, lp, &p );
934// }
935// if( status == 0 ) {
936// /* Size of 1st descriptor becomes 0x3a bytes */
937// SET_BUF_SIZE( *desc, HCF_DMA_RX_BUF1_SIZE );
938//
939// /* Make 2nd descriptor point at offset 0x3a of the buffer */
940// SET_BUF_SIZE( p, ( HCF_MAX_PACKET_SIZE - HCF_DMA_RX_BUF1_SIZE ));
941// p->buf_addr = (*desc)->buf_addr + HCF_DMA_RX_BUF1_SIZE;
942// p->buf_phys_addr = (*desc)->buf_phys_addr + HCF_DMA_RX_BUF1_SIZE;
943// p->next_desc_addr = NULL;
944//
945// /* Chain 2nd descriptor to 1st descriptor */
946// (*desc)->next_desc_addr = p;
947// (*desc)->next_desc_phys_addr = p->desc_phys_addr;
948// }
949
950 return status;
951} // wl_pci_dma_alloc_rx_packet
952/*============================================================================*/
953
954/*******************************************************************************
955 * wl_pci_dma_free_rx_packet()
956 *******************************************************************************
957 *
958 * DESCRIPTION:
959 *
960 * Frees a single Rx packet, described in the corresponding alloc function.
961 *
962 * PARAMETERS:
963 *
964 * pdev - a pointer to the device's pci_dev structure
965 * lp - the device's private adapter structure
966 * desc - a pointer which will reference the descriptor to be alloc'd.
967 *
968 * RETURNS:
969 *
970 * 0 on success
971 * errno value otherwise
972 *
973 ******************************************************************************/
974int wl_pci_dma_free_rx_packet( struct pci_dev *pdev, struct wl_private *lp,
975 DESC_STRCT **desc )
976{
977 int status = 0;
978 DESC_STRCT *p;
979 /*------------------------------------------------------------------------*/
980
981 if( *desc == NULL ) {
982 status = -EFAULT;
983 }
984 if( status == 0 ) {
985 p = (*desc)->next_desc_addr;
986
987 /* Free the 2nd descriptor */
988 if( p != NULL ) {
989 p->buf_addr = NULL;
990 p->buf_phys_addr = 0;
991
992 status = wl_pci_dma_free_desc( pdev, lp, &p );
993 }
994 }
995
996 /* Free the buffer and 1st descriptor */
997 if( status == 0 ) {
998 SET_BUF_SIZE( *desc, HCF_MAX_PACKET_SIZE );
999 status = wl_pci_dma_free_desc_and_buf( pdev, lp, desc );
1000 }
1001 return status;
1002} // wl_pci_dma_free_rx_packet
1003/*============================================================================*/
1004
1005/*******************************************************************************
1006 * wl_pci_dma_alloc_desc_and_buf()
1007 *******************************************************************************
1008 *
1009 * DESCRIPTION:
1010 *
1011 * Allocates a DMA descriptor and buffer, and associates them with one
1012 * another.
1013 *
1014 * PARAMETERS:
1015 *
1016 * pdev - a pointer to the device's pci_dev structure
1017 * lp - the device's private adapter structure
1018 * desc - a pointer which will reference the descriptor to be alloc'd
1019 *
1020 * RETURNS:
1021 *
1022 * 0 on success
1023 * errno value otherwise
1024 *
1025 ******************************************************************************/
1026int wl_pci_dma_alloc_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp,
1027 DESC_STRCT **desc, int size )
1028{
1029 int status = 0;
1030 /*------------------------------------------------------------------------*/
1031
1032// if( desc == NULL ) {
1033// status = -EFAULT;
1034// }
1035// if( status == 0 ) {
1036// status = wl_pci_dma_alloc_desc( pdev, lp, desc );
1037//
1038// if( status == 0 ) {
1039// status = wl_pci_dma_alloc_buf( pdev, lp, *desc, size );
1040// }
1041// }
1042 return status;
1043} // wl_pci_dma_alloc_desc_and_buf
1044/*============================================================================*/
1045
1046/*******************************************************************************
1047 * wl_pci_dma_free_desc_and_buf()
1048 *******************************************************************************
1049 *
1050 * DESCRIPTION:
1051 *
1052 * Frees a DMA descriptor and associated buffer.
1053 *
1054 * PARAMETERS:
1055 *
1056 * pdev - a pointer to the device's pci_dev structure
1057 * lp - the device's private adapter structure
1058 * desc - a pointer which will reference the descriptor to be alloc'd
1059 *
1060 * RETURNS:
1061 *
1062 * 0 on success
1063 * errno value otherwise
1064 *
1065 ******************************************************************************/
1066int wl_pci_dma_free_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp,
1067 DESC_STRCT **desc )
1068{
1069 int status = 0;
1070 /*------------------------------------------------------------------------*/
1071
1072 if( desc == NULL ) {
1073 status = -EFAULT;
1074 }
1075 if( status == 0 && *desc == NULL ) {
1076 status = -EFAULT;
1077 }
1078 if( status == 0 ) {
1079 status = wl_pci_dma_free_buf( pdev, lp, *desc );
1080
1081 if( status == 0 ) {
1082 status = wl_pci_dma_free_desc( pdev, lp, desc );
1083 }
1084 }
1085 return status;
1086} // wl_pci_dma_free_desc_and_buf
1087/*============================================================================*/
1088
1089/*******************************************************************************
1090 * wl_pci_dma_alloc_desc()
1091 *******************************************************************************
1092 *
1093 * DESCRIPTION:
1094 *
1095 * Allocates one DMA descriptor in cache coherent memory.
1096 *
1097 * PARAMETERS:
1098 *
1099 * pdev - a pointer to the device's pci_dev structure
1100 * lp - the device's private adapter structure
1101 *
1102 * RETURNS:
1103 *
1104 * 0 on success
1105 * errno value otherwise
1106 *
1107 ******************************************************************************/
1108int wl_pci_dma_alloc_desc( struct pci_dev *pdev, struct wl_private *lp,
1109 DESC_STRCT **desc )
1110{
1111// int status = 0;
1112// dma_addr_t pa;
1113// /*------------------------------------------------------------------------*/
1114//
1115// DBG_FUNC( "wl_pci_dma_alloc_desc" );
1116// DBG_ENTER( DbgInfo );
1117//
1118// if( desc == NULL ) {
1119// status = -EFAULT;
1120// }
1121// if( status == 0 ) {
1122// *desc = pci_alloc_consistent( pdev, sizeof( DESC_STRCT ), &pa );
1123// }
1124// if( *desc == NULL ) {
1125// DBG_ERROR( DbgInfo, "pci_alloc_consistent() failed\n" );
1126// status = -ENOMEM;
1127// } else {
1128// memset( *desc, 0, sizeof( DESC_STRCT ));
1129// (*desc)->desc_phys_addr = cpu_to_le32( pa );
1130// }
1131// DBG_LEAVE( DbgInfo );
1132// return status;
1133} // wl_pci_dma_alloc_desc
1134/*============================================================================*/
1135
1136/*******************************************************************************
1137 * wl_pci_dma_free_desc()
1138 *******************************************************************************
1139 *
1140 * DESCRIPTION:
1141 *
1142 * Frees one DMA descriptor in cache coherent memory.
1143 *
1144 * PARAMETERS:
1145 *
1146 * pdev - a pointer to the device's pci_dev structure
1147 * lp - the device's private adapter structure
1148 *
1149 * RETURNS:
1150 *
1151 * 0 on success
1152 * errno value otherwise
1153 *
1154 ******************************************************************************/
1155int wl_pci_dma_free_desc( struct pci_dev *pdev, struct wl_private *lp,
1156 DESC_STRCT **desc )
1157{
1158 int status = 0;
1159 /*------------------------------------------------------------------------*/
1160
1161 if( *desc == NULL ) {
1162 status = -EFAULT;
1163 }
1164 if( status == 0 ) {
1165 pci_free_consistent( pdev, sizeof( DESC_STRCT ), *desc,
1166 (*desc)->desc_phys_addr );
1167 }
1168 *desc = NULL;
1169 return status;
1170} // wl_pci_dma_free_desc
1171/*============================================================================*/
1172
1173/*******************************************************************************
1174 * wl_pci_dma_alloc_buf()
1175 *******************************************************************************
1176 *
1177 * DESCRIPTION:
1178 *
1179 * Allocates one DMA buffer in cache coherent memory, and associates a DMA
1180 * descriptor with this buffer.
1181 *
1182 * PARAMETERS:
1183 *
1184 * pdev - a pointer to the device's pci_dev structure
1185 * lp - the device's private adapter structure
1186 *
1187 * RETURNS:
1188 *
1189 * 0 on success
1190 * errno value otherwise
1191 *
1192 ******************************************************************************/
1193int wl_pci_dma_alloc_buf( struct pci_dev *pdev, struct wl_private *lp,
1194 DESC_STRCT *desc, int size )
1195{
1196 int status = 0;
1197 dma_addr_t pa;
1198 /*------------------------------------------------------------------------*/
1199
1200// DBG_FUNC( "wl_pci_dma_alloc_buf" );
1201// DBG_ENTER( DbgInfo );
1202//
1203// if( desc == NULL ) {
1204// status = -EFAULT;
1205// }
1206// if( status == 0 && desc->buf_addr != NULL ) {
1207// status = -EFAULT;
1208// }
1209// if( status == 0 ) {
1210// desc->buf_addr = pci_alloc_consistent( pdev, size, &pa );
1211// }
1212// if( desc->buf_addr == NULL ) {
1213// DBG_ERROR( DbgInfo, "pci_alloc_consistent() failed\n" );
1214// status = -ENOMEM;
1215// } else {
1216// desc->buf_phys_addr = cpu_to_le32( pa );
1217// SET_BUF_SIZE( desc, size );
1218// }
1219// DBG_LEAVE( DbgInfo );
1220 return status;
1221} // wl_pci_dma_alloc_buf
1222/*============================================================================*/
1223
1224/*******************************************************************************
1225 * wl_pci_dma_free_buf()
1226 *******************************************************************************
1227 *
1228 * DESCRIPTION:
1229 *
1230 * Allocates one DMA buffer in cache coherent memory, and associates a DMA
1231 * descriptor with this buffer.
1232 *
1233 * PARAMETERS:
1234 *
1235 * pdev - a pointer to the device's pci_dev structure
1236 * lp - the device's private adapter structure
1237 *
1238 * RETURNS:
1239 *
1240 * 0 on success
1241 * errno value otherwise
1242 *
1243 ******************************************************************************/
1244int wl_pci_dma_free_buf( struct pci_dev *pdev, struct wl_private *lp,
1245 DESC_STRCT *desc )
1246{
1247 int status = 0;
1248 /*------------------------------------------------------------------------*/
1249
1250 if( desc == NULL ) {
1251 status = -EFAULT;
1252 }
1253 if( status == 0 && desc->buf_addr == NULL ) {
1254 status = -EFAULT;
1255 }
1256 if( status == 0 ) {
1257 pci_free_consistent( pdev, GET_BUF_SIZE( desc ), desc->buf_addr,
1258 desc->buf_phys_addr );
1259
1260 desc->buf_addr = 0;
1261 desc->buf_phys_addr = 0;
1262 SET_BUF_SIZE( desc, 0 );
1263 }
1264 return status;
1265} // wl_pci_dma_free_buf
1266/*============================================================================*/
1267
1268/*******************************************************************************
1269 * wl_pci_dma_hcf_supply()
1270 *******************************************************************************
1271 *
1272 * DESCRIPTION:
1273 *
1274 * Supply HCF with DMA-related resources. These consist of:
1275 * - buffers and descriptors for receive purposes
1276 * - one 'reclaim' descriptor for the transmit path, used to fulfill a
1277 * certain H25 DMA engine requirement
1278 * - one 'reclaim' descriptor for the receive path, used to fulfill a
1279 * certain H25 DMA engine requirement
1280 *
1281 * This function is called at start-of-day or at re-initialization.
1282 *
1283 * PARAMETERS:
1284 *
1285 * lp - the device's private adapter structure
1286 *
1287 * RETURNS:
1288 *
1289 * 0 on success
1290 * errno value otherwise
1291 *
1292 ******************************************************************************/
1293void wl_pci_dma_hcf_supply( struct wl_private *lp )
1294{
1295 int i;
1296 /*------------------------------------------------------------------------*/
1297
1298 DBG_FUNC( "wl_pci_dma_hcf_supply" );
1299 DBG_ENTER( DbgInfo );
1300
1301 //if( lp->dma.status == 0 );
1302 //{
1303 /* Hand over the Rx/Tx reclaim descriptors to the HCF */
1304 if( lp->dma.tx_reclaim_desc ) {
1305 DBG_PRINT( "lp->dma.tx_reclaim_desc: 0x%p\n", lp->dma.tx_reclaim_desc );
1306 hcf_dma_tx_put( &lp->hcfCtx, lp->dma.tx_reclaim_desc, 0 );
1307 lp->dma.tx_reclaim_desc = NULL;
1308 DBG_PRINT( "lp->dma.tx_reclaim_desc: 0x%p\n", lp->dma.tx_reclaim_desc );
1309 }
1310 if( lp->dma.rx_reclaim_desc ) {
1311 DBG_PRINT( "lp->dma.rx_reclaim_desc: 0x%p\n", lp->dma.rx_reclaim_desc );
1312 hcf_dma_rx_put( &lp->hcfCtx, lp->dma.rx_reclaim_desc );
1313 lp->dma.rx_reclaim_desc = NULL;
1314 DBG_PRINT( "lp->dma.rx_reclaim_desc: 0x%p\n", lp->dma.rx_reclaim_desc );
1315 }
1316 /* Hand over the Rx descriptor chain to the HCF */
1317 for( i = 0; i < NUM_RX_DESC; i++ ) {
1318 DBG_PRINT( "lp->dma.rx_packet[%d]: 0x%p\n", i, lp->dma.rx_packet[i] );
1319 hcf_dma_rx_put( &lp->hcfCtx, lp->dma.rx_packet[i] );
1320 lp->dma.rx_packet[i] = NULL;
1321 DBG_PRINT( "lp->dma.rx_packet[%d]: 0x%p\n", i, lp->dma.rx_packet[i] );
1322 }
1323 //}
1324
1325 DBG_LEAVE( DbgInfo );
1326 return;
1327} // wl_pci_dma_hcf_supply
1328/*============================================================================*/
1329
1330/*******************************************************************************
1331 * wl_pci_dma_hcf_reclaim()
1332 *******************************************************************************
1333 *
1334 * DESCRIPTION:
1335 *
1336 * Return DMA-related resources from the HCF. These consist of:
1337 * - buffers and descriptors for receive purposes
1338 * - buffers and descriptors for transmit purposes
1339 * - one 'reclaim' descriptor for the transmit path, used to fulfill a
1340 * certain H25 DMA engine requirement
1341 * - one 'reclaim' descriptor for the receive path, used to fulfill a
1342 * certain H25 DMA engine requirement
1343 *
1344 * This function is called at end-of-day or at re-initialization.
1345 *
1346 * PARAMETERS:
1347 *
1348 * lp - the device's private adapter structure
1349 *
1350 * RETURNS:
1351 *
1352 * 0 on success
1353 * errno value otherwise
1354 *
1355 ******************************************************************************/
1356void wl_pci_dma_hcf_reclaim( struct wl_private *lp )
1357{
1358 int i;
1359 /*------------------------------------------------------------------------*/
1360
1361 DBG_FUNC( "wl_pci_dma_hcf_reclaim" );
1362 DBG_ENTER( DbgInfo );
1363
1364 wl_pci_dma_hcf_reclaim_rx( lp );
1365 for( i = 0; i < NUM_RX_DESC; i++ ) {
1366 DBG_PRINT( "rx_packet[%d] 0x%p\n", i, lp->dma.rx_packet[i] );
1367// if( lp->dma.rx_packet[i] == NULL ) {
1368// DBG_PRINT( "wl_pci_dma_hcf_reclaim: rx_packet[%d] NULL\n", i );
1369// }
1370 }
1371
1372 wl_pci_dma_hcf_reclaim_tx( lp );
1373 for( i = 0; i < NUM_TX_DESC; i++ ) {
1374 DBG_PRINT( "tx_packet[%d] 0x%p\n", i, lp->dma.tx_packet[i] );
1375// if( lp->dma.tx_packet[i] == NULL ) {
1376// DBG_PRINT( "wl_pci_dma_hcf_reclaim: tx_packet[%d] NULL\n", i );
1377// }
1378 }
1379
1380 DBG_LEAVE( DbgInfo );
1381 return;
1382} // wl_pci_dma_hcf_reclaim
1383/*============================================================================*/
1384
1385/*******************************************************************************
1386 * wl_pci_dma_hcf_reclaim_rx()
1387 *******************************************************************************
1388 *
1389 * DESCRIPTION:
1390 *
1391 * Reclaim Rx packets that have already been processed by the HCF.
1392 *
1393 * PARAMETERS:
1394 *
1395 * lp - the device's private adapter structure
1396 *
1397 * RETURNS:
1398 *
1399 * 0 on success
1400 * errno value otherwise
1401 *
1402 ******************************************************************************/
1403void wl_pci_dma_hcf_reclaim_rx( struct wl_private *lp )
1404{
1405 int i;
1406 DESC_STRCT *p;
1407 /*------------------------------------------------------------------------*/
1408
1409 DBG_FUNC( "wl_pci_dma_hcf_reclaim_rx" );
1410 DBG_ENTER( DbgInfo );
1411
1412 //if( lp->dma.status == 0 )
1413 //{
1414 while ( ( p = hcf_dma_rx_get( &lp->hcfCtx ) ) != NULL ) {
1415 if( p && p->buf_addr == NULL ) {
1416 /* A reclaim descriptor is being given back by the HCF. Reclaim
1417 descriptors have a NULL buf_addr */
1418 lp->dma.rx_reclaim_desc = p;
1419 DBG_PRINT( "reclaim_descriptor: 0x%p\n", p );
1420 continue;
1421 }
1422 for( i = 0; i < NUM_RX_DESC; i++ ) {
1423 if( lp->dma.rx_packet[i] == NULL ) {
1424 break;
1425 }
1426 }
1427 /* An Rx buffer descriptor is being given back by the HCF */
1428 lp->dma.rx_packet[i] = p;
1429 lp->dma.rx_rsc_ind++;
1430 DBG_PRINT( "rx_packet[%d] 0x%p\n", i, lp->dma.rx_packet[i] );
1431 }
1432 //}
1433 DBG_LEAVE( DbgInfo );
1434} // wl_pci_dma_hcf_reclaim_rx
1435/*============================================================================*/
1436
1437/*******************************************************************************
1438 * wl_pci_dma_get_tx_packet()
1439 *******************************************************************************
1440 *
1441 * DESCRIPTION:
1442 *
1443 * Obtains a Tx descriptor from the chain to use for Tx.
1444 *
1445 * PARAMETERS:
1446 *
1447 * lp - a pointer to the device's wl_private structure.
1448 *
1449 * RETURNS:
1450 *
1451 * A pointer to the retrieved descriptor
1452 *
1453 ******************************************************************************/
1454DESC_STRCT * wl_pci_dma_get_tx_packet( struct wl_private *lp )
1455{
1456 int i;
1457 DESC_STRCT *desc = NULL;
1458 /*------------------------------------------------------------------------*/
1459
1460 for( i = 0; i < NUM_TX_DESC; i++ ) {
1461 if( lp->dma.tx_packet[i] ) {
1462 break;
1463 }
1464 }
1465
1466 if( i != NUM_TX_DESC ) {
1467 desc = lp->dma.tx_packet[i];
1468
1469 lp->dma.tx_packet[i] = NULL;
1470 lp->dma.tx_rsc_ind--;
1471
1472 memset( desc->buf_addr, 0, HCF_DMA_TX_BUF1_SIZE );
1473 }
1474
1475 return desc;
1476} // wl_pci_dma_get_tx_packet
1477/*============================================================================*/
1478
1479/*******************************************************************************
1480 * wl_pci_dma_put_tx_packet()
1481 *******************************************************************************
1482 *
1483 * DESCRIPTION:
1484 *
1485 * Returns a Tx descriptor to the chain.
1486 *
1487 * PARAMETERS:
1488 *
1489 * lp - a pointer to the device's wl_private structure.
1490 * desc - a pointer to the descriptor to return.
1491 *
1492 * RETURNS:
1493 *
1494 * N/A
1495 *
1496 ******************************************************************************/
1497void wl_pci_dma_put_tx_packet( struct wl_private *lp, DESC_STRCT *desc )
1498{
1499 int i;
1500 /*------------------------------------------------------------------------*/
1501
1502 for( i = 0; i < NUM_TX_DESC; i++ ) {
1503 if( lp->dma.tx_packet[i] == NULL ) {
1504 break;
1505 }
1506 }
1507
1508 if( i != NUM_TX_DESC ) {
1509 lp->dma.tx_packet[i] = desc;
1510 lp->dma.tx_rsc_ind++;
1511 }
1512} // wl_pci_dma_put_tx_packet
1513/*============================================================================*/
1514
1515/*******************************************************************************
1516 * wl_pci_dma_hcf_reclaim_tx()
1517 *******************************************************************************
1518 *
1519 * DESCRIPTION:
1520 *
1521 * Reclaim Tx packets that have either been processed by the HCF due to a
1522 * port disable or a Tx completion.
1523 *
1524 * PARAMETERS:
1525 *
1526 * lp - the device's private adapter structure
1527 *
1528 * RETURNS:
1529 *
1530 * 0 on success
1531 * errno value otherwise
1532 *
1533 ******************************************************************************/
1534void wl_pci_dma_hcf_reclaim_tx( struct wl_private *lp )
1535{
1536 int i;
1537 DESC_STRCT *p;
1538 /*------------------------------------------------------------------------*/
1539
1540 DBG_FUNC( "wl_pci_dma_hcf_reclaim_tx" );
1541 DBG_ENTER( DbgInfo );
1542
1543 //if( lp->dma.status == 0 )
1544 //{
1545 while ( ( p = hcf_dma_tx_get( &lp->hcfCtx ) ) != NULL ) {
1546
1547 if( p != NULL && p->buf_addr == NULL ) {
1548 /* A Reclaim descriptor is being given back by the HCF. Reclaim
1549 descriptors have a NULL buf_addr */
1550 lp->dma.tx_reclaim_desc = p;
1551 DBG_PRINT( "reclaim_descriptor: 0x%p\n", p );
1552 continue;
1553 }
1554 for( i = 0; i < NUM_TX_DESC; i++ ) {
1555 if( lp->dma.tx_packet[i] == NULL ) {
1556 break;
1557 }
1558 }
1559 /* An Rx buffer descriptor is being given back by the HCF */
1560 lp->dma.tx_packet[i] = p;
1561 lp->dma.tx_rsc_ind++;
1562 DBG_PRINT( "tx_packet[%d] 0x%p\n", i, lp->dma.tx_packet[i] );
1563 }
1564 //}
1565
1566 if( lp->netif_queue_on == FALSE ) {
1567 netif_wake_queue( lp->dev );
1568 WL_WDS_NETIF_WAKE_QUEUE( lp );
1569 lp->netif_queue_on = TRUE;
1570 }
1571 DBG_LEAVE( DbgInfo );
1572 return;
1573} // wl_pci_dma_hcf_reclaim_tx
1574/*============================================================================*/
1575#endif // ENABLE_DMA