Skip to content

Commit

Permalink
Merge branch 'for_2.6.38' of git://gitorious.org/iommu_mailbox/iommu_…
Browse files Browse the repository at this point in the history
…mailbox into devel-iommu-mailbox
  • Loading branch information
Tony Lindgren committed Dec 18, 2010
2 parents 28257f7 + 1cd25df commit c7d3e9e
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 101 deletions.
19 changes: 11 additions & 8 deletions arch/arm/mach-omap2/mailbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ static struct omap_mbox_ops omap2_mbox_ops = {

/* FIXME: the following structs should be filled automatically by the user id */

#if defined(CONFIG_ARCH_OMAP3430) || defined(CONFIG_ARCH_OMAP2420)
#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP2)
/* DSP */
static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
.tx_fifo = {
Expand All @@ -306,7 +306,7 @@ struct omap_mbox mbox_dsp_info = {
};
#endif

#if defined(CONFIG_ARCH_OMAP3430)
#if defined(CONFIG_ARCH_OMAP3)
struct omap_mbox *omap3_mboxes[] = { &mbox_dsp_info, NULL };
#endif

Expand Down Expand Up @@ -394,15 +394,19 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev)

if (false)
;
#if defined(CONFIG_ARCH_OMAP3430)
else if (cpu_is_omap3430()) {
#if defined(CONFIG_ARCH_OMAP3)
else if (cpu_is_omap34xx()) {
list = omap3_mboxes;

list[0]->irq = platform_get_irq_byname(pdev, "dsp");
}
#endif
#if defined(CONFIG_ARCH_OMAP2420)
else if (cpu_is_omap2420()) {
#if defined(CONFIG_ARCH_OMAP2)
else if (cpu_is_omap2430()) {
list = omap2_mboxes;

list[0]->irq = platform_get_irq_byname(pdev, "dsp");
} else if (cpu_is_omap2420()) {
list = omap2_mboxes;

list[0]->irq = platform_get_irq_byname(pdev, "dsp");
Expand Down Expand Up @@ -432,9 +436,8 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev)
iounmap(mbox_base);
return ret;
}
return 0;

return ret;
return 0;
}

static int __devexit omap2_mbox_remove(struct platform_device *pdev)
Expand Down
10 changes: 9 additions & 1 deletion arch/arm/mach-omap2/omap-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,20 @@ static struct iommu_device omap3_devices[] = {
.name = "isp",
.nr_tlb_entries = 8,
.clk_name = "cam_ick",
.da_start = 0x0,
.da_end = 0xFFFFF000,
},
},
#if defined(CONFIG_MPU_BRIDGE_IOMMU)
#if defined(CONFIG_OMAP_IOMMU_IVA2)
{
.base = 0x5d000000,
.irq = 28,
.pdata = {
.name = "iva2",
.nr_tlb_entries = 32,
.clk_name = "iva2_ck",
.da_start = 0x11000000,
.da_end = 0xFFFFF000,
},
},
#endif
Expand All @@ -64,6 +68,8 @@ static struct iommu_device omap4_devices[] = {
.name = "ducati",
.nr_tlb_entries = 32,
.clk_name = "ducati_ick",
.da_start = 0x0,
.da_end = 0xFFFFF000,
},
},
#if defined(CONFIG_MPU_TESLA_IOMMU)
Expand All @@ -74,6 +80,8 @@ static struct iommu_device omap4_devices[] = {
.name = "tesla",
.nr_tlb_entries = 32,
.clk_name = "tesla_ick",
.da_start = 0x0,
.da_end = 0xFFFFF000,
},
},
#endif
Expand Down
3 changes: 3 additions & 0 deletions arch/arm/plat-omap/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ config OMAP_IOMMU_DEBUG

Say N unless you know you need this.

config OMAP_IOMMU_IVA2
bool

choice
prompt "System timer"
default OMAP_32K_TIMER if !ARCH_OMAP15XX
Expand Down
5 changes: 5 additions & 0 deletions arch/arm/plat-omap/include/plat/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ struct iommu {
int (*isr)(struct iommu *obj);

void *ctx; /* iommu context: registres saved area */
u32 da_start;
u32 da_end;
};

struct cr_regs {
Expand Down Expand Up @@ -103,6 +105,8 @@ struct iommu_platform_data {
const char *name;
const char *clk_name;
const int nr_tlb_entries;
u32 da_start;
u32 da_end;
};

#if defined(CONFIG_ARCH_OMAP1)
Expand Down Expand Up @@ -152,6 +156,7 @@ extern void flush_iotlb_all(struct iommu *obj);
extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e);
extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova);

