be2net: fix unmap_single/page() called incorrectly in Tx compl processing
authorSathya Perla <sathyap@serverengines.com>
Mon, 22 Mar 2010 20:41:34 +0000 (20:41 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 23 Mar 2010 20:22:40 +0000 (13:22 -0700)
The first wrb seen by tx compl processing does not have a dma handle in it.
Currently, pci_unmap_single() is attempted on this wrb and pci_unmap_page() on the
rest. So, pci_unmap_page() gets incorrectly called on the dma hdl of skb->data (that
was mapped using map_single()). This patch fixes this issue.

Signed-off-by: Sathya Perla <sathyap@serverengines.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/benet/be_main.c

index 0800c63639083208a9285234dd0331c365e10090..174e5f8996097ff005b24dbe6047a94ec829d452 100644 (file)
@@ -1047,35 +1047,26 @@ static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index)
        struct be_eth_wrb *wrb;
        struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list;
        struct sk_buff *sent_skb;
-       u64 busaddr;
-       u16 cur_index, num_wrbs = 0;
+       u16 cur_index, num_wrbs = 1; /* account for hdr wrb */
+       bool unmap_skb_hdr = true;
 
-       cur_index = txq->tail;
-       sent_skb = sent_skbs[cur_index];
+       sent_skb = sent_skbs[txq->tail];
        BUG_ON(!sent_skb);
-       sent_skbs[cur_index] = NULL;
-       wrb = queue_tail_node(txq);
-       be_dws_le_to_cpu(wrb, sizeof(*wrb));
-       busaddr = ((u64)wrb->frag_pa_hi << 32) | (u64)wrb->frag_pa_lo;
-       if (busaddr != 0) {
-               pci_unmap_single(adapter->pdev, busaddr,
-                                wrb->frag_len, PCI_DMA_TODEVICE);
-       }
-       num_wrbs++;
+       sent_skbs[txq->tail] = NULL;
+
+       /* skip header wrb */
        queue_tail_inc(txq);
 
-       while (cur_index != last_index) {
+       do {
                cur_index = txq->tail;
                wrb = queue_tail_node(txq);
-               be_dws_le_to_cpu(wrb, sizeof(*wrb));
-               busaddr = ((u64)wrb->frag_pa_hi << 32) | (u64)wrb->frag_pa_lo;
-               if (busaddr != 0) {
-                       pci_unmap_page(adapter->pdev, busaddr,
-                                      wrb->frag_len, PCI_DMA_TODEVICE);
-               }
+               unmap_tx_frag(adapter->pdev, wrb, (unmap_skb_hdr &&
+                                       sent_skb->len > sent_skb->data_len));
+               unmap_skb_hdr = false;
+
                num_wrbs++;
                queue_tail_inc(txq);
-       }
+       } while (cur_index != last_index);
 
        atomic_sub(num_wrbs, &txq->used);