be2net: fix unmap_single/page() called incorrectly in Tx compl processing

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>
This commit is contained in:
Sathya Perla 2010-03-22 20:41:34 +00:00 committed by David S. Miller
parent 7101e11121
commit ec43b1a64a
1 changed files with 12 additions and 21 deletions

View File

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