include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[linux-2.6.git] / arch / s390 / hypfs / hypfs_diag.c
1 /*
2  *  arch/s390/hypfs/hypfs_diag.c
3  *    Hypervisor filesystem for Linux on s390. Diag 204 and 224
4  *    implementation.
5  *
6  *    Copyright IBM Corp. 2006, 2008
7  *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
8  */
9
10 #define KMSG_COMPONENT "hypfs"
11 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
12
13 #include <linux/types.h>
14 #include <linux/errno.h>
15 #include <linux/slab.h>
16 #include <linux/string.h>
17 #include <linux/vmalloc.h>
18 #include <asm/ebcdic.h>
19 #include "hypfs.h"
20
21 #define LPAR_NAME_LEN 8         /* lpar name len in diag 204 data */
22 #define CPU_NAME_LEN 16         /* type name len of cpus in diag224 name table */
23 #define TMP_SIZE 64             /* size of temporary buffers */
24
25 /* diag 204 subcodes */
26 enum diag204_sc {
27         SUBC_STIB4 = 4,
28         SUBC_RSI = 5,
29         SUBC_STIB6 = 6,
30         SUBC_STIB7 = 7
31 };
32
33 /* The two available diag 204 data formats */
34 enum diag204_format {
35         INFO_SIMPLE = 0,
36         INFO_EXT = 0x00010000
37 };
38
39 /* bit is set in flags, when physical cpu info is included in diag 204 data */
40 #define LPAR_PHYS_FLG  0x80
41
42 static char *diag224_cpu_names;                 /* diag 224 name table */
43 static enum diag204_sc diag204_store_sc;        /* used subcode for store */
44 static enum diag204_format diag204_info_type;   /* used diag 204 data format */
45
46 static void *diag204_buf;               /* 4K aligned buffer for diag204 data */
47 static void *diag204_buf_vmalloc;       /* vmalloc pointer for diag204 data */
48 static int diag204_buf_pages;           /* number of pages for diag204 data */
49
50 /*
51  * DIAG 204 data structures and member access functions.
52  *
53  * Since we have two different diag 204 data formats for old and new s390
54  * machines, we do not access the structs directly, but use getter functions for
55  * each struct member instead. This should make the code more readable.
56  */
57
58 /* Time information block */
59
60 struct info_blk_hdr {
61         __u8  npar;
62         __u8  flags;
63         __u16 tslice;
64         __u16 phys_cpus;
65         __u16 this_part;
66         __u64 curtod;
67 } __attribute__ ((packed));
68
69 struct x_info_blk_hdr {
70         __u8  npar;
71         __u8  flags;
72         __u16 tslice;
73         __u16 phys_cpus;
74         __u16 this_part;
75         __u64 curtod1;
76         __u64 curtod2;
77         char reserved[40];
78 } __attribute__ ((packed));
79
80 static inline int info_blk_hdr__size(enum diag204_format type)
81 {
82         if (type == INFO_SIMPLE)
83                 return sizeof(struct info_blk_hdr);
84         else /* INFO_EXT */
85                 return sizeof(struct x_info_blk_hdr);
86 }
87
88 static inline __u8 info_blk_hdr__npar(enum diag204_format type, void *hdr)
89 {
90         if (type == INFO_SIMPLE)
91                 return ((struct info_blk_hdr *)hdr)->npar;
92         else /* INFO_EXT */
93                 return ((struct x_info_blk_hdr *)hdr)->npar;
94 }
95
96 static inline __u8 info_blk_hdr__flags(enum diag204_format type, void *hdr)
97 {
98         if (type == INFO_SIMPLE)
99                 return ((struct info_blk_hdr *)hdr)->flags;
100         else /* INFO_EXT */
101                 return ((struct x_info_blk_hdr *)hdr)->flags;
102 }
103
104 static inline __u16 info_blk_hdr__pcpus(enum diag204_format type, void *hdr)
105 {
106         if (type == INFO_SIMPLE)
107                 return ((struct info_blk_hdr *)hdr)->phys_cpus;
108         else /* INFO_EXT */
109                 return ((struct x_info_blk_hdr *)hdr)->phys_cpus;
110 }
111
112 /* Partition header */
113
114 struct part_hdr {
115         __u8 pn;
116         __u8 cpus;
117         char reserved[6];
118         char part_name[LPAR_NAME_LEN];
119 } __attribute__ ((packed));
120
121 struct x_part_hdr {
122         __u8  pn;
123         __u8  cpus;
124         __u8  rcpus;
125         __u8  pflag;
126         __u32 mlu;
127         char  part_name[LPAR_NAME_LEN];
128         char  lpc_name[8];
129         char  os_name[8];
130         __u64 online_cs;
131         __u64 online_es;
132         __u8  upid;
133         char  reserved1[3];
134         __u32 group_mlu;
135         char  group_name[8];
136         char  reserved2[32];
137 } __attribute__ ((packed));
138
139 static inline int part_hdr__size(enum diag204_format type)
140 {
141         if (type == INFO_SIMPLE)
142                 return sizeof(struct part_hdr);
143         else /* INFO_EXT */
144                 return sizeof(struct x_part_hdr);
145 }
146
147 static inline __u8 part_hdr__rcpus(enum diag204_format type, void *hdr)
148 {
149         if (type == INFO_SIMPLE)
150                 return ((struct part_hdr *)hdr)->cpus;
151         else /* INFO_EXT */
152                 return ((struct x_part_hdr *)hdr)->rcpus;
153 }
154
155 static inline void part_hdr__part_name(enum diag204_format type, void *hdr,
156                                        char *name)
157 {
158         if (type == INFO_SIMPLE)
159                 memcpy(name, ((struct part_hdr *)hdr)->part_name,
160                        LPAR_NAME_LEN);
161         else /* INFO_EXT */
162                 memcpy(name, ((struct x_part_hdr *)hdr)->part_name,
163                        LPAR_NAME_LEN);
164         EBCASC(name, LPAR_NAME_LEN);
165         name[LPAR_NAME_LEN] = 0;
166         strim(name);
167 }
168
169 struct cpu_info {
170         __u16 cpu_addr;
171         char  reserved1[2];
172         __u8  ctidx;
173         __u8  cflag;
174         __u16 weight;
175         __u64 acc_time;
176         __u64 lp_time;
177 } __attribute__ ((packed));
178
179 struct x_cpu_info {
180         __u16 cpu_addr;
181         char  reserved1[2];
182         __u8  ctidx;
183         __u8  cflag;
184         __u16 weight;
185         __u64 acc_time;
186         __u64 lp_time;
187         __u16 min_weight;
188         __u16 cur_weight;
189         __u16 max_weight;
190         char  reseved2[2];
191         __u64 online_time;
192         __u64 wait_time;
193         __u32 pma_weight;
194         __u32 polar_weight;
195         char  reserved3[40];
196 } __attribute__ ((packed));
197
198 /* CPU info block */
199
200 static inline int cpu_info__size(enum diag204_format type)
201 {
202         if (type == INFO_SIMPLE)
203                 return sizeof(struct cpu_info);
204         else /* INFO_EXT */
205                 return sizeof(struct x_cpu_info);
206 }
207
208 static inline __u8 cpu_info__ctidx(enum diag204_format type, void *hdr)
209 {
210         if (type == INFO_SIMPLE)
211                 return ((struct cpu_info *)hdr)->ctidx;
212         else /* INFO_EXT */
213                 return ((struct x_cpu_info *)hdr)->ctidx;
214 }
215
216 static inline __u16 cpu_info__cpu_addr(enum diag204_format type, void *hdr)
217 {
218         if (type == INFO_SIMPLE)
219                 return ((struct cpu_info *)hdr)->cpu_addr;
220         else /* INFO_EXT */
221                 return ((struct x_cpu_info *)hdr)->cpu_addr;
222 }
223
224 static inline __u64 cpu_info__acc_time(enum diag204_format type, void *hdr)
225 {
226         if (type == INFO_SIMPLE)
227                 return ((struct cpu_info *)hdr)->acc_time;
228         else /* INFO_EXT */
229                 return ((struct x_cpu_info *)hdr)->acc_time;
230 }
231
232 static inline __u64 cpu_info__lp_time(enum diag204_format type, void *hdr)
233 {
234         if (type == INFO_SIMPLE)
235                 return ((struct cpu_info *)hdr)->lp_time;
236         else /* INFO_EXT */
237                 return ((struct x_cpu_info *)hdr)->lp_time;
238 }
239
240 static inline __u64 cpu_info__online_time(enum diag204_format type, void *hdr)
241 {
242         if (type == INFO_SIMPLE)
243                 return 0;       /* online_time not available in simple info */
244         else /* INFO_EXT */
245                 return ((struct x_cpu_info *)hdr)->online_time;
246 }
247
248 /* Physical header */
249
250 struct phys_hdr {
251         char reserved1[1];
252         __u8 cpus;
253         char reserved2[6];
254         char mgm_name[8];
255 } __attribute__ ((packed));
256
257 struct x_phys_hdr {
258         char reserved1[1];
259         __u8 cpus;
260         char reserved2[6];
261         char mgm_name[8];
262         char reserved3[80];
263 } __attribute__ ((packed));
264
265 static inline int phys_hdr__size(enum diag204_format type)
266 {
267         if (type == INFO_SIMPLE)
268                 return sizeof(struct phys_hdr);
269         else /* INFO_EXT */
270                 return sizeof(struct x_phys_hdr);
271 }
272
273 static inline __u8 phys_hdr__cpus(enum diag204_format type, void *hdr)
274 {
275         if (type == INFO_SIMPLE)
276                 return ((struct phys_hdr *)hdr)->cpus;
277         else /* INFO_EXT */
278                 return ((struct x_phys_hdr *)hdr)->cpus;
279 }
280
281 /* Physical CPU info block */
282
283 struct phys_cpu {
284         __u16 cpu_addr;
285         char  reserved1[2];
286         __u8  ctidx;
287         char  reserved2[3];
288         __u64 mgm_time;
289         char  reserved3[8];
290 } __attribute__ ((packed));
291
292 struct x_phys_cpu {
293         __u16 cpu_addr;
294         char  reserved1[2];
295         __u8  ctidx;
296         char  reserved2[3];
297         __u64 mgm_time;
298         char  reserved3[80];
299 } __attribute__ ((packed));
300
301 static inline int phys_cpu__size(enum diag204_format type)
302 {
303         if (type == INFO_SIMPLE)
304                 return sizeof(struct phys_cpu);
305         else /* INFO_EXT */
306                 return sizeof(struct x_phys_cpu);
307 }
308
309 static inline __u16 phys_cpu__cpu_addr(enum diag204_format type, void *hdr)
310 {
311         if (type == INFO_SIMPLE)
312                 return ((struct phys_cpu *)hdr)->cpu_addr;
313         else /* INFO_EXT */
314                 return ((struct x_phys_cpu *)hdr)->cpu_addr;
315 }
316
317 static inline __u64 phys_cpu__mgm_time(enum diag204_format type, void *hdr)
318 {
319         if (type == INFO_SIMPLE)
320                 return ((struct phys_cpu *)hdr)->mgm_time;
321         else /* INFO_EXT */
322                 return ((struct x_phys_cpu *)hdr)->mgm_time;
323 }
324
325 static inline __u64 phys_cpu__ctidx(enum diag204_format type, void *hdr)
326 {
327         if (type == INFO_SIMPLE)
328                 return ((struct phys_cpu *)hdr)->ctidx;
329         else /* INFO_EXT */
330                 return ((struct x_phys_cpu *)hdr)->ctidx;
331 }
332
333 /* Diagnose 204 functions */
334
335 static int diag204(unsigned long subcode, unsigned long size, void *addr)
336 {
337         register unsigned long _subcode asm("0") = subcode;
338         register unsigned long _size asm("1") = size;
339
340         asm volatile(
341                 "       diag    %2,%0,0x204\n"
342                 "0:\n"
343                 EX_TABLE(0b,0b)
344                 : "+d" (_subcode), "+d" (_size) : "d" (addr) : "memory");
345         if (_subcode)
346                 return -1;
347         return _size;
348 }
349
350 /*
351  * For the old diag subcode 4 with simple data format we have to use real
352  * memory. If we use subcode 6 or 7 with extended data format, we can (and
353  * should) use vmalloc, since we need a lot of memory in that case. Currently
354  * up to 93 pages!
355  */
356
357 static void diag204_free_buffer(void)
358 {
359         if (!diag204_buf)
360                 return;
361         if (diag204_buf_vmalloc) {
362                 vfree(diag204_buf_vmalloc);
363                 diag204_buf_vmalloc = NULL;
364         } else {
365                 free_pages((unsigned long) diag204_buf, 0);
366         }
367         diag204_buf_pages = 0;
368         diag204_buf = NULL;
369 }
370
371 static void *diag204_alloc_vbuf(int pages)
372 {
373         /* The buffer has to be page aligned! */
374         diag204_buf_vmalloc = vmalloc(PAGE_SIZE * (pages + 1));
375         if (!diag204_buf_vmalloc)
376                 return ERR_PTR(-ENOMEM);
377         diag204_buf = (void*)((unsigned long)diag204_buf_vmalloc
378                                 & ~0xfffUL) + 0x1000;
379         diag204_buf_pages = pages;
380         return diag204_buf;
381 }
382
383 static void *diag204_alloc_rbuf(void)
384 {
385         diag204_buf = (void*)__get_free_pages(GFP_KERNEL,0);
386         if (!diag204_buf)
387                 return ERR_PTR(-ENOMEM);
388         diag204_buf_pages = 1;
389         return diag204_buf;
390 }
391
392 static void *diag204_get_buffer(enum diag204_format fmt, int *pages)
393 {
394         if (diag204_buf) {
395                 *pages = diag204_buf_pages;
396                 return diag204_buf;
397         }
398         if (fmt == INFO_SIMPLE) {
399                 *pages = 1;
400                 return diag204_alloc_rbuf();
401         } else {/* INFO_EXT */
402                 *pages = diag204((unsigned long)SUBC_RSI |
403                                  (unsigned long)INFO_EXT, 0, NULL);
404                 if (*pages <= 0)
405                         return ERR_PTR(-ENOSYS);
406                 else
407                         return diag204_alloc_vbuf(*pages);
408         }
409 }
410
411 /*
412  * diag204_probe() has to find out, which type of diagnose 204 implementation
413  * we have on our machine. Currently there are three possible scanarios:
414  *   - subcode 4   + simple data format (only one page)
415  *   - subcode 4-6 + extended data format
416  *   - subcode 4-7 + extended data format
417  *
418  * Subcode 5 is used to retrieve the size of the data, provided by subcodes
419  * 6 and 7. Subcode 7 basically has the same function as subcode 6. In addition
420  * to subcode 6 it provides also information about secondary cpus.
421  * In order to get as much information as possible, we first try
422  * subcode 7, then 6 and if both fail, we use subcode 4.
423  */
424
425 static int diag204_probe(void)
426 {
427         void *buf;
428         int pages, rc;
429
430         buf = diag204_get_buffer(INFO_EXT, &pages);
431         if (!IS_ERR(buf)) {
432                 if (diag204((unsigned long)SUBC_STIB7 |
433                             (unsigned long)INFO_EXT, pages, buf) >= 0) {
434                         diag204_store_sc = SUBC_STIB7;
435                         diag204_info_type = INFO_EXT;
436                         goto out;
437                 }
438                 if (diag204((unsigned long)SUBC_STIB6 |
439                             (unsigned long)INFO_EXT, pages, buf) >= 0) {
440                         diag204_store_sc = SUBC_STIB6;
441                         diag204_info_type = INFO_EXT;
442                         goto out;
443                 }
444                 diag204_free_buffer();
445         }
446
447         /* subcodes 6 and 7 failed, now try subcode 4 */
448
449         buf = diag204_get_buffer(INFO_SIMPLE, &pages);
450         if (IS_ERR(buf)) {
451                 rc = PTR_ERR(buf);
452                 goto fail_alloc;
453         }
454         if (diag204((unsigned long)SUBC_STIB4 |
455                     (unsigned long)INFO_SIMPLE, pages, buf) >= 0) {
456                 diag204_store_sc = SUBC_STIB4;
457                 diag204_info_type = INFO_SIMPLE;
458                 goto out;
459         } else {
460                 rc = -ENOSYS;
461                 goto fail_store;
462         }
463 out:
464         rc = 0;
465 fail_store:
466         diag204_free_buffer();
467 fail_alloc:
468         return rc;
469 }
470
471 static void *diag204_store(void)
472 {
473         void *buf;
474         int pages;
475
476         buf = diag204_get_buffer(diag204_info_type, &pages);
477         if (IS_ERR(buf))
478                 goto out;
479         if (diag204((unsigned long)diag204_store_sc |
480                     (unsigned long)diag204_info_type, pages, buf) < 0)
481                 return ERR_PTR(-ENOSYS);
482 out:
483         return buf;
484 }
485
486 /* Diagnose 224 functions */
487
488 static int diag224(void *ptr)
489 {
490         int rc = -EOPNOTSUPP;
491
492         asm volatile(
493                 "       diag    %1,%2,0x224\n"
494                 "0:     lhi     %0,0x0\n"
495                 "1:\n"
496                 EX_TABLE(0b,1b)
497                 : "+d" (rc) :"d" (0), "d" (ptr) : "memory");
498         return rc;
499 }
500
501 static int diag224_get_name_table(void)
502 {
503         /* memory must be below 2GB */
504         diag224_cpu_names = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
505         if (!diag224_cpu_names)
506                 return -ENOMEM;
507         if (diag224(diag224_cpu_names)) {
508                 kfree(diag224_cpu_names);
509                 return -EOPNOTSUPP;
510         }
511         EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16);
512         return 0;
513 }
514
515 static void diag224_delete_name_table(void)
516 {
517         kfree(diag224_cpu_names);
518 }
519
520 static int diag224_idx2name(int index, char *name)
521 {
522         memcpy(name, diag224_cpu_names + ((index + 1) * CPU_NAME_LEN),
523                 CPU_NAME_LEN);
524         name[CPU_NAME_LEN] = 0;
525         strim(name);
526         return 0;
527 }
528
529 __init int hypfs_diag_init(void)
530 {
531         int rc;
532
533         if (diag204_probe()) {
534                 pr_err("The hardware system does not support hypfs\n");
535                 return -ENODATA;
536         }
537         rc = diag224_get_name_table();
538         if (rc) {
539                 diag204_free_buffer();
540                 pr_err("The hardware system does not provide all "
541                        "functions required by hypfs\n");
542         }
543         return rc;
544 }
545
546 void hypfs_diag_exit(void)
547 {
548         diag224_delete_name_table();
549         diag204_free_buffer();
550 }
551
552 /*
553  * Functions to create the directory structure
554  * *******************************************
555  */
556
557 static int hypfs_create_cpu_files(struct super_block *sb,
558                                   struct dentry *cpus_dir, void *cpu_info)
559 {
560         struct dentry *cpu_dir;
561         char buffer[TMP_SIZE];
562         void *rc;
563
564         snprintf(buffer, TMP_SIZE, "%d", cpu_info__cpu_addr(diag204_info_type,
565                                                             cpu_info));
566         cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer);
567         rc = hypfs_create_u64(sb, cpu_dir, "mgmtime",
568                               cpu_info__acc_time(diag204_info_type, cpu_info) -
569                               cpu_info__lp_time(diag204_info_type, cpu_info));
570         if (IS_ERR(rc))
571                 return PTR_ERR(rc);
572         rc = hypfs_create_u64(sb, cpu_dir, "cputime",
573                               cpu_info__lp_time(diag204_info_type, cpu_info));
574         if (IS_ERR(rc))
575                 return PTR_ERR(rc);
576         if (diag204_info_type == INFO_EXT) {
577                 rc = hypfs_create_u64(sb, cpu_dir, "onlinetime",
578                                       cpu_info__online_time(diag204_info_type,
579                                                             cpu_info));
580                 if (IS_ERR(rc))
581                         return PTR_ERR(rc);
582         }
583         diag224_idx2name(cpu_info__ctidx(diag204_info_type, cpu_info), buffer);
584         rc = hypfs_create_str(sb, cpu_dir, "type", buffer);
585         if (IS_ERR(rc))
586                 return PTR_ERR(rc);
587         return 0;
588 }
589
590 static void *hypfs_create_lpar_files(struct super_block *sb,
591                                      struct dentry *systems_dir, void *part_hdr)
592 {
593         struct dentry *cpus_dir;
594         struct dentry *lpar_dir;
595         char lpar_name[LPAR_NAME_LEN + 1];
596         void *cpu_info;
597         int i;
598
599         part_hdr__part_name(diag204_info_type, part_hdr, lpar_name);
600         lpar_name[LPAR_NAME_LEN] = 0;
601         lpar_dir = hypfs_mkdir(sb, systems_dir, lpar_name);
602         if (IS_ERR(lpar_dir))
603                 return lpar_dir;
604         cpus_dir = hypfs_mkdir(sb, lpar_dir, "cpus");
605         if (IS_ERR(cpus_dir))
606                 return cpus_dir;
607         cpu_info = part_hdr + part_hdr__size(diag204_info_type);
608         for (i = 0; i < part_hdr__rcpus(diag204_info_type, part_hdr); i++) {
609                 int rc;
610                 rc = hypfs_create_cpu_files(sb, cpus_dir, cpu_info);
611                 if (rc)
612                         return ERR_PTR(rc);
613                 cpu_info += cpu_info__size(diag204_info_type);
614         }
615         return cpu_info;
616 }
617
618 static int hypfs_create_phys_cpu_files(struct super_block *sb,
619                                        struct dentry *cpus_dir, void *cpu_info)
620 {
621         struct dentry *cpu_dir;
622         char buffer[TMP_SIZE];
623         void *rc;
624
625         snprintf(buffer, TMP_SIZE, "%i", phys_cpu__cpu_addr(diag204_info_type,
626                                                             cpu_info));
627         cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer);
628         if (IS_ERR(cpu_dir))
629                 return PTR_ERR(cpu_dir);
630         rc = hypfs_create_u64(sb, cpu_dir, "mgmtime",
631                               phys_cpu__mgm_time(diag204_info_type, cpu_info));
632         if (IS_ERR(rc))
633                 return PTR_ERR(rc);
634         diag224_idx2name(phys_cpu__ctidx(diag204_info_type, cpu_info), buffer);
635         rc = hypfs_create_str(sb, cpu_dir, "type", buffer);
636         if (IS_ERR(rc))
637                 return PTR_ERR(rc);
638         return 0;
639 }
640
641 static void *hypfs_create_phys_files(struct super_block *sb,
642                                      struct dentry *parent_dir, void *phys_hdr)
643 {
644         int i;
645         void *cpu_info;
646         struct dentry *cpus_dir;
647
648         cpus_dir = hypfs_mkdir(sb, parent_dir, "cpus");
649         if (IS_ERR(cpus_dir))
650                 return cpus_dir;
651         cpu_info = phys_hdr + phys_hdr__size(diag204_info_type);
652         for (i = 0; i < phys_hdr__cpus(diag204_info_type, phys_hdr); i++) {
653                 int rc;
654                 rc = hypfs_create_phys_cpu_files(sb, cpus_dir, cpu_info);
655                 if (rc)
656                         return ERR_PTR(rc);
657                 cpu_info += phys_cpu__size(diag204_info_type);
658         }
659         return cpu_info;
660 }
661
662 int hypfs_diag_create_files(struct super_block *sb, struct dentry *root)
663 {
664         struct dentry *systems_dir, *hyp_dir;
665         void *time_hdr, *part_hdr;
666         int i, rc;
667         void *buffer, *ptr;
668
669         buffer = diag204_store();
670         if (IS_ERR(buffer))
671                 return PTR_ERR(buffer);
672
673         systems_dir = hypfs_mkdir(sb, root, "systems");
674         if (IS_ERR(systems_dir)) {
675                 rc = PTR_ERR(systems_dir);
676                 goto err_out;
677         }
678         time_hdr = (struct x_info_blk_hdr *)buffer;
679         part_hdr = time_hdr + info_blk_hdr__size(diag204_info_type);
680         for (i = 0; i < info_blk_hdr__npar(diag204_info_type, time_hdr); i++) {
681                 part_hdr = hypfs_create_lpar_files(sb, systems_dir, part_hdr);
682                 if (IS_ERR(part_hdr)) {
683                         rc = PTR_ERR(part_hdr);
684                         goto err_out;
685                 }
686         }
687         if (info_blk_hdr__flags(diag204_info_type, time_hdr) & LPAR_PHYS_FLG) {
688                 ptr = hypfs_create_phys_files(sb, root, part_hdr);
689                 if (IS_ERR(ptr)) {
690                         rc = PTR_ERR(ptr);
691                         goto err_out;
692                 }
693         }
694         hyp_dir = hypfs_mkdir(sb, root, "hyp");
695         if (IS_ERR(hyp_dir)) {
696                 rc = PTR_ERR(hyp_dir);
697                 goto err_out;
698         }
699         ptr = hypfs_create_str(sb, hyp_dir, "type", "LPAR Hypervisor");
700         if (IS_ERR(ptr)) {
701                 rc = PTR_ERR(ptr);
702                 goto err_out;
703         }
704         rc = 0;
705
706 err_out:
707         return rc;
708 }