lkml.org 
[lkml]   [2009]   [Feb]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patches in this message
/
Date
SubjectRe: [PATCH 08/16] dma-debug: add core checking functions
From
On Thu, Feb 12, 2009 at 6:49 AM, Joerg Roedel <joro@8bytes.org> wrote:
> On Thu, Feb 05, 2009 at 09:07:59PM +0000, David Woodhouse wrote:
>> On Mon, 2009-01-19 at 15:46 +0100, Joerg Roedel wrote:
>> >
>> > + if (ref->type != entry->type) {
>> > + err_printk(ref->dev, "DMA-API: device driver frees "
>> > + "DMA memory with wrong function "
>> > + "[device address=0x%016llx] [size=%llu bytes] "
>> > + "[mapped as %s] [unmapped as %s]\n",
>> > + ref->dev_addr, ref->size,
>> > + type2name[entry->type], type2name[ref->type]);
>>
>> e1000e 0000:00:19.0: DMA-API: device driver frees DMA memory with wrong
>> function [device address=0x00000000ffedc002] [size=90 bytes] [mapped as
>> single] [unmapped as page]
>>
>>
>> <davem> That debug check is excessive, substituting those two things
>> works for every DMA API implementation I am aware of
>
> True. Buts it is an API violation, isn't it?

I have a fix for this, for both e1000 and e1000e, the patches are not
(deeply) tested and are RFC right now.
Both e1000e patches must be applied for the actual bug fix to apply cleanly
01 - e1000e_remove_old_workarounds
02 - e1000e_fix_dma_unmap

Jesse
e1000e: remove old hardware workarounds

From: Jesse Brandeburg <jesse.brandeburg@intel.com>

e1000e is including some workarounds for old hardware that
are not necessary on PCIe and newer devices.

drop the sentinel descriptor workarounds

Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
CC: Bruce Allan <bruce.w.allan@intel.com>
---
drivers/net/e1000e/netdev.c | 9 ---------
1 files changed, 0 insertions(+), 9 deletions(-)

diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 91817d0..ef8d2c5 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -3842,11 +3842,6 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
buffer_info = &tx_ring->buffer_info[i];
size = min(len, max_per_txd);

- /* Workaround for premature desc write-backs
- * in TSO mode. Append 4-byte sentinel desc */
- if (mss && !nr_frags && size == len && size > 8)
- size -= 4;
-
buffer_info->length = size;
/* set time_stamp *before* dma to help avoid a possible race */
buffer_info->time_stamp = jiffies;
@@ -3880,10 +3875,6 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
while (len) {
buffer_info = &tx_ring->buffer_info[i];
size = min(len, max_per_txd);
- /* Workaround for premature desc write-backs
- * in TSO mode. Append 4-byte sentinel desc */
- if (mss && f == (nr_frags-1) && size == len && size > 8)
- size -= 4;

buffer_info->length = size;
buffer_info->time_stamp = jiffies;e1000: fix unmap bug

From: Jesse Brandeburg <jesse.brandeburg@intel.com>

this is in reference to
issue shown in kerneloops (search e1000 unmap)

the e1000 transmit code was calling pci_unmap_page on dma handles
that it might have called pci_map_single on.

same bug as e1000e

Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
---
drivers/net/e1000/e1000_main.c | 45 +++++++++++++++++++---------------------
1 files changed, 21 insertions(+), 24 deletions(-)

diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index c986978..4a2692c 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -2056,14 +2056,10 @@ void e1000_free_all_tx_resources(struct e1000_adapter *adapter)
static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
struct e1000_buffer *buffer_info)
{
- if (buffer_info->dma) {
- pci_unmap_page(adapter->pdev,
- buffer_info->dma,
- buffer_info->length,
- PCI_DMA_TODEVICE);
- buffer_info->dma = 0;
- }
+ buffer_info->dma = 0;
if (buffer_info->skb) {
+ skb_dma_unmap(&adapter->pdev->dev, buffer_info->skb,
+ DMA_TO_DEVICE);
dev_kfree_skb_any(buffer_info->skb);
buffer_info->skb = NULL;
}
@@ -2914,16 +2910,24 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
unsigned int mss)
{
struct e1000_hw *hw = &adapter->hw;
- struct e1000_buffer *buffer_info;
- unsigned int len = skb->len;
- unsigned int offset = 0, size, count = 0, i;
+ unsigned int len = skb_headlen(skb);
+ unsigned int offset, size, count = 0, i;
unsigned int f;
- len -= skb->data_len;
+ 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");
+ dev_kfree_skb(skb);
+ return -2;
+ }
+
+ map = skb_shinfo(skb)->dma_maps[0];
+ offset = 0;
+
while (len) {
- buffer_info = &tx_ring->buffer_info[i];
+ struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i];
size = min(len, max_per_txd);
/* Workaround for Controller erratum --
* descriptor for non-tso packet in a linear SKB that follows a
@@ -2956,11 +2960,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
size -= 4;

buffer_info->length = size;
- buffer_info->dma =
- pci_map_single(adapter->pdev,
- skb->data + offset,
- size,
- PCI_DMA_TODEVICE);
+ buffer_info->dma = map + offset;
buffer_info->time_stamp = jiffies;
buffer_info->next_to_watch = i;

@@ -2975,9 +2975,11 @@ static int e1000_tx_map(struct e1000_adapter *adapter,

frag = &skb_shinfo(skb)->frags[f];
len = frag->size;
- offset = frag->page_offset;
+ map = skb_shinfo(skb)->dma_maps[f + 1];
+ offset = 0;

while (len) {
+ struct e1000_buffer *buffer_info;
buffer_info = &tx_ring->buffer_info[i];
size = min(len, max_per_txd);
/* Workaround for premature desc write-backs
@@ -2993,12 +2995,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
size -= 4;

buffer_info->length = size;
- buffer_info->dma =
- pci_map_page(adapter->pdev,
- frag->page,
- offset,
- size,
- PCI_DMA_TODEVICE);
+ buffer_info->dma = map + offset;
buffer_info->time_stamp = jiffies;
buffer_info->next_to_watch = i;
e1000e: fix unmap bug

From: Jesse Brandeburg <jesse.brandeburg@intel.com>

this is in reference to
https://bugzilla.redhat.com/show_bug.cgi?id=484494
also addresses issue shown in kerneloops

the e1000e transmit code was calling pci_unmap_page on dma handles
that it might have called pci_map_single on.

Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
---
drivers/net/e1000e/netdev.c | 56 +++++++++++++++++--------------------------
1 files changed, 22 insertions(+), 34 deletions(-)

diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index ef8d2c5..7ef8519 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -565,12 +565,10 @@ next_desc:
static void e1000_put_txbuf(struct e1000_adapter *adapter,
struct e1000_buffer *buffer_info)
{
- if (buffer_info->dma) {
- pci_unmap_page(adapter->pdev, buffer_info->dma,
- buffer_info->length, PCI_DMA_TODEVICE);
- buffer_info->dma = 0;
- }
+ buffer_info->dma = 0;
if (buffer_info->skb) {
+ skb_dma_unmap(&adapter->pdev->dev, buffer_info->skb,
+ DMA_TO_DEVICE);
dev_kfree_skb_any(buffer_info->skb);
buffer_info->skb = NULL;
}
@@ -3831,30 +3829,31 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
unsigned int mss)
{
struct e1000_ring *tx_ring = adapter->tx_ring;
- struct e1000_buffer *buffer_info;
- unsigned int len = skb->len - skb->data_len;
- unsigned int offset = 0, size, count = 0, i;
+ unsigned int len = skb_headlen(skb);
+ unsigned int offset, size, count = 0, i;
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");
+ adapter->tx_dma_failed++;
+ dev_kfree_skb(skb);
+ return -2;
+ }
+
+ map = skb_shinfo(skb)->dma_maps[0];
+ offset = 0;
+
while (len) {
- buffer_info = &tx_ring->buffer_info[i];
+ struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i];
size = min(len, max_per_txd);

buffer_info->length = size;
/* set time_stamp *before* dma to help avoid a possible race */
buffer_info->time_stamp = jiffies;
- buffer_info->dma =
- pci_map_single(adapter->pdev,
- skb->data + offset,
- size,
- PCI_DMA_TODEVICE);
- if (pci_dma_mapping_error(adapter->pdev, buffer_info->dma)) {
- dev_err(&adapter->pdev->dev, "TX DMA map failed\n");
- adapter->tx_dma_failed++;
- return -1;
- }
+ buffer_info->dma = map + offset;
buffer_info->next_to_watch = i;

len -= size;
@@ -3870,28 +3869,17 @@ static int e1000_tx_map(struct e1000_adapter *adapter,

frag = &skb_shinfo(skb)->frags[f];
len = frag->size;
- offset = frag->page_offset;
+ map = skb_shinfo(skb)->dma_maps[f + 1];
+ offset = 0;

while (len) {
+ struct e1000_buffer *buffer_info;
buffer_info = &tx_ring->buffer_info[i];
size = min(len, max_per_txd);

buffer_info->length = size;
buffer_info->time_stamp = jiffies;
- buffer_info->dma =
- pci_map_page(adapter->pdev,
- frag->page,
- offset,
- size,
- PCI_DMA_TODEVICE);
- if (pci_dma_mapping_error(adapter->pdev,
- buffer_info->dma)) {
- dev_err(&adapter->pdev->dev,
- "TX DMA page map failed\n");
- adapter->tx_dma_failed++;
- return -1;
- }
-
+ buffer_info->dma = map + offset;
buffer_info->next_to_watch = i;

len -= size;
\
 
 \ /
  Last update: 2009-02-13 20:51    [from the cache]
©2003-2011 Jasper Spaans