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.c58
1 files changed, 41 insertions, 17 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 20aee2783847..e8d331493fd8 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;
@@ -496,6 +496,15 @@ cio_disable_subchannel (struct subchannel *sch)
496 return ret; 496 return ret;
497} 497}
498 498
499static int cio_create_sch_lock(struct subchannel *sch)
500{
501 sch->lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
502 if (!sch->lock)
503 return -ENOMEM;
504 spin_lock_init(sch->lock);
505 return 0;
506}
507
499/* 508/*
500 * cio_validate_subchannel() 509 * cio_validate_subchannel()
501 * 510 *
@@ -513,6 +522,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
513{ 522{
514 char dbf_txt[15]; 523 char dbf_txt[15];
515 int ccode; 524 int ccode;
525 int err;
516 526
517 sprintf (dbf_txt, "valsch%x", schid.sch_no); 527 sprintf (dbf_txt, "valsch%x", schid.sch_no);
518 CIO_TRACE_EVENT (4, dbf_txt); 528 CIO_TRACE_EVENT (4, dbf_txt);
@@ -520,9 +530,15 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
520 /* Nuke all fields. */ 530 /* Nuke all fields. */
521 memset(sch, 0, sizeof(struct subchannel)); 531 memset(sch, 0, sizeof(struct subchannel));
522 532
523 spin_lock_init(&sch->lock); 533 sch->schid = schid;
534 if (cio_is_console(schid)) {
535 sch->lock = cio_get_console_lock();
536 } else {
537 err = cio_create_sch_lock(sch);
538 if (err)
539 goto out;
540 }
524 mutex_init(&sch->reg_mutex); 541 mutex_init(&sch->reg_mutex);
525
526 /* Set a name for the subchannel */ 542 /* Set a name for the subchannel */
527 snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid, 543 snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
528 schid.sch_no); 544 schid.sch_no);
@@ -534,10 +550,10 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
534 * is not valid. 550 * is not valid.
535 */ 551 */
536 ccode = stsch_err (schid, &sch->schib); 552 ccode = stsch_err (schid, &sch->schib);
537 if (ccode) 553 if (ccode) {
538 return (ccode == 3) ? -ENXIO : ccode; 554 err = (ccode == 3) ? -ENXIO : ccode;
539 555 goto out;
540 sch->schid = schid; 556 }
541 /* Copy subchannel type from path management control word. */ 557 /* Copy subchannel type from path management control word. */
542 sch->st = sch->schib.pmcw.st; 558 sch->st = sch->schib.pmcw.st;
543 559
@@ -550,14 +566,16 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
550 "non-I/O subchannel type %04X\n", 566 "non-I/O subchannel type %04X\n",
551 sch->schid.ssid, sch->schid.sch_no, sch->st); 567 sch->schid.ssid, sch->schid.sch_no, sch->st);
552 /* We stop here for non-io subchannels. */ 568 /* We stop here for non-io subchannels. */
553 return sch->st; 569 err = sch->st;
570 goto out;
554 } 571 }
555 572
556 /* Initialization for io subchannels. */ 573 /* Initialization for io subchannels. */
557 if (!sch->schib.pmcw.dnv) 574 if (!sch->schib.pmcw.dnv) {
558 /* io subchannel but device number is invalid. */ 575 /* io subchannel but device number is invalid. */
559 return -ENODEV; 576 err = -ENODEV;
560 577 goto out;
578 }
561 /* Devno is valid. */ 579 /* Devno is valid. */
562 if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) { 580 if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) {
563 /* 581 /*
@@ -567,7 +585,8 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
567 CIO_MSG_EVENT(0, "Blacklisted device detected " 585 CIO_MSG_EVENT(0, "Blacklisted device detected "
568 "at devno %04X, subchannel set %x\n", 586 "at devno %04X, subchannel set %x\n",
569 sch->schib.pmcw.dev, sch->schid.ssid); 587 sch->schib.pmcw.dev, sch->schid.ssid);
570 return -ENODEV; 588 err = -ENODEV;
589 goto out;
571 } 590 }
572 sch->opm = 0xff; 591 sch->opm = 0xff;
573 if (!cio_is_console(sch->schid)) 592 if (!cio_is_console(sch->schid))
@@ -595,6 +614,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
595 if ((sch->lpm & (sch->lpm - 1)) != 0) 614 if ((sch->lpm & (sch->lpm - 1)) != 0)
596 sch->schib.pmcw.mp = 1; /* multipath mode */ 615 sch->schib.pmcw.mp = 1; /* multipath mode */
597 return 0; 616 return 0;
617out:
618 if (!cio_is_console(schid))
619 kfree(sch->lock);
620 sch->lock = NULL;
621 return err;
598} 622}
599 623
600/* 624/*
@@ -637,7 +661,7 @@ do_IRQ (struct pt_regs *regs)
637 } 661 }
638 sch = (struct subchannel *)(unsigned long)tpi_info->intparm; 662 sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
639 if (sch) 663 if (sch)
640 spin_lock(&sch->lock); 664 spin_lock(sch->lock);
641 /* Store interrupt response block to lowcore. */ 665 /* Store interrupt response block to lowcore. */
642 if (tsch (tpi_info->schid, irb) == 0 && sch) { 666 if (tsch (tpi_info->schid, irb) == 0 && sch) {
643 /* Keep subchannel information word up to date. */ 667 /* Keep subchannel information word up to date. */
@@ -648,7 +672,7 @@ do_IRQ (struct pt_regs *regs)
648 sch->driver->irq(&sch->dev); 672 sch->driver->irq(&sch->dev);
649 } 673 }
650 if (sch) 674 if (sch)
651 spin_unlock(&sch->lock); 675 spin_unlock(sch->lock);
652 /* 676 /*
653 * Are more interrupts pending? 677 * Are more interrupts pending?
654 * If so, the tpi instruction will update the lowcore 678 * If so, the tpi instruction will update the lowcore
@@ -687,10 +711,10 @@ wait_cons_dev (void)
687 __ctl_load (cr6, 6, 6); 711 __ctl_load (cr6, 6, 6);
688 712
689 do { 713 do {
690 spin_unlock(&console_subchannel.lock); 714 spin_unlock(console_subchannel.lock);
691 if (!cio_tpi()) 715 if (!cio_tpi())
692 cpu_relax(); 716 cpu_relax();
693 spin_lock(&console_subchannel.lock); 717 spin_lock(console_subchannel.lock);
694 } while (console_subchannel.schib.scsw.actl != 0); 718 } while (console_subchannel.schib.scsw.actl != 0);
695 /* 719 /*
696 * restore previous isc value 720 * restore previous isc value