1 /* 2 * drivers/s390/char/sclp_cmd.c 3 * 4 * Copyright IBM Corp. 2007 5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>, 6 * Peter Oberparleiter <peter.oberparleiter@de.ibm.com> 7 */ 8 9 #include <linux/completion.h> 10 #include <linux/init.h> 11 #include <linux/errno.h> 12 #include <linux/slab.h> 13 #include <linux/string.h> 14 #include <asm/chpid.h> 15 #include <asm/sclp.h> 16 #include "sclp.h" 17 18 #define TAG "sclp_cmd: " 19 20 #define SCLP_CMDW_READ_SCP_INFO 0x00020001 21 #define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 22 23 struct read_info_sccb { 24 struct sccb_header header; /* 0-7 */ 25 u16 rnmax; /* 8-9 */ 26 u8 rnsize; /* 10 */ 27 u8 _reserved0[24 - 11]; /* 11-15 */ 28 u8 loadparm[8]; /* 24-31 */ 29 u8 _reserved1[48 - 32]; /* 32-47 */ 30 u64 facilities; /* 48-55 */ 31 u8 _reserved2[84 - 56]; /* 56-83 */ 32 u8 fac84; /* 84 */ 33 u8 _reserved3[91 - 85]; /* 85-90 */ 34 u8 flags; /* 91 */ 35 u8 _reserved4[100 - 92]; /* 92-99 */ 36 u32 rnsize2; /* 100-103 */ 37 u64 rnmax2; /* 104-111 */ 38 u8 _reserved5[4096 - 112]; /* 112-4095 */ 39 } __attribute__((packed, aligned(PAGE_SIZE))); 40 41 static struct read_info_sccb __initdata early_read_info_sccb; 42 static int __initdata early_read_info_sccb_valid; 43 44 u64 sclp_facilities; 45 static u8 sclp_fac84; 46 47 static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) 48 { 49 int rc; 50 51 __ctl_set_bit(0, 9); 52 rc = sclp_service_call(cmd, sccb); 53 if (rc) 54 goto out; 55 __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT | 56 PSW_MASK_WAIT | PSW_DEFAULT_KEY); 57 local_irq_disable(); 58 out: 59 /* Contents of the sccb might have changed. */ 60 barrier(); 61 __ctl_clear_bit(0, 9); 62 return rc; 63 } 64 65 void __init sclp_read_info_early(void) 66 { 67 int rc; 68 int i; 69 struct read_info_sccb *sccb; 70 sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, 71 SCLP_CMDW_READ_SCP_INFO}; 72 73 sccb = &early_read_info_sccb; 74 for (i = 0; i < ARRAY_SIZE(commands); i++) { 75 do { 76 memset(sccb, 0, sizeof(*sccb)); 77 sccb->header.length = sizeof(*sccb); 78 sccb->header.control_mask[2] = 0x80; 79 rc = sclp_cmd_sync_early(commands[i], sccb); 80 } while (rc == -EBUSY); 81 82 if (rc) 83 break; 84 if (sccb->header.response_code == 0x10) { 85 early_read_info_sccb_valid = 1; 86 break; 87 } 88 if (sccb->header.response_code != 0x1f0) 89 break; 90 } 91 } 92 93 void __init sclp_facilities_detect(void) 94 { 95 if (!early_read_info_sccb_valid) 96 return; 97 sclp_facilities = early_read_info_sccb.facilities; 98 sclp_fac84 = early_read_info_sccb.fac84; 99 } 100 101 unsigned long long __init sclp_memory_detect(void) 102 { 103 unsigned long long memsize; 104 struct read_info_sccb *sccb; 105 106 if (!early_read_info_sccb_valid) 107 return 0; 108 sccb = &early_read_info_sccb; 109 if (sccb->rnsize) 110 memsize = sccb->rnsize << 20; 111 else 112 memsize = sccb->rnsize2 << 20; 113 if (sccb->rnmax) 114 memsize *= sccb->rnmax; 115 else 116 memsize *= sccb->rnmax2; 117 return memsize; 118 } 119 120 /* 121 * This function will be called after sclp_memory_detect(), which gets called 122 * early from early.c code. Therefore the sccb should have valid contents. 123 */ 124 void __init sclp_get_ipl_info(struct sclp_ipl_info *info) 125 { 126 struct read_info_sccb *sccb; 127 128 if (!early_read_info_sccb_valid) 129 return; 130 sccb = &early_read_info_sccb; 131 info->is_valid = 1; 132 if (sccb->flags & 0x2) 133 info->has_dump = 1; 134 memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN); 135 } 136 137 static void sclp_sync_callback(struct sclp_req *req, void *data) 138 { 139 struct completion *completion = data; 140 141 complete(completion); 142 } 143 144 static int do_sync_request(sclp_cmdw_t cmd, void *sccb) 145 { 146 struct completion completion; 147 struct sclp_req *request; 148 int rc; 149 150 request = kzalloc(sizeof(*request), GFP_KERNEL); 151 if (!request) 152 return -ENOMEM; 153 request->command = cmd; 154 request->sccb = sccb; 155 request->status = SCLP_REQ_FILLED; 156 request->callback = sclp_sync_callback; 157 request->callback_data = &completion; 158 init_completion(&completion); 159 160 /* Perform sclp request. */ 161 rc = sclp_add_request(request); 162 if (rc) 163 goto out; 164 wait_for_completion(&completion); 165 166 /* Check response. */ 167 if (request->status != SCLP_REQ_DONE) { 168 printk(KERN_WARNING TAG "sync request failed " 169 "(cmd=0x%08x, status=0x%02x)\n", cmd, request->status); 170 rc = -EIO; 171 } 172 out: 173 kfree(request); 174 return rc; 175 } 176 177 /* 178 * CPU configuration related functions. 179 */ 180 181 #define SCLP_CMDW_READ_CPU_INFO 0x00010001 182 #define SCLP_CMDW_CONFIGURE_CPU 0x00110001 183 #define SCLP_CMDW_DECONFIGURE_CPU 0x00100001 184 185 struct read_cpu_info_sccb { 186 struct sccb_header header; 187 u16 nr_configured; 188 u16 offset_configured; 189 u16 nr_standby; 190 u16 offset_standby; 191 u8 reserved[4096 - 16]; 192 } __attribute__((packed, aligned(PAGE_SIZE))); 193 194 static void sclp_fill_cpu_info(struct sclp_cpu_info *info, 195 struct read_cpu_info_sccb *sccb) 196 { 197 char *page = (char *) sccb; 198 199 memset(info, 0, sizeof(*info)); 200 info->configured = sccb->nr_configured; 201 info->standby = sccb->nr_standby; 202 info->combined = sccb->nr_configured + sccb->nr_standby; 203 info->has_cpu_type = sclp_fac84 & 0x1; 204 memcpy(&info->cpu, page + sccb->offset_configured, 205 info->combined * sizeof(struct sclp_cpu_entry)); 206 } 207 208 int sclp_get_cpu_info(struct sclp_cpu_info *info) 209 { 210 int rc; 211 struct read_cpu_info_sccb *sccb; 212 213 if (!SCLP_HAS_CPU_INFO) 214 return -EOPNOTSUPP; 215 sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 216 if (!sccb) 217 return -ENOMEM; 218 sccb->header.length = sizeof(*sccb); 219 rc = do_sync_request(SCLP_CMDW_READ_CPU_INFO, sccb); 220 if (rc) 221 goto out; 222 if (sccb->header.response_code != 0x0010) { 223 printk(KERN_WARNING TAG "readcpuinfo failed " 224 "(response=0x%04x)\n", sccb->header.response_code); 225 rc = -EIO; 226 goto out; 227 } 228 sclp_fill_cpu_info(info, sccb); 229 out: 230 free_page((unsigned long) sccb); 231 return rc; 232 } 233 234 struct cpu_configure_sccb { 235 struct sccb_header header; 236 } __attribute__((packed, aligned(8))); 237 238 static int do_cpu_configure(sclp_cmdw_t cmd) 239 { 240 struct cpu_configure_sccb *sccb; 241 int rc; 242 243 if (!SCLP_HAS_CPU_RECONFIG) 244 return -EOPNOTSUPP; 245 /* 246 * This is not going to cross a page boundary since we force 247 * kmalloc to have a minimum alignment of 8 bytes on s390. 248 */ 249 sccb = kzalloc(sizeof(*sccb), GFP_KERNEL | GFP_DMA); 250 if (!sccb) 251 return -ENOMEM; 252 sccb->header.length = sizeof(*sccb); 253 rc = do_sync_request(cmd, sccb); 254 if (rc) 255 goto out; 256 switch (sccb->header.response_code) { 257 case 0x0020: 258 case 0x0120: 259 break; 260 default: 261 printk(KERN_WARNING TAG "configure cpu failed (cmd=0x%08x, " 262 "response=0x%04x)\n", cmd, sccb->header.response_code); 263 rc = -EIO; 264 break; 265 } 266 out: 267 kfree(sccb); 268 return rc; 269 } 270 271 int sclp_cpu_configure(u8 cpu) 272 { 273 return do_cpu_configure(SCLP_CMDW_CONFIGURE_CPU | cpu << 8); 274 } 275 276 int sclp_cpu_deconfigure(u8 cpu) 277 { 278 return do_cpu_configure(SCLP_CMDW_DECONFIGURE_CPU | cpu << 8); 279 } 280 281 /* 282 * Channel path configuration related functions. 283 */ 284 285 #define SCLP_CMDW_CONFIGURE_CHPATH 0x000f0001 286 #define SCLP_CMDW_DECONFIGURE_CHPATH 0x000e0001 287 #define SCLP_CMDW_READ_CHPATH_INFORMATION 0x00030001 288 289 struct chp_cfg_sccb { 290 struct sccb_header header; 291 u8 ccm; 292 u8 reserved[6]; 293 u8 cssid; 294 } __attribute__((packed)); 295 296 static int do_chp_configure(sclp_cmdw_t cmd) 297 { 298 struct chp_cfg_sccb *sccb; 299 int rc; 300 301 if (!SCLP_HAS_CHP_RECONFIG) 302 return -EOPNOTSUPP; 303 /* Prepare sccb. */ 304 sccb = (struct chp_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 305 if (!sccb) 306 return -ENOMEM; 307 sccb->header.length = sizeof(*sccb); 308 rc = do_sync_request(cmd, sccb); 309 if (rc) 310 goto out; 311 switch (sccb->header.response_code) { 312 case 0x0020: 313 case 0x0120: 314 case 0x0440: 315 case 0x0450: 316 break; 317 default: 318 printk(KERN_WARNING TAG "configure channel-path failed " 319 "(cmd=0x%08x, response=0x%04x)\n", cmd, 320 sccb->header.response_code); 321 rc = -EIO; 322 break; 323 } 324 out: 325 free_page((unsigned long) sccb); 326 return rc; 327 } 328 329 /** 330 * sclp_chp_configure - perform configure channel-path sclp command 331 * @chpid: channel-path ID 332 * 333 * Perform configure channel-path command sclp command for specified chpid. 334 * Return 0 after command successfully finished, non-zero otherwise. 335 */ 336 int sclp_chp_configure(struct chp_id chpid) 337 { 338 return do_chp_configure(SCLP_CMDW_CONFIGURE_CHPATH | chpid.id << 8); 339 } 340 341 /** 342 * sclp_chp_deconfigure - perform deconfigure channel-path sclp command 343 * @chpid: channel-path ID 344 * 345 * Perform deconfigure channel-path command sclp command for specified chpid 346 * and wait for completion. On success return 0. Return non-zero otherwise. 347 */ 348 int sclp_chp_deconfigure(struct chp_id chpid) 349 { 350 return do_chp_configure(SCLP_CMDW_DECONFIGURE_CHPATH | chpid.id << 8); 351 } 352 353 struct chp_info_sccb { 354 struct sccb_header header; 355 u8 recognized[SCLP_CHP_INFO_MASK_SIZE]; 356 u8 standby[SCLP_CHP_INFO_MASK_SIZE]; 357 u8 configured[SCLP_CHP_INFO_MASK_SIZE]; 358 u8 ccm; 359 u8 reserved[6]; 360 u8 cssid; 361 } __attribute__((packed)); 362 363 /** 364 * sclp_chp_read_info - perform read channel-path information sclp command 365 * @info: resulting channel-path information data 366 * 367 * Perform read channel-path information sclp command and wait for completion. 368 * On success, store channel-path information in @info and return 0. Return 369 * non-zero otherwise. 370 */ 371 int sclp_chp_read_info(struct sclp_chp_info *info) 372 { 373 struct chp_info_sccb *sccb; 374 int rc; 375 376 if (!SCLP_HAS_CHP_INFO) 377 return -EOPNOTSUPP; 378 /* Prepare sccb. */ 379 sccb = (struct chp_info_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 380 if (!sccb) 381 return -ENOMEM; 382 sccb->header.length = sizeof(*sccb); 383 rc = do_sync_request(SCLP_CMDW_READ_CHPATH_INFORMATION, sccb); 384 if (rc) 385 goto out; 386 if (sccb->header.response_code != 0x0010) { 387 printk(KERN_WARNING TAG "read channel-path info failed " 388 "(response=0x%04x)\n", sccb->header.response_code); 389 rc = -EIO; 390 goto out; 391 } 392 memcpy(info->recognized, sccb->recognized, SCLP_CHP_INFO_MASK_SIZE); 393 memcpy(info->standby, sccb->standby, SCLP_CHP_INFO_MASK_SIZE); 394 memcpy(info->configured, sccb->configured, SCLP_CHP_INFO_MASK_SIZE); 395 out: 396 free_page((unsigned long) sccb); 397 return rc; 398 } 399