diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2006-12-08 09:54:26 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-12-08 09:54:26 -0500 |
commit | 2ec2298412e1ab4674b3780005058d4f0b8bd858 (patch) | |
tree | 7d48542e666636de17ac18e50ed33b4639be43fb /drivers/s390/cio/cio.c | |
parent | 7674da77cb2d27ae6559c55151da171ceb02beb4 (diff) |
[S390] subchannel lock conversion.
Convert the subchannel lock to a pointer to a lock. Needed for the dynamic
subchannel mapping patch.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/cio.c')
-rw-r--r-- | drivers/s390/cio/cio.c | 58 |
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 | ||
499 | static 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; |
617 | out: | ||
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 |