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