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(struct scsw *scsw) 32 { 33 /* CC is only valid if start function bit is set. */ 34 if ((scsw->fctl & SCSW_FCTL_START_FUNC) && scsw->cc == 1) 35 return 1; 36 /* No more activity. For sense and set PGID we stubbornly try again. */ 37 if (!scsw->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(2, "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.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.cc == 3) { 159 u8 lpm; 160 161 lpm = to_io_private(sch)->orb.lpm; 162 CIO_MSG_EVENT(2, "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.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_MULTI_PATH; 248 ccw->cmd_code = CCW_CMD_SUSPEND_RECONN; 249 ccw->cda = 0; 250 ccw->count = 0; 251 ccw->flags = CCW_FLAG_SLI | CCW_FLAG_CC; 252 ccw++; 253 } else 254 cdev->private->pgid[0].inf.fc |= SPID_FUNC_SINGLE_PATH; 255 256 ccw->cmd_code = CCW_CMD_SET_PGID; 257 ccw->cda = (__u32) __pa (&cdev->private->pgid[0]); 258 ccw->count = sizeof (struct pgid); 259 ccw->flags = CCW_FLAG_SLI; 260 261 /* Reset device status. */ 262 memset(&cdev->private->irb, 0, sizeof(struct irb)); 263 264 /* Try multiple times. */ 265 ret = -EACCES; 266 if (cdev->private->iretry > 0) { 267 cdev->private->iretry--; 268 /* Reset internal retry indication. */ 269 cdev->private->flags.intretry = 0; 270 ret = cio_start (sch, cdev->private->iccws, 271 cdev->private->imask); 272 /* We expect an interrupt in case of success or busy 273 * indication. */ 274 if ((ret == 0) || (ret == -EBUSY)) 275 return ret; 276 } 277 /* PGID command failed on this path. */ 278 CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel " 279 "0.%x.%04x, lpm %02X, became 'not operational'\n", 280 cdev->private->dev_id.devno, sch->schid.ssid, 281 sch->schid.sch_no, cdev->private->imask); 282 return ret; 283 } 284 285 /* 286 * Helper function to send a nop ccw down a path. 287 */ 288 static int __ccw_device_do_nop(struct ccw_device *cdev) 289 { 290 struct subchannel *sch; 291 struct ccw1 *ccw; 292 int ret; 293 294 sch = to_subchannel(cdev->dev.parent); 295 296 /* Setup nop channel program. */ 297 ccw = cdev->private->iccws; 298 ccw->cmd_code = CCW_CMD_NOOP; 299 ccw->cda = 0; 300 ccw->count = 0; 301 ccw->flags = CCW_FLAG_SLI; 302 303 /* Reset device status. */ 304 memset(&cdev->private->irb, 0, sizeof(struct irb)); 305 306 /* Try multiple times. */ 307 ret = -EACCES; 308 if (cdev->private->iretry > 0) { 309 cdev->private->iretry--; 310 /* Reset internal retry indication. */ 311 cdev->private->flags.intretry = 0; 312 ret = cio_start (sch, cdev->private->iccws, 313 cdev->private->imask); 314 /* We expect an interrupt in case of success or busy 315 * indication. */ 316 if ((ret == 0) || (ret == -EBUSY)) 317 return ret; 318 } 319 /* nop command failed on this path. */ 320 CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel " 321 "0.%x.%04x, lpm %02X, became 'not operational'\n", 322 cdev->private->dev_id.devno, sch->schid.ssid, 323 sch->schid.sch_no, cdev->private->imask); 324 return ret; 325 } 326 327 328 /* 329 * Called from interrupt context to check if a valid answer 330 * to Set Path Group ID was received. 331 */ 332 static int 333 __ccw_device_check_pgid(struct ccw_device *cdev) 334 { 335 struct subchannel *sch; 336 struct irb *irb; 337 338 sch = to_subchannel(cdev->dev.parent); 339 irb = &cdev->private->irb; 340 if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) { 341 /* Retry Set PGID if requested. */ 342 if (cdev->private->flags.intretry) { 343 cdev->private->flags.intretry = 0; 344 return -EAGAIN; 345 } 346 return -ETIME; 347 } 348 if (irb->esw.esw0.erw.cons) { 349 if (irb->ecw[0] & SNS0_CMD_REJECT) 350 return -EOPNOTSUPP; 351 /* Hmm, whatever happened, try again. */ 352 CIO_MSG_EVENT(2, "SPID - device 0.%x.%04x, unit check, " 353 "cnt %02d, " 354 "sns : %02X%02X%02X%02X %02X%02X%02X%02X ...\n", 355 cdev->private->dev_id.ssid, 356 cdev->private->dev_id.devno, 357 irb->esw.esw0.erw.scnt, 358 irb->ecw[0], irb->ecw[1], 359 irb->ecw[2], irb->ecw[3], 360 irb->ecw[4], irb->ecw[5], 361 irb->ecw[6], irb->ecw[7]); 362 return -EAGAIN; 363 } 364 if (irb->scsw.cc == 3) { 365 CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel 0.%x.%04x," 366 " lpm %02X, became 'not operational'\n", 367 cdev->private->dev_id.devno, sch->schid.ssid, 368 sch->schid.sch_no, cdev->private->imask); 369 return -EACCES; 370 } 371 return 0; 372 } 373 374 /* 375 * Called from interrupt context to check the path status after a nop has 376 * been send. 377 */ 378 static int __ccw_device_check_nop(struct ccw_device *cdev) 379 { 380 struct subchannel *sch; 381 struct irb *irb; 382 383 sch = to_subchannel(cdev->dev.parent); 384 irb = &cdev->private->irb; 385 if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) { 386 /* Retry NOP if requested. */ 387 if (cdev->private->flags.intretry) { 388 cdev->private->flags.intretry = 0; 389 return -EAGAIN; 390 } 391 return -ETIME; 392 } 393 if (irb->scsw.cc == 3) { 394 CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel 0.%x.%04x," 395 " lpm %02X, became 'not operational'\n", 396 cdev->private->dev_id.devno, sch->schid.ssid, 397 sch->schid.sch_no, cdev->private->imask); 398 return -EACCES; 399 } 400 return 0; 401 } 402 403 static void 404 __ccw_device_verify_start(struct ccw_device *cdev) 405 { 406 struct subchannel *sch; 407 __u8 func; 408 int ret; 409 410 sch = to_subchannel(cdev->dev.parent); 411 /* Repeat for all paths. */ 412 for (; cdev->private->imask; cdev->private->imask >>= 1, 413 cdev->private->iretry = 5) { 414 if ((cdev->private->imask & sch->schib.pmcw.pam) == 0) 415 /* Path not available, try next. */ 416 continue; 417 if (cdev->private->options.pgroup) { 418 if (sch->opm & cdev->private->imask) 419 func = SPID_FUNC_ESTABLISH; 420 else 421 func = SPID_FUNC_RESIGN; 422 ret = __ccw_device_do_pgid(cdev, func); 423 } else 424 ret = __ccw_device_do_nop(cdev); 425 /* We expect an interrupt in case of success or busy 426 * indication. */ 427 if (ret == 0 || ret == -EBUSY) 428 return; 429 /* Permanent path failure, try next. */ 430 } 431 /* Done with all paths. */ 432 ccw_device_verify_done(cdev, (sch->vpm != 0) ? 0 : -ENODEV); 433 } 434 435 /* 436 * Got interrupt for Set Path Group ID. 437 */ 438 void 439 ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event) 440 { 441 struct subchannel *sch; 442 struct irb *irb; 443 int ret; 444 445 irb = (struct irb *) __LC_IRB; 446 447 if (irb->scsw.stctl == 448 (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { 449 if (__ccw_device_should_retry(&irb->scsw)) 450 __ccw_device_verify_start(cdev); 451 return; 452 } 453 if (ccw_device_accumulate_and_sense(cdev, irb) != 0) 454 return; 455 sch = to_subchannel(cdev->dev.parent); 456 if (cdev->private->options.pgroup) 457 ret = __ccw_device_check_pgid(cdev); 458 else 459 ret = __ccw_device_check_nop(cdev); 460 memset(&cdev->private->irb, 0, sizeof(struct irb)); 461 462 switch (ret) { 463 /* 0, -ETIME, -EAGAIN, -EOPNOTSUPP or -EACCES */ 464 case 0: 465 /* Path verification ccw finished successfully, update lpm. */ 466 sch->vpm |= sch->opm & cdev->private->imask; 467 /* Go on with next path. */ 468 cdev->private->imask >>= 1; 469 cdev->private->iretry = 5; 470 __ccw_device_verify_start(cdev); 471 break; 472 case -EOPNOTSUPP: 473 /* 474 * One of those strange devices which claim to be able 475 * to do multipathing but not for Set Path Group ID. 476 */ 477 if (cdev->private->flags.pgid_single) 478 cdev->private->options.pgroup = 0; 479 else 480 cdev->private->flags.pgid_single = 1; 481 /* Retry */ 482 sch->vpm = 0; 483 cdev->private->imask = 0x80; 484 cdev->private->iretry = 5; 485 /* fall through. */ 486 case -EAGAIN: /* Try again. */ 487 __ccw_device_verify_start(cdev); 488 break; 489 case -ETIME: /* Set path group id stopped by timeout. */ 490 ccw_device_verify_done(cdev, -ETIME); 491 break; 492 case -EACCES: /* channel is not operational. */ 493 cdev->private->imask >>= 1; 494 cdev->private->iretry = 5; 495 __ccw_device_verify_start(cdev); 496 break; 497 } 498 } 499 500 void 501 ccw_device_verify_start(struct ccw_device *cdev) 502 { 503 struct subchannel *sch = to_subchannel(cdev->dev.parent); 504 505 cdev->private->flags.pgid_single = 0; 506 cdev->private->imask = 0x80; 507 cdev->private->iretry = 5; 508 509 /* Start with empty vpm. */ 510 sch->vpm = 0; 511 512 /* Get current pam. */ 513 if (stsch(sch->schid, &sch->schib)) { 514 ccw_device_verify_done(cdev, -ENODEV); 515 return; 516 } 517 /* After 60s path verification is considered to have failed. */ 518 ccw_device_set_timeout(cdev, 60*HZ); 519 __ccw_device_verify_start(cdev); 520 } 521 522 static void 523 __ccw_device_disband_start(struct ccw_device *cdev) 524 { 525 struct subchannel *sch; 526 int ret; 527 528 sch = to_subchannel(cdev->dev.parent); 529 while (cdev->private->imask != 0) { 530 if (sch->lpm & cdev->private->imask) { 531 ret = __ccw_device_do_pgid(cdev, SPID_FUNC_DISBAND); 532 if (ret == 0) 533 return; 534 } 535 cdev->private->iretry = 5; 536 cdev->private->imask >>= 1; 537 } 538 ccw_device_disband_done(cdev, (sch->lpm != 0) ? 0 : -ENODEV); 539 } 540 541 /* 542 * Got interrupt for Unset Path Group ID. 543 */ 544 void 545 ccw_device_disband_irq(struct ccw_device *cdev, enum dev_event dev_event) 546 { 547 struct subchannel *sch; 548 struct irb *irb; 549 int ret; 550 551 irb = (struct irb *) __LC_IRB; 552 553 if (irb->scsw.stctl == 554 (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { 555 if (__ccw_device_should_retry(&irb->scsw)) 556 __ccw_device_disband_start(cdev); 557 return; 558 } 559 if (ccw_device_accumulate_and_sense(cdev, irb) != 0) 560 return; 561 sch = to_subchannel(cdev->dev.parent); 562 ret = __ccw_device_check_pgid(cdev); 563 memset(&cdev->private->irb, 0, sizeof(struct irb)); 564 switch (ret) { 565 /* 0, -ETIME, -EAGAIN, -EOPNOTSUPP or -EACCES */ 566 case 0: /* disband successful. */ 567 ccw_device_disband_done(cdev, ret); 568 break; 569 case -EOPNOTSUPP: 570 /* 571 * One of those strange devices which claim to be able 572 * to do multipathing but not for Unset Path Group ID. 573 */ 574 cdev->private->flags.pgid_single = 1; 575 /* fall through. */ 576 case -EAGAIN: /* Try again. */ 577 __ccw_device_disband_start(cdev); 578 break; 579 case -ETIME: /* Set path group id stopped by timeout. */ 580 ccw_device_disband_done(cdev, -ETIME); 581 break; 582 case -EACCES: /* channel is not operational. */ 583 cdev->private->imask >>= 1; 584 cdev->private->iretry = 5; 585 __ccw_device_disband_start(cdev); 586 break; 587 } 588 } 589 590 void 591 ccw_device_disband_start(struct ccw_device *cdev) 592 { 593 /* After 60s disbanding is considered to have failed. */ 594 ccw_device_set_timeout(cdev, 60*HZ); 595 596 cdev->private->flags.pgid_single = 0; 597 cdev->private->iretry = 5; 598 cdev->private->imask = 0x80; 599 __ccw_device_disband_start(cdev); 600 } 601