diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2011-06-21 14:25:45 +0300 |
---|---|---|
committer | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2011-07-01 07:57:45 -0700 |
commit | a0f6b0a211fbdfbae603ffa434f0d9e691e55ab9 (patch) | |
tree | 61ecef92736d4a15dfe1a18c1fe5f7667761a0dc /drivers/net/wireless/iwlwifi/iwl-trans.c | |
parent | c85eb6196958ae54eba3ff0660d2b5af3d58521a (diff) |
iwlagn: add rx_free to transport layer
The transport layer ness to release all rx ressources. This function is an API for it.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-trans.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.c | 78 |
1 files changed, 59 insertions, 19 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index ccf73ff6395..1f5834b8a63 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -60,7 +60,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ - #include "iwl-dev.h" +#include "iwl-dev.h" #include "iwl-trans.h" static int iwl_trans_rx_alloc(struct iwl_priv *priv) @@ -78,12 +78,11 @@ static int iwl_trans_rx_alloc(struct iwl_priv *priv) return -EINVAL; /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */ - /*Every descriptor is an __le32, hence its */ - rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma, - GFP_KERNEL); + rxq->bd = dma_alloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, + &rxq->bd_dma, GFP_KERNEL); if (!rxq->bd) goto err_bd; - memset(rxq->bd, 0, 4 * RX_QUEUE_SIZE); + memset(rxq->bd, 0, sizeof(__le32) * RX_QUEUE_SIZE); /*Allocate the driver's pointer to receive buffer status */ rxq->rb_stts = dma_alloc_coherent(dev, sizeof(*rxq->rb_stts), @@ -95,28 +94,18 @@ static int iwl_trans_rx_alloc(struct iwl_priv *priv) return 0; err_rb_stts: - dma_free_coherent(dev, 4 * RX_QUEUE_SIZE, rxq->bd, rxq->bd_dma); + dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, + rxq->bd, rxq->bd_dma); memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); rxq->bd = NULL; err_bd: return -ENOMEM; } -static int iwl_trans_rx_init(struct iwl_priv *priv) +static void iwl_trans_rxq_free_rx_bufs(struct iwl_priv *priv) { struct iwl_rx_queue *rxq = &priv->rxq; - int i, err; - unsigned long flags; - - if (!rxq->bd) { - err = iwl_trans_rx_alloc(priv); - if (err) - return err; - } - - spin_lock_irqsave(&rxq->lock, flags); - INIT_LIST_HEAD(&rxq->rx_free); - INIT_LIST_HEAD(&rxq->rx_used); + int i; /* Fill the rx_used queue with _all_ of the Rx buffers */ for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { @@ -131,6 +120,25 @@ static int iwl_trans_rx_init(struct iwl_priv *priv) } list_add_tail(&rxq->pool[i].list, &rxq->rx_used); } +} + +static int iwl_trans_rx_init(struct iwl_priv *priv) +{ + struct iwl_rx_queue *rxq = &priv->rxq; + int i, err; + unsigned long flags; + + if (!rxq->bd) { + err = iwl_trans_rx_alloc(priv); + if (err) + return err; + } + + spin_lock_irqsave(&rxq->lock, flags); + INIT_LIST_HEAD(&rxq->rx_free); + INIT_LIST_HEAD(&rxq->rx_used); + + iwl_trans_rxq_free_rx_bufs(priv); for (i = 0; i < RX_QUEUE_SIZE; i++) rxq->queue[i] = NULL; @@ -145,8 +153,40 @@ static int iwl_trans_rx_init(struct iwl_priv *priv) return 0; } +static void iwl_trans_rx_free(struct iwl_priv *priv) +{ + struct iwl_rx_queue *rxq = &priv->rxq; + unsigned long flags; + + /*if rxq->bd is NULL, it means that nothing has been allocated, + * exit now */ + if (!rxq->bd) { + IWL_DEBUG_INFO(priv, "Free NULL rx context\n"); + return; + } + + spin_lock_irqsave(&rxq->lock, flags); + iwl_trans_rxq_free_rx_bufs(priv); + spin_unlock_irqrestore(&rxq->lock, flags); + + dma_free_coherent(priv->bus.dev, sizeof(__le32) * RX_QUEUE_SIZE, + rxq->bd, rxq->bd_dma); + memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); + rxq->bd = NULL; + + if (rxq->rb_stts) + dma_free_coherent(priv->bus.dev, + sizeof(struct iwl_rb_status), + rxq->rb_stts, rxq->rb_stts_dma); + else + IWL_DEBUG_INFO(priv, "Free rxq->rb_stts which is NULL\n"); + memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma)); + rxq->rb_stts = NULL; +} + static const struct iwl_trans_ops trans_ops = { .rx_init = iwl_trans_rx_init, + .rx_free = iwl_trans_rx_free, }; void iwl_trans_register(struct iwl_trans *trans) |