1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Channel Subsystem tests library 4 * 5 * Copyright (c) 2020 IBM Corp 6 * 7 * Authors: 8 * Pierre Morel <pmorel@linux.ibm.com> 9 */ 10 #include <libcflat.h> 11 #include <alloc_phys.h> 12 #include <asm/page.h> 13 #include <string.h> 14 #include <interrupt.h> 15 #include <asm/arch_def.h> 16 #include <asm/time.h> 17 #include <asm/arch_def.h> 18 #include <alloc_page.h> 19 #include <malloc_io.h> 20 #include <css.h> 21 22 struct schib schib; 23 struct chsc_scsc *chsc_scsc; 24 25 static const char * const chsc_rsp_description[] = { 26 "CHSC unknown error", 27 "Command executed", 28 "Invalid command", 29 "Request-block error", 30 "Command not installed", 31 "Data not available", 32 "Absolute address of channel-subsystem communication block exceeds 2G - 1.", 33 "Invalid command format", 34 "Invalid channel-subsystem identification (CSSID)", 35 "The command-request block specified an invalid format for the command response block.", 36 "Invalid subchannel-set identification (SSID)", 37 "A busy condition precludes execution.", 38 }; 39 40 static bool check_response(void *p) 41 { 42 struct chsc_header *h = p; 43 44 if (h->code == CHSC_RSP_OK) 45 return true; 46 47 if (h->code > CHSC_RSP_MAX) 48 h->code = 0; 49 50 report_abort("Response code %04x: %s", h->code, 51 chsc_rsp_description[h->code]); 52 return false; 53 } 54 55 bool chsc(void *p, uint16_t code, uint16_t len) 56 { 57 struct chsc_header *h = p; 58 59 h->code = code; 60 h->len = len; 61 62 switch (_chsc(p)) { 63 case 3: 64 report_abort("Subchannel invalid or not enabled."); 65 break; 66 case 2: 67 report_abort("CHSC subchannel busy."); 68 break; 69 case 1: 70 report_abort("Subchannel invalid or not enabled."); 71 break; 72 case 0: 73 return check_response(p + len); 74 } 75 return false; 76 } 77 78 bool get_chsc_scsc(void) 79 { 80 int i, n; 81 char buffer[510]; 82 char *p; 83 84 if (chsc_scsc) /* chsc_scsc already initialized */ 85 return true; 86 87 chsc_scsc = alloc_page(); 88 if (!chsc_scsc) { 89 report_abort("could not allocate chsc_scsc page!"); 90 return false; 91 } 92 93 if (!chsc(chsc_scsc, CHSC_SCSC, CHSC_SCSC_LEN)) 94 return false; 95 96 for (i = 0, p = buffer; i < CSS_GENERAL_FEAT_BITLEN; i++) { 97 if (css_test_general_feature(i)) { 98 n = snprintf(p, sizeof(buffer), "%d,", i); 99 p += n; 100 } 101 } 102 report_info("General features: %s", buffer); 103 104 for (i = 0, p = buffer; i < CSS_CHSC_FEAT_BITLEN; i++) { 105 if (css_test_chsc_feature(i)) { 106 n = snprintf(p, sizeof(buffer), "%d,", i); 107 p += n; 108 } 109 } 110 report_info("CHSC features: %s", buffer); 111 112 return true; 113 } 114 115 /* 116 * css_enumerate: 117 * On success return the first subchannel ID found. 118 * On error return an invalid subchannel ID containing cc 119 */ 120 int css_enumerate(void) 121 { 122 struct pmcw *pmcw = &schib.pmcw; 123 int scn_found = 0; 124 int dev_found = 0; 125 int schid = 0; 126 int cc; 127 int scn; 128 129 for (scn = 0; scn < 0xffff; scn++) { 130 cc = stsch(scn | SCHID_ONE, &schib); 131 switch (cc) { 132 case 0: /* 0 means SCHIB stored */ 133 break; 134 case 3: /* 3 means no more channels */ 135 goto out; 136 default: /* 1 or 2 should never happen for STSCH */ 137 report_abort("Unexpected error %d on subchannel %08x", 138 cc, scn | SCHID_ONE); 139 return cc; 140 } 141 142 /* We currently only support type 0, a.k.a. I/O channels */ 143 if (PMCW_CHANNEL_TYPE(pmcw) != 0) 144 continue; 145 146 /* We ignore I/O channels without valid devices */ 147 scn_found++; 148 if (!(pmcw->flags & PMCW_DNV)) 149 continue; 150 151 /* We keep track of the first device as our test device */ 152 if (!schid) 153 schid = scn | SCHID_ONE; 154 report_info("Found subchannel %08x", scn | SCHID_ONE); 155 dev_found++; 156 } 157 158 out: 159 report_info("Tested subchannels: %d, I/O subchannels: %d, I/O devices: %d", 160 scn, scn_found, dev_found); 161 return schid; 162 } 163 164 /* 165 * css_enabled: report if the subchannel is enabled 166 * @schid: Subchannel Identifier 167 * Return value: 168 * true if the subchannel is enabled 169 * false otherwise 170 */ 171 bool css_enabled(int schid) 172 { 173 struct pmcw *pmcw = &schib.pmcw; 174 int cc; 175 176 cc = stsch(schid, &schib); 177 if (cc) { 178 report_info("stsch: updating sch %08x failed with cc=%d", 179 schid, cc); 180 return false; 181 } 182 183 if (!(pmcw->flags & PMCW_ENABLE)) { 184 report_info("stsch: sch %08x not enabled", schid); 185 return false; 186 } 187 return true; 188 } 189 /* 190 * css_enable: enable the subchannel with the specified ISC 191 * @schid: Subchannel Identifier 192 * @isc : number of the interruption subclass to use 193 * Return value: 194 * On success: 0 195 * On error the CC of the faulty instruction 196 * or -1 if the retry count is exceeded. 197 */ 198 int css_enable(int schid, int isc) 199 { 200 struct pmcw *pmcw = &schib.pmcw; 201 int retry_count = 0; 202 uint16_t flags; 203 int cc; 204 205 /* Read the SCHIB for this subchannel */ 206 cc = stsch(schid, &schib); 207 if (cc) { 208 report_info("stsch: sch %08x failed with cc=%d", schid, cc); 209 return cc; 210 } 211 212 flags = PMCW_ENABLE | (isc << PMCW_ISC_SHIFT); 213 if ((pmcw->flags & (PMCW_ISC_MASK | PMCW_ENABLE)) == flags) { 214 report_info("stsch: sch %08x already enabled", schid); 215 return 0; 216 } 217 218 retry: 219 /* Update the SCHIB to enable the channel and set the ISC */ 220 pmcw->flags &= ~PMCW_ISC_MASK; 221 pmcw->flags |= flags; 222 223 /* Tell the CSS we want to modify the subchannel */ 224 cc = msch(schid, &schib); 225 if (cc) { 226 /* 227 * If the subchannel is status pending or 228 * if a function is in progress, 229 * we consider both cases as errors. 230 */ 231 report_info("msch: sch %08x failed with cc=%d", schid, cc); 232 return cc; 233 } 234 235 /* 236 * Read the SCHIB again to verify the enablement 237 */ 238 if (css_enabled(schid)) 239 return 0; 240 241 if (retry_count++ < MAX_ENABLE_RETRIES) { 242 mdelay(10); /* the hardware was not ready, give it some time */ 243 goto retry; 244 } 245 246 report_info("msch: modifying sch %08x failed after %d retries. pmcw flags: %04x", 247 schid, retry_count, pmcw->flags); 248 return -1; 249 } 250 251 /* 252 * schib_update_mb: update the subchannel Measurement Block 253 * @schid: Subchannel Identifier 254 * @mb : 64bit address of the measurement block 255 * @mbi : the measurement block offset 256 * @flags : PMCW_MBUE to enable measurement block update 257 * PMCW_DCTME to enable device connect time 258 * 0 to disable measurement 259 * @format1: set if format 1 is to be used 260 */ 261 static bool schib_update_mb(int schid, uint64_t mb, uint16_t mbi, 262 uint16_t flags, bool format1) 263 { 264 struct pmcw *pmcw = &schib.pmcw; 265 int cc; 266 267 /* Read the SCHIB for this subchannel */ 268 cc = stsch(schid, &schib); 269 if (cc) { 270 report_info("stsch: sch %08x failed with cc=%d", schid, cc); 271 return false; 272 } 273 274 /* Update the SCHIB to enable the measurement block */ 275 if (flags) { 276 pmcw->flags |= flags; 277 278 if (format1) 279 pmcw->flags2 |= PMCW_MBF1; 280 else 281 pmcw->flags2 &= ~PMCW_MBF1; 282 283 pmcw->mbi = mbi; 284 schib.mbo = mb & ~0x3f; 285 } else { 286 pmcw->flags &= ~(PMCW_MBUE | PMCW_DCTME); 287 } 288 289 /* Tell the CSS we want to modify the subchannel */ 290 cc = msch(schid, &schib); 291 if (cc) { 292 /* 293 * If the subchannel is status pending or 294 * if a function is in progress, 295 * we consider both cases as errors. 296 */ 297 report_info("msch: sch %08x failed with cc=%d", schid, cc); 298 return false; 299 } 300 301 /* 302 * Read the SCHIB again 303 */ 304 cc = stsch(schid, &schib); 305 if (cc) { 306 report_info("stsch: updating sch %08x failed with cc=%d", 307 schid, cc); 308 return false; 309 } 310 311 return true; 312 } 313 314 /* 315 * css_enable_mb: enable the subchannel Measurement Block 316 * @schid: Subchannel Identifier 317 * @mb : 64bit address of the measurement block 318 * @format1: set if format 1 is to be used 319 * @mbi : the measurement block offset 320 * @flags : PMCW_MBUE to enable measurement block update 321 * PMCW_DCTME to enable device connect time 322 */ 323 bool css_enable_mb(int schid, uint64_t mb, uint16_t mbi, uint16_t flags, 324 bool format1) 325 { 326 int retry_count = MAX_ENABLE_RETRIES; 327 struct pmcw *pmcw = &schib.pmcw; 328 329 while (retry_count-- && 330 !schib_update_mb(schid, mb, mbi, flags, format1)) 331 mdelay(10); /* the hardware was not ready, give it some time */ 332 333 return schib.mbo == mb && pmcw->mbi == mbi; 334 } 335 336 /* 337 * css_disable_mb: disable the subchannel Measurement Block 338 * @schid: Subchannel Identifier 339 */ 340 bool css_disable_mb(int schid) 341 { 342 int retry_count = MAX_ENABLE_RETRIES; 343 344 while (retry_count-- && 345 !schib_update_mb(schid, 0, 0, 0, 0)) 346 mdelay(10); /* the hardware was not ready, give it some time */ 347 348 return retry_count > 0; 349 } 350 351 static struct irb irb; 352 353 void css_irq_io(void) 354 { 355 int ret = 0; 356 char *flags; 357 int sid; 358 359 report_prefix_push("Interrupt"); 360 sid = lowcore_ptr->subsys_id_word; 361 /* Lowlevel set the SID as interrupt parameter. */ 362 if (lowcore_ptr->io_int_param != sid) { 363 report(0, 364 "io_int_param: %x differs from subsys_id_word: %x", 365 lowcore_ptr->io_int_param, sid); 366 goto pop; 367 } 368 report_prefix_pop(); 369 370 report_prefix_push("tsch"); 371 ret = tsch(sid, &irb); 372 switch (ret) { 373 case 1: 374 dump_irb(&irb); 375 flags = dump_scsw_flags(irb.scsw.ctrl); 376 report(0, 377 "I/O interrupt, but tsch returns CC 1 for subchannel %08x. SCSW flags: %s", 378 sid, flags); 379 break; 380 case 2: 381 report(0, "tsch returns unexpected CC 2"); 382 break; 383 case 3: 384 report(0, "tsch reporting sch %08x as not operational", sid); 385 break; 386 case 0: 387 /* Stay humble on success */ 388 break; 389 } 390 pop: 391 report_prefix_pop(); 392 lowcore_ptr->io_old_psw.mask &= ~PSW_MASK_WAIT; 393 } 394 395 int start_ccw1_chain(unsigned int sid, struct ccw1 *ccw) 396 { 397 struct orb orb = { 398 .intparm = sid, 399 .ctrl = ORB_CTRL_ISIC|ORB_CTRL_FMT|ORB_LPM_DFLT, 400 .cpa = (unsigned int) (unsigned long)ccw, 401 }; 402 403 return ssch(sid, &orb); 404 } 405 406 struct ccw1 *ccw_alloc(int code, void *data, int count, unsigned char flags) 407 { 408 struct ccw1 *ccw; 409 410 ccw = alloc_io_mem(sizeof(*ccw), 0); 411 if (!ccw) 412 return NULL; 413 414 ccw->code = code; 415 ccw->flags = flags; 416 ccw->count = count; 417 ccw->data_address = (int)(unsigned long)data; 418 419 return ccw; 420 } 421 422 /* wait_and_check_io_completion: 423 * @schid: the subchannel ID 424 * 425 * Makes the most common check to validate a successful I/O 426 * completion. 427 * Only report failures. 428 */ 429 int wait_and_check_io_completion(int schid) 430 { 431 int ret = 0; 432 433 wait_for_interrupt(PSW_MASK_IO); 434 435 report_prefix_push("check I/O completion"); 436 437 if (lowcore_ptr->io_int_param != schid) { 438 report(0, "interrupt parameter: expected %08x got %08x", 439 schid, lowcore_ptr->io_int_param); 440 ret = -1; 441 goto end; 442 } 443 444 /* Verify that device status is valid */ 445 if (!(irb.scsw.ctrl & SCSW_SC_PENDING)) { 446 report(0, "No status pending after interrupt. Subch Ctrl: %08x", 447 irb.scsw.ctrl); 448 ret = -1; 449 goto end; 450 } 451 452 if (!(irb.scsw.ctrl & (SCSW_SC_SECONDARY | SCSW_SC_PRIMARY))) { 453 report(0, "Primary or secondary status missing. Subch Ctrl: %08x", 454 irb.scsw.ctrl); 455 ret = -1; 456 goto end; 457 } 458 459 if (!(irb.scsw.dev_stat & (SCSW_DEVS_DEV_END | SCSW_DEVS_SCH_END))) { 460 report(0, "No device end or sch end. Dev. status: %02x", 461 irb.scsw.dev_stat); 462 ret = -1; 463 goto end; 464 } 465 466 if (irb.scsw.sch_stat & ~SCSW_SCHS_IL) { 467 report_info("Unexpected Subch. status %02x", irb.scsw.sch_stat); 468 ret = -1; 469 goto end; 470 } 471 472 end: 473 report_prefix_pop(); 474 return ret; 475 } 476 477 /* 478 * css_residual_count 479 * Return the residual count, if it is valid. 480 * 481 * Return value: 482 * Success: the residual count 483 * Not meaningful: -1 (-1 can not be a valid count) 484 */ 485 int css_residual_count(unsigned int schid) 486 { 487 488 if (!(irb.scsw.ctrl & (SCSW_SC_PENDING | SCSW_SC_PRIMARY))) 489 return -1; 490 491 if (irb.scsw.dev_stat) 492 if (irb.scsw.sch_stat & ~(SCSW_SCHS_PCI | SCSW_SCHS_IL)) 493 return -1; 494 495 return irb.scsw.count; 496 } 497 498 /* 499 * enable_io_isc: setup ISC in Control Register 6 500 * @isc: The interruption Sub Class as a bitfield 501 */ 502 void enable_io_isc(uint8_t isc) 503 { 504 uint64_t value; 505 506 value = (uint64_t)isc << 24; 507 lctlg(6, value); 508 } 509