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