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