Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 27a90700 authored by Kai Jiang's avatar Kai Jiang Committed by Greg Kroah-Hartman
Browse files

uio: Support physical addresses >32 bits on 32-bit systems



To support >32-bit physical addresses for UIO_MEM_PHYS type we need to
extend the width of 'addr' in struct uio_mem.  Numerous platforms like
embedded PPC, ARM, and X86 have support for systems with larger physical
address than logical.

Since 'addr' may contain a physical, logical, or virtual address the
easiest solution is to just change the type to 'phys_addr_t' which
should always be greater than or equal to the sizeof(void *) such that
it can properly hold any of the address types.

For physical address we can support up to a 44-bit physical address on a
typical 32-bit system as we utilize remap_pfn_range() for the mapping of
the memory region and pfn's are represnted by shifting the address by
the page size (typically 4k).

Signed-off-by: default avatarKai Jiang <Kai.Jiang@freescale.com>
Signed-off-by: default avatarMinghuan Lian <Minghuan.Lian@freescale.com>
Signed-off-by: default avatarKumar Gala <galak@kernel.crashing.org>
Signed-off-by: default avatarHans J. Koch <hjk@hansjkoch.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent c4253cb0
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -529,7 +529,7 @@ memory (e.g. allocated with <function>kmalloc()</function>). There's also
</para></listitem>

<listitem><para>
<varname>unsigned long addr</varname>: Required if the mapping is used.
<varname>phys_addr_t addr</varname>: Required if the mapping is used.
Fill in the address of your memory block. This address is the one that
appears in sysfs.
</para></listitem>
+3 −4
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ static ssize_t map_name_show(struct uio_mem *mem, char *buf)

static ssize_t map_addr_show(struct uio_mem *mem, char *buf)
{
	return sprintf(buf, "0x%lx\n", mem->addr);
	return sprintf(buf, "0x%llx\n", (unsigned long long)mem->addr);
}

static ssize_t map_size_show(struct uio_mem *mem, char *buf)
@@ -79,7 +79,7 @@ static ssize_t map_size_show(struct uio_mem *mem, char *buf)

static ssize_t map_offset_show(struct uio_mem *mem, char *buf)
{
	return sprintf(buf, "0x%lx\n", mem->addr & ~PAGE_MASK);
	return sprintf(buf, "0x%llx\n", (unsigned long long)mem->addr & ~PAGE_MASK);
}

struct map_sysfs_entry {
@@ -634,8 +634,7 @@ static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
	if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL)
		page = virt_to_page(idev->info->mem[mi].addr + offset);
	else
		page = vmalloc_to_page((void *)idev->info->mem[mi].addr
							+ offset);
		page = vmalloc_to_page((void *)(unsigned long)idev->info->mem[mi].addr + offset);
	get_page(page);
	vmf->page = page;
	return 0;
+5 −2
Original line number Diff line number Diff line
@@ -23,7 +23,10 @@ struct uio_map;
/**
 * struct uio_mem - description of a UIO memory region
 * @name:		name of the memory region for identification
 * @addr:		address of the device's memory
 * @addr:		address of the device's memory (phys_addr is used since
 * 			addr can be logical, virtual, or physical & phys_addr_t
 * 			should always be large enough to handle any of the
 * 			address types)
 * @size:		size of IO
 * @memtype:		type of memory addr points to
 * @internal_addr:	ioremap-ped version of addr, for driver internal use
@@ -31,7 +34,7 @@ struct uio_map;
 */
struct uio_mem {
	const char		*name;
	unsigned long		addr;
	phys_addr_t		addr;
	unsigned long		size;
	int			memtype;
	void __iomem		*internal_addr;