From: Mark Hounschell <markh@compro.net>
To: Joerg Roedel <joro@8bytes.org>
Cc: iommu@lists.linux-foundation.org, Hannes Reinecke <hare@suse.de>,
"linux-scsi@vger.kernel.org >> SCSI development list"
<linux-scsi@vger.kernel.org>,
linux-kernel@vger.kernel.org
Subject: Re: BUG: SCSI aic7xxx driver and AMD IOMMU
Date: Thu, 26 Mar 2015 10:58:15 -0400 [thread overview]
Message-ID: <55141E87.8040506@compro.net> (raw)
In-Reply-To: <20150326124559.GV4441@8bytes.org>
Hi Joerg,
On 03/26/2015 08:45 AM, Joerg Roedel wrote:
> On Wed, Mar 25, 2015 at 12:36:34PM -0400, Mark Hounschell wrote:
>> BTW, so far the first 2 patches are working well. I was going to
>> wait until the end of the day to report but so far I have been
>> unable to produce the problems I was seeing. And I am in the middle
>> of some driver work so lots of unloading/loading going on.
>
> Great, thanks. Please let me know when you have test results for the
> other patches too.
>
>
> Joerg
Sorry but CMA was still badly broken. I have a patch below that works.
I've tested it with small (no CMA) and large (with CMA) dma's using
dma_alloc_coherent. The patch below is just the "git diff" from your
cloned tree piped to a file then copied into this email. If you require
an official patch I can send one. Just let me know.
Also, in my opinion, this CMA thing is clearly a BUG not a feature
request. The AMD iommu clearly breaks CMA. I feel what ever fix
you are happy with should be back ported to stable.
Regards
Mark
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index a0197d0..5ea4fed 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2917,28 +2917,36 @@ static void *alloc_coherent(struct device *dev, size_t size,
u64 dma_mask = dev->coherent_dma_mask;
struct protection_domain *domain;
unsigned long flags;
- struct page *page;
+ struct page *page = 0;
+ int order;
+ unsigned int count;
+
+ size = PAGE_ALIGN(size);
+ order = get_order(size);
+ count = size >> PAGE_SHIFT;
INC_STATS_COUNTER(cnt_alloc_coherent);
domain = get_domain(dev);
if (PTR_ERR(domain) == -EINVAL) {
- page = alloc_pages(flag, get_order(size));
+ page = alloc_pages(flag, order);
*dma_addr = page_to_phys(page);
return page_address(page);
} else if (IS_ERR(domain))
return NULL;
- dma_mask = dev->coherent_dma_mask;
flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
+ flag |= __GFP_ZERO;
- page = alloc_pages(flag, get_order(size));
+ if (flag & __GFP_WAIT) {
+ page = dma_alloc_from_contiguous(dev, count, order);
+ if (page && page_to_phys(page) + size > dma_mask) {
+ dma_release_from_contiguous(dev, page, count);
+ page = NULL;
+ }
+ }
if (!page) {
- if (!(flag & __GFP_WAIT))
- return NULL;
-
- page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
- get_order(size));
+ page = alloc_pages(flag, order);
if (!page)
return NULL;
}
@@ -2951,7 +2959,7 @@ static void *alloc_coherent(struct device *dev, size_t size,
*dma_addr = __map_single(dev, domain->priv, page_to_phys(page),
size, DMA_BIDIRECTIONAL, true, dma_mask);
- if (*dma_addr == DMA_ERROR_CODE) {
+ if (!dma_addr || (*dma_addr == DMA_ERROR_CODE)) {
spin_unlock_irqrestore(&domain->lock, flags);
goto out_free;
}
@@ -2965,7 +2973,7 @@ static void *alloc_coherent(struct device *dev, size_t size,
out_free:
if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
- __free_pages(page, get_order(size));
+ __free_pages(page, order);
return NULL;
}
@@ -2979,6 +2987,11 @@ static void free_coherent(struct device *dev, size_t size,
{
unsigned long flags;
struct protection_domain *domain;
+ int order;
+ struct page *page = virt_to_page(virt_addr);
+
+ size = PAGE_ALIGN(size);
+ order = get_order(size);
INC_STATS_COUNTER(cnt_free_coherent);
@@ -2995,7 +3008,9 @@ static void free_coherent(struct device *dev, size_t size,
spin_unlock_irqrestore(&domain->lock, flags);
free_mem:
- free_pages((unsigned long)virt_addr, get_order(size));
+ if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
+ __free_pages(page, order);
+
}
/*
next prev parent reply other threads:[~2015-03-26 14:58 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-16 14:34 BUG: SCSI aic7xxx driver and AMD IOMMU Mark Hounschell
2015-03-03 19:36 ` Mark Hounschell
2015-03-23 15:03 ` Joerg Roedel
2015-03-24 11:57 ` Mark Hounschell
2015-03-25 13:59 ` Joerg Roedel
2015-03-25 15:13 ` Joerg Roedel
2015-03-25 16:36 ` Mark Hounschell
2015-03-26 12:45 ` Joerg Roedel
2015-03-26 14:58 ` Mark Hounschell [this message]
2015-03-26 15:52 ` Joerg Roedel
2015-03-26 17:09 ` Mark Hounschell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=55141E87.8040506@compro.net \
--to=markh@compro.net \
--cc=hare@suse.de \
--cc=iommu@lists.linux-foundation.org \
--cc=joro@8bytes.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).