Skip to content

Commit

Permalink
iwlagn: add rx_free to transport layer
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Emmanuel Grumbach authored and Wey-Yi Guy committed Jul 1, 2011
1 parent c85eb61 commit a0f6b0a
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 49 deletions.
27 changes: 0 additions & 27 deletions drivers/net/wireless/iwlwifi/iwl-agn-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -910,33 +910,6 @@ void iwlagn_rx_replenish_now(struct iwl_priv *priv)
iwlagn_rx_queue_restock(priv);
}

/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
* If an SKB has been detached, the POOL needs to have its SKB set to NULL
* This free routine walks the list of POOL entries and if SKB is set to
* non NULL it is unmapped and freed
*/
void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
{
int i;
for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
if (rxq->pool[i].page != NULL) {
dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma,
PAGE_SIZE << priv->hw_params.rx_page_order,
DMA_FROM_DEVICE);
__iwl_free_pages(priv, rxq->pool[i].page);
rxq->pool[i].page = NULL;
}
}

dma_free_coherent(priv->bus.dev, 4 * RX_QUEUE_SIZE,
rxq->bd, rxq->bd_dma);
dma_free_coherent(priv->bus.dev,
sizeof(struct iwl_rb_status),
rxq->rb_stts, rxq->rb_stts_dma);
rxq->bd = NULL;
rxq->rb_stts = NULL;
}

int iwlagn_rxq_stop(struct iwl_priv *priv)
{

Expand Down
3 changes: 1 addition & 2 deletions drivers/net/wireless/iwlwifi/iwl-agn.c
Original file line number Diff line number Diff line change
Expand Up @@ -3718,8 +3718,7 @@ void __devexit iwl_remove(struct iwl_priv * priv)

iwl_dealloc_ucode(priv);

if (priv->rxq.bd)
iwlagn_rx_queue_free(priv, &priv->rxq);
priv->trans.ops->rx_free(priv);
iwlagn_hw_txq_ctx_free(priv);

iwl_eeprom_free(priv);
Expand Down
1 change: 0 additions & 1 deletion drivers/net/wireless/iwlwifi/iwl-agn.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ void iwlagn_rx_queue_restock(struct iwl_priv *priv);
void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority);
void iwlagn_rx_replenish(struct iwl_priv *priv);
void iwlagn_rx_replenish_now(struct iwl_priv *priv);
void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
int iwlagn_rxq_stop(struct iwl_priv *priv);
int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
void iwl_setup_rx_handlers(struct iwl_priv *priv);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/iwlwifi/iwl-dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -1233,9 +1233,11 @@ struct iwl_trans;
* struct iwl_trans_ops - transport specific operations
* @rx_init: inits the rx memory, allocate it if needed
*@rx_free: frees the rx memory
*/
struct iwl_trans_ops {
int (*rx_init)(struct iwl_priv *priv);
void (*rx_free)(struct iwl_priv *priv);
};

struct iwl_trans {
Expand Down
78 changes: 59 additions & 19 deletions drivers/net/wireless/iwlwifi/iwl-trans.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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),
Expand All @@ -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++) {
Expand All @@ -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;
Expand All @@ -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)
Expand Down

0 comments on commit a0f6b0a

Please sign in to comment.