diff options
author | Jiri Kosina <jkosina@suse.cz> | 2017-11-15 11:04:13 +0100 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2017-11-15 11:04:13 +0100 |
commit | 5cc619db5c34146ee821acd08382b9d78579b52e (patch) | |
tree | ee28e3cefdb35d56e33887f05db0a50589aa5883 /arch/mips/cavium-octeon/executive/cvmx-bootmem.c | |
parent | Merge branch 'for-4.14/upstream-fixes' into for-linus (diff) | |
parent | HID: alps: add new U1 device ID (diff) | |
download | linux-5cc619db5c34146ee821acd08382b9d78579b52e.tar.xz linux-5cc619db5c34146ee821acd08382b9d78579b52e.zip |
Merge branch 'for-4.15/alps' into for-linus
- New ALPS touchpad (T4, found currently on HP EliteBook 1000, Zbook Stduio
and HP Elite book x360) support from Masaki Ota
Diffstat (limited to 'arch/mips/cavium-octeon/executive/cvmx-bootmem.c')
-rw-r--r-- | arch/mips/cavium-octeon/executive/cvmx-bootmem.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c index 8d54d774933c..94d97ebfa036 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c +++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c @@ -44,6 +44,55 @@ static struct cvmx_bootmem_desc *cvmx_bootmem_desc; /* See header file for descriptions of functions */ +/** + * This macro returns the size of a member of a structure. + * Logically it is the same as "sizeof(s::field)" in C++, but + * C lacks the "::" operator. + */ +#define SIZEOF_FIELD(s, field) sizeof(((s *)NULL)->field) + +/** + * This macro returns a member of the + * cvmx_bootmem_named_block_desc_t structure. These members can't + * be directly addressed as they might be in memory not directly + * reachable. In the case where bootmem is compiled with + * LINUX_HOST, the structure itself might be located on a remote + * Octeon. The argument "field" is the member name of the + * cvmx_bootmem_named_block_desc_t to read. Regardless of the type + * of the field, the return type is always a uint64_t. The "addr" + * parameter is the physical address of the structure. + */ +#define CVMX_BOOTMEM_NAMED_GET_FIELD(addr, field) \ + __cvmx_bootmem_desc_get(addr, \ + offsetof(struct cvmx_bootmem_named_block_desc, field), \ + SIZEOF_FIELD(struct cvmx_bootmem_named_block_desc, field)) + +/** + * This function is the implementation of the get macros defined + * for individual structure members. The argument are generated + * by the macros inorder to read only the needed memory. + * + * @param base 64bit physical address of the complete structure + * @param offset Offset from the beginning of the structure to the member being + * accessed. + * @param size Size of the structure member. + * + * @return Value of the structure member promoted into a uint64_t. + */ +static inline uint64_t __cvmx_bootmem_desc_get(uint64_t base, int offset, + int size) +{ + base = (1ull << 63) | (base + offset); + switch (size) { + case 4: + return cvmx_read64_uint32(base); + case 8: + return cvmx_read64_uint64(base); + default: + return 0; + } +} + /* * Wrapper functions are provided for reading/writing the size and * next block values as these may not be directly addressible (in 32 @@ -98,6 +147,42 @@ void *cvmx_bootmem_alloc(uint64_t size, uint64_t alignment) return cvmx_bootmem_alloc_range(size, alignment, 0, 0); } +void *cvmx_bootmem_alloc_named_range_once(uint64_t size, uint64_t min_addr, + uint64_t max_addr, uint64_t align, + char *name, + void (*init) (void *)) +{ + int64_t addr; + void *ptr; + uint64_t named_block_desc_addr; + + named_block_desc_addr = (uint64_t) + cvmx_bootmem_phy_named_block_find(name, + (uint32_t)CVMX_BOOTMEM_FLAG_NO_LOCKING); + + if (named_block_desc_addr) { + addr = CVMX_BOOTMEM_NAMED_GET_FIELD(named_block_desc_addr, + base_addr); + return cvmx_phys_to_ptr(addr); + } + + addr = cvmx_bootmem_phy_named_block_alloc(size, min_addr, max_addr, + align, name, + (uint32_t)CVMX_BOOTMEM_FLAG_NO_LOCKING); + + if (addr < 0) + return NULL; + ptr = cvmx_phys_to_ptr(addr); + + if (init) + init(ptr); + else + memset(ptr, 0, size); + + return ptr; +} +EXPORT_SYMBOL(cvmx_bootmem_alloc_named_range_once); + void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr, uint64_t max_addr, uint64_t align, char *name) |