iommu/tegra: gart: Couple corrections
Subsystems (3)
cover iommu/tegra: gart: Couple corrections
I've added an experimental support of the GART to the Tegra DRM driver and it ended up with a very positive result. During the testing of the GART driver I've noticed couple of its minor shortcomings, so here the patches to remedy them.
Dmitry Osipenko (4):
iommu/tegra: gart: Don't unnecessarily allocate registers context iommu/tegra: gart: Check whether page is already mapped iommu/tegra: gart: Move PFN validation out of spinlock iommu/tegra: gart: Correct number of unmapped bytes
drivers/iommu/tegra-gart.c | 49 +++++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 14 deletions(-)
Signature · 1 line
2.13.2
A message that is not in the archive (sent off-list or not yet received): cover.1499270277.git.digetx-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
PATCH 1/4 iommu/tegra: gart: Don't unnecessarily allocate registers context
GART looses it's state only in case of a deepest suspend level. Let's not waste memory if machine doesn't support that suspend level.
--- drivers/iommu/tegra-gart.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-)
drivers/iommu/tegra-gart.c +25 -11
@@ -31,6 +31,8 @@#include <linux/iommu.h> #include <linux/of.h> +#include <soc/tegra/pmc.h> +#include <asm/cacheflush.h> /* bitmap of the page sizes currently supported */
@@ -354,10 +356,13 @@ static int tegra_gart_suspend(struct device *dev)u32 *data = gart->savedata;unsigned long flags; -spin_lock_irqsave (&gart->pte_lock, flags); -for_each_gart_pte (gart, iova) - *(data++) =gart_read_pte (gart, iova); -spin_unlock_irqrestore (&gart->pte_lock, flags); +if (gart->savedata !=NULL ) { +spin_lock_irqsave (&gart->pte_lock, flags); +for_each_gart_pte (gart, iova) + *(data++) =gart_read_pte (gart, iova); +spin_unlock_irqrestore (&gart->pte_lock, flags); + } +return 0 ; }
@@ -366,9 +371,12 @@ static int tegra_gart_resume(struct device *dev)struct gart_device *gart =dev_get_drvdata (dev);unsigned long flags; -spin_lock_irqsave (&gart->pte_lock, flags); -do_gart_setup (gart, gart->savedata); -spin_unlock_irqrestore (&gart->pte_lock, flags); +if (gart->savedata !=NULL ) { +spin_lock_irqsave (&gart->pte_lock, flags); +do_gart_setup (gart, gart->savedata); +spin_unlock_irqrestore (&gart->pte_lock, flags); + } +return 0 ; }
@@ -412,10 +420,16 @@ static int tegra_gart_probe(struct platform_device *pdev) gart->iovmm_base = (dma_addr_t )res_remap->start; gart->page_count = (resource_size (res_remap) >>GART_PAGE_SHIFT ); - gart->savedata =vmalloc (sizeof (u32) * gart->page_count); -if (!gart->savedata) { -dev_err (dev,"failed to allocate context save area\n" ); -return -ENOMEM ; +/* +* The registers store/restore is required only in case of a +* deepest sleep state, do not waste memory if it's unnecessary. +*/ +if (tegra_pmc_get_suspend_mode () ==TEGRA_SUSPEND_LP0 ) { + gart->savedata =vmalloc (sizeof (u32) * gart->page_count); +if (!gart->savedata) { +dev_err (dev,"failed to allocate context save area\n" ); +return -ENOMEM ; + } }platform_set_drvdata (pdev, gart);
Signature · 1 line
2.13.2
A message that is not in the archive (sent off-list or not yet received): df570fb6649da6bc3b5f2a68afcb5471e6148269.1499270277.git.digetx-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
Re: [PATCH v1 1/4] iommu/tegra: gart: Don't unnecessarily allocate registers context
Quoted 7 lines · Dmitry Osipenko
GART looses it's state only in case of a deepest suspend level. Let's not waste memory if machine doesn't support that suspend level.
Signed-off-by Dmitry Osipenko <[email protected]>--- drivers/iommu/tegra-gart.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-)
I'm not sure about this. The savedata region uses 32 KiB of memory, which is really not a whole lot.
In addition, the suspend mode can be set in different places during the boot process, some of which fairly late. I'm concerned that this boot order dependency is going to come back to bite us eventually.
Thierry
Re: [PATCH v1 1/4] iommu/tegra: gart: Don't unnecessarily allocate registers context
Quoted 9 lines · Thierry Reding
Quoted 7 lines · Dmitry Osipenko
GART looses it's state only in case of a deepest suspend level. Let's not waste memory if machine doesn't support that suspend level.
Signed-off-by Dmitry Osipenko <[email protected]>--- drivers/iommu/tegra-gart.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-)
Quoted 7 lines
I'm not sure about this. The savedata region uses 32 KiB of memory, which is really not a whole lot.
In addition, the suspend mode can be set in different places during the boot process, some of which fairly late. I'm concerned that this boot order dependency is going to come back to bite us eventually.
Indeed, suspend mode is set after drivers been probed, my bad.
On the other hand LP0 support haven't been implemented for years, some of drivers do not implement suspend/resume. So maybe it's worth to give up on LP0 entirely...
Signature · 1 line
Dmitry
PATCH 2/4 iommu/tegra: gart: Check whether page is already mapped
In reply to a message not in the archiveDue to a bug, multiple devices may try to map the same IOVA region. We can catch that case by checking that 'VALID' bit of the GART's page entry is unset prior to mapping of the page.
--- drivers/iommu/tegra-gart.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/iommu/tegra-gart.c +7 -0
@@ -271,6 +271,7 @@ static int gart_iommu_map(struct iommu_domain *domain, unsigned long iova,struct gart_device *gart = gart_domain->gart;unsigned long flags;unsigned long pfn; +unsigned long pte;if (!gart_iova_range_valid (gart, iova, bytes))return -EINVAL ;
@@ -282,6 +283,12 @@ static int gart_iommu_map(struct iommu_domain *domain, unsigned long iova,spin_unlock_irqrestore (&gart->pte_lock, flags);return -EINVAL ; } + pte =gart_read_pte (gart, iova); +if (pte &GART_ENTRY_PHYS_ADDR_VALID ) { +spin_unlock_irqrestore (&gart->pte_lock, flags); +dev_err (gart->dev,"Page entry is used already\n" ); +return -EBUSY ; + }gart_set_pte (gart, iova,GART_PTE (pfn));FLUSH_GART_REGS (gart);spin_unlock_irqrestore (&gart->pte_lock, flags);
Signature · 1 line
2.13.2
A message that is not in the archive (sent off-list or not yet received): a19ba1ca835aa2526d2c0492e6b0d0b35889596a.1499270277.git.digetx-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
Re: [PATCH v1 2/4] iommu/tegra: gart: Check whether page is already mapped
Quoted 3 lines · Dmitry Osipenko
Due to a bug, multiple devices may try to map the same IOVA region. We can catch that case by checking that 'VALID' bit of the GART's page entry is unset prior to mapping of the page.
Due to what bug? Sounds to me like access to the GART should be exclusive, so that only a single driver can ever access it.
Thierry
Re: [PATCH v1 2/4] iommu/tegra: gart: Check whether page is already mapped
Quoted 8 lines · Thierry Reding
Quoted 3 lines · Dmitry Osipenko
Due to a bug, multiple devices may try to map the same IOVA region. We can catch that case by checking that 'VALID' bit of the GART's page entry is unset prior to mapping of the page.
Due to what bug? Sounds to me like access to the GART should be exclusive, so that only a single driver can ever access it.
Actually, there are a lot of peripherals behind the GART. But yes, probably we would use it exclusively for the GPU allocations.
In a case of the GPU allocations there could be a bug in the allocation code (drm_mm_scan) that would cause re-mapping of the already mapped pages, we would be able to catch such a bug.
Signature · 1 line
Dmitry
A message that is not in the archive (sent off-list or not yet received): e59eb818-4edf-f3a2-947a-bc21507b0b85-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
Re: [PATCH v1 2/4] iommu/tegra: gart: Check whether page is already mapped
Quoted 10 lines · Dmitry Osipenko
Quoted 8 lines · Thierry Reding
Quoted 3 lines · Dmitry Osipenko
Due to a bug, multiple devices may try to map the same IOVA region. We can catch that case by checking that 'VALID' bit of the GART's page entry is unset prior to mapping of the page.
Due to what bug? Sounds to me like access to the GART should be exclusive, so that only a single driver can ever access it.
Quoted 6 lines
Actually, there are a lot of peripherals behind the GART. But yes, probably we would use it exclusively for the GPU allocations.
In a case of the GPU allocations there could be a bug in the allocation code (
drm_mm_scan) that would cause re-mapping of the already mapped pages, we would be able to catch such a bug.
Sounds to me like something that should be opt-in. Given that we could potentially map a lot of memory, the additional read seems like it could incur a significant performance penalty.
How about protecting this by some Kconfig symbol (or debug module parameter) and adding a WARN instead of failing the mapping operation?
The reason is that we really should be using the GART from a single driver because it is a shared memory region. To avoid drivers from treading on each others' feet the allocations must be managed by some central entity. So either something like DMA API should manage it, or we hardwire it to Tegra DRM explicitly.
And if a central allocator is responsible for all mappings through the GART, then we should assume that it isn't buggy, and therefore the extra check of the PTEs should not be needed in most cases, hence we can get a performance boost by disabling the check by default.
Of course if there is not much performance impact, maybe it is okay to keep it always enabled.
Thierry
Re: [PATCH v1 2/4] iommu/tegra: gart: Check whether page is already mapped
Quoted 31 lines · Thierry Reding
Quoted 10 lines · Dmitry Osipenko
Quoted 8 lines · Thierry Reding
Quoted 3 lines · Dmitry Osipenko
Due to a bug, multiple devices may try to map the same IOVA region. We can catch that case by checking that 'VALID' bit of the GART's page entry is unset prior to mapping of the page.
Due to what bug? Sounds to me like access to the GART should be exclusive, so that only a single driver can ever access it.
Quoted 6 lines
Actually, there are a lot of peripherals behind the GART. But yes, probably we would use it exclusively for the GPU allocations.
In a case of the GPU allocations there could be a bug in the allocation code (
drm_mm_scan) that would cause re-mapping of the already mapped pages, we would be able to catch such a bug.Sounds to me like something that should be opt-in. Given that we could potentially map a lot of memory, the additional read seems like it could incur a significant performance penalty.
How about protecting this by some
Kconfigsymbol (or debug module parameter) and adding a WARN instead of failing the mapping operation?The reason is that we really should be using the GART from a single driver because it is a shared memory region. To avoid drivers from treading on each others' feet the allocations must be managed by some central entity. So either something like DMA API should manage it, or we hardwire it to Tegra DRM explicitly.
Quoted 8 lines
And if a central allocator is responsible for all mappings through the GART, then we should assume that it isn't buggy, and therefore the extra check of the PTEs should not be needed in most cases, hence we can get a performance boost by disabling the check by default.
Of course if there is not much performance impact, maybe it is okay to keep it always enabled.
I had a similar thought about making this checking and the "proper" unmapping optional, but decided that it is not very worthy to implement it now because caching of mappings helps to get rid of all IOVA expenses. The "checking" is nearly "free" in terms of performance, it's the unmapping that causes measurable performance impact. Maybe the improper unmapping was made intentionally for better performance.
Given that you've made suggestion to make the checking optional, I'm going to update this patchset, adding a new "debug" Kconfig option.
Signature · 1 line
Dmitry
PATCH 3/4 iommu/tegra: gart: Move PFN validation out of spinlock
In reply to a message not in the archiveValidation of page frame number doesn't require protection with a spinlock, let's move it out of spinlock for consistency.
--- drivers/iommu/tegra-gart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/iommu/tegra-gart.c +2 -2
@@ -276,13 +276,13 @@ static int gart_iommu_map(struct iommu_domain *domain, unsigned long iova,if (!gart_iova_range_valid (gart, iova, bytes))return -EINVAL ; -spin_lock_irqsave (&gart->pte_lock, flags); pfn =__phys_to_pfn (pa);if (!pfn_valid (pfn)) {dev_err (gart->dev,"Invalid page: %pa\n" , &pa); -spin_unlock_irqrestore (&gart->pte_lock, flags);return -EINVAL ; } + +spin_lock_irqsave (&gart->pte_lock, flags); pte =gart_read_pte (gart, iova);if (pte &GART_ENTRY_PHYS_ADDR_VALID ) {spin_unlock_irqrestore (&gart->pte_lock, flags);
Signature · 1 line
2.13.2
A message that is not in the archive (sent off-list or not yet received): 301b5e91fae43beae4542e8c4a7d5ca6a6918ba0.1499270277.git.digetx-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
Thierry Reding
Acked-byRe: [PATCH v1 3/4] iommu/tegra: gart: Move PFN validation out of spinlock
Quoted 7 lines · Dmitry Osipenko
Validation of page frame number doesn't require protection with a spinlock, let's move it out of spinlock for consistency.
Signed-off-by Dmitry Osipenko <[email protected]>--- drivers/iommu/tegra-gart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
PATCH 4/4 iommu/tegra: gart: Correct number of unmapped bytes
In reply to a message not in the archiveThe iommu_unmap() treats zero bytes number returned by an IOMMU driver as an indicator that unmapping should be stopped. As a result, GART driver unmaps only the first page entry of the whole range, which is incorrect.
--- drivers/iommu/tegra-gart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iommu/tegra-gart.c +1 -1
@@ -309,7 +309,7 @@ static size_t gart_iommu_unmap(struct iommu_domain *domain, unsigned long iova,gart_set_pte (gart, iova,0 );FLUSH_GART_REGS (gart);spin_unlock_irqrestore (&gart->pte_lock, flags); -return 0 ; +return bytes; } static phys_addr_t gart_iommu_iova_to_phys(struct iommu_domain *domain,
Signature · 1 line
2.13.2
A message that is not in the archive (sent off-list or not yet received): f30500403195b029ee236fff3b3c6f0b4dc60cbb.1499270277.git.digetx-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
Thierry Reding
Acked-byRe: [PATCH v1 4/4] iommu/tegra: gart: Correct number of unmapped bytes
Quoted 8 lines · Dmitry Osipenko
The
iommu_unmap()treats zero bytes number returned by an IOMMU driver as an indicator that unmapping should be stopped. As a result, GART driver unmaps only the first page entry of the whole range, which is incorrect.Signed-off-by Dmitry Osipenko <[email protected]>--- drivers/iommu/tegra-gart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Is this perhaps the bug that you were referring to in an earlier patch? Looks to me like you'd run into that bug everytime you try mapping an IOVA that wasn't properly unmapped before.
Anyway, this looks like the right thing to do:
Quoted 10 lines · Dmitry Osipenko
I've added an experimental support of the GART to the Tegra DRM driver and it ended up with a very positive result. During the testing of the GART driver I've noticed couple of its minor shortcomings, so here the patches to remedy them.
Dmitry Osipenko (4):
iommu/tegra: gart: Don't unnecessarily allocate registers context iommu/tegra: gart: Check whether page is already mapped iommu/tegra: gart: Move PFN validation out of spinlock iommu/tegra: gart: Correct number of unmapped bytes
Patches look good to me (except patch 1, which I am not sure about, but maybe only due my limited knowledge about the hardware).
So I take them when Thierry gives his Acked-by.
Joerg
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 12 lines · Joerg Roedel
Quoted 10 lines · Dmitry Osipenko
I've added an experimental support of the GART to the Tegra DRM driver and it ended up with a very positive result. During the testing of the GART driver I've noticed couple of its minor shortcomings, so here the patches to remedy them.
Dmitry Osipenko (4):
iommu/tegra: gart: Don't unnecessarily allocate registers context iommu/tegra: gart: Check whether page is already mapped iommu/tegra: gart: Move PFN validation out of spinlock iommu/tegra: gart: Correct number of unmapped bytes
Quoted 5 lines
Patches look good to me (except patch 1, which I am not sure about, but maybe only due my limited knowledge about the hardware).
So I take them when Thierry gives his Acked-by.
Okay, Thierry should get to this patchset eventually.
Signature · 1 line
Dmitry
A message that is not in the archive (sent off-list or not yet received): 430af3ab-29cd-bbe8-087d-82d8113d2a89-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
Quoted 13 lines · Dmitry Osipenko
Quoted 12 lines · Joerg Roedel
Quoted 10 lines · Dmitry Osipenko
I've added an experimental support of the GART to the Tegra DRM driver and it ended up with a very positive result. During the testing of the GART driver I've noticed couple of its minor shortcomings, so here the patches to remedy them.
Dmitry Osipenko (4):
iommu/tegra: gart: Don't unnecessarily allocate registers context iommu/tegra: gart: Check whether page is already mapped iommu/tegra: gart: Move PFN validation out of spinlock iommu/tegra: gart: Correct number of unmapped bytes
Quoted 8 lines
Quoted 5 lines
Patches look good to me (except patch 1, which I am not sure about, but maybe only due my limited knowledge about the hardware).
So I take them when Thierry gives his Acked-by.
Okay, Thierry should get to this patchset eventually.
BTW, looks like Hiroshi isn't in NVIDIA anymore, his email address isn't valid. Probably somebody else should take over maintaining of the affected Tegra drivers.
Signature · 1 line
Dmitry