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: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-16 14:34 BUG: SCSI aic7xxx driver and AMD IOMMU Mark Hounschell
[not found] ` <54E1FFFA.1060403-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2015-03-03 19:36 ` Mark Hounschell
2015-03-03 19:36 ` Mark Hounschell
2015-03-23 15:03 ` Joerg Roedel
[not found] ` <20150323150304.GQ4441-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2015-03-24 11:57 ` Mark Hounschell
2015-03-24 11:57 ` Mark Hounschell
2015-03-25 13:59 ` Joerg Roedel
[not found] ` <20150325135937.GR4441-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2015-03-25 15:13 ` Joerg Roedel
2015-03-25 15:13 ` Joerg Roedel
2015-03-25 16:36 ` Mark Hounschell
[not found] ` <5512E412.9040807-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2015-03-26 12:45 ` Joerg Roedel
2015-03-26 12:45 ` Joerg Roedel
2015-03-26 14:58 ` Mark Hounschell [this message]
2015-03-26 15:52 ` Joerg Roedel
[not found] ` <20150326155248.GW4441-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2015-03-26 17:09 ` Mark Hounschell
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.