aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/cio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/cio.c')
-rw-r--r--drivers/s390/cio/cio.c62
1 files changed, 45 insertions, 17 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 20aee2783847..7835a714a405 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -143,11 +143,11 @@ cio_tpi(void)
143 return 1; 143 return 1;
144 local_bh_disable(); 144 local_bh_disable();
145 irq_enter (); 145 irq_enter ();
146 spin_lock(&sch->lock); 146 spin_lock(sch->lock);
147 memcpy (&sch->schib.scsw, &irb->scsw, sizeof (struct scsw)); 147 memcpy (&sch->schib.scsw, &irb->scsw, sizeof (struct scsw));
148 if (sch->driver && sch->driver->irq) 148 if (sch->driver && sch->driver->irq)
149 sch->driver->irq(&sch->dev); 149 sch->driver->irq(&sch->dev);
150 spin_unlock(&sch->lock); 150 spin_unlock(sch->lock);
151 irq_exit (); 151 irq_exit ();
152 _local_bh_enable(); 152 _local_bh_enable();
153 return 1; 153 return 1;
@@ -415,6 +415,8 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
415 CIO_TRACE_EVENT (2, "ensch"); 415 CIO_TRACE_EVENT (2, "ensch");
416 CIO_TRACE_EVENT (2, sch->dev.bus_id); 416 CIO_TRACE_EVENT (2, sch->dev.bus_id);
417 417
418 if (sch_is_pseudo_sch(sch))
419 return -EINVAL;
418 ccode = stsch (sch->schid, &sch->schib); 420 ccode = stsch (sch->schid, &sch->schib);
419 if (ccode) 421 if (ccode)
420 return -ENODEV; 422 return -ENODEV;
@@ -462,6 +464,8 @@ cio_disable_subchannel (struct subchannel *sch)
462 CIO_TRACE_EVENT (2, "dissch"); 464 CIO_TRACE_EVENT (2, "dissch");
463 CIO_TRACE_EVENT (2, sch->dev.bus_id); 465 CIO_TRACE_EVENT (2, sch->dev.bus_id);
464 466
467 if (sch_is_pseudo_sch(sch))
468 return 0;
465 ccode = stsch (sch->schid, &sch->schib); 469 ccode = stsch (sch->schid, &sch->schib);
466 if (ccode == 3) /* Not operational. */ 470 if (ccode == 3) /* Not operational. */
467 return -ENODEV; 471 return -ENODEV;
@@ -496,6 +500,15 @@ cio_disable_subchannel (struct subchannel *sch)
496 return ret; 500 return ret;
497} 501}
498 502
503int cio_create_sch_lock(struct subchannel *sch)
504{
505 sch->lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
506 if (!sch->lock)
507 return -ENOMEM;
508 spin_lock_init(sch->lock);
509 return 0;
510}
511
499/* 512/*
500 * cio_validate_subchannel() 513 * cio_validate_subchannel()
501 * 514 *
@@ -513,6 +526,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
513{ 526{
514 char dbf_txt[15]; 527 char dbf_txt[15];
515 int ccode; 528 int ccode;
529 int err;
516 530
517 sprintf (dbf_txt, "valsch%x", schid.sch_no); 531 sprintf (dbf_txt, "valsch%x", schid.sch_no);
518 CIO_TRACE_EVENT (4, dbf_txt); 532 CIO_TRACE_EVENT (4, dbf_txt);
@@ -520,9 +534,15 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
520 /* Nuke all fields. */ 534 /* Nuke all fields. */
521 memset(sch, 0, sizeof(struct subchannel)); 535 memset(sch, 0, sizeof(struct subchannel));
522 536
523 spin_lock_init(&sch->lock); 537 sch->schid = schid;
538 if (cio_is_console(schid)) {
539 sch->lock = cio_get_console_lock();
540 } else {
541 err = cio_create_sch_lock(sch);
542 if (err)
543 goto out;
544 }
524 mutex_init(&sch->reg_mutex); 545 mutex_init(&sch->reg_mutex);
525
526 /* Set a name for the subchannel */ 546 /* Set a name for the subchannel */
527 snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid, 547 snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
528 schid.sch_no); 548 schid.sch_no);
@@ -534,10 +554,10 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
534 * is not valid. 554 * is not valid.
535 */ 555 */
536 ccode = stsch_err (schid, &sch->schib); 556 ccode = stsch_err (schid, &sch->schib);
537 if (ccode) 557 if (ccode) {
538 return (ccode == 3) ? -ENXIO : ccode; 558 err = (ccode == 3) ? -ENXIO : ccode;
539 559 goto out;
540 sch->schid = schid; 560 }
541 /* Copy subchannel type from path management control word. */ 561 /* Copy subchannel type from path management control word. */
542 sch->st = sch->schib.pmcw.st; 562 sch->st = sch->schib.pmcw.st;
543 563
@@ -550,14 +570,16 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
550 "non-I/O subchannel type %04X\n", 570 "non-I/O subchannel type %04X\n",
551 sch->schid.ssid, sch->schid.sch_no, sch->st); 571 sch->schid.ssid, sch->schid.sch_no, sch->st);
552 /* We stop here for non-io subchannels. */ 572 /* We stop here for non-io subchannels. */
553 return sch->st; 573 err = sch->st;
574 goto out;
554 } 575 }
555 576
556 /* Initialization for io subchannels. */ 577 /* Initialization for io subchannels. */
557 if (!sch->schib.pmcw.dnv) 578 if (!sch->schib.pmcw.dnv) {
558 /* io subchannel but device number is invalid. */ 579 /* io subchannel but device number is invalid. */
559 return -ENODEV; 580 err = -ENODEV;
560 581 goto out;
582 }
561 /* Devno is valid. */ 583 /* Devno is valid. */
562 if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) { 584 if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) {
563 /* 585 /*
@@ -567,7 +589,8 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
567 CIO_MSG_EVENT(0, "Blacklisted device detected " 589 CIO_MSG_EVENT(0, "Blacklisted device detected "
568 "at devno %04X, subchannel set %x\n", 590 "at devno %04X, subchannel set %x\n",
569 sch->schib.pmcw.dev, sch->schid.ssid); 591 sch->schib.pmcw.dev, sch->schid.ssid);
570 return -ENODEV; 592 err = -ENODEV;
593 goto out;
571 } 594 }
572 sch->opm = 0xff; 595 sch->opm = 0xff;
573 if (!cio_is_console(sch->schid)) 596 if (!cio_is_console(sch->schid))
@@ -595,6 +618,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
595 if ((sch->lpm & (sch->lpm - 1)) != 0) 618 if ((sch->lpm & (sch->lpm - 1)) != 0)
596 sch->schib.pmcw.mp = 1; /* multipath mode */ 619 sch->schib.pmcw.mp = 1; /* multipath mode */
597 return 0; 620 return 0;
621out:
622 if (!cio_is_console(schid))
623 kfree(sch->lock);
624 sch->lock = NULL;
625 return err;
598} 626}
599 627
600/* 628/*
@@ -637,7 +665,7 @@ do_IRQ (struct pt_regs *regs)
637 } 665 }
638 sch = (struct subchannel *)(unsigned long)tpi_info->intparm; 666 sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
639 if (sch) 667 if (sch)
640 spin_lock(&sch->lock); 668 spin_lock(sch->lock);
641 /* Store interrupt response block to lowcore. */ 669 /* Store interrupt response block to lowcore. */
642 if (tsch (tpi_info->schid, irb) == 0 && sch) { 670 if (tsch (tpi_info->schid, irb) == 0 && sch) {
643 /* Keep subchannel information word up to date. */ 671 /* Keep subchannel information word up to date. */
@@ -648,7 +676,7 @@ do_IRQ (struct pt_regs *regs)
648 sch->driver->irq(&sch->dev); 676 sch->driver->irq(&sch->dev);
649 } 677 }
650 if (sch) 678 if (sch)
651 spin_unlock(&sch->lock); 679 spin_unlock(sch->lock);
652 /* 680 /*
653 * Are more interrupts pending? 681 * Are more interrupts pending?
654 * If so, the tpi instruction will update the lowcore 682 * If so, the tpi instruction will update the lowcore
@@ -687,10 +715,10 @@ wait_cons_dev (void)
687 __ctl_load (cr6, 6, 6); 715 __ctl_load (cr6, 6, 6);
688 716
689 do { 717 do {
690 spin_unlock(&console_subchannel.lock); 718 spin_unlock(console_subchannel.lock);
691 if (!cio_tpi()) 719 if (!cio_tpi())
692 cpu_relax(); 720 cpu_relax();
693 spin_lock(&console_subchannel.lock); 721 spin_lock(console_subchannel.lock);
694 } while (console_subchannel.schib.scsw.actl != 0); 722 } while (console_subchannel.schib.scsw.actl != 0);
695 /* 723 /*
696 * restore previous isc value 724 * restore previous isc value