1 /* 2 * drivers/s390/cio/device_pgid.c 3 * 4 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, 5 * IBM Corporation 6 * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) 7 * Martin Schwidefsky (schwidefsky@de.ibm.com) 8 * 9 * Path Group ID functions. 10 */ 11 12 #include <linux/module.h> 13 #include <linux/init.h> 14 15 #include <asm/ccwdev.h> 16 #include <asm/cio.h> 17 #include <asm/delay.h> 18 #include <asm/lowcore.h> 19 20 #include "cio.h" 21 #include "cio_debug.h" 22 #include "css.h" 23 #include "device.h" 24 #include "ioasm.h" 25 #include "io_sch.h" 26 27 /* 28 * Helper function called from interrupt context to decide whether an 29 * operation should be tried again. 30 */ 31 static int __ccw_device_should_retry(union scsw *scsw) 32 { 33 /* CC is only valid if start function bit is set. */ 34 if ((scsw->cmd.fctl & SCSW_FCTL_START_FUNC) && scsw->cmd.cc == 1) 35 return 1; 36 /* No more activity. For sense and set PGID we stubbornly try again. */ 37 if (!scsw->cmd.actl) 38 return 1; 39 return 0; 40 } 41 42 /* 43 * Start Sense Path Group ID helper function. Used in ccw_device_recog 44 * and ccw_device_sense_pgid. 45 */ 46 static int 47 __ccw_device_sense_pgid_start(struct ccw_device *cdev) 48 { 49 struct subchannel *sch; 50 struct ccw1 *ccw; 51 int ret; 52 int i; 53 54 sch = to_subchannel(cdev->dev.parent); 55 /* Return if we already checked on all paths. */ 56 if (cdev->private->imask == 0) 57 return (sch->lpm == 0) ? -ENODEV : -EACCES; 58 i = 8 - ffs(cdev->private->imask); 59 60 /* Setup sense path group id channel program. */ 61 ccw = cdev->private->iccws; 62 ccw->cmd_code = CCW_CMD_SENSE_PGID; 63 ccw->count = sizeof (struct pgid); 64 ccw->flags = CCW_FLAG_SLI; 65 66 /* Reset device status. */ 67 memset(&cdev->private->irb, 0, sizeof(struct irb)); 68 /* Try on every path. */ 69 ret = -ENODEV; 70 while (cdev->private->imask != 0) { 71 /* Try every path multiple times. */ 72 ccw->cda = (__u32) __pa (&cdev->private->pgid[i]); 73 if (cdev->private->iretry > 0) { 74 cdev->private->iretry--; 75 /* Reset internal retry indication. */ 76 cdev->private->flags.intretry = 0; 77 ret = cio_start (sch, cdev->private->iccws, 78 cdev->private->imask); 79 /* ret is 0, -EBUSY, -EACCES or -ENODEV */ 80 if (ret != -EACCES) 81 return ret; 82 CIO_MSG_EVENT(3, "SNID - Device %04x on Subchannel " 83 "0.%x.%04x, lpm %02X, became 'not " 84 "operational'\n", 85 cdev->private->dev_id.devno, 86 sch->schid.ssid, 87 sch->schid.sch_no, cdev->private->imask); 88 89 } 90 cdev->private->imask >>= 1; 91 cdev->private->iretry = 5; 92 i++; 93 } 94 95 return ret; 96 } 97 98 void 99 ccw_device_sense_pgid_start(struct ccw_device *cdev) 100 { 101 int ret; 102 103 /* Set a timeout of 60s */ 104 ccw_device_set_timeout(cdev, 60*HZ); 105 106 cdev->private->state = DEV_STATE_SENSE_PGID; 107 cdev->private->imask = 0x80; 108 cdev->private->iretry = 5; 109 memset (&cdev->private->pgid, 0, sizeof (cdev->private->pgid)); 110 ret = __ccw_device_sense_pgid_start(cdev); 111 if (ret && ret != -EBUSY) 112 ccw_device_sense_pgid_done(cdev, ret); 113 } 114 115 /* 116 * Called from interrupt context to check if a valid answer 117 * to Sense Path Group ID was received. 118 */ 119 static int 120 __ccw_device_check_sense_pgid(struct ccw_device *cdev) 121 { 122 struct subchannel *sch; 123 struct irb *irb; 124 int i; 125 126 sch = to_subchannel(cdev->dev.parent); 127 irb = &cdev->private->irb; 128 if (irb->scsw.cmd.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) { 129 /* Retry Sense PGID if requested. */ 130 if (cdev->private->flags.intretry) { 131 cdev->private->flags.intretry = 0; 132 return -EAGAIN; 133 } 134 return -ETIME; 135 } 136 if (irb->esw.esw0.erw.cons && 137 (irb->ecw[0]&(SNS0_CMD_REJECT|SNS0_INTERVENTION_REQ))) { 138 /* 139 * If the device doesn't support the Sense Path Group ID 140 * command further retries wouldn't help ... 141 */ 142 return -EOPNOTSUPP; 143 } 144 if (irb->esw.esw0.erw.cons) { 145 CIO_MSG_EVENT(2, "SNID - device 0.%x.%04x, unit check, " 146 "lpum %02X, cnt %02d, sns : " 147 "%02X%02X%02X%02X %02X%02X%02X%02X ...\n", 148 cdev->private->dev_id.ssid, 149 cdev->private->dev_id.devno, 150 irb->esw.esw0.sublog.lpum, 151 irb->esw.esw0.erw.scnt, 152 irb->ecw[0], irb->ecw[1], 153 irb->ecw[2], irb->ecw[3], 154 irb->ecw[4], irb->ecw[5], 155 irb->ecw[6], irb->ecw[7]); 156 return -EAGAIN; 157 } 158 if (irb->scsw.cmd.cc == 3) { 159 u8 lpm; 160 161 lpm = to_io_private(sch)->orb.cmd.lpm; 162 CIO_MSG_EVENT(3, "SNID - Device %04x on Subchannel 0.%x.%04x," 163 " lpm %02X, became 'not operational'\n", 164 cdev->private->dev_id.devno, sch->schid.ssid, 165 sch->schid.sch_no, lpm); 166 return -EACCES; 167 } 168 i = 8 - ffs(cdev->private->imask); 169 if (cdev->private->pgid[i].inf.ps.state2 == SNID_STATE2_RESVD_ELSE) { 170 CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x " 171 "is reserved by someone else\n", 172 cdev->private->dev_id.devno, sch->schid.ssid, 173 sch->schid.sch_no); 174 return -EUSERS; 175 } 176 return 0; 177 } 178 179 /* 180 * Got interrupt for Sense Path Group ID. 181 */ 182 void 183 ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event) 184 { 185 struct subchannel *sch; 186 struct irb *irb; 187 int ret; 188 189 irb = (struct irb *) __LC_IRB; 190 191 if (irb->scsw.cmd.stctl == 192 (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { 193 if (__ccw_device_should_retry(&irb->scsw)) { 194 ret = __ccw_device_sense_pgid_start(cdev); 195 if (ret && ret != -EBUSY) 196 ccw_device_sense_pgid_done(cdev, ret); 197 } 198 return; 199 } 200 if (ccw_device_accumulate_and_sense(cdev, irb) != 0) 201 return; 202 sch = to_subchannel(cdev->dev.parent); 203 ret = __ccw_device_check_sense_pgid(cdev); 204 memset(&cdev->private->irb, 0, sizeof(struct irb)); 205 switch (ret) { 206 /* 0, -ETIME, -EOPNOTSUPP, -EAGAIN, -EACCES or -EUSERS */ 207 case -EOPNOTSUPP: /* Sense Path Group ID not supported */ 208 ccw_device_sense_pgid_done(cdev, -EOPNOTSUPP); 209 break; 210 case -ETIME: /* Sense path group id stopped by timeout. */ 211 ccw_device_sense_pgid_done(cdev, -ETIME); 212 break; 213 case -EACCES: /* channel is not operational. */ 214 sch->lpm &= ~cdev->private->imask; 215 /* Fall through. */ 216 case 0: /* Sense Path Group ID successful. */ 217 cdev->private->imask >>= 1; 218 cdev->private->iretry = 5; 219 /* Fall through. */ 220 case -EAGAIN: /* Try again. */ 221 ret = __ccw_device_sense_pgid_start(cdev); 222 if (ret != 0 && ret != -EBUSY) 223 ccw_device_sense_pgid_done(cdev, ret); 224 break; 225 case -EUSERS: /* device is reserved for someone else. */ 226 ccw_device_sense_pgid_done(cdev, -EUSERS); 227 break; 228 } 229 } 230 231 /* 232 * Path Group ID helper function. 233 */ 234 static int 235 __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func) 236 { 237 struct subchannel *sch; 238 struct ccw1 *ccw; 239 int ret; 240 241 sch = to_subchannel(cdev->dev.parent); 242 243 /* Setup sense path group id channel program. */ 244 cdev->private->pgid[0].inf.fc = func; 245 ccw = cdev->private->iccws; 246 if (cdev->private->flags.pgid_single) 247 cdev->private->pgid[0].inf.fc |= SPID_FUNC_SINGLE_PATH; 248 else 249 cdev->private->pgid[0].inf.fc |= SPID_FUNC_MULTI_PATH; 250 ccw->cmd_code = CCW_CMD_SET_PGID; 251 ccw->cda = (__u32) __pa (&cdev->private->pgid[0]); 252 ccw->count = sizeof (struct pgid); 253 ccw->flags = CCW_FLAG_SLI; 254 255 /* Reset device status. */ 256 memset(&cdev->private->irb, 0, sizeof(struct irb)); 257 258 /* Try multiple times. */ 259 ret = -EACCES; 260 if (cdev->private->iretry > 0) { 261 cdev->private->iretry--; 262 /* Reset internal retry indication. */ 263 cdev->private->flags.intretry = 0; 264 ret = cio_start (sch, cdev->private->iccws, 265 cdev->private->imask); 266 /* We expect an interrupt in case of success or busy 267 * indication. */ 268 if ((ret == 0) || (ret == -EBUSY)) 269 return ret; 270 } 271 /* PGID command failed on this path. */ 272 CIO_MSG_EVENT(3, "SPID - Device %04x on Subchannel " 273 "0.%x.%04x, lpm %02X, became 'not operational'\n", 274 cdev->private->dev_id.devno, sch->schid.ssid, 275 sch->schid.sch_no, cdev->private->imask); 276 return ret; 277 } 278 279 /* 280 * Helper function to send a nop ccw down a path. 281 */ 282 static int __ccw_device_do_nop(struct ccw_device *cdev) 283 { 284 struct subchannel *sch; 285 struct ccw1 *ccw; 286 int ret; 287 288 sch = to_subchannel(cdev->dev.parent); 289 290 /* Setup nop channel program. */ 291 ccw = cdev->private->iccws; 292 ccw->cmd_code = CCW_CMD_NOOP; 293 ccw->cda = 0; 294 ccw->count = 0; 295 ccw->flags = CCW_FLAG_SLI; 296 297 /* Reset device status. */ 298 memset(&cdev->private->irb, 0, sizeof(struct irb)); 299 300 /* Try multiple times. */ 301 ret = -EACCES; 302 if (cdev->private->iretry > 0) { 303 cdev->private->iretry--; 304 /* Reset internal retry indication. */ 305 cdev->private->flags.intretry = 0; 306 ret = cio_start (sch, cdev->private->iccws, 307 cdev->private->imask); 308 /* We expect an interrupt in case of success or busy 309 * indication. */ 310 if ((ret == 0) || (ret == -EBUSY)) 311 return ret; 312 } 313 /* nop command failed on this path. */ 314 CIO_MSG_EVENT(3, "NOP - Device %04x on Subchannel " 315 "0.%x.%04x, lpm %02X, became 'not operational'\n", 316 cdev->private->dev_id.devno, sch->schid.ssid, 317 sch->schid.sch_no, cdev->private->imask); 318 return ret; 319 } 320 321 322 /* 323 * Called from interrupt context to check if a valid answer 324 * to Set Path Group ID was received. 325 */ 326 static int 327 __ccw_device_check_pgid(struct ccw_device *cdev) 328 { 329 struct subchannel *sch; 330 struct irb *irb; 331 332 sch = to_subchannel(cdev->dev.parent); 333 irb = &cdev->private->irb; 334 if (irb->scsw.cmd.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) { 335 /* Retry Set PGID if requested. */ 336 if (cdev->private->flags.intretry) { 337 cdev->private->flags.intretry = 0; 338 return -EAGAIN; 339 } 340 return -ETIME; 341 } 342 if (irb->esw.esw0.erw.cons) { 343 if (irb->ecw[0] & SNS0_CMD_REJECT) 344 return -EOPNOTSUPP; 345 /* Hmm, whatever happened, try again. */ 346 CIO_MSG_EVENT(2, "SPID - device 0.%x.%04x, unit check, " 347 "cnt %02d, " 348 "sns : %02X%02X%02X%02X %02X%02X%02X%02X ...\n", 349 cdev->private->dev_id.ssid, 350 cdev->private->dev_id.devno, 351 irb->esw.esw0.erw.scnt, 352 irb->ecw[0], irb->ecw[1], 353 irb->ecw[2], irb->ecw[3], 354 irb->ecw[4], irb->ecw[5], 355 irb->ecw[6], irb->ecw[7]); 356 return -EAGAIN; 357 } 358 if (irb->scsw.cmd.cc == 3) { 359 CIO_MSG_EVENT(3, "SPID - Device %04x on Subchannel 0.%x.%04x," 360 " lpm %02X, became 'not operational'\n", 361 cdev->private->dev_id.devno, sch->schid.ssid, 362 sch->schid.sch_no, cdev->private->imask); 363 return -EACCES; 364 } 365 return 0; 366 } 367 368 /* 369 * Called from interrupt context to check the path status after a nop has 370 * been send. 371 */ 372 static int __ccw_device_check_nop(struct ccw_device *cdev) 373 { 374 struct subchannel *sch; 375 struct irb *irb; 376 377 sch = to_subchannel(cdev->dev.parent); 378 irb = &cdev->private->irb; 379 if (irb->scsw.cmd.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) { 380 /* Retry NOP if requested. */ 381 if (cdev->private->flags.intretry) { 382 cdev->private->flags.intretry = 0; 383 return -EAGAIN; 384 } 385 return -ETIME; 386 } 387 if (irb->scsw.cmd.cc == 3) { 388 CIO_MSG_EVENT(3, "NOP - Device %04x on Subchannel 0.%x.%04x," 389 " lpm %02X, became 'not operational'\n", 390 cdev->private->dev_id.devno, sch->schid.ssid, 391 sch->schid.sch_no, cdev->private->imask); 392 return -EACCES; 393 } 394 return 0; 395 } 396 397 static void 398 __ccw_device_verify_start(struct ccw_device *cdev) 399 { 400 struct subchannel *sch; 401 __u8 func; 402 int ret; 403 404 sch = to_subchannel(cdev->dev.parent); 405 /* Repeat for all paths. */ 406 for (; cdev->private->imask; cdev->private->imask >>= 1, 407 cdev->private->iretry = 5) { 408 if ((cdev->private->imask & sch->schib.pmcw.pam) == 0) 409 /* Path not available, try next. */ 410 continue; 411 if (cdev->private->options.pgroup) { 412 if (sch->opm & cdev->private->imask) 413 func = SPID_FUNC_ESTABLISH; 414 else 415 func = SPID_FUNC_RESIGN; 416 ret = __ccw_device_do_pgid(cdev, func); 417 } else 418 ret = __ccw_device_do_nop(cdev); 419 /* We expect an interrupt in case of success or busy 420 * indication. */ 421 if (ret == 0 || ret == -EBUSY) 422 return; 423 /* Permanent path failure, try next. */ 424 } 425 /* Done with all paths. */ 426 ccw_device_verify_done(cdev, (sch->vpm != 0) ? 0 : -ENODEV); 427 } 428 429 /* 430 * Got interrupt for Set Path Group ID. 431 */ 432 void 433 ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event) 434 { 435 struct subchannel *sch; 436 struct irb *irb; 437 int ret; 438 439 irb = (struct irb *) __LC_IRB; 440 441 if (irb->scsw.cmd.stctl == 442 (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { 443 if (__ccw_device_should_retry(&irb->scsw)) 444 __ccw_device_verify_start(cdev); 445 return; 446 } 447 if (ccw_device_accumulate_and_sense(cdev, irb) != 0) 448 return; 449 sch = to_subchannel(cdev->dev.parent); 450 if (cdev->private->options.pgroup) 451 ret = __ccw_device_check_pgid(cdev); 452 else 453 ret = __ccw_device_check_nop(cdev); 454 memset(&cdev->private->irb, 0, sizeof(struct irb)); 455 456 switch (ret) { 457 /* 0, -ETIME, -EAGAIN, -EOPNOTSUPP or -EACCES */ 458 case 0: 459 /* Path verification ccw finished successfully, update lpm. */ 460 sch->vpm |= sch->opm & cdev->private->imask; 461 /* Go on with next path. */ 462 cdev->private->imask >>= 1; 463 cdev->private->iretry = 5; 464 __ccw_device_verify_start(cdev); 465 break; 466 case -EOPNOTSUPP: 467 /* 468 * One of those strange devices which claim to be able 469 * to do multipathing but not for Set Path Group ID. 470 */ 471 if (cdev->private->flags.pgid_single) 472 cdev->private->options.pgroup = 0; 473 else 474 cdev->private->flags.pgid_single = 1; 475 /* Retry */ 476 sch->vpm = 0; 477 cdev->private->imask = 0x80; 478 cdev->private->iretry = 5; 479 /* fall through. */ 480 case -EAGAIN: /* Try again. */ 481 __ccw_device_verify_start(cdev); 482 break; 483 case -ETIME: /* Set path group id stopped by timeout. */ 484 ccw_device_verify_done(cdev, -ETIME); 485 break; 486 case -EACCES: /* channel is not operational. */ 487 cdev->private->imask >>= 1; 488 cdev->private->iretry = 5; 489 __ccw_device_verify_start(cdev); 490 break; 491 } 492 } 493 494 void 495 ccw_device_verify_start(struct ccw_device *cdev) 496 { 497 struct subchannel *sch = to_subchannel(cdev->dev.parent); 498 499 cdev->private->flags.pgid_single = 0; 500 cdev->private->imask = 0x80; 501 cdev->private->iretry = 5; 502 503 /* Start with empty vpm. */ 504 sch->vpm = 0; 505 506 /* Get current pam. */ 507 if (stsch(sch->schid, &sch->schib)) { 508 ccw_device_verify_done(cdev, -ENODEV); 509 return; 510 } 511 /* After 60s path verification is considered to have failed. */ 512 ccw_device_set_timeout(cdev, 60*HZ); 513 __ccw_device_verify_start(cdev); 514 } 515 516 static void 517 __ccw_device_disband_start(struct ccw_device *cdev) 518 { 519 struct subchannel *sch; 520 int ret; 521 522 sch = to_subchannel(cdev->dev.parent); 523 while (cdev->private->imask != 0) { 524 if (sch->lpm & cdev->private->imask) { 525 ret = __ccw_device_do_pgid(cdev, SPID_FUNC_DISBAND); 526 if (ret == 0) 527 return; 528 } 529 cdev->private->iretry = 5; 530 cdev->private->imask >>= 1; 531 } 532 ccw_device_disband_done(cdev, (sch->lpm != 0) ? 0 : -ENODEV); 533 } 534 535 /* 536 * Got interrupt for Unset Path Group ID. 537 */ 538 void 539 ccw_device_disband_irq(struct ccw_device *cdev, enum dev_event dev_event) 540 { 541 struct subchannel *sch; 542 struct irb *irb; 543 int ret; 544 545 irb = (struct irb *) __LC_IRB; 546 547 if (irb->scsw.cmd.stctl == 548 (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { 549 if (__ccw_device_should_retry(&irb->scsw)) 550 __ccw_device_disband_start(cdev); 551 return; 552 } 553 if (ccw_device_accumulate_and_sense(cdev, irb) != 0) 554 return; 555 sch = to_subchannel(cdev->dev.parent); 556 ret = __ccw_device_check_pgid(cdev); 557 memset(&cdev->private->irb, 0, sizeof(struct irb)); 558 switch (ret) { 559 /* 0, -ETIME, -EAGAIN, -EOPNOTSUPP or -EACCES */ 560 case 0: /* disband successful. */ 561 ccw_device_disband_done(cdev, ret); 562 break; 563 case -EOPNOTSUPP: 564 /* 565 * One of those strange devices which claim to be able 566 * to do multipathing but not for Unset Path Group ID. 567 */ 568 cdev->private->flags.pgid_single = 1; 569 /* fall through. */ 570 case -EAGAIN: /* Try again. */ 571 __ccw_device_disband_start(cdev); 572 break; 573 case -ETIME: /* Set path group id stopped by timeout. */ 574 ccw_device_disband_done(cdev, -ETIME); 575 break; 576 case -EACCES: /* channel is not operational. */ 577 cdev->private->imask >>= 1; 578 cdev->private->iretry = 5; 579 __ccw_device_disband_start(cdev); 580 break; 581 } 582 } 583 584 void 585 ccw_device_disband_start(struct ccw_device *cdev) 586 { 587 /* After 60s disbanding is considered to have failed. */ 588 ccw_device_set_timeout(cdev, 60*HZ); 589 590 cdev->private->flags.pgid_single = 0; 591 cdev->private->iretry = 5; 592 cdev->private->imask = 0x80; 593 __ccw_device_disband_start(cdev); 594 } 595