extern int iommu_set_da_range(struct iommu *obj, u32 start, u32 end);
extern struct iommu *iommu_get(const char *name);
extern void iommu_put(struct iommu *obj);

Expand Down
8 changes: 5 additions & 3 deletions arch/arm/plat-omap/include/plat/mailbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ struct omap_mbox_queue {
struct kfifo fifo;
struct work_struct work;
struct tasklet_struct tasklet;
int (*callback)(void *);
struct omap_mbox *mbox;
bool full;
};

struct omap_mbox {
Expand All @@ -57,13 +57,15 @@ struct omap_mbox {
struct omap_mbox_ops *ops;
struct device *dev;
void *priv;
int use_count;
struct blocking_notifier_head notifier;
};

int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg);
void omap_mbox_init_seq(struct omap_mbox *);

struct omap_mbox *omap_mbox_get(const char *);
void omap_mbox_put(struct omap_mbox *);
struct omap_mbox *omap_mbox_get(const char *, struct notifier_block *nb);
void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb);

int omap_mbox_register(struct device *parent, struct omap_mbox **);
int omap_mbox_unregister(void);
Expand Down
24 changes: 24 additions & 0 deletions arch/arm/plat-omap/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,28 @@ static int device_match_by_alias(struct device *dev, void *data)
return strcmp(obj->name, name) == 0;
}

/**
* iommu_set_da_range - Set a valid device address range
* @obj: target iommu
* @start Start of valid range
* @end End of valid range
**/
int iommu_set_da_range(struct iommu *obj, u32 start, u32 end)
{

if (!obj)
return -EFAULT;

if (end < start || !PAGE_ALIGN(start | end))
return -EINVAL;

obj->da_start = start;
obj->da_end = end;

return 0;
}
EXPORT_SYMBOL_GPL(iommu_set_da_range);

/**
* iommu_get - Get iommu handler
* @name: target iommu name
Expand Down Expand Up @@ -922,6 +944,8 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
obj->name = pdata->name;
obj->dev = &pdev->dev;
obj->ctx = (void *)obj + sizeof(*obj);
obj->da_start = pdata->da_start;
obj->da_end = pdata->da_end;

mutex_init(&obj->iommu_lock);
mutex_init(&obj->mmap_lock);
Expand Down
81 changes: 46 additions & 35 deletions arch/arm/plat-omap/iovmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,35 +87,43 @@ static size_t sgtable_len(const struct sg_table *sgt)
}
#define sgtable_ok(x) (!!sgtable_len(x))

static unsigned max_alignment(u32 addr)
{
int i;
unsigned pagesize[] = { SZ_16M, SZ_1M, SZ_64K, SZ_4K, };
for (i = 0; i < ARRAY_SIZE(pagesize) && addr & (pagesize[i] - 1); i++)
;
return (i < ARRAY_SIZE(pagesize)) ? pagesize[i] : 0;
}

/*
* calculate the optimal number sg elements from total bytes based on
* iommu superpages
*/
static unsigned int sgtable_nents(size_t bytes)
static unsigned sgtable_nents(size_t bytes, u32 da, u32 pa)
{
int i;
unsigned int nr_entries;
const unsigned long pagesize[] = { SZ_16M, SZ_1M, SZ_64K, SZ_4K, };
unsigned nr_entries = 0, ent_sz;

if (!IS_ALIGNED(bytes, PAGE_SIZE)) {
pr_err("%s: wrong size %08x\n", __func__, bytes);
return 0;
}

nr_entries = 0;
for (i = 0; i < ARRAY_SIZE(pagesize); i++) {
if (bytes >= pagesize[i]) {
nr_entries += (bytes / pagesize[i]);
bytes %= pagesize[i];
}
while (bytes) {
ent_sz = max_alignment(da | pa);
ent_sz = min_t(unsigned, ent_sz, iopgsz_max(bytes));
nr_entries++;
da += ent_sz;
pa += ent_sz;
bytes -= ent_sz;
}
BUG_ON(bytes);

return nr_entries;
}

/* allocate and initialize sg_table header(a kind of 'superblock') */
static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags)
static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags,
u32 da, u32 pa)
{
unsigned int nr_entries;
int err;
Expand All @@ -127,9 +135,8 @@ static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags)
if (!IS_ALIGNED(bytes, PAGE_SIZE))
return ERR_PTR(-EINVAL);

/* FIXME: IOVMF_DA_FIXED should support 'superpages' */
if ((flags & IOVMF_LINEAR) && (flags & IOVMF_DA_ANON)) {
nr_entries = sgtable_nents(bytes);
if (flags & IOVMF_LINEAR) {
nr_entries = sgtable_nents(bytes, da, pa);
if (!nr_entries)
return ERR_PTR(-EINVAL);
} else
Expand Down Expand Up @@ -273,13 +280,14 @@ static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
alignement = PAGE_SIZE;

if (flags & IOVMF_DA_ANON) {
/*
* Reserve the first page for NULL
*/
start = PAGE_SIZE;
start = obj->da_start;

if (flags & IOVMF_LINEAR)
alignement = iopgsz_max(bytes);
start = roundup(start, alignement);
} else if (start < obj->da_start || start > obj->da_end ||
obj->da_end - start < bytes) {
return ERR_PTR(-EINVAL);
}

tmp = NULL;
Expand All @@ -289,19 +297,19 @@ static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
prev_end = 0;
list_for_each_entry(tmp, &obj->mmap, list) {

if (prev_end >= start)
if (prev_end > start)
break;

if (start + bytes < tmp->da_start)
if (tmp->da_start > start && (tmp->da_start - start) >= bytes)
goto found;

if (flags & IOVMF_DA_ANON)
if (tmp->da_end >= start && flags & IOVMF_DA_ANON)
start = roundup(tmp->da_end + 1, alignement);

prev_end = tmp->da_end;
}

if ((start > prev_end) && (ULONG_MAX - start >= bytes))
if ((start >= prev_end) && (obj->da_end - start >= bytes))
goto found;

dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n",
Expand Down Expand Up @@ -409,7 +417,8 @@ static inline void sgtable_drain_vmalloc(struct sg_table *sgt)
BUG_ON(!sgt);
}

static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, size_t len)
static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, u32 da,
size_t len)
{
unsigned int i;
struct scatterlist *sg;
Expand All @@ -418,9 +427,10 @@ static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, size_t len)
va = phys_to_virt(pa);

for_each_sg(sgt->sgl, sg, sgt->nents, i) {
size_t bytes;
unsigned bytes;

bytes = iopgsz_max(len);
bytes = max_alignment(da | pa);
bytes = min_t(unsigned, bytes, iopgsz_max(len));

BUG_ON(!iopgsz_ok(bytes));

Expand All @@ -429,6 +439,7 @@ static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, size_t len)
* 'pa' is cotinuous(linear).
*/
pa += bytes;
da += bytes;
len -= bytes;
}
BUG_ON(len);
Expand Down Expand Up @@ -695,18 +706,18 @@ u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
if (!va)
return -ENOMEM;

sgt = sgtable_alloc(bytes, flags);
flags &= IOVMF_HW_MASK;
flags |= IOVMF_DISCONT;
flags |= IOVMF_ALLOC;
flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);

sgt = sgtable_alloc(bytes, flags, da, 0);
if (IS_ERR(sgt)) {
da = PTR_ERR(sgt);
goto err_sgt_alloc;
}
sgtable_fill_vmalloc(sgt, va);

flags &= IOVMF_HW_MASK;
flags |= IOVMF_DISCONT;
flags |= IOVMF_ALLOC;
flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);

da = __iommu_vmap(obj, da, sgt, va, bytes, flags);
if (IS_ERR_VALUE(da))
goto err_iommu_vmap;
Expand Down Expand Up @@ -746,11 +757,11 @@ static u32 __iommu_kmap(struct iommu *obj, u32 da, u32 pa, void *va,
{
struct sg_table *sgt;

sgt = sgtable_alloc(bytes, flags);
sgt = sgtable_alloc(bytes, flags, da, pa);
if (IS_ERR(sgt))
return PTR_ERR(sgt);

sgtable_fill_kmalloc(sgt, pa, bytes);
sgtable_fill_kmalloc(sgt, pa, da, bytes);

da = map_iommu_region(obj, da, sgt, va, bytes, flags);
if (IS_ERR_VALUE(da)) {
Expand Down Expand Up @@ -811,7 +822,7 @@ void iommu_kunmap(struct iommu *obj, u32 da)
struct sg_table *sgt;
typedef void (*func_t)(const void *);

sgt = unmap_vm_area(obj, da, (func_t)__iounmap,
sgt = unmap_vm_area(obj, da, (func_t)iounmap,
IOVMF_LINEAR | IOVMF_MMIO);
if (!sgt)
dev_dbg(obj->dev, "%s: No sgt\n", __func__);
Expand Down
Loading

0 comments on commit c7d3e9e

Please sign in to comment.