summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-trans.c
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2011-06-21 14:25:45 +0300
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2011-07-01 07:57:45 -0700
commita0f6b0a211fbdfbae603ffa434f0d9e691e55ab9 (patch)
tree61ecef92736d4a15dfe1a18c1fe5f7667761a0dc /drivers/net/wireless/iwlwifi/iwl-trans.c
parentc85eb6196958ae54eba3ff0660d2b5af3d58521a (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.c78
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)