mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 18:43:33 +02:00
s390/hypfs: simplify memory allocation
Simplify memory allocation for diagnose 204 memory buffer: - allocate with __vmalloc_node() to enure page alignment - allocate real / physical memory area also within vmalloc area and handle vmalloc to real / physical address translation within diag204(). Acked-by: Alexander Gordeev <agordeev@linux.ibm.com> Reviewed-by: Mete Durlu <meted@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
This commit is contained in:
parent
5ac8c72462
commit
83f9567194
|
|
@ -29,7 +29,6 @@ static enum diag204_sc diag204_store_sc; /* used subcode for store */
|
|||
static enum diag204_format diag204_info_type; /* used diag 204 data format */
|
||||
|
||||
static void *diag204_buf; /* 4K aligned buffer for diag204 data */
|
||||
static void *diag204_buf_vmalloc; /* vmalloc pointer for diag204 data */
|
||||
static int diag204_buf_pages; /* number of pages for diag204 data */
|
||||
|
||||
static struct dentry *dbfs_d204_file;
|
||||
|
|
@ -212,14 +211,7 @@ static inline __u64 phys_cpu__ctidx(enum diag204_format type, void *hdr)
|
|||
|
||||
static void diag204_free_buffer(void)
|
||||
{
|
||||
if (!diag204_buf)
|
||||
return;
|
||||
if (diag204_buf_vmalloc) {
|
||||
vfree(diag204_buf_vmalloc);
|
||||
diag204_buf_vmalloc = NULL;
|
||||
} else {
|
||||
free_pages((unsigned long) diag204_buf, 0);
|
||||
}
|
||||
vfree(diag204_buf);
|
||||
diag204_buf = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -228,26 +220,6 @@ static void *page_align_ptr(void *ptr)
|
|||
return (void *) PAGE_ALIGN((unsigned long) ptr);
|
||||
}
|
||||
|
||||
static void *diag204_alloc_vbuf(int pages)
|
||||
{
|
||||
/* The buffer has to be page aligned! */
|
||||
diag204_buf_vmalloc = vmalloc(array_size(PAGE_SIZE, (pages + 1)));
|
||||
if (!diag204_buf_vmalloc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
diag204_buf = page_align_ptr(diag204_buf_vmalloc);
|
||||
diag204_buf_pages = pages;
|
||||
return diag204_buf;
|
||||
}
|
||||
|
||||
static void *diag204_alloc_rbuf(void)
|
||||
{
|
||||
diag204_buf = (void*)__get_free_pages(GFP_KERNEL,0);
|
||||
if (!diag204_buf)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
diag204_buf_pages = 1;
|
||||
return diag204_buf;
|
||||
}
|
||||
|
||||
static void *diag204_get_buffer(enum diag204_format fmt, int *pages)
|
||||
{
|
||||
if (diag204_buf) {
|
||||
|
|
@ -256,15 +228,19 @@ static void *diag204_get_buffer(enum diag204_format fmt, int *pages)
|
|||
}
|
||||
if (fmt == DIAG204_INFO_SIMPLE) {
|
||||
*pages = 1;
|
||||
return diag204_alloc_rbuf();
|
||||
} else {/* DIAG204_INFO_EXT */
|
||||
*pages = diag204((unsigned long)DIAG204_SUBC_RSI |
|
||||
(unsigned long)DIAG204_INFO_EXT, 0, NULL);
|
||||
if (*pages <= 0)
|
||||
return ERR_PTR(-ENOSYS);
|
||||
else
|
||||
return diag204_alloc_vbuf(*pages);
|
||||
}
|
||||
diag204_buf = __vmalloc_node(array_size(*pages, PAGE_SIZE),
|
||||
PAGE_SIZE, GFP_KERNEL, NUMA_NO_NODE,
|
||||
__builtin_return_address(0));
|
||||
if (!diag204_buf)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
diag204_buf_pages = *pages;
|
||||
return diag204_buf;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/cpu.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <asm/asm-extable.h>
|
||||
#include <asm/diag.h>
|
||||
#include <asm/trace/diag.h>
|
||||
|
|
@ -168,11 +169,30 @@ static inline int __diag204(unsigned long *subcode, unsigned long size, void *ad
|
|||
return rp.odd;
|
||||
}
|
||||
|
||||
/**
|
||||
* diag204() - Issue diagnose 204 call.
|
||||
* @subcode: Subcode of diagnose 204 to be executed.
|
||||
* @size: Size of area in pages which @area points to, if given.
|
||||
* @addr: Vmalloc'ed memory area where the result is written to.
|
||||
*
|
||||
* Execute diagnose 204 with the given subcode and write the result to the
|
||||
* memory area specified with @addr. For subcodes which do not write a
|
||||
* result to memory both @size and @addr must be zero. If @addr is
|
||||
* specified it must be page aligned and must have been allocated with
|
||||
* vmalloc(). Conversion to real / physical addresses will be handled by
|
||||
* this function if required.
|
||||
*/
|
||||
int diag204(unsigned long subcode, unsigned long size, void *addr)
|
||||
{
|
||||
diag_stat_inc(DIAG_STAT_X204);
|
||||
if (addr) {
|
||||
if (WARN_ON_ONCE(!is_vmalloc_addr(addr)))
|
||||
return -1;
|
||||
if (WARN_ON_ONCE(!IS_ALIGNED((unsigned long)addr, PAGE_SIZE)))
|
||||
return -1;
|
||||
}
|
||||
if ((subcode & DIAG204_SUBCODE_MASK) == DIAG204_SUBC_STIB4)
|
||||
addr = (void *)__pa(addr);
|
||||
addr = (void *)pfn_to_phys(vmalloc_to_pfn(addr));
|
||||
diag_stat_inc(DIAG_STAT_X204);
|
||||
size = __diag204(&subcode, size, addr);
|
||||
if (subcode)
|
||||
return -1;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user