From: Arnd Bergmann <arnd@arndb.de>
To: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: linux-arm-kernel@lists.infradead.org,
linux-samsung-soc@vger.kernel.org, linux-media@vger.kernel.org,
Kyungmin Park <kyungmin.park@samsung.com>,
Andrzej Pietrasiwiecz <andrzej.p@samsung.com>,
Sylwester Nawrocki <s.nawrocki@samsung.com>,
Kukjin Kim <kgene.kim@samsung.com>
Subject: Re: [PATCH 2/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
Date: Mon, 18 Apr 2011 16:12:35 +0200 [thread overview]
Message-ID: <201104181612.35833.arnd@arndb.de> (raw)
In-Reply-To: <1303118804-5575-3-git-send-email-m.szyprowski@samsung.com>
On Monday 18 April 2011, Marek Szyprowski wrote:
> From: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
>
> This patch performs a complete rewrite of sysmmu driver for Samsung platform:
> - simplified the resource management: no more single platform
> device with 32 resources is needed, better fits into linux driver model,
> each sysmmu instance has it's own resource definition
> - the new version uses kernel wide common iommu api defined in include/iommu.h
> - cleaned support for sysmmu clocks
> - added support for custom fault handlers and tlb replacement policy
Looks like good progress, but I fear that there is still quite a bit more
work needed here.
> +static int debug;
> +module_param(debug, int, 0644);
> +
> +#define sysmmu_debug(level, fmt, arg...) \
> + do { \
> + if (debug >= level) \
> + printk(KERN_DEBUG "[%s] " fmt, __func__, ## arg);\
> + } while (0)
Just use dev_dbg() here, the kernel already has all the infrastructure.
> +
> +#define generic_extract(l, s, entry) \
> + ((entry) & l##LPT_##s##_MASK)
> +#define flpt_get_1m(entry) generic_extract(F, 1M, deref_va(entry))
> +#define flpt_get_16m(entry) generic_extract(F, 16M, deref_va(entry))
> +#define slpt_get_4k(entry) generic_extract(S, 4K, deref_va(entry))
> +#define slpt_get_64k(entry) generic_extract(S, 64K, deref_va(entry))
> +
> +#define generic_entry(l, s, entry) \
> + (generic_extract(l, s, entry) | PAGE_##s)
> +#define flpt_ent_4k_64k(entry) generic_entry(F, 4K_64K, entry)
> +#define flpt_ent_1m(entry) generic_entry(F, 1M, entry)
> +#define flpt_ent_16m(entry) generic_entry(F, 16M, entry)
> +#define slpt_ent_4k(entry) generic_entry(S, 4K, entry)
> +#define slpt_ent_64k(entry) generic_entry(S, 64K, entry)
> +
> +#define page_4k_64k(entry) (deref_va(entry) & PAGE_4K_64K)
> +#define page_1m(entry) (deref_va(entry) & PAGE_1M)
> +#define page_16m(entry) ((deref_va(entry) & PAGE_16M) == PAGE_16M)
> +#define page_4k(entry) (deref_va(entry) & PAGE_4K)
> +#define page_64k(entry) (deref_va(entry) & PAGE_64K)
> +
> +#define generic_pg_offs(l, s, va) \
> + (va & ~l##LPT_##s##_MASK)
> +#define pg_offs_1m(va) generic_pg_offs(F, 1M, va)
> +#define pg_offs_16m(va) generic_pg_offs(F, 16M, va)
> +#define pg_offs_4k(va) generic_pg_offs(S, 4K, va)
> +#define pg_offs_64k(va) generic_pg_offs(S, 64K, va)
> +
> +#define flpt_index(va) (((va) >> FLPT_IDX_SHIFT) & FLPT_IDX_MASK)
> +
> +#define generic_offset(l, va) (((va) >> l##LPT_OFFS_SHIFT) & l##LPT_OFFS_MASK)
> +#define flpt_offs(va) generic_offset(F, va)
> +#define slpt_offs(va) generic_offset(S, va)
> +
> +#define invalidate_slpt_ent(slpt_va) (deref_va(slpt_va) = 0UL)
> +
> +#define get_irq_callb(cb) \
> + (s5p_domain->irq_callb ? \
> + (s5p_domain->irq_callb->cb ? \
> + s5p_domain->irq_callb->cb : \
> + s5p_sysmmu_irq_callb.cb) \
> + : s5p_sysmmu_irq_callb.cb)
These macros are really confusing, especially the ones that implicitly
access variables with a specific name. How about converting them into
inline functions?
> +phys_addr_t s5p_iova_to_phys(struct iommu_domain *domain, unsigned long iova)
This should be static.
> +struct device *s5p_sysmmu_get(enum s5p_sysmmu_ip ip)
> +{
> + struct device *ret = NULL;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&sysmmu_slock, flags);
> + if (sysmmu_table[ip]) {
> + try_module_get(THIS_MODULE);
> + ret = sysmmu_table[ip]->dev;
> + }
> + spin_unlock_irqrestore(&sysmmu_slock, flags);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(s5p_sysmmu_get);
> +
> +void s5p_sysmmu_put(void *dev)
> +{
> + BUG_ON(!dev);
> + module_put(THIS_MODULE);
> +}
> +EXPORT_SYMBOL_GPL(s5p_sysmmu_put);
These look wrong for a number of reasons:
* try_module_get(THIS_MODULE) makes no sense at all, the idea of the
try_module_get is to pin down another module that was calling down,
which I suppose is not needed here.
* This extends the generic IOMMU API in platform specific ways, don't
do that.
* I think you can do without these functions by including a pointer
to the iommu structure in dev_archdata, see
arch/powerpc/include/asm/device.h for an example.
> +void s5p_sysmmu_domain_irq_callb(struct iommu_domain *domain,
> + struct s5p_sysmmu_irq_callb *ops, void *priv)
> +{
> + struct s5p_sysmmu_domain *s5p_domain = domain->priv;
> + s5p_domain->irq_callb = ops;
> + s5p_domain->irq_callb_priv = priv;
> +}
> +EXPORT_SYMBOL(s5p_sysmmu_domain_irq_callb);
> +
> +
> +void s5p_sysmmu_domain_tlb_policy(struct iommu_domain *domain, int policy)
> +{
> + struct s5p_sysmmu_domain *s5p_domain = domain->priv;
> + s5p_domain->policy = policy;
> +}
> +EXPORT_SYMBOL(s5p_sysmmu_domain_tlb_policy);
More private extensions that should not be here. Better extend the generic
IOMMU API to contain callbacks for these if they are required, and document
them in a generic location.
> +static void s5p_sysmmu_irq_page_fault(struct iommu_domain *domain, int reason,
> + unsigned long addr, void *priv)
> +{
> + sysmmu_debug(3, "%s: Faulting virtual address: 0x%08lx\n",
> + irq_reasons[reason], addr);
> + BUG();
> +}
> +
> +static void s5p_sysmmu_irq_generic_callb(struct iommu_domain *domain,
> + int reason, unsigned long addr,
> + void *priv)
> +{
> + sysmmu_debug(3, "%s\n", irq_reasons[reason]);
> + BUG();
> +}
Why BUG() here? The backtrace of an interrupt handler should be rather
uninteresting, and you just end up in panic() since this is run
from an interrupt handler.
> +static struct s5p_sysmmu_irq_callb s5p_sysmmu_irq_callb = {
> + .page_fault = s5p_sysmmu_irq_page_fault,
> + .ar_fault = s5p_sysmmu_irq_generic_callb,
> + .aw_fault = s5p_sysmmu_irq_generic_callb,
> + .bus_error = s5p_sysmmu_irq_generic_callb,
> + .ar_security = s5p_sysmmu_irq_generic_callb,
> + .ar_prot = s5p_sysmmu_irq_generic_callb,
> + .aw_security = s5p_sysmmu_irq_generic_callb,
> + .aw_prot = s5p_sysmmu_irq_generic_callb,
> +};
> +
> +static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id)
> +{
> + struct s5p_sysmmu_info *sysmmu = dev_id;
> + struct s5p_sysmmu_domain *s5p_domain = sysmmu->domain->priv;
> + unsigned int reg_INT_STATUS;
> +
> + if (false == sysmmu->enabled)
> + return IRQ_HANDLED;
> +
> + reg_INT_STATUS = readl(sysmmu->regs + S5P_INT_STATUS);
> + if (reg_INT_STATUS & 0xFF) {
> + S5P_IRQ_CB(cb);
> + enum s5p_sysmmu_fault reason = 0;
> + unsigned long fault = 0;
> + unsigned reg = 0;
> + cb = NULL;
> + switch (reg_INT_STATUS & 0xFF) {
> + case 0x1:
> + cb = get_irq_callb(page_fault);
> + reason = S5P_SYSMMU_PAGE_FAULT;
> + reg = S5P_PAGE_FAULT_ADDR;
> + break;
> + case 0x2:
> + cb = get_irq_callb(ar_fault);
> + reason = S5P_SYSMMU_AR_FAULT;
> + reg = S5P_AR_FAULT_ADDR;
> + break;
> + case 0x4:
> + cb = get_irq_callb(aw_fault);
> + reason = S5P_SYSMMU_AW_FAULT;
> + reg = S5P_AW_FAULT_ADDR;
> + break;
> + case 0x8:
> + cb = get_irq_callb(bus_error);
> + reason = S5P_SYSMMU_BUS_ERROR;
> + /* register common to page fault and bus error */
> + reg = S5P_PAGE_FAULT_ADDR;
> + break;
> + case 0x10:
> + cb = get_irq_callb(ar_security);
> + reason = S5P_SYSMMU_AR_SECURITY;
> + reg = S5P_AR_FAULT_ADDR;
> + break;
> + case 0x20:
> + cb = get_irq_callb(ar_prot);
> + reason = S5P_SYSMMU_AR_PROT;
> + reg = S5P_AR_FAULT_ADDR;
> + break;
> + case 0x40:
> + cb = get_irq_callb(aw_security);
> + reason = S5P_SYSMMU_AW_SECURITY;
> + reg = S5P_AW_FAULT_ADDR;
> + break;
> + case 0x80:
> + cb = get_irq_callb(aw_prot);
> + reason = S5P_SYSMMU_AW_PROT;
> + reg = S5P_AW_FAULT_ADDR;
> + break;
> + }
> + fault = readl(sysmmu->regs + reg);
> + cb(sysmmu->domain, reason, fault, s5p_domain->irq_callb_priv);
> + writel(reg_INT_STATUS, sysmmu->regs + S5P_INT_CLEAR);
> + }
> + return IRQ_HANDLED;
> +}
I think it would be more readable and more efficient to just use a lookup
table here instead of the long switch/case statement.
> +static int
> +s5p_sysmmu_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> + int ret = 0;
> + sysmmu_debug(3, "begin\n");
> +
> + return ret;
> +}
> +
> +static int s5p_sysmmu_resume(struct platform_device *pdev)
> +{
> + int ret = 0;
> + sysmmu_debug(3, "begin\n");
> +
> + return ret;
> +}
> +
> +static int s5p_sysmmu_runtime_suspend(struct device *dev)
> +{
> + sysmmu_debug(3, "begin\n");
> + return 0;
> +}
> +
> +static int s5p_sysmmu_runtime_resume(struct device *dev)
> +{
> + sysmmu_debug(3, "begin\n");
> + return 0;
> +}
Why even provide these when they don't do anything?
> +static int __init
> +s5p_sysmmu_register(void)
> +{
> + int ret;
> +
> + sysmmu_debug(3, "Registering sysmmu driver...\n");
> +
> + slpt_cache = kmem_cache_create("slpt_cache", 1024, 1024,
> + SLAB_HWCACHE_ALIGN, NULL);
> + if (!slpt_cache) {
> + printk(KERN_ERR
> + "%s: failed to allocated slpt cache\n", __func__);
> + return -ENOMEM;
> + }
> +
> + ret = platform_driver_register(&s5p_sysmmu_driver);
> +
> + if (ret) {
> + printk(KERN_ERR
> + "%s: failed to register sysmmu driver\n", __func__);
> + return -EINVAL;
> + }
> +
> + register_iommu(&s5p_sysmmu_ops);
> +
> + return ret;
> +}
When you register the iommu unconditionally, it becomes impossible for
this driver to coexist with other iommu drivers in the same kernel,
which does against the concept of having a platform driver for this.
It might be better to call the s5p_sysmmu_register function from
the board files and have no platform devices at all if each IOMMU
is always bound to a specific device anyway.
> diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
> index f0da6b7..0ae5dd0 100644
> --- a/arch/arm/plat-samsung/include/plat/devs.h
> +++ b/arch/arm/plat-samsung/include/plat/devs.h
> @@ -142,7 +142,7 @@ extern struct platform_device s5p_device_fimc3;
> extern struct platform_device s5p_device_mipi_csis0;
> extern struct platform_device s5p_device_mipi_csis1;
>
> -extern struct platform_device exynos4_device_sysmmu;
> +extern struct platform_device exynos4_device_sysmmu[];
Why is this a global variable? I would expect this to be private to the
implementation.
Arnd
WARNING: multiple messages have this Message-ID (diff)
From: arnd@arndb.de (Arnd Bergmann)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 2/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
Date: Mon, 18 Apr 2011 16:12:35 +0200 [thread overview]
Message-ID: <201104181612.35833.arnd@arndb.de> (raw)
In-Reply-To: <1303118804-5575-3-git-send-email-m.szyprowski@samsung.com>
On Monday 18 April 2011, Marek Szyprowski wrote:
> From: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
>
> This patch performs a complete rewrite of sysmmu driver for Samsung platform:
> - simplified the resource management: no more single platform
> device with 32 resources is needed, better fits into linux driver model,
> each sysmmu instance has it's own resource definition
> - the new version uses kernel wide common iommu api defined in include/iommu.h
> - cleaned support for sysmmu clocks
> - added support for custom fault handlers and tlb replacement policy
Looks like good progress, but I fear that there is still quite a bit more
work needed here.
> +static int debug;
> +module_param(debug, int, 0644);
> +
> +#define sysmmu_debug(level, fmt, arg...) \
> + do { \
> + if (debug >= level) \
> + printk(KERN_DEBUG "[%s] " fmt, __func__, ## arg);\
> + } while (0)
Just use dev_dbg() here, the kernel already has all the infrastructure.
> +
> +#define generic_extract(l, s, entry) \
> + ((entry) & l##LPT_##s##_MASK)
> +#define flpt_get_1m(entry) generic_extract(F, 1M, deref_va(entry))
> +#define flpt_get_16m(entry) generic_extract(F, 16M, deref_va(entry))
> +#define slpt_get_4k(entry) generic_extract(S, 4K, deref_va(entry))
> +#define slpt_get_64k(entry) generic_extract(S, 64K, deref_va(entry))
> +
> +#define generic_entry(l, s, entry) \
> + (generic_extract(l, s, entry) | PAGE_##s)
> +#define flpt_ent_4k_64k(entry) generic_entry(F, 4K_64K, entry)
> +#define flpt_ent_1m(entry) generic_entry(F, 1M, entry)
> +#define flpt_ent_16m(entry) generic_entry(F, 16M, entry)
> +#define slpt_ent_4k(entry) generic_entry(S, 4K, entry)
> +#define slpt_ent_64k(entry) generic_entry(S, 64K, entry)
> +
> +#define page_4k_64k(entry) (deref_va(entry) & PAGE_4K_64K)
> +#define page_1m(entry) (deref_va(entry) & PAGE_1M)
> +#define page_16m(entry) ((deref_va(entry) & PAGE_16M) == PAGE_16M)
> +#define page_4k(entry) (deref_va(entry) & PAGE_4K)
> +#define page_64k(entry) (deref_va(entry) & PAGE_64K)
> +
> +#define generic_pg_offs(l, s, va) \
> + (va & ~l##LPT_##s##_MASK)
> +#define pg_offs_1m(va) generic_pg_offs(F, 1M, va)
> +#define pg_offs_16m(va) generic_pg_offs(F, 16M, va)
> +#define pg_offs_4k(va) generic_pg_offs(S, 4K, va)
> +#define pg_offs_64k(va) generic_pg_offs(S, 64K, va)
> +
> +#define flpt_index(va) (((va) >> FLPT_IDX_SHIFT) & FLPT_IDX_MASK)
> +
> +#define generic_offset(l, va) (((va) >> l##LPT_OFFS_SHIFT) & l##LPT_OFFS_MASK)
> +#define flpt_offs(va) generic_offset(F, va)
> +#define slpt_offs(va) generic_offset(S, va)
> +
> +#define invalidate_slpt_ent(slpt_va) (deref_va(slpt_va) = 0UL)
> +
> +#define get_irq_callb(cb) \
> + (s5p_domain->irq_callb ? \
> + (s5p_domain->irq_callb->cb ? \
> + s5p_domain->irq_callb->cb : \
> + s5p_sysmmu_irq_callb.cb) \
> + : s5p_sysmmu_irq_callb.cb)
These macros are really confusing, especially the ones that implicitly
access variables with a specific name. How about converting them into
inline functions?
> +phys_addr_t s5p_iova_to_phys(struct iommu_domain *domain, unsigned long iova)
This should be static.
> +struct device *s5p_sysmmu_get(enum s5p_sysmmu_ip ip)
> +{
> + struct device *ret = NULL;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&sysmmu_slock, flags);
> + if (sysmmu_table[ip]) {
> + try_module_get(THIS_MODULE);
> + ret = sysmmu_table[ip]->dev;
> + }
> + spin_unlock_irqrestore(&sysmmu_slock, flags);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(s5p_sysmmu_get);
> +
> +void s5p_sysmmu_put(void *dev)
> +{
> + BUG_ON(!dev);
> + module_put(THIS_MODULE);
> +}
> +EXPORT_SYMBOL_GPL(s5p_sysmmu_put);
These look wrong for a number of reasons:
* try_module_get(THIS_MODULE) makes no sense at all, the idea of the
try_module_get is to pin down another module that was calling down,
which I suppose is not needed here.
* This extends the generic IOMMU API in platform specific ways, don't
do that.
* I think you can do without these functions by including a pointer
to the iommu structure in dev_archdata, see
arch/powerpc/include/asm/device.h for an example.
> +void s5p_sysmmu_domain_irq_callb(struct iommu_domain *domain,
> + struct s5p_sysmmu_irq_callb *ops, void *priv)
> +{
> + struct s5p_sysmmu_domain *s5p_domain = domain->priv;
> + s5p_domain->irq_callb = ops;
> + s5p_domain->irq_callb_priv = priv;
> +}
> +EXPORT_SYMBOL(s5p_sysmmu_domain_irq_callb);
> +
> +
> +void s5p_sysmmu_domain_tlb_policy(struct iommu_domain *domain, int policy)
> +{
> + struct s5p_sysmmu_domain *s5p_domain = domain->priv;
> + s5p_domain->policy = policy;
> +}
> +EXPORT_SYMBOL(s5p_sysmmu_domain_tlb_policy);
More private extensions that should not be here. Better extend the generic
IOMMU API to contain callbacks for these if they are required, and document
them in a generic location.
> +static void s5p_sysmmu_irq_page_fault(struct iommu_domain *domain, int reason,
> + unsigned long addr, void *priv)
> +{
> + sysmmu_debug(3, "%s: Faulting virtual address: 0x%08lx\n",
> + irq_reasons[reason], addr);
> + BUG();
> +}
> +
> +static void s5p_sysmmu_irq_generic_callb(struct iommu_domain *domain,
> + int reason, unsigned long addr,
> + void *priv)
> +{
> + sysmmu_debug(3, "%s\n", irq_reasons[reason]);
> + BUG();
> +}
Why BUG() here? The backtrace of an interrupt handler should be rather
uninteresting, and you just end up in panic() since this is run
from an interrupt handler.
> +static struct s5p_sysmmu_irq_callb s5p_sysmmu_irq_callb = {
> + .page_fault = s5p_sysmmu_irq_page_fault,
> + .ar_fault = s5p_sysmmu_irq_generic_callb,
> + .aw_fault = s5p_sysmmu_irq_generic_callb,
> + .bus_error = s5p_sysmmu_irq_generic_callb,
> + .ar_security = s5p_sysmmu_irq_generic_callb,
> + .ar_prot = s5p_sysmmu_irq_generic_callb,
> + .aw_security = s5p_sysmmu_irq_generic_callb,
> + .aw_prot = s5p_sysmmu_irq_generic_callb,
> +};
> +
> +static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id)
> +{
> + struct s5p_sysmmu_info *sysmmu = dev_id;
> + struct s5p_sysmmu_domain *s5p_domain = sysmmu->domain->priv;
> + unsigned int reg_INT_STATUS;
> +
> + if (false == sysmmu->enabled)
> + return IRQ_HANDLED;
> +
> + reg_INT_STATUS = readl(sysmmu->regs + S5P_INT_STATUS);
> + if (reg_INT_STATUS & 0xFF) {
> + S5P_IRQ_CB(cb);
> + enum s5p_sysmmu_fault reason = 0;
> + unsigned long fault = 0;
> + unsigned reg = 0;
> + cb = NULL;
> + switch (reg_INT_STATUS & 0xFF) {
> + case 0x1:
> + cb = get_irq_callb(page_fault);
> + reason = S5P_SYSMMU_PAGE_FAULT;
> + reg = S5P_PAGE_FAULT_ADDR;
> + break;
> + case 0x2:
> + cb = get_irq_callb(ar_fault);
> + reason = S5P_SYSMMU_AR_FAULT;
> + reg = S5P_AR_FAULT_ADDR;
> + break;
> + case 0x4:
> + cb = get_irq_callb(aw_fault);
> + reason = S5P_SYSMMU_AW_FAULT;
> + reg = S5P_AW_FAULT_ADDR;
> + break;
> + case 0x8:
> + cb = get_irq_callb(bus_error);
> + reason = S5P_SYSMMU_BUS_ERROR;
> + /* register common to page fault and bus error */
> + reg = S5P_PAGE_FAULT_ADDR;
> + break;
> + case 0x10:
> + cb = get_irq_callb(ar_security);
> + reason = S5P_SYSMMU_AR_SECURITY;
> + reg = S5P_AR_FAULT_ADDR;
> + break;
> + case 0x20:
> + cb = get_irq_callb(ar_prot);
> + reason = S5P_SYSMMU_AR_PROT;
> + reg = S5P_AR_FAULT_ADDR;
> + break;
> + case 0x40:
> + cb = get_irq_callb(aw_security);
> + reason = S5P_SYSMMU_AW_SECURITY;
> + reg = S5P_AW_FAULT_ADDR;
> + break;
> + case 0x80:
> + cb = get_irq_callb(aw_prot);
> + reason = S5P_SYSMMU_AW_PROT;
> + reg = S5P_AW_FAULT_ADDR;
> + break;
> + }
> + fault = readl(sysmmu->regs + reg);
> + cb(sysmmu->domain, reason, fault, s5p_domain->irq_callb_priv);
> + writel(reg_INT_STATUS, sysmmu->regs + S5P_INT_CLEAR);
> + }
> + return IRQ_HANDLED;
> +}
I think it would be more readable and more efficient to just use a lookup
table here instead of the long switch/case statement.
> +static int
> +s5p_sysmmu_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> + int ret = 0;
> + sysmmu_debug(3, "begin\n");
> +
> + return ret;
> +}
> +
> +static int s5p_sysmmu_resume(struct platform_device *pdev)
> +{
> + int ret = 0;
> + sysmmu_debug(3, "begin\n");
> +
> + return ret;
> +}
> +
> +static int s5p_sysmmu_runtime_suspend(struct device *dev)
> +{
> + sysmmu_debug(3, "begin\n");
> + return 0;
> +}
> +
> +static int s5p_sysmmu_runtime_resume(struct device *dev)
> +{
> + sysmmu_debug(3, "begin\n");
> + return 0;
> +}
Why even provide these when they don't do anything?
> +static int __init
> +s5p_sysmmu_register(void)
> +{
> + int ret;
> +
> + sysmmu_debug(3, "Registering sysmmu driver...\n");
> +
> + slpt_cache = kmem_cache_create("slpt_cache", 1024, 1024,
> + SLAB_HWCACHE_ALIGN, NULL);
> + if (!slpt_cache) {
> + printk(KERN_ERR
> + "%s: failed to allocated slpt cache\n", __func__);
> + return -ENOMEM;
> + }
> +
> + ret = platform_driver_register(&s5p_sysmmu_driver);
> +
> + if (ret) {
> + printk(KERN_ERR
> + "%s: failed to register sysmmu driver\n", __func__);
> + return -EINVAL;
> + }
> +
> + register_iommu(&s5p_sysmmu_ops);
> +
> + return ret;
> +}
When you register the iommu unconditionally, it becomes impossible for
this driver to coexist with other iommu drivers in the same kernel,
which does against the concept of having a platform driver for this.
It might be better to call the s5p_sysmmu_register function from
the board files and have no platform devices at all if each IOMMU
is always bound to a specific device anyway.
> diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
> index f0da6b7..0ae5dd0 100644
> --- a/arch/arm/plat-samsung/include/plat/devs.h
> +++ b/arch/arm/plat-samsung/include/plat/devs.h
> @@ -142,7 +142,7 @@ extern struct platform_device s5p_device_fimc3;
> extern struct platform_device s5p_device_mipi_csis0;
> extern struct platform_device s5p_device_mipi_csis1;
>
> -extern struct platform_device exynos4_device_sysmmu;
> +extern struct platform_device exynos4_device_sysmmu[];
Why is this a global variable? I would expect this to be private to the
implementation.
Arnd
next prev parent reply other threads:[~2011-04-18 14:12 UTC|newest]
Thread overview: 66+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-04-18 9:26 [RFC/PATCH v3 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update Marek Szyprowski
2011-04-18 9:26 ` Marek Szyprowski
2011-04-18 9:26 ` [PATCH 1/7] ARM: EXYNOS4: power domains: fixes and code cleanup Marek Szyprowski
2011-04-18 9:26 ` Marek Szyprowski
2011-04-18 9:26 ` [PATCH 2/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver Marek Szyprowski
2011-04-18 9:26 ` Marek Szyprowski
2011-04-18 14:12 ` Arnd Bergmann [this message]
2011-04-18 14:12 ` Arnd Bergmann
2011-04-19 8:23 ` Marek Szyprowski
2011-04-19 8:23 ` Marek Szyprowski
2011-04-19 12:49 ` Arnd Bergmann
2011-04-19 12:49 ` Arnd Bergmann
2011-04-19 13:50 ` Roedel, Joerg
2011-04-19 13:50 ` Roedel, Joerg
2011-04-19 14:28 ` Arnd Bergmann
2011-04-19 14:28 ` Arnd Bergmann
2011-04-19 14:51 ` Roedel, Joerg
2011-04-19 14:51 ` Roedel, Joerg
2011-04-19 14:03 ` Marek Szyprowski
2011-04-19 14:03 ` Marek Szyprowski
2011-04-19 14:29 ` Arnd Bergmann
2011-04-19 14:29 ` Arnd Bergmann
2011-04-20 14:55 ` Marek Szyprowski
2011-04-20 14:55 ` Marek Szyprowski
2011-04-20 16:07 ` Arnd Bergmann
2011-04-20 16:07 ` Arnd Bergmann
2011-04-21 11:32 ` Marek Szyprowski
2011-04-21 11:32 ` Marek Szyprowski
2011-04-21 12:00 ` Arnd Bergmann
2011-04-21 12:00 ` Arnd Bergmann
2011-04-21 14:03 ` Marek Szyprowski
2011-04-21 14:03 ` Marek Szyprowski
2011-04-21 14:18 ` Arnd Bergmann
2011-04-21 14:18 ` Arnd Bergmann
2011-04-22 7:33 ` Marek Szyprowski
2011-04-22 7:33 ` Marek Szyprowski
2011-04-26 14:10 ` Arnd Bergmann
2011-04-26 14:10 ` Arnd Bergmann
2011-04-26 14:23 ` Marek Szyprowski
2011-04-26 14:23 ` Marek Szyprowski
2011-04-19 15:00 ` Roedel, Joerg
2011-04-19 15:00 ` Roedel, Joerg
2011-04-19 15:37 ` Arnd Bergmann
2011-04-19 15:37 ` Arnd Bergmann
2011-04-18 9:26 ` [PATCH 3/7] v4l: videobuf2: dma-sg: move some generic functions to memops Marek Szyprowski
2011-04-18 9:26 ` Marek Szyprowski
2011-04-18 9:26 ` [PATCH 4/7] v4l: videobuf2: add IOMMU based DMA memory allocator Marek Szyprowski
2011-04-18 9:26 ` Marek Szyprowski
2011-04-18 14:15 ` Arnd Bergmann
2011-04-18 14:15 ` Arnd Bergmann
2011-04-19 9:02 ` Marek Szyprowski
2011-04-19 9:02 ` Marek Szyprowski
2011-04-19 9:21 ` Russell King - ARM Linux
2011-04-19 9:21 ` Russell King - ARM Linux
2011-04-19 12:00 ` Arnd Bergmann
2011-04-19 12:00 ` Arnd Bergmann
2011-04-18 9:26 ` [PATCH 5/7] v4l: s5p-fimc: add pm_runtime support Marek Szyprowski
2011-04-18 9:26 ` Marek Szyprowski
2011-04-18 9:26 ` [PATCH 6/7] v4l: s5p-fimc: Add support for vb2-dma-iommu allocator Marek Szyprowski
2011-04-18 9:26 ` Marek Szyprowski
2011-04-18 9:26 ` [PATCH 7/7] ARM: EXYNOS4: enable FIMC on Universal_C210 Marek Szyprowski
2011-04-18 9:26 ` Marek Szyprowski
2011-04-18 13:24 ` [RFC/PATCH v3 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update Marek Szyprowski
2011-04-18 13:24 ` Marek Szyprowski
-- strict thread matches above, loose matches on Subject: below --
2011-04-05 14:06 [RFC/PATCH v2 " Marek Szyprowski
2011-04-05 14:06 ` [PATCH 2/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver Marek Szyprowski
2011-04-05 14:06 ` Marek Szyprowski
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=201104181612.35833.arnd@arndb.de \
--to=arnd@arndb.de \
--cc=andrzej.p@samsung.com \
--cc=kgene.kim@samsung.com \
--cc=kyungmin.park@samsung.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-samsung-soc@vger.kernel.org \
--cc=m.szyprowski@samsung.com \
--cc=s.nawrocki@samsung.com \
/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.