Commit 72240498 authored by Abhijeet Kolekar's avatar Abhijeet Kolekar Committed by John W. Linville
Browse files

iwl3945: fix lock dependency



Patch seperates rx_used and rx_free into two
different atomic contexts. We can now avoid using GFP_ATOMIC
for skb allocation and use GFP_KERNEL.

Signed-off-by: default avatarAbhijeet Kolekar <abhijeet.kolekar@intel.com>
Signed-off-by: default avatarReinette Chatre <reinette.chatre@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 84379cba
Loading
Loading
Loading
Loading
+17 −20
Original line number Diff line number Diff line
@@ -1344,15 +1344,24 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv)
	struct list_head *element;
	struct iwl_rx_mem_buffer *rxb;
	unsigned long flags;

	while (1) {
		spin_lock_irqsave(&rxq->lock, flags);
	while (!list_empty(&rxq->rx_used)) {

		if (list_empty(&rxq->rx_used)) {
			spin_unlock_irqrestore(&rxq->lock, flags);
			return;
		}

		element = rxq->rx_used.next;
		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
		list_del(element);
		spin_unlock_irqrestore(&rxq->lock, flags);

		/* Alloc a new receive buffer */
		rxb->skb =
		    alloc_skb(priv->hw_params.rx_buf_size,
				__GFP_NOWARN | GFP_ATOMIC);
				GFP_KERNEL);
		if (!rxb->skb) {
			if (net_ratelimit())
				IWL_CRIT(priv, ": Can not allocate SKB buffers\n");
@@ -1370,19 +1379,19 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv)
		 */
		skb_reserve(rxb->skb, 4);

		priv->alloc_rxb_skb++;
		list_del(element);

		/* Get physical address of RB/SKB */
		rxb->real_dma_addr = pci_map_single(priv->pci_dev,
						rxb->skb->data,
						priv->hw_params.rx_buf_size,
						PCI_DMA_FROMDEVICE);

		spin_lock_irqsave(&rxq->lock, flags);
		list_add_tail(&rxb->list, &rxq->rx_free);
		priv->alloc_rxb_skb++;
		rxq->free_count++;
	}
		spin_unlock_irqrestore(&rxq->lock, flags);
	}
}

void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
{
@@ -1414,18 +1423,6 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
	spin_unlock_irqrestore(&rxq->lock, flags);
}

/*
 * this should be called while priv->lock is locked
 */
static void __iwl3945_rx_replenish(void *data)
{
	struct iwl_priv *priv = data;

	iwl3945_rx_allocate(priv);
	iwl3945_rx_queue_restock(priv);
}


void iwl3945_rx_replenish(void *data)
{
	struct iwl_priv *priv = data;
@@ -1644,7 +1641,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
			count++;
			if (count >= 8) {
				priv->rxq.read = i;
				__iwl3945_rx_replenish(priv);
				iwl3945_rx_queue_restock(priv);
				count = 0;
			}
		}