1
0
Fork 0
alistair23-linux/drivers/staging/wlags49_h2/wl_pci.c

1584 lines
52 KiB
C
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*******************************************************************************
* Agere Systems Inc.
* Wireless device driver for Linux (wlags49).
*
* Copyright (c) 1998-2003 Agere Systems Inc.
* All rights reserved.
* http://www.agere.com
*
* Initially developed by TriplePoint, Inc.
* http://www.triplepoint.com
*
*------------------------------------------------------------------------------
*
* This file contains processing and initialization specific to PCI/miniPCI
* devices.
*
*------------------------------------------------------------------------------
*
* SOFTWARE LICENSE
*
* This software is provided subject to the following terms and conditions,
* which you should read carefully before using the software. Using this
* software indicates your acceptance of these terms and conditions. If you do
* not agree with these terms and conditions, do not use the software.
*
* Copyright © 2003 Agere Systems Inc.
* All rights reserved.
*
* Redistribution and use in source or binary forms, with or without
* modifications, are permitted provided that the following conditions are met:
*
* . Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following Disclaimer as comments in the code as
* well as in the documentation and/or other materials provided with the
* distribution.
*
* . Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following Disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* . Neither the name of Agere Systems Inc. nor the names of the contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* Disclaimer
*
* THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
* USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
* RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
******************************************************************************/
/*******************************************************************************
* include files
******************************************************************************/
#include <wireless/wl_version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/ctype.h>
#include <linux/string.h>
//#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/in.h>
#include <linux/delay.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <linux/ethtool.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/ioport.h>
#include <hcf/debug.h>
#include <hcf.h>
#include <dhf.h>
#include <hcfdef.h>
#include <wireless/wl_if.h>
#include <wireless/wl_internal.h>
#include <wireless/wl_util.h>
#include <wireless/wl_main.h>
#include <wireless/wl_netdev.h>
#include <wireless/wl_pci.h>
/*******************************************************************************
* global variables
******************************************************************************/
#if DBG
extern dbg_info_t *DbgInfo;
#endif // DBG
/* define the PCI device Table Cardname and id tables */
enum hermes_pci_versions {
CH_Agere_Systems_Mini_PCI_V1 = 0,
};
static struct pci_device_id wl_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_0,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Agere_Systems_Mini_PCI_V1 },
{ PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_1,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Agere_Systems_Mini_PCI_V1 },
{ PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Agere_Systems_Mini_PCI_V1 },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, wl_pci_tbl);
/*******************************************************************************
* function prototypes
******************************************************************************/
int __devinit wl_pci_probe( struct pci_dev *pdev,
const struct pci_device_id *ent );
void __devexit wl_pci_remove(struct pci_dev *pdev);
int wl_pci_setup( struct pci_dev *pdev );
void wl_pci_enable_cardbus_interrupts( struct pci_dev *pdev );
#ifdef ENABLE_DMA
int wl_pci_dma_alloc( struct pci_dev *pdev, struct wl_private *lp );
int wl_pci_dma_free( struct pci_dev *pdev, struct wl_private *lp );
int wl_pci_dma_alloc_tx_packet( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc );
int wl_pci_dma_free_tx_packet( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc );
int wl_pci_dma_alloc_rx_packet( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc );
int wl_pci_dma_free_rx_packet( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc );
int wl_pci_dma_alloc_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc, int size );
int wl_pci_dma_free_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc );
int wl_pci_dma_alloc_desc( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc );
int wl_pci_dma_free_desc( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc );
int wl_pci_dma_alloc_buf( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT *desc, int size );
int wl_pci_dma_free_buf( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT *desc );
void wl_pci_dma_hcf_reclaim_rx( struct wl_private *lp );
#endif // ENABLE_DMA
/*******************************************************************************
* PCI module function registration
******************************************************************************/
static struct pci_driver wl_driver =
{
name: MODULE_NAME,
id_table: wl_pci_tbl,
probe: wl_pci_probe,
remove: __devexit_p(wl_pci_remove),
suspend: NULL,
resume: NULL,
};
/*******************************************************************************
* wl_adapter_init_module()
*******************************************************************************
*
* DESCRIPTION:
*
* Called by init_module() to perform PCI-specific driver initialization.
*
* PARAMETERS:
*
* N/A
*
* RETURNS:
*
* 0
*
******************************************************************************/
int wl_adapter_init_module( void )
{
int result;
/*------------------------------------------------------------------------*/
DBG_FUNC( "wl_adapter_init_module()" );
DBG_ENTER( DbgInfo );
DBG_TRACE( DbgInfo, "wl_adapter_init_module() -- PCI\n" );
result = pci_register_driver( &wl_driver ); //;?replace with pci_module_init, Rubini pg 490
//;? why not do something with the result
DBG_LEAVE( DbgInfo );
return 0;
} // wl_adapter_init_module
/*============================================================================*/
/*******************************************************************************
* wl_adapter_cleanup_module()
*******************************************************************************
*
* DESCRIPTION:
*
* Called by cleanup_module() to perform PCI-specific driver cleanup.
*
* PARAMETERS:
*
* N/A
*
* RETURNS:
*
* N/A
*
******************************************************************************/
void wl_adapter_cleanup_module( void )
{
//;?how comes wl_adapter_cleanup_module is located in a seemingly pci specific module
DBG_FUNC( "wl_adapter_cleanup_module" );
DBG_ENTER( DbgInfo );
//;?DBG_TRACE below feels like nearly redundant in the light of DBG_ENTER above
DBG_TRACE( DbgInfo, "wl_adapter_cleanup_module() -- PCI\n" );
pci_unregister_driver( &wl_driver );
DBG_LEAVE( DbgInfo );
return;
} // wl_adapter_cleanup_module
/*============================================================================*/
/*******************************************************************************
* wl_adapter_insert()
*******************************************************************************
*
* DESCRIPTION:
*
* Called by wl_pci_probe() to continue the process of device insertion.
*
* PARAMETERS:
*
* dev - a pointer to the device's net_device structure
*
* RETURNS:
*
* TRUE or FALSE
*
******************************************************************************/
int wl_adapter_insert( struct net_device *dev )
{
int result = FALSE;
/*------------------------------------------------------------------------*/
DBG_FUNC( "wl_adapter_insert" );
DBG_ENTER( DbgInfo );
DBG_TRACE( DbgInfo, "wl_adapter_insert() -- PCI\n" );
if( dev == NULL ) {
DBG_ERROR( DbgInfo, "net_device pointer is NULL!!!\n" );
} else if( dev->priv == NULL ) {
DBG_ERROR( DbgInfo, "wl_private pointer is NULL!!!\n" );
} else if( wl_insert( dev ) ) { /* Perform remaining device initialization */
result = TRUE;
} else {
DBG_TRACE( DbgInfo, "wl_insert() FAILED\n" );
}
DBG_LEAVE( DbgInfo );
return result;
} // wl_adapter_insert
/*============================================================================*/
/*******************************************************************************
* wl_adapter_open()
*******************************************************************************
*
* DESCRIPTION:
*
* Open the device.
*
* PARAMETERS:
*
* dev - a pointer to the device's net_device structure
*
* RETURNS:
*
* an HCF status code
*
******************************************************************************/
int wl_adapter_open( struct net_device *dev )
{
int result = 0;
int hcf_status = HCF_SUCCESS;
/*------------------------------------------------------------------------*/
DBG_FUNC( "wl_adapter_open" );
DBG_ENTER( DbgInfo );
DBG_TRACE( DbgInfo, "wl_adapter_open() -- PCI\n" );
hcf_status = wl_open( dev );
if( hcf_status != HCF_SUCCESS ) {
result = -ENODEV;
}
DBG_LEAVE( DbgInfo );
return result;
} // wl_adapter_open
/*============================================================================*/
/*******************************************************************************
* wl_adapter_close()
*******************************************************************************
*
* DESCRIPTION:
*
* Close the device
*
* PARAMETERS:
*
* dev - a pointer to the device's net_device structure
*
* RETURNS:
*
* 0
*
******************************************************************************/
int wl_adapter_close( struct net_device *dev )
{
DBG_FUNC( "wl_adapter_close" );
DBG_ENTER( DbgInfo );
DBG_TRACE( DbgInfo, "wl_adapter_close() -- PCI\n" );
DBG_TRACE( DbgInfo, "%s: Shutting down adapter.\n", dev->name );
wl_close( dev );
DBG_LEAVE( DbgInfo );
return 0;
} // wl_adapter_close
/*============================================================================*/
/*******************************************************************************
* wl_adapter_is_open()
*******************************************************************************
*
* DESCRIPTION:
*
* Check whether this device is open. Returns
*
* PARAMETERS:
*
* dev - a pointer to the device's net_device structure
*
* RETURNS:
*
* nonzero if device is open.
*
******************************************************************************/
int wl_adapter_is_open( struct net_device *dev )
{
/* This function is used in PCMCIA to check the status of the 'open' field
in the dev_link_t structure associated with a network device. There
doesn't seem to be an analog to this for PCI, and checking the status
contained in the net_device structure doesn't have the same effect.
For now, return TRUE, but find out if this is necessary for PCI. */
return TRUE;
} // wl_adapter_is_open
/*============================================================================*/
/*******************************************************************************
* wl_pci_probe()
*******************************************************************************
*
* DESCRIPTION:
*
* Registered in the pci_driver structure, this function is called when the
* PCI subsystem finds a new PCI device which matches the infomation contained
* in the pci_device_id table.
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
* ent - this device's entry in the pci_device_id table
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
int __devinit wl_pci_probe( struct pci_dev *pdev,
const struct pci_device_id *ent )
{
int result;
/*------------------------------------------------------------------------*/
DBG_FUNC( "wl_pci_probe" );
DBG_ENTER( DbgInfo );
DBG_PRINT( "%s\n", VERSION_INFO );
result = wl_pci_setup( pdev );
DBG_LEAVE( DbgInfo );
return result;
} // wl_pci_probe
/*============================================================================*/
/*******************************************************************************
* wl_pci_remove()
*******************************************************************************
*
* DESCRIPTION:
*
* Registered in the pci_driver structure, this function is called when the
* PCI subsystem detects that a PCI device which matches the infomation
* contained in the pci_device_id table has been removed.
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
*
* RETURNS:
*
* N/A
*
******************************************************************************/
void __devexit wl_pci_remove(struct pci_dev *pdev)
{
struct net_device *dev = NULL;
/*------------------------------------------------------------------------*/
DBG_FUNC( "wl_pci_remove" );
DBG_ENTER( DbgInfo );
/* Make sure the pci_dev pointer passed in is valid */
if( pdev == NULL ) {
DBG_ERROR( DbgInfo, "PCI subsys passed in an invalid pci_dev pointer\n" );
return;
}
dev = pci_get_drvdata( pdev );
if( dev == NULL ) {
DBG_ERROR( DbgInfo, "Could not retrieve net_device structure\n" );
return;
}
/* Perform device cleanup */
wl_remove( dev );
free_irq( dev->irq, dev );
#ifdef ENABLE_DMA
wl_pci_dma_free( pdev, dev->priv );
#endif
wl_device_dealloc( dev );
DBG_LEAVE( DbgInfo );
return;
} // wl_pci_remove
/*============================================================================*/
/*******************************************************************************
* wl_pci_setup()
*******************************************************************************
*
* DESCRIPTION:
*
* Called by wl_pci_probe() to begin a device's initialization process.
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
int wl_pci_setup( struct pci_dev *pdev )
{
int result = 0;
struct net_device *dev = NULL;
struct wl_private *lp = NULL;
/*------------------------------------------------------------------------*/
DBG_FUNC( "wl_pci_setup" );
DBG_ENTER( DbgInfo );
/* Make sure the pci_dev pointer passed in is valid */
if( pdev == NULL ) {
DBG_ERROR( DbgInfo, "PCI subsys passed in an invalid pci_dev pointer\n" );
return -ENODEV;
}
result = pci_enable_device( pdev );
if( result != 0 ) {
DBG_ERROR( DbgInfo, "pci_enable_device() failed\n" );
DBG_LEAVE( DbgInfo );
return result;
}
/* We found our device! Let's register it with the system */
DBG_TRACE( DbgInfo, "Found our device, now registering\n" );
dev = wl_device_alloc( );
if( dev == NULL ) {
DBG_ERROR( DbgInfo, "Could not register device!!!\n" );
DBG_LEAVE( DbgInfo );
return -ENOMEM;
}
/* Make sure that space was allocated for our private adapter struct */
if( dev->priv == NULL ) {
DBG_ERROR( DbgInfo, "Private adapter struct was not allocated!!!\n" );
DBG_LEAVE( DbgInfo );
return -ENOMEM;
}
#ifdef ENABLE_DMA
/* Allocate DMA Descriptors */
if( wl_pci_dma_alloc( pdev, dev->priv ) < 0 ) {
DBG_ERROR( DbgInfo, "Could not allocate DMA descriptor memory!!!\n" );
DBG_LEAVE( DbgInfo );
return -ENOMEM;
}
#endif
/* Register our private adapter structure with PCI */
pci_set_drvdata( pdev, dev );
/* Fill out bus specific information in the net_device struct */
dev->irq = pdev->irq;
SET_MODULE_OWNER( dev );
DBG_TRACE( DbgInfo, "Device Base Address: %#03lx\n", pdev->resource[0].start );
dev->base_addr = pdev->resource[0].start;
/* Initialize our device here */
if( !wl_adapter_insert( dev )) {
DBG_ERROR( DbgInfo, "wl_adapter_insert() FAILED!!!\n" );
wl_device_dealloc( dev );
DBG_LEAVE( DbgInfo );
return -EINVAL;
}
/* Register our ISR */
DBG_TRACE( DbgInfo, "Registering ISR...\n" );
result = request_irq(dev->irq, wl_isr, SA_SHIRQ, dev->name, dev);
if( result ) {
DBG_WARNING( DbgInfo, "Could not register ISR!!!\n" );
DBG_LEAVE( DbgInfo );
return result;
}
/* Make sure interrupts are enabled properly for CardBus */
lp = dev->priv;
if( lp->hcfCtx.IFB_BusType == CFG_NIC_BUS_TYPE_CARDBUS ||
lp->hcfCtx.IFB_BusType == CFG_NIC_BUS_TYPE_PCI ) {
DBG_TRACE( DbgInfo, "This is a PCI/CardBus card, enable interrupts\n" );
wl_pci_enable_cardbus_interrupts( pdev );
}
/* Enable bus mastering */
pci_set_master( pdev );
DBG_LEAVE( DbgInfo );
return 0;
} // wl_pci_setup
/*============================================================================*/
/*******************************************************************************
* wl_pci_enable_cardbus_interrupts()
*******************************************************************************
*
* DESCRIPTION:
*
* Called by wl_pci_setup() to enable interrupts on a CardBus device. This
* is done by writing bit 15 to the function event mask register. This
* CardBus-specific register is located in BAR2 (counting from BAR0), in memory
* space at byte offset 1f4 (7f4 for WARP).
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
*
* RETURNS:
*
* N/A
*
******************************************************************************/
void wl_pci_enable_cardbus_interrupts( struct pci_dev *pdev )
{
u32 bar2_reg;
u32 mem_addr_bus;
u32 func_evt_mask_reg;
void *mem_addr_kern = NULL;
/*------------------------------------------------------------------------*/
DBG_FUNC( "wl_pci_enable_cardbus_interrupts" );
DBG_ENTER( DbgInfo );
/* Initialize to known bad values */
bar2_reg = 0xdeadbeef;
mem_addr_bus = 0xdeadbeef;
/* Read the BAR2 register; this register contains the base address of the
memory region where the function event mask register lives */
pci_read_config_dword( pdev, PCI_BASE_ADDRESS_2, &bar2_reg );
mem_addr_bus = bar2_reg & PCI_BASE_ADDRESS_MEM_MASK;
/* Once the base address is obtained, remap the memory region to kernel
space so we can retrieve the register */
mem_addr_kern = ioremap( mem_addr_bus, 0x200 );
#ifdef HERMES25
#define REG_OFFSET 0x07F4
#else
#define REG_OFFSET 0x01F4
#endif // HERMES25
#define BIT15 0x8000
/* Retrieve the functional event mask register, enable interrupts by
setting Bit 15, and write back the value */
func_evt_mask_reg = *(u32 *)( mem_addr_kern + REG_OFFSET );
func_evt_mask_reg |= BIT15;
*(u32 *)( mem_addr_kern + REG_OFFSET ) = func_evt_mask_reg;
/* Once complete, unmap the region and exit */
iounmap( mem_addr_kern );
DBG_LEAVE( DbgInfo );
return;
} // wl_pci_enable_cardbus_interrupts
/*============================================================================*/
#ifdef ENABLE_DMA
/*******************************************************************************
* wl_pci_dma_alloc()
*******************************************************************************
*
* DESCRIPTION:
*
* Allocates all resources needed for PCI/CardBus DMA operation
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
* lp - the device's private adapter structure
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
int wl_pci_dma_alloc( struct pci_dev *pdev, struct wl_private *lp )
{
int i;
int status = 0;
/*------------------------------------------------------------------------*/
DBG_FUNC( "wl_pci_dma_alloc" );
DBG_ENTER( DbgInfo );
// lp->dma.tx_rsc_ind = lp->dma.rx_rsc_ind = 0;
//
// /* Alloc for the Tx chain and its reclaim descriptor */
// for( i = 0; i < NUM_TX_DESC; i++ ) {
// status = wl_pci_dma_alloc_tx_packet( pdev, lp, &lp->dma.tx_packet[i] );
// if( status == 0 ) {
// DBG_PRINT( "lp->dma.tx_packet[%d] : 0x%p\n", i, lp->dma.tx_packet[i] );
// DBG_PRINT( "lp->dma.tx_packet[%d]->next_desc_addr : 0x%p\n", i, lp->dma.tx_packet[i]->next_desc_addr );
// lp->dma.tx_rsc_ind++;
// } else {
// DBG_ERROR( DbgInfo, "Could not alloc DMA Tx Packet\n" );
// break;
// }
// }
// if( status == 0 ) {
// status = wl_pci_dma_alloc_desc( pdev, lp, &lp->dma.tx_reclaim_desc );
// DBG_PRINT( "lp->dma.tx_reclaim_desc: 0x%p\n", lp->dma.tx_reclaim_desc );
// }
// /* Alloc for the Rx chain and its reclaim descriptor */
// if( status == 0 ) {
// for( i = 0; i < NUM_RX_DESC; i++ ) {
// status = wl_pci_dma_alloc_rx_packet( pdev, lp, &lp->dma.rx_packet[i] );
// if( status == 0 ) {
// DBG_PRINT( "lp->dma.rx_packet[%d] : 0x%p\n", i, lp->dma.rx_packet[i] );
// DBG_PRINT( "lp->dma.rx_packet[%d]->next_desc_addr : 0x%p\n", i, lp->dma.rx_packet[i]->next_desc_addr );
// lp->dma.rx_rsc_ind++;
// } else {
// DBG_ERROR( DbgInfo, "Could not alloc DMA Rx Packet\n" );
// break;
// }
// }
// }
// if( status == 0 ) {
// status = wl_pci_dma_alloc_desc( pdev, lp, &lp->dma.rx_reclaim_desc );
// DBG_PRINT( "lp->dma.rx_reclaim_desc: 0x%p\n", lp->dma.rx_reclaim_desc );
// }
// /* Store status, as host should not call HCF functions if this fails */
// lp->dma.status = status; //;?all useages of dma.status have been commented out
// DBG_LEAVE( DbgInfo );
return status;
} // wl_pci_dma_alloc
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_free()
*******************************************************************************
*
* DESCRIPTION:
*
* Deallocated all resources needed for PCI/CardBus DMA operation
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
* lp - the device's private adapter structure
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
int wl_pci_dma_free( struct pci_dev *pdev, struct wl_private *lp )
{
int i;
int status = 0;
/*------------------------------------------------------------------------*/
DBG_FUNC( "wl_pci_dma_free" );
DBG_ENTER( DbgInfo );
/* Reclaim all Rx packets that were handed over to the HCF */
/* Do I need to do this? Before this free is called, I've already disabled
the port which will call wl_pci_dma_hcf_reclaim */
//if( lp->dma.status == 0 )
//{
// wl_pci_dma_hcf_reclaim( lp );
//}
/* Free everything needed for DMA Rx */
for( i = 0; i < NUM_RX_DESC; i++ ) {
if( lp->dma.rx_packet[i] ) {
status = wl_pci_dma_free_rx_packet( pdev, lp, &lp->dma.rx_packet[i] );
if( status != 0 ) {
DBG_WARNING( DbgInfo, "Problem freeing Rx packet\n" );
}
}
}
lp->dma.rx_rsc_ind = 0;
if( lp->dma.rx_reclaim_desc ) {
status = wl_pci_dma_free_desc( pdev, lp, &lp->dma.rx_reclaim_desc );
if( status != 0 ) {
DBG_WARNING( DbgInfo, "Problem freeing Rx reclaim descriptor\n" );
}
}
/* Free everything needed for DMA Tx */
for( i = 0; i < NUM_TX_DESC; i++ ) {
if( lp->dma.tx_packet[i] ) {
status = wl_pci_dma_free_tx_packet( pdev, lp, &lp->dma.tx_packet[i] );
if( status != 0 ) {
DBG_WARNING( DbgInfo, "Problem freeing Tx packet\n" );
}
}
}
lp->dma.tx_rsc_ind = 0;
if( lp->dma.tx_reclaim_desc ) {
status = wl_pci_dma_free_desc( pdev, lp, &lp->dma.tx_reclaim_desc );
if( status != 0 ) {
DBG_WARNING( DbgInfo, "Problem freeing Tx reclaim descriptor\n" );
}
}
DBG_LEAVE( DbgInfo );
return status;
} // wl_pci_dma_free
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_alloc_tx_packet()
*******************************************************************************
*
* DESCRIPTION:
*
* Allocates a single Tx packet, consisting of several descriptors and
* buffers. Data to transmit is first copied into the 'payload' buffer
* before being transmitted.
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
* lp - the device's private adapter structure
* desc - a pointer which will reference the descriptor to be alloc'd.
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
int wl_pci_dma_alloc_tx_packet( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc )
{
// int status = 0;
// /*------------------------------------------------------------------------*/
//
// if( desc == NULL ) {
// status = -EFAULT;
// }
// if( status == 0 ) {
// status = wl_pci_dma_alloc_desc_and_buf( pdev, lp, desc,
// HCF_DMA_TX_BUF1_SIZE );
//
// if( status == 0 ) {
// status = wl_pci_dma_alloc_desc_and_buf( pdev, lp,
// &( (*desc)->next_desc_addr ),
// HCF_MAX_PACKET_SIZE );
// }
// }
// if( status == 0 ) {
// (*desc)->next_desc_phys_addr = (*desc)->next_desc_addr->desc_phys_addr;
// }
// return status;
} // wl_pci_dma_alloc_tx_packet
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_free_tx_packet()
*******************************************************************************
*
* DESCRIPTION:
*
* Frees a single Tx packet, described in the corresponding alloc function.
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
* lp - the device's private adapter structure
* desc - a pointer which will reference the descriptor to be alloc'd.
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
int wl_pci_dma_free_tx_packet( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc )
{
int status = 0;
/*------------------------------------------------------------------------*/
if( *desc == NULL ) {
DBG_PRINT( "Null descriptor\n" );
status = -EFAULT;
}
//;?the "limited" NDIS strategy, assuming a frame consists ALWAYS out of 2
//descriptors, make this robust
if( status == 0 && (*desc)->next_desc_addr ) {
status = wl_pci_dma_free_desc_and_buf( pdev, lp, &(*desc)->next_desc_addr );
}
if( status == 0 ) {
status = wl_pci_dma_free_desc_and_buf( pdev, lp, desc );
}
return status;
} // wl_pci_dma_free_tx_packet
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_alloc_rx_packet()
*******************************************************************************
*
* DESCRIPTION:
*
* Allocates a single Rx packet, consisting of two descriptors and one
* contiguous buffer. THe buffer starts with the hermes-specific header.
* One descriptor points at the start, the other at offset 0x3a of the
* buffer.
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
* lp - the device's private adapter structure
* desc - a pointer which will reference the descriptor to be alloc'd.
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
int wl_pci_dma_alloc_rx_packet( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc )
{
int status = 0;
DESC_STRCT *p;
/*------------------------------------------------------------------------*/
// if( desc == NULL ) {
// status = -EFAULT;
// }
// //;?the "limited" NDIS strategy, assuming a frame consists ALWAYS out of 2
// //descriptors, make this robust
// if( status == 0 ) {
// status = wl_pci_dma_alloc_desc( pdev, lp, desc );
// }
// if( status == 0 ) {
// status = wl_pci_dma_alloc_buf( pdev, lp, *desc, HCF_MAX_PACKET_SIZE );
// }
// if( status == 0 ) {
// status = wl_pci_dma_alloc_desc( pdev, lp, &p );
// }
// if( status == 0 ) {
// /* Size of 1st descriptor becomes 0x3a bytes */
// SET_BUF_SIZE( *desc, HCF_DMA_RX_BUF1_SIZE );
//
// /* Make 2nd descriptor point at offset 0x3a of the buffer */
// SET_BUF_SIZE( p, ( HCF_MAX_PACKET_SIZE - HCF_DMA_RX_BUF1_SIZE ));
// p->buf_addr = (*desc)->buf_addr + HCF_DMA_RX_BUF1_SIZE;
// p->buf_phys_addr = (*desc)->buf_phys_addr + HCF_DMA_RX_BUF1_SIZE;
// p->next_desc_addr = NULL;
//
// /* Chain 2nd descriptor to 1st descriptor */
// (*desc)->next_desc_addr = p;
// (*desc)->next_desc_phys_addr = p->desc_phys_addr;
// }
return status;
} // wl_pci_dma_alloc_rx_packet
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_free_rx_packet()
*******************************************************************************
*
* DESCRIPTION:
*
* Frees a single Rx packet, described in the corresponding alloc function.
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
* lp - the device's private adapter structure
* desc - a pointer which will reference the descriptor to be alloc'd.
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
int wl_pci_dma_free_rx_packet( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc )
{
int status = 0;
DESC_STRCT *p;
/*------------------------------------------------------------------------*/
if( *desc == NULL ) {
status = -EFAULT;
}
if( status == 0 ) {
p = (*desc)->next_desc_addr;
/* Free the 2nd descriptor */
if( p != NULL ) {
p->buf_addr = NULL;
p->buf_phys_addr = 0;
status = wl_pci_dma_free_desc( pdev, lp, &p );
}
}
/* Free the buffer and 1st descriptor */
if( status == 0 ) {
SET_BUF_SIZE( *desc, HCF_MAX_PACKET_SIZE );
status = wl_pci_dma_free_desc_and_buf( pdev, lp, desc );
}
return status;
} // wl_pci_dma_free_rx_packet
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_alloc_desc_and_buf()
*******************************************************************************
*
* DESCRIPTION:
*
* Allocates a DMA descriptor and buffer, and associates them with one
* another.
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
* lp - the device's private adapter structure
* desc - a pointer which will reference the descriptor to be alloc'd
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
int wl_pci_dma_alloc_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc, int size )
{
int status = 0;
/*------------------------------------------------------------------------*/
// if( desc == NULL ) {
// status = -EFAULT;
// }
// if( status == 0 ) {
// status = wl_pci_dma_alloc_desc( pdev, lp, desc );
//
// if( status == 0 ) {
// status = wl_pci_dma_alloc_buf( pdev, lp, *desc, size );
// }
// }
return status;
} // wl_pci_dma_alloc_desc_and_buf
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_free_desc_and_buf()
*******************************************************************************
*
* DESCRIPTION:
*
* Frees a DMA descriptor and associated buffer.
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
* lp - the device's private adapter structure
* desc - a pointer which will reference the descriptor to be alloc'd
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
int wl_pci_dma_free_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc )
{
int status = 0;
/*------------------------------------------------------------------------*/
if( desc == NULL ) {
status = -EFAULT;
}
if( status == 0 && *desc == NULL ) {
status = -EFAULT;
}
if( status == 0 ) {
status = wl_pci_dma_free_buf( pdev, lp, *desc );
if( status == 0 ) {
status = wl_pci_dma_free_desc( pdev, lp, desc );
}
}
return status;
} // wl_pci_dma_free_desc_and_buf
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_alloc_desc()
*******************************************************************************
*
* DESCRIPTION:
*
* Allocates one DMA descriptor in cache coherent memory.
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
* lp - the device's private adapter structure
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
int wl_pci_dma_alloc_desc( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc )
{
// int status = 0;
// dma_addr_t pa;
// /*------------------------------------------------------------------------*/
//
// DBG_FUNC( "wl_pci_dma_alloc_desc" );
// DBG_ENTER( DbgInfo );
//
// if( desc == NULL ) {
// status = -EFAULT;
// }
// if( status == 0 ) {
// *desc = pci_alloc_consistent( pdev, sizeof( DESC_STRCT ), &pa );
// }
// if( *desc == NULL ) {
// DBG_ERROR( DbgInfo, "pci_alloc_consistent() failed\n" );
// status = -ENOMEM;
// } else {
// memset( *desc, 0, sizeof( DESC_STRCT ));
// (*desc)->desc_phys_addr = cpu_to_le32( pa );
// }
// DBG_LEAVE( DbgInfo );
// return status;
} // wl_pci_dma_alloc_desc
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_free_desc()
*******************************************************************************
*
* DESCRIPTION:
*
* Frees one DMA descriptor in cache coherent memory.
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
* lp - the device's private adapter structure
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
int wl_pci_dma_free_desc( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT **desc )
{
int status = 0;
/*------------------------------------------------------------------------*/
if( *desc == NULL ) {
status = -EFAULT;
}
if( status == 0 ) {
pci_free_consistent( pdev, sizeof( DESC_STRCT ), *desc,
(*desc)->desc_phys_addr );
}
*desc = NULL;
return status;
} // wl_pci_dma_free_desc
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_alloc_buf()
*******************************************************************************
*
* DESCRIPTION:
*
* Allocates one DMA buffer in cache coherent memory, and associates a DMA
* descriptor with this buffer.
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
* lp - the device's private adapter structure
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
int wl_pci_dma_alloc_buf( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT *desc, int size )
{
int status = 0;
dma_addr_t pa;
/*------------------------------------------------------------------------*/
// DBG_FUNC( "wl_pci_dma_alloc_buf" );
// DBG_ENTER( DbgInfo );
//
// if( desc == NULL ) {
// status = -EFAULT;
// }
// if( status == 0 && desc->buf_addr != NULL ) {
// status = -EFAULT;
// }
// if( status == 0 ) {
// desc->buf_addr = pci_alloc_consistent( pdev, size, &pa );
// }
// if( desc->buf_addr == NULL ) {
// DBG_ERROR( DbgInfo, "pci_alloc_consistent() failed\n" );
// status = -ENOMEM;
// } else {
// desc->buf_phys_addr = cpu_to_le32( pa );
// SET_BUF_SIZE( desc, size );
// }
// DBG_LEAVE( DbgInfo );
return status;
} // wl_pci_dma_alloc_buf
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_free_buf()
*******************************************************************************
*
* DESCRIPTION:
*
* Allocates one DMA buffer in cache coherent memory, and associates a DMA
* descriptor with this buffer.
*
* PARAMETERS:
*
* pdev - a pointer to the device's pci_dev structure
* lp - the device's private adapter structure
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
int wl_pci_dma_free_buf( struct pci_dev *pdev, struct wl_private *lp,
DESC_STRCT *desc )
{
int status = 0;
/*------------------------------------------------------------------------*/
if( desc == NULL ) {
status = -EFAULT;
}
if( status == 0 && desc->buf_addr == NULL ) {
status = -EFAULT;
}
if( status == 0 ) {
pci_free_consistent( pdev, GET_BUF_SIZE( desc ), desc->buf_addr,
desc->buf_phys_addr );
desc->buf_addr = 0;
desc->buf_phys_addr = 0;
SET_BUF_SIZE( desc, 0 );
}
return status;
} // wl_pci_dma_free_buf
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_hcf_supply()
*******************************************************************************
*
* DESCRIPTION:
*
* Supply HCF with DMA-related resources. These consist of:
* - buffers and descriptors for receive purposes
* - one 'reclaim' descriptor for the transmit path, used to fulfill a
* certain H25 DMA engine requirement
* - one 'reclaim' descriptor for the receive path, used to fulfill a
* certain H25 DMA engine requirement
*
* This function is called at start-of-day or at re-initialization.
*
* PARAMETERS:
*
* lp - the device's private adapter structure
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
void wl_pci_dma_hcf_supply( struct wl_private *lp )
{
int i;
/*------------------------------------------------------------------------*/
DBG_FUNC( "wl_pci_dma_hcf_supply" );
DBG_ENTER( DbgInfo );
//if( lp->dma.status == 0 );
//{
/* Hand over the Rx/Tx reclaim descriptors to the HCF */
if( lp->dma.tx_reclaim_desc ) {
DBG_PRINT( "lp->dma.tx_reclaim_desc: 0x%p\n", lp->dma.tx_reclaim_desc );
hcf_dma_tx_put( &lp->hcfCtx, lp->dma.tx_reclaim_desc, 0 );
lp->dma.tx_reclaim_desc = NULL;
DBG_PRINT( "lp->dma.tx_reclaim_desc: 0x%p\n", lp->dma.tx_reclaim_desc );
}
if( lp->dma.rx_reclaim_desc ) {
DBG_PRINT( "lp->dma.rx_reclaim_desc: 0x%p\n", lp->dma.rx_reclaim_desc );
hcf_dma_rx_put( &lp->hcfCtx, lp->dma.rx_reclaim_desc );
lp->dma.rx_reclaim_desc = NULL;
DBG_PRINT( "lp->dma.rx_reclaim_desc: 0x%p\n", lp->dma.rx_reclaim_desc );
}
/* Hand over the Rx descriptor chain to the HCF */
for( i = 0; i < NUM_RX_DESC; i++ ) {
DBG_PRINT( "lp->dma.rx_packet[%d]: 0x%p\n", i, lp->dma.rx_packet[i] );
hcf_dma_rx_put( &lp->hcfCtx, lp->dma.rx_packet[i] );
lp->dma.rx_packet[i] = NULL;
DBG_PRINT( "lp->dma.rx_packet[%d]: 0x%p\n", i, lp->dma.rx_packet[i] );
}
//}
DBG_LEAVE( DbgInfo );
return;
} // wl_pci_dma_hcf_supply
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_hcf_reclaim()
*******************************************************************************
*
* DESCRIPTION:
*
* Return DMA-related resources from the HCF. These consist of:
* - buffers and descriptors for receive purposes
* - buffers and descriptors for transmit purposes
* - one 'reclaim' descriptor for the transmit path, used to fulfill a
* certain H25 DMA engine requirement
* - one 'reclaim' descriptor for the receive path, used to fulfill a
* certain H25 DMA engine requirement
*
* This function is called at end-of-day or at re-initialization.
*
* PARAMETERS:
*
* lp - the device's private adapter structure
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
void wl_pci_dma_hcf_reclaim( struct wl_private *lp )
{
int i;
/*------------------------------------------------------------------------*/
DBG_FUNC( "wl_pci_dma_hcf_reclaim" );
DBG_ENTER( DbgInfo );
wl_pci_dma_hcf_reclaim_rx( lp );
for( i = 0; i < NUM_RX_DESC; i++ ) {
DBG_PRINT( "rx_packet[%d] 0x%p\n", i, lp->dma.rx_packet[i] );
// if( lp->dma.rx_packet[i] == NULL ) {
// DBG_PRINT( "wl_pci_dma_hcf_reclaim: rx_packet[%d] NULL\n", i );
// }
}
wl_pci_dma_hcf_reclaim_tx( lp );
for( i = 0; i < NUM_TX_DESC; i++ ) {
DBG_PRINT( "tx_packet[%d] 0x%p\n", i, lp->dma.tx_packet[i] );
// if( lp->dma.tx_packet[i] == NULL ) {
// DBG_PRINT( "wl_pci_dma_hcf_reclaim: tx_packet[%d] NULL\n", i );
// }
}
DBG_LEAVE( DbgInfo );
return;
} // wl_pci_dma_hcf_reclaim
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_hcf_reclaim_rx()
*******************************************************************************
*
* DESCRIPTION:
*
* Reclaim Rx packets that have already been processed by the HCF.
*
* PARAMETERS:
*
* lp - the device's private adapter structure
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
void wl_pci_dma_hcf_reclaim_rx( struct wl_private *lp )
{
int i;
DESC_STRCT *p;
/*------------------------------------------------------------------------*/
DBG_FUNC( "wl_pci_dma_hcf_reclaim_rx" );
DBG_ENTER( DbgInfo );
//if( lp->dma.status == 0 )
//{
while ( ( p = hcf_dma_rx_get( &lp->hcfCtx ) ) != NULL ) {
if( p && p->buf_addr == NULL ) {
/* A reclaim descriptor is being given back by the HCF. Reclaim
descriptors have a NULL buf_addr */
lp->dma.rx_reclaim_desc = p;
DBG_PRINT( "reclaim_descriptor: 0x%p\n", p );
continue;
}
for( i = 0; i < NUM_RX_DESC; i++ ) {
if( lp->dma.rx_packet[i] == NULL ) {
break;
}
}
/* An Rx buffer descriptor is being given back by the HCF */
lp->dma.rx_packet[i] = p;
lp->dma.rx_rsc_ind++;
DBG_PRINT( "rx_packet[%d] 0x%p\n", i, lp->dma.rx_packet[i] );
}
//}
DBG_LEAVE( DbgInfo );
} // wl_pci_dma_hcf_reclaim_rx
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_get_tx_packet()
*******************************************************************************
*
* DESCRIPTION:
*
* Obtains a Tx descriptor from the chain to use for Tx.
*
* PARAMETERS:
*
* lp - a pointer to the device's wl_private structure.
*
* RETURNS:
*
* A pointer to the retrieved descriptor
*
******************************************************************************/
DESC_STRCT * wl_pci_dma_get_tx_packet( struct wl_private *lp )
{
int i;
DESC_STRCT *desc = NULL;
/*------------------------------------------------------------------------*/
for( i = 0; i < NUM_TX_DESC; i++ ) {
if( lp->dma.tx_packet[i] ) {
break;
}
}
if( i != NUM_TX_DESC ) {
desc = lp->dma.tx_packet[i];
lp->dma.tx_packet[i] = NULL;
lp->dma.tx_rsc_ind--;
memset( desc->buf_addr, 0, HCF_DMA_TX_BUF1_SIZE );
}
return desc;
} // wl_pci_dma_get_tx_packet
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_put_tx_packet()
*******************************************************************************
*
* DESCRIPTION:
*
* Returns a Tx descriptor to the chain.
*
* PARAMETERS:
*
* lp - a pointer to the device's wl_private structure.
* desc - a pointer to the descriptor to return.
*
* RETURNS:
*
* N/A
*
******************************************************************************/
void wl_pci_dma_put_tx_packet( struct wl_private *lp, DESC_STRCT *desc )
{
int i;
/*------------------------------------------------------------------------*/
for( i = 0; i < NUM_TX_DESC; i++ ) {
if( lp->dma.tx_packet[i] == NULL ) {
break;
}
}
if( i != NUM_TX_DESC ) {
lp->dma.tx_packet[i] = desc;
lp->dma.tx_rsc_ind++;
}
} // wl_pci_dma_put_tx_packet
/*============================================================================*/
/*******************************************************************************
* wl_pci_dma_hcf_reclaim_tx()
*******************************************************************************
*
* DESCRIPTION:
*
* Reclaim Tx packets that have either been processed by the HCF due to a
* port disable or a Tx completion.
*
* PARAMETERS:
*
* lp - the device's private adapter structure
*
* RETURNS:
*
* 0 on success
* errno value otherwise
*
******************************************************************************/
void wl_pci_dma_hcf_reclaim_tx( struct wl_private *lp )
{
int i;
DESC_STRCT *p;
/*------------------------------------------------------------------------*/
DBG_FUNC( "wl_pci_dma_hcf_reclaim_tx" );
DBG_ENTER( DbgInfo );
//if( lp->dma.status == 0 )
//{
while ( ( p = hcf_dma_tx_get( &lp->hcfCtx ) ) != NULL ) {
if( p != NULL && p->buf_addr == NULL ) {
/* A Reclaim descriptor is being given back by the HCF. Reclaim
descriptors have a NULL buf_addr */
lp->dma.tx_reclaim_desc = p;
DBG_PRINT( "reclaim_descriptor: 0x%p\n", p );
continue;
}
for( i = 0; i < NUM_TX_DESC; i++ ) {
if( lp->dma.tx_packet[i] == NULL ) {
break;
}
}
/* An Rx buffer descriptor is being given back by the HCF */
lp->dma.tx_packet[i] = p;
lp->dma.tx_rsc_ind++;
DBG_PRINT( "tx_packet[%d] 0x%p\n", i, lp->dma.tx_packet[i] );
}
//}
if( lp->netif_queue_on == FALSE ) {
netif_wake_queue( lp->dev );
WL_WDS_NETIF_WAKE_QUEUE( lp );
lp->netif_queue_on = TRUE;
}
DBG_LEAVE( DbgInfo );
return;
} // wl_pci_dma_hcf_reclaim_tx
/*============================================================================*/
#endif // ENABLE_DMA