Skip to content

Commit

Permalink
ixgbe: remove skb_dma_map/unmap calls from driver
Browse files Browse the repository at this point in the history
This patch removes skb_dma_map/unmap calls from the ixgbe driver due to the
fact that the calls don't work with HW IOMMU enabled systems.  The problem
is that multiple mappings will give different results when HW IOMMU is
enabled and the skb_dma_map/unmap calls only have one location to store
mappings.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Acked-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Alexander Duyck authored and David S. Miller committed Dec 3, 2009
1 parent adeaa90 commit e5a4354
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 14 deletions.
1 change: 1 addition & 0 deletions drivers/net/ixgbe/ixgbe.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ struct ixgbe_tx_buffer {
unsigned long time_stamp;
u16 length;
u16 next_to_watch;
u16 mapped_as_page;
};

struct ixgbe_rx_buffer {
Expand Down
63 changes: 49 additions & 14 deletions drivers/net/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,20 @@ static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter,
struct ixgbe_tx_buffer
*tx_buffer_info)
{
tx_buffer_info->dma = 0;
if (tx_buffer_info->dma) {
if (tx_buffer_info->mapped_as_page)
pci_unmap_page(adapter->pdev,
tx_buffer_info->dma,
tx_buffer_info->length,
PCI_DMA_TODEVICE);
else
pci_unmap_single(adapter->pdev,
tx_buffer_info->dma,
tx_buffer_info->length,
PCI_DMA_TODEVICE);
tx_buffer_info->dma = 0;
}
if (tx_buffer_info->skb) {
skb_dma_unmap(&adapter->pdev->dev, tx_buffer_info->skb,
DMA_TO_DEVICE);
dev_kfree_skb_any(tx_buffer_info->skb);
tx_buffer_info->skb = NULL;
}
Expand Down Expand Up @@ -5024,23 +5034,16 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
struct sk_buff *skb, u32 tx_flags,
unsigned int first)
{
struct pci_dev *pdev = adapter->pdev;
struct ixgbe_tx_buffer *tx_buffer_info;
unsigned int len;
unsigned int total = skb->len;
unsigned int offset = 0, size, count = 0, i;
unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
unsigned int f;
dma_addr_t *map;

i = tx_ring->next_to_use;

if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) {
dev_err(&adapter->pdev->dev, "TX DMA map failed\n");
return 0;
}

map = skb_shinfo(skb)->dma_maps;

if (tx_flags & IXGBE_TX_FLAGS_FCOE)
/* excluding fcoe_crc_eof for FCoE */
total -= sizeof(struct fcoe_crc_eof);
Expand All @@ -5051,7 +5054,12 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
size = min(len, (uint)IXGBE_MAX_DATA_PER_TXD);

tx_buffer_info->length = size;
tx_buffer_info->dma = skb_shinfo(skb)->dma_head + offset;
tx_buffer_info->mapped_as_page = false;
tx_buffer_info->dma = pci_map_single(pdev,
skb->data + offset,
size, PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(pdev, tx_buffer_info->dma))
goto dma_error;
tx_buffer_info->time_stamp = jiffies;
tx_buffer_info->next_to_watch = i;

Expand All @@ -5072,7 +5080,7 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter,

frag = &skb_shinfo(skb)->frags[f];
len = min((unsigned int)frag->size, total);
offset = 0;
offset = frag->page_offset;

while (len) {
i++;
Expand All @@ -5083,7 +5091,13 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
size = min(len, (uint)IXGBE_MAX_DATA_PER_TXD);

tx_buffer_info->length = size;
tx_buffer_info->dma = map[f] + offset;
tx_buffer_info->dma = pci_map_page(adapter->pdev,
frag->page,
offset, size,
PCI_DMA_TODEVICE);
tx_buffer_info->mapped_as_page = true;
if (pci_dma_mapping_error(pdev, tx_buffer_info->dma))
goto dma_error;
tx_buffer_info->time_stamp = jiffies;
tx_buffer_info->next_to_watch = i;

Expand All @@ -5099,6 +5113,27 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
tx_ring->tx_buffer_info[i].skb = skb;
tx_ring->tx_buffer_info[first].next_to_watch = i;

return count;

dma_error:
dev_err(&pdev->dev, "TX DMA map failed\n");

/* clear timestamp and dma mappings for failed tx_buffer_info map */
tx_buffer_info->dma = 0;
tx_buffer_info->time_stamp = 0;
tx_buffer_info->next_to_watch = 0;
count--;

/* clear timestamp and dma mappings for remaining portion of packet */
while (count >= 0) {
count--;
i--;
if (i < 0)
i += tx_ring->count;
tx_buffer_info = &tx_ring->tx_buffer_info[i];
ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info);
}

return count;
}

Expand Down

0 comments on commit e5a4354

Please sign in to comment.