Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *    Hypervisor filesystem for Linux on s390. Diag 204 and 224
0004  *    implementation.
0005  *
0006  *    Copyright IBM Corp. 2006, 2008
0007  *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
0008  */
0009 
0010 #define KMSG_COMPONENT "hypfs"
0011 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
0012 
0013 #include <linux/types.h>
0014 #include <linux/errno.h>
0015 #include <linux/slab.h>
0016 #include <linux/string.h>
0017 #include <linux/vmalloc.h>
0018 #include <linux/mm.h>
0019 #include <asm/diag.h>
0020 #include <asm/ebcdic.h>
0021 #include "hypfs.h"
0022 
0023 #define TMP_SIZE 64     /* size of temporary buffers */
0024 
0025 #define DBFS_D204_HDR_VERSION   0
0026 
0027 static char *diag224_cpu_names;         /* diag 224 name table */
0028 static enum diag204_sc diag204_store_sc;    /* used subcode for store */
0029 static enum diag204_format diag204_info_type;   /* used diag 204 data format */
0030 
0031 static void *diag204_buf;       /* 4K aligned buffer for diag204 data */
0032 static void *diag204_buf_vmalloc;   /* vmalloc pointer for diag204 data */
0033 static int diag204_buf_pages;       /* number of pages for diag204 data */
0034 
0035 static struct dentry *dbfs_d204_file;
0036 
0037 /*
0038  * DIAG 204 member access functions.
0039  *
0040  * Since we have two different diag 204 data formats for old and new s390
0041  * machines, we do not access the structs directly, but use getter functions for
0042  * each struct member instead. This should make the code more readable.
0043  */
0044 
0045 /* Time information block */
0046 
0047 static inline int info_blk_hdr__size(enum diag204_format type)
0048 {
0049     if (type == DIAG204_INFO_SIMPLE)
0050         return sizeof(struct diag204_info_blk_hdr);
0051     else /* DIAG204_INFO_EXT */
0052         return sizeof(struct diag204_x_info_blk_hdr);
0053 }
0054 
0055 static inline __u8 info_blk_hdr__npar(enum diag204_format type, void *hdr)
0056 {
0057     if (type == DIAG204_INFO_SIMPLE)
0058         return ((struct diag204_info_blk_hdr *)hdr)->npar;
0059     else /* DIAG204_INFO_EXT */
0060         return ((struct diag204_x_info_blk_hdr *)hdr)->npar;
0061 }
0062 
0063 static inline __u8 info_blk_hdr__flags(enum diag204_format type, void *hdr)
0064 {
0065     if (type == DIAG204_INFO_SIMPLE)
0066         return ((struct diag204_info_blk_hdr *)hdr)->flags;
0067     else /* DIAG204_INFO_EXT */
0068         return ((struct diag204_x_info_blk_hdr *)hdr)->flags;
0069 }
0070 
0071 static inline __u16 info_blk_hdr__pcpus(enum diag204_format type, void *hdr)
0072 {
0073     if (type == DIAG204_INFO_SIMPLE)
0074         return ((struct diag204_info_blk_hdr *)hdr)->phys_cpus;
0075     else /* DIAG204_INFO_EXT */
0076         return ((struct diag204_x_info_blk_hdr *)hdr)->phys_cpus;
0077 }
0078 
0079 /* Partition header */
0080 
0081 static inline int part_hdr__size(enum diag204_format type)
0082 {
0083     if (type == DIAG204_INFO_SIMPLE)
0084         return sizeof(struct diag204_part_hdr);
0085     else /* DIAG204_INFO_EXT */
0086         return sizeof(struct diag204_x_part_hdr);
0087 }
0088 
0089 static inline __u8 part_hdr__rcpus(enum diag204_format type, void *hdr)
0090 {
0091     if (type == DIAG204_INFO_SIMPLE)
0092         return ((struct diag204_part_hdr *)hdr)->cpus;
0093     else /* DIAG204_INFO_EXT */
0094         return ((struct diag204_x_part_hdr *)hdr)->rcpus;
0095 }
0096 
0097 static inline void part_hdr__part_name(enum diag204_format type, void *hdr,
0098                        char *name)
0099 {
0100     if (type == DIAG204_INFO_SIMPLE)
0101         memcpy(name, ((struct diag204_part_hdr *)hdr)->part_name,
0102                DIAG204_LPAR_NAME_LEN);
0103     else /* DIAG204_INFO_EXT */
0104         memcpy(name, ((struct diag204_x_part_hdr *)hdr)->part_name,
0105                DIAG204_LPAR_NAME_LEN);
0106     EBCASC(name, DIAG204_LPAR_NAME_LEN);
0107     name[DIAG204_LPAR_NAME_LEN] = 0;
0108     strim(name);
0109 }
0110 
0111 /* CPU info block */
0112 
0113 static inline int cpu_info__size(enum diag204_format type)
0114 {
0115     if (type == DIAG204_INFO_SIMPLE)
0116         return sizeof(struct diag204_cpu_info);
0117     else /* DIAG204_INFO_EXT */
0118         return sizeof(struct diag204_x_cpu_info);
0119 }
0120 
0121 static inline __u8 cpu_info__ctidx(enum diag204_format type, void *hdr)
0122 {
0123     if (type == DIAG204_INFO_SIMPLE)
0124         return ((struct diag204_cpu_info *)hdr)->ctidx;
0125     else /* DIAG204_INFO_EXT */
0126         return ((struct diag204_x_cpu_info *)hdr)->ctidx;
0127 }
0128 
0129 static inline __u16 cpu_info__cpu_addr(enum diag204_format type, void *hdr)
0130 {
0131     if (type == DIAG204_INFO_SIMPLE)
0132         return ((struct diag204_cpu_info *)hdr)->cpu_addr;
0133     else /* DIAG204_INFO_EXT */
0134         return ((struct diag204_x_cpu_info *)hdr)->cpu_addr;
0135 }
0136 
0137 static inline __u64 cpu_info__acc_time(enum diag204_format type, void *hdr)
0138 {
0139     if (type == DIAG204_INFO_SIMPLE)
0140         return ((struct diag204_cpu_info *)hdr)->acc_time;
0141     else /* DIAG204_INFO_EXT */
0142         return ((struct diag204_x_cpu_info *)hdr)->acc_time;
0143 }
0144 
0145 static inline __u64 cpu_info__lp_time(enum diag204_format type, void *hdr)
0146 {
0147     if (type == DIAG204_INFO_SIMPLE)
0148         return ((struct diag204_cpu_info *)hdr)->lp_time;
0149     else /* DIAG204_INFO_EXT */
0150         return ((struct diag204_x_cpu_info *)hdr)->lp_time;
0151 }
0152 
0153 static inline __u64 cpu_info__online_time(enum diag204_format type, void *hdr)
0154 {
0155     if (type == DIAG204_INFO_SIMPLE)
0156         return 0;   /* online_time not available in simple info */
0157     else /* DIAG204_INFO_EXT */
0158         return ((struct diag204_x_cpu_info *)hdr)->online_time;
0159 }
0160 
0161 /* Physical header */
0162 
0163 static inline int phys_hdr__size(enum diag204_format type)
0164 {
0165     if (type == DIAG204_INFO_SIMPLE)
0166         return sizeof(struct diag204_phys_hdr);
0167     else /* DIAG204_INFO_EXT */
0168         return sizeof(struct diag204_x_phys_hdr);
0169 }
0170 
0171 static inline __u8 phys_hdr__cpus(enum diag204_format type, void *hdr)
0172 {
0173     if (type == DIAG204_INFO_SIMPLE)
0174         return ((struct diag204_phys_hdr *)hdr)->cpus;
0175     else /* DIAG204_INFO_EXT */
0176         return ((struct diag204_x_phys_hdr *)hdr)->cpus;
0177 }
0178 
0179 /* Physical CPU info block */
0180 
0181 static inline int phys_cpu__size(enum diag204_format type)
0182 {
0183     if (type == DIAG204_INFO_SIMPLE)
0184         return sizeof(struct diag204_phys_cpu);
0185     else /* DIAG204_INFO_EXT */
0186         return sizeof(struct diag204_x_phys_cpu);
0187 }
0188 
0189 static inline __u16 phys_cpu__cpu_addr(enum diag204_format type, void *hdr)
0190 {
0191     if (type == DIAG204_INFO_SIMPLE)
0192         return ((struct diag204_phys_cpu *)hdr)->cpu_addr;
0193     else /* DIAG204_INFO_EXT */
0194         return ((struct diag204_x_phys_cpu *)hdr)->cpu_addr;
0195 }
0196 
0197 static inline __u64 phys_cpu__mgm_time(enum diag204_format type, void *hdr)
0198 {
0199     if (type == DIAG204_INFO_SIMPLE)
0200         return ((struct diag204_phys_cpu *)hdr)->mgm_time;
0201     else /* DIAG204_INFO_EXT */
0202         return ((struct diag204_x_phys_cpu *)hdr)->mgm_time;
0203 }
0204 
0205 static inline __u64 phys_cpu__ctidx(enum diag204_format type, void *hdr)
0206 {
0207     if (type == DIAG204_INFO_SIMPLE)
0208         return ((struct diag204_phys_cpu *)hdr)->ctidx;
0209     else /* DIAG204_INFO_EXT */
0210         return ((struct diag204_x_phys_cpu *)hdr)->ctidx;
0211 }
0212 
0213 /* Diagnose 204 functions */
0214 /*
0215  * For the old diag subcode 4 with simple data format we have to use real
0216  * memory. If we use subcode 6 or 7 with extended data format, we can (and
0217  * should) use vmalloc, since we need a lot of memory in that case. Currently
0218  * up to 93 pages!
0219  */
0220 
0221 static void diag204_free_buffer(void)
0222 {
0223     if (!diag204_buf)
0224         return;
0225     if (diag204_buf_vmalloc) {
0226         vfree(diag204_buf_vmalloc);
0227         diag204_buf_vmalloc = NULL;
0228     } else {
0229         free_pages((unsigned long) diag204_buf, 0);
0230     }
0231     diag204_buf = NULL;
0232 }
0233 
0234 static void *page_align_ptr(void *ptr)
0235 {
0236     return (void *) PAGE_ALIGN((unsigned long) ptr);
0237 }
0238 
0239 static void *diag204_alloc_vbuf(int pages)
0240 {
0241     /* The buffer has to be page aligned! */
0242     diag204_buf_vmalloc = vmalloc(array_size(PAGE_SIZE, (pages + 1)));
0243     if (!diag204_buf_vmalloc)
0244         return ERR_PTR(-ENOMEM);
0245     diag204_buf = page_align_ptr(diag204_buf_vmalloc);
0246     diag204_buf_pages = pages;
0247     return diag204_buf;
0248 }
0249 
0250 static void *diag204_alloc_rbuf(void)
0251 {
0252     diag204_buf = (void*)__get_free_pages(GFP_KERNEL,0);
0253     if (!diag204_buf)
0254         return ERR_PTR(-ENOMEM);
0255     diag204_buf_pages = 1;
0256     return diag204_buf;
0257 }
0258 
0259 static void *diag204_get_buffer(enum diag204_format fmt, int *pages)
0260 {
0261     if (diag204_buf) {
0262         *pages = diag204_buf_pages;
0263         return diag204_buf;
0264     }
0265     if (fmt == DIAG204_INFO_SIMPLE) {
0266         *pages = 1;
0267         return diag204_alloc_rbuf();
0268     } else {/* DIAG204_INFO_EXT */
0269         *pages = diag204((unsigned long)DIAG204_SUBC_RSI |
0270                  (unsigned long)DIAG204_INFO_EXT, 0, NULL);
0271         if (*pages <= 0)
0272             return ERR_PTR(-ENOSYS);
0273         else
0274             return diag204_alloc_vbuf(*pages);
0275     }
0276 }
0277 
0278 /*
0279  * diag204_probe() has to find out, which type of diagnose 204 implementation
0280  * we have on our machine. Currently there are three possible scanarios:
0281  *   - subcode 4   + simple data format (only one page)
0282  *   - subcode 4-6 + extended data format
0283  *   - subcode 4-7 + extended data format
0284  *
0285  * Subcode 5 is used to retrieve the size of the data, provided by subcodes
0286  * 6 and 7. Subcode 7 basically has the same function as subcode 6. In addition
0287  * to subcode 6 it provides also information about secondary cpus.
0288  * In order to get as much information as possible, we first try
0289  * subcode 7, then 6 and if both fail, we use subcode 4.
0290  */
0291 
0292 static int diag204_probe(void)
0293 {
0294     void *buf;
0295     int pages, rc;
0296 
0297     buf = diag204_get_buffer(DIAG204_INFO_EXT, &pages);
0298     if (!IS_ERR(buf)) {
0299         if (diag204((unsigned long)DIAG204_SUBC_STIB7 |
0300                 (unsigned long)DIAG204_INFO_EXT, pages, buf) >= 0) {
0301             diag204_store_sc = DIAG204_SUBC_STIB7;
0302             diag204_info_type = DIAG204_INFO_EXT;
0303             goto out;
0304         }
0305         if (diag204((unsigned long)DIAG204_SUBC_STIB6 |
0306                 (unsigned long)DIAG204_INFO_EXT, pages, buf) >= 0) {
0307             diag204_store_sc = DIAG204_SUBC_STIB6;
0308             diag204_info_type = DIAG204_INFO_EXT;
0309             goto out;
0310         }
0311         diag204_free_buffer();
0312     }
0313 
0314     /* subcodes 6 and 7 failed, now try subcode 4 */
0315 
0316     buf = diag204_get_buffer(DIAG204_INFO_SIMPLE, &pages);
0317     if (IS_ERR(buf)) {
0318         rc = PTR_ERR(buf);
0319         goto fail_alloc;
0320     }
0321     if (diag204((unsigned long)DIAG204_SUBC_STIB4 |
0322             (unsigned long)DIAG204_INFO_SIMPLE, pages, buf) >= 0) {
0323         diag204_store_sc = DIAG204_SUBC_STIB4;
0324         diag204_info_type = DIAG204_INFO_SIMPLE;
0325         goto out;
0326     } else {
0327         rc = -ENOSYS;
0328         goto fail_store;
0329     }
0330 out:
0331     rc = 0;
0332 fail_store:
0333     diag204_free_buffer();
0334 fail_alloc:
0335     return rc;
0336 }
0337 
0338 static int diag204_do_store(void *buf, int pages)
0339 {
0340     int rc;
0341 
0342     rc = diag204((unsigned long) diag204_store_sc |
0343              (unsigned long) diag204_info_type, pages, buf);
0344     return rc < 0 ? -ENOSYS : 0;
0345 }
0346 
0347 static void *diag204_store(void)
0348 {
0349     void *buf;
0350     int pages, rc;
0351 
0352     buf = diag204_get_buffer(diag204_info_type, &pages);
0353     if (IS_ERR(buf))
0354         goto out;
0355     rc = diag204_do_store(buf, pages);
0356     if (rc)
0357         return ERR_PTR(rc);
0358 out:
0359     return buf;
0360 }
0361 
0362 /* Diagnose 224 functions */
0363 
0364 static int diag224_get_name_table(void)
0365 {
0366     /* memory must be below 2GB */
0367     diag224_cpu_names = (char *) __get_free_page(GFP_KERNEL | GFP_DMA);
0368     if (!diag224_cpu_names)
0369         return -ENOMEM;
0370     if (diag224(diag224_cpu_names)) {
0371         free_page((unsigned long) diag224_cpu_names);
0372         return -EOPNOTSUPP;
0373     }
0374     EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16);
0375     return 0;
0376 }
0377 
0378 static void diag224_delete_name_table(void)
0379 {
0380     free_page((unsigned long) diag224_cpu_names);
0381 }
0382 
0383 static int diag224_idx2name(int index, char *name)
0384 {
0385     memcpy(name, diag224_cpu_names + ((index + 1) * DIAG204_CPU_NAME_LEN),
0386            DIAG204_CPU_NAME_LEN);
0387     name[DIAG204_CPU_NAME_LEN] = 0;
0388     strim(name);
0389     return 0;
0390 }
0391 
0392 struct dbfs_d204_hdr {
0393     u64 len;        /* Length of d204 buffer without header */
0394     u16 version;    /* Version of header */
0395     u8  sc;     /* Used subcode */
0396     char    reserved[53];
0397 } __attribute__ ((packed));
0398 
0399 struct dbfs_d204 {
0400     struct dbfs_d204_hdr    hdr;    /* 64 byte header */
0401     char            buf[];  /* d204 buffer */
0402 } __attribute__ ((packed));
0403 
0404 static int dbfs_d204_create(void **data, void **data_free_ptr, size_t *size)
0405 {
0406     struct dbfs_d204 *d204;
0407     int rc, buf_size;
0408     void *base;
0409 
0410     buf_size = PAGE_SIZE * (diag204_buf_pages + 1) + sizeof(d204->hdr);
0411     base = vzalloc(buf_size);
0412     if (!base)
0413         return -ENOMEM;
0414     d204 = page_align_ptr(base + sizeof(d204->hdr)) - sizeof(d204->hdr);
0415     rc = diag204_do_store(d204->buf, diag204_buf_pages);
0416     if (rc) {
0417         vfree(base);
0418         return rc;
0419     }
0420     d204->hdr.version = DBFS_D204_HDR_VERSION;
0421     d204->hdr.len = PAGE_SIZE * diag204_buf_pages;
0422     d204->hdr.sc = diag204_store_sc;
0423     *data = d204;
0424     *data_free_ptr = base;
0425     *size = d204->hdr.len + sizeof(struct dbfs_d204_hdr);
0426     return 0;
0427 }
0428 
0429 static struct hypfs_dbfs_file dbfs_file_d204 = {
0430     .name       = "diag_204",
0431     .data_create    = dbfs_d204_create,
0432     .data_free  = vfree,
0433 };
0434 
0435 __init int hypfs_diag_init(void)
0436 {
0437     int rc;
0438 
0439     if (diag204_probe()) {
0440         pr_info("The hardware system does not support hypfs\n");
0441         return -ENODATA;
0442     }
0443 
0444     if (diag204_info_type == DIAG204_INFO_EXT)
0445         hypfs_dbfs_create_file(&dbfs_file_d204);
0446 
0447     if (MACHINE_IS_LPAR) {
0448         rc = diag224_get_name_table();
0449         if (rc) {
0450             pr_err("The hardware system does not provide all "
0451                    "functions required by hypfs\n");
0452             debugfs_remove(dbfs_d204_file);
0453             return rc;
0454         }
0455     }
0456     return 0;
0457 }
0458 
0459 void hypfs_diag_exit(void)
0460 {
0461     debugfs_remove(dbfs_d204_file);
0462     diag224_delete_name_table();
0463     diag204_free_buffer();
0464     hypfs_dbfs_remove_file(&dbfs_file_d204);
0465 }
0466 
0467 /*
0468  * Functions to create the directory structure
0469  * *******************************************
0470  */
0471 
0472 static int hypfs_create_cpu_files(struct dentry *cpus_dir, void *cpu_info)
0473 {
0474     struct dentry *cpu_dir;
0475     char buffer[TMP_SIZE];
0476     void *rc;
0477 
0478     snprintf(buffer, TMP_SIZE, "%d", cpu_info__cpu_addr(diag204_info_type,
0479                                 cpu_info));
0480     cpu_dir = hypfs_mkdir(cpus_dir, buffer);
0481     rc = hypfs_create_u64(cpu_dir, "mgmtime",
0482                   cpu_info__acc_time(diag204_info_type, cpu_info) -
0483                   cpu_info__lp_time(diag204_info_type, cpu_info));
0484     if (IS_ERR(rc))
0485         return PTR_ERR(rc);
0486     rc = hypfs_create_u64(cpu_dir, "cputime",
0487                   cpu_info__lp_time(diag204_info_type, cpu_info));
0488     if (IS_ERR(rc))
0489         return PTR_ERR(rc);
0490     if (diag204_info_type == DIAG204_INFO_EXT) {
0491         rc = hypfs_create_u64(cpu_dir, "onlinetime",
0492                       cpu_info__online_time(diag204_info_type,
0493                                 cpu_info));
0494         if (IS_ERR(rc))
0495             return PTR_ERR(rc);
0496     }
0497     diag224_idx2name(cpu_info__ctidx(diag204_info_type, cpu_info), buffer);
0498     rc = hypfs_create_str(cpu_dir, "type", buffer);
0499     return PTR_ERR_OR_ZERO(rc);
0500 }
0501 
0502 static void *hypfs_create_lpar_files(struct dentry *systems_dir, void *part_hdr)
0503 {
0504     struct dentry *cpus_dir;
0505     struct dentry *lpar_dir;
0506     char lpar_name[DIAG204_LPAR_NAME_LEN + 1];
0507     void *cpu_info;
0508     int i;
0509 
0510     part_hdr__part_name(diag204_info_type, part_hdr, lpar_name);
0511     lpar_name[DIAG204_LPAR_NAME_LEN] = 0;
0512     lpar_dir = hypfs_mkdir(systems_dir, lpar_name);
0513     if (IS_ERR(lpar_dir))
0514         return lpar_dir;
0515     cpus_dir = hypfs_mkdir(lpar_dir, "cpus");
0516     if (IS_ERR(cpus_dir))
0517         return cpus_dir;
0518     cpu_info = part_hdr + part_hdr__size(diag204_info_type);
0519     for (i = 0; i < part_hdr__rcpus(diag204_info_type, part_hdr); i++) {
0520         int rc;
0521         rc = hypfs_create_cpu_files(cpus_dir, cpu_info);
0522         if (rc)
0523             return ERR_PTR(rc);
0524         cpu_info += cpu_info__size(diag204_info_type);
0525     }
0526     return cpu_info;
0527 }
0528 
0529 static int hypfs_create_phys_cpu_files(struct dentry *cpus_dir, void *cpu_info)
0530 {
0531     struct dentry *cpu_dir;
0532     char buffer[TMP_SIZE];
0533     void *rc;
0534 
0535     snprintf(buffer, TMP_SIZE, "%i", phys_cpu__cpu_addr(diag204_info_type,
0536                                 cpu_info));
0537     cpu_dir = hypfs_mkdir(cpus_dir, buffer);
0538     if (IS_ERR(cpu_dir))
0539         return PTR_ERR(cpu_dir);
0540     rc = hypfs_create_u64(cpu_dir, "mgmtime",
0541                   phys_cpu__mgm_time(diag204_info_type, cpu_info));
0542     if (IS_ERR(rc))
0543         return PTR_ERR(rc);
0544     diag224_idx2name(phys_cpu__ctidx(diag204_info_type, cpu_info), buffer);
0545     rc = hypfs_create_str(cpu_dir, "type", buffer);
0546     return PTR_ERR_OR_ZERO(rc);
0547 }
0548 
0549 static void *hypfs_create_phys_files(struct dentry *parent_dir, void *phys_hdr)
0550 {
0551     int i;
0552     void *cpu_info;
0553     struct dentry *cpus_dir;
0554 
0555     cpus_dir = hypfs_mkdir(parent_dir, "cpus");
0556     if (IS_ERR(cpus_dir))
0557         return cpus_dir;
0558     cpu_info = phys_hdr + phys_hdr__size(diag204_info_type);
0559     for (i = 0; i < phys_hdr__cpus(diag204_info_type, phys_hdr); i++) {
0560         int rc;
0561         rc = hypfs_create_phys_cpu_files(cpus_dir, cpu_info);
0562         if (rc)
0563             return ERR_PTR(rc);
0564         cpu_info += phys_cpu__size(diag204_info_type);
0565     }
0566     return cpu_info;
0567 }
0568 
0569 int hypfs_diag_create_files(struct dentry *root)
0570 {
0571     struct dentry *systems_dir, *hyp_dir;
0572     void *time_hdr, *part_hdr;
0573     int i, rc;
0574     void *buffer, *ptr;
0575 
0576     buffer = diag204_store();
0577     if (IS_ERR(buffer))
0578         return PTR_ERR(buffer);
0579 
0580     systems_dir = hypfs_mkdir(root, "systems");
0581     if (IS_ERR(systems_dir)) {
0582         rc = PTR_ERR(systems_dir);
0583         goto err_out;
0584     }
0585     time_hdr = (struct x_info_blk_hdr *)buffer;
0586     part_hdr = time_hdr + info_blk_hdr__size(diag204_info_type);
0587     for (i = 0; i < info_blk_hdr__npar(diag204_info_type, time_hdr); i++) {
0588         part_hdr = hypfs_create_lpar_files(systems_dir, part_hdr);
0589         if (IS_ERR(part_hdr)) {
0590             rc = PTR_ERR(part_hdr);
0591             goto err_out;
0592         }
0593     }
0594     if (info_blk_hdr__flags(diag204_info_type, time_hdr) &
0595         DIAG204_LPAR_PHYS_FLG) {
0596         ptr = hypfs_create_phys_files(root, part_hdr);
0597         if (IS_ERR(ptr)) {
0598             rc = PTR_ERR(ptr);
0599             goto err_out;
0600         }
0601     }
0602     hyp_dir = hypfs_mkdir(root, "hyp");
0603     if (IS_ERR(hyp_dir)) {
0604         rc = PTR_ERR(hyp_dir);
0605         goto err_out;
0606     }
0607     ptr = hypfs_create_str(hyp_dir, "type", "LPAR Hypervisor");
0608     if (IS_ERR(ptr)) {
0609         rc = PTR_ERR(ptr);
0610         goto err_out;
0611     }
0612     rc = 0;
0613 
0614 err_out:
0615     return rc;
0616 }