9 #define KMSG_COMPONENT "hypfs"
10 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
12 #include <linux/types.h>
13 #include <linux/errno.h>
14 #include <linux/slab.h>
15 #include <linux/string.h>
21 #define LPAR_NAME_LEN 8
22 #define CPU_NAME_LEN 16
25 #define DBFS_D204_HDR_VERSION 0
42 #define LPAR_PHYS_FLG 0x80
44 static char *diag224_cpu_names;
48 static void *diag204_buf;
49 static void *diag204_buf_vmalloc;
50 static int diag204_buf_pages;
52 static struct dentry *dbfs_d204_file;
159 static inline void part_hdr__part_name(
enum diag204_format type,
void *hdr,
223 return ((
struct cpu_info *)hdr)->cpu_addr;
231 return ((
struct cpu_info *)hdr)->acc_time;
239 return ((
struct cpu_info *)hdr)->lp_time;
249 return ((
struct x_cpu_info *)hdr)->online_time;
280 return ((
struct phys_hdr *)hdr)->cpus;
316 return ((
struct phys_cpu *)hdr)->cpu_addr;
324 return ((
struct phys_cpu *)hdr)->mgm_time;
332 return ((
struct phys_cpu *)hdr)->ctidx;
339 static int diag204(
unsigned long subcode,
unsigned long size,
void *
addr)
341 register unsigned long _subcode
asm(
"0") = subcode;
342 register unsigned long _size asm(
"1") = size;
345 " diag %2,%0,0x204\n"
348 :
"+d" (_subcode),
"+d" (
_size) :
"d" (addr) :
"memory");
361 static void diag204_free_buffer(
void)
365 if (diag204_buf_vmalloc) {
366 vfree(diag204_buf_vmalloc);
367 diag204_buf_vmalloc =
NULL;
374 static void *page_align_ptr(
void *
ptr)
376 return (
void *)
PAGE_ALIGN((
unsigned long) ptr);
379 static void *diag204_alloc_vbuf(
int pages)
383 if (!diag204_buf_vmalloc)
385 diag204_buf = page_align_ptr(diag204_buf_vmalloc);
386 diag204_buf_pages =
pages;
390 static void *diag204_alloc_rbuf(
void)
395 diag204_buf_pages = 1;
402 *pages = diag204_buf_pages;
407 return diag204_alloc_rbuf();
409 *pages = diag204((
unsigned long)
SUBC_RSI |
414 return diag204_alloc_vbuf(*pages);
432 static int diag204_probe(
void)
437 buf = diag204_get_buffer(
INFO_EXT, &pages);
440 (
unsigned long)
INFO_EXT, pages, buf) >= 0) {
446 (
unsigned long)INFO_EXT, pages, buf) >= 0) {
451 diag204_free_buffer();
473 diag204_free_buffer();
478 static int diag204_do_store(
void *buf,
int pages)
482 rc = diag204((
unsigned long) diag204_store_sc |
483 (
unsigned long) diag204_info_type, pages, buf);
484 return rc < 0 ? -
ENOSYS : 0;
487 static void *diag204_store(
void)
492 buf = diag204_get_buffer(diag204_info_type, &pages);
495 rc = diag204_do_store(buf, pages);
504 static int diag224(
void *ptr)
509 " diag %1,%2,0x224\n"
513 :
"+d" (rc) :
"d" (0),
"d" (ptr) :
"memory");
517 static int diag224_get_name_table(
void)
521 if (!diag224_cpu_names)
523 if (diag224(diag224_cpu_names)) {
524 kfree(diag224_cpu_names);
527 EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16);
531 static void diag224_delete_name_table(
void)
533 kfree(diag224_cpu_names);
536 static int diag224_idx2name(
int index,
char *
name)
557 static int dbfs_d204_create(
void **
data,
void **data_free_ptr,
size_t *size)
563 buf_size =
PAGE_SIZE * (diag204_buf_pages + 1) +
sizeof(d204->
hdr);
567 d204 = page_align_ptr(base +
sizeof(d204->
hdr)) -
sizeof(d204->
hdr);
568 rc = diag204_do_store(d204->
buf, diag204_buf_pages);
575 d204->
hdr.sc = diag204_store_sc;
577 *data_free_ptr = base;
584 .data_create = dbfs_d204_create,
592 if (diag204_probe()) {
593 pr_err(
"The hardware system does not support hypfs\n");
596 if (diag204_info_type == INFO_EXT) {
602 rc = diag224_get_name_table();
604 pr_err(
"The hardware system does not provide all "
605 "functions required by hypfs\n");
616 diag224_delete_name_table();
617 diag204_free_buffer();
637 cpu_info__acc_time(diag204_info_type, cpu_info) -
638 cpu_info__lp_time(diag204_info_type, cpu_info));
642 cpu_info__lp_time(diag204_info_type, cpu_info));
645 if (diag204_info_type == INFO_EXT) {
647 cpu_info__online_time(diag204_info_type,
652 diag224_idx2name(cpu_info__ctidx(diag204_info_type, cpu_info), buffer);
659 static void *hypfs_create_lpar_files(
struct super_block *sb,
668 part_hdr__part_name(diag204_info_type, part_hdr, lpar_name);
670 lpar_dir =
hypfs_mkdir(sb, systems_dir, lpar_name);
671 if (IS_ERR(lpar_dir))
674 if (IS_ERR(cpus_dir))
676 cpu_info = part_hdr + part_hdr__size(diag204_info_type);
677 for (i = 0; i < part_hdr__rcpus(diag204_info_type, part_hdr); i++) {
679 rc = hypfs_create_cpu_files(sb, cpus_dir, cpu_info);
682 cpu_info += cpu_info__size(diag204_info_type);
687 static int hypfs_create_phys_cpu_files(
struct super_block *sb,
688 struct dentry *cpus_dir,
void *cpu_info)
698 return PTR_ERR(cpu_dir);
700 phys_cpu__mgm_time(diag204_info_type, cpu_info));
703 diag224_idx2name(phys_cpu__ctidx(diag204_info_type, cpu_info), buffer);
710 static void *hypfs_create_phys_files(
struct super_block *sb,
718 if (IS_ERR(cpus_dir))
720 cpu_info = phys_hdr + phys_hdr__size(diag204_info_type);
721 for (i = 0; i < phys_hdr__cpus(diag204_info_type, phys_hdr); i++) {
723 rc = hypfs_create_phys_cpu_files(sb, cpus_dir, cpu_info);
726 cpu_info += phys_cpu__size(diag204_info_type);
733 struct dentry *systems_dir, *hyp_dir;
734 void *time_hdr, *part_hdr;
738 buffer = diag204_store();
740 return PTR_ERR(buffer);
743 if (IS_ERR(systems_dir)) {
744 rc = PTR_ERR(systems_dir);
748 part_hdr = time_hdr + info_blk_hdr__size(diag204_info_type);
749 for (i = 0; i < info_blk_hdr__npar(diag204_info_type, time_hdr); i++) {
750 part_hdr = hypfs_create_lpar_files(sb, systems_dir, part_hdr);
751 if (IS_ERR(part_hdr)) {
752 rc = PTR_ERR(part_hdr);
756 if (info_blk_hdr__flags(diag204_info_type, time_hdr) &
LPAR_PHYS_FLG) {
757 ptr = hypfs_create_phys_files(sb, root, part_hdr);
764 if (IS_ERR(hyp_dir)) {
765 rc = PTR_ERR(hyp_dir);