Skip to content

Commit

Permalink
gpu/drm, x86, PAT: io_mapping_create_wc and resource_size_t
Browse files Browse the repository at this point in the history
io_mapping_create_wc should take a resource_size_t parameter in place of
unsigned long. With unsigned long, there will be no way to map greater than 4GB
address in i386/32 bit.

On x86, greater than 4GB addresses cannot be mapped on i386 without PAE. Return
error for such a case.

Patch also adds a structure for io_mapping, that saves the base, size and
type on HAVE_ATOMIC_IOMAP archs, that can be used to verify the offset on
io_mapping_map calls.

Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: Dave Airlie <airlied@redhat.com>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Eric Anholt <eric@anholt.net>
Cc: Keith Packard <keithp@keithp.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Venkatesh Pallipadi authored and Ingo Molnar committed Feb 25, 2009
1 parent 6644107 commit 4ab0d47
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 11 deletions.
3 changes: 3 additions & 0 deletions arch/x86/include/asm/iomap.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#include <asm/pgtable.h>
#include <asm/tlbflush.h>

int
is_io_mapping_possible(resource_size_t base, unsigned long size);

void *
iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);

Expand Down
18 changes: 18 additions & 0 deletions arch/x86/mm/iomap_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@
#include <asm/pat.h>
#include <linux/module.h>

#ifdef CONFIG_X86_PAE
int
is_io_mapping_possible(resource_size_t base, unsigned long size)
{
return 1;
}
#else
int
is_io_mapping_possible(resource_size_t base, unsigned long size)
{
/* There is no way to map greater than 1 << 32 address without PAE */
if (base + size > 0x100000000ULL)
return 0;

return 1;
}
#endif

/* Map 'pfn' using fixed map 'type' and protections 'prot'
*/
void *
Expand Down
46 changes: 35 additions & 11 deletions include/linux/io-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@
* See Documentation/io_mapping.txt
*/

/* this struct isn't actually defined anywhere */
struct io_mapping;

#ifdef CONFIG_HAVE_ATOMIC_IOMAP

struct io_mapping {
resource_size_t base;
unsigned long size;
pgprot_t prot;
};

/*
* For small address space machines, mapping large objects
* into the kernel virtual space isn't practical. Where
Expand All @@ -43,23 +46,40 @@ struct io_mapping;
*/

static inline struct io_mapping *
io_mapping_create_wc(unsigned long base, unsigned long size)
io_mapping_create_wc(resource_size_t base, unsigned long size)
{
return (struct io_mapping *) base;
struct io_mapping *iomap;

if (!is_io_mapping_possible(base, size))
return NULL;

iomap = kmalloc(sizeof(*iomap), GFP_KERNEL);
if (!iomap)
return NULL;

iomap->base = base;
iomap->size = size;
iomap->prot = pgprot_writecombine(__pgprot(__PAGE_KERNEL));
return iomap;
}

static inline void
io_mapping_free(struct io_mapping *mapping)
{
kfree(mapping);
}

/* Atomic map/unmap */
static inline void *
io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset)
{
offset += (unsigned long) mapping;
return iomap_atomic_prot_pfn(offset >> PAGE_SHIFT, KM_USER0,
__pgprot(__PAGE_KERNEL_WC));
resource_size_t phys_addr;
unsigned long pfn;

BUG_ON(offset >= mapping->size);
phys_addr = mapping->base + offset;
pfn = (unsigned long) (phys_addr >> PAGE_SHIFT);
return iomap_atomic_prot_pfn(pfn, KM_USER0, mapping->prot);
}

static inline void
Expand All @@ -71,8 +91,9 @@ io_mapping_unmap_atomic(void *vaddr)
static inline void *
io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset)
{
offset += (unsigned long) mapping;
return ioremap_wc(offset, PAGE_SIZE);
BUG_ON(offset >= mapping->size);
resource_size_t phys_addr = mapping->base + offset;
return ioremap_wc(phys_addr, PAGE_SIZE);
}

static inline void
Expand All @@ -83,9 +104,12 @@ io_mapping_unmap(void *vaddr)

#else

/* this struct isn't actually defined anywhere */
struct io_mapping;

/* Create the io_mapping object*/
static inline struct io_mapping *
io_mapping_create_wc(unsigned long base, unsigned long size)
io_mapping_create_wc(resource_size_t base, unsigned long size)
{
return (struct io_mapping *) ioremap_wc(base, size);
}
Expand Down

0 comments on commit 4ab0d47

Please sign in to comment.