diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/s390/cio/chsc.c | 28 | ||||
-rw-r--r-- | drivers/s390/cio/cio.c | 58 | ||||
-rw-r--r-- | drivers/s390/cio/cio.h | 4 | ||||
-rw-r--r-- | drivers/s390/cio/css.c | 22 | ||||
-rw-r--r-- | drivers/s390/cio/device.c | 21 | ||||
-rw-r--r-- | drivers/s390/cio/device_ops.c | 28 |
6 files changed, 98 insertions, 63 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index dbfb77b03928..cbab8d2ce5cf 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -183,7 +183,7 @@ css_get_ssd_info(struct subchannel *sch) | |||
183 | page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); | 183 | page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); |
184 | if (!page) | 184 | if (!page) |
185 | return -ENOMEM; | 185 | return -ENOMEM; |
186 | spin_lock_irq(&sch->lock); | 186 | spin_lock_irq(sch->lock); |
187 | ret = chsc_get_sch_desc_irq(sch, page); | 187 | ret = chsc_get_sch_desc_irq(sch, page); |
188 | if (ret) { | 188 | if (ret) { |
189 | static int cio_chsc_err_msg; | 189 | static int cio_chsc_err_msg; |
@@ -197,7 +197,7 @@ css_get_ssd_info(struct subchannel *sch) | |||
197 | cio_chsc_err_msg = 1; | 197 | cio_chsc_err_msg = 1; |
198 | } | 198 | } |
199 | } | 199 | } |
200 | spin_unlock_irq(&sch->lock); | 200 | spin_unlock_irq(sch->lock); |
201 | free_page((unsigned long)page); | 201 | free_page((unsigned long)page); |
202 | if (!ret) { | 202 | if (!ret) { |
203 | int j, chpid, mask; | 203 | int j, chpid, mask; |
@@ -233,7 +233,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) | |||
233 | if (j >= 8) | 233 | if (j >= 8) |
234 | return 0; | 234 | return 0; |
235 | 235 | ||
236 | spin_lock_irq(&sch->lock); | 236 | spin_lock_irq(sch->lock); |
237 | 237 | ||
238 | stsch(sch->schid, &schib); | 238 | stsch(sch->schid, &schib); |
239 | if (!schib.pmcw.dnv) | 239 | if (!schib.pmcw.dnv) |
@@ -265,10 +265,10 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) | |||
265 | else if (sch->lpm == mask) | 265 | else if (sch->lpm == mask) |
266 | goto out_unreg; | 266 | goto out_unreg; |
267 | out_unlock: | 267 | out_unlock: |
268 | spin_unlock_irq(&sch->lock); | 268 | spin_unlock_irq(sch->lock); |
269 | return 0; | 269 | return 0; |
270 | out_unreg: | 270 | out_unreg: |
271 | spin_unlock_irq(&sch->lock); | 271 | spin_unlock_irq(sch->lock); |
272 | sch->lpm = 0; | 272 | sch->lpm = 0; |
273 | if (css_enqueue_subchannel_slow(sch->schid)) { | 273 | if (css_enqueue_subchannel_slow(sch->schid)) { |
274 | css_clear_subchannel_slow_list(); | 274 | css_clear_subchannel_slow_list(); |
@@ -378,12 +378,12 @@ __s390_process_res_acc(struct subchannel_id schid, void *data) | |||
378 | /* Check if a subchannel is newly available. */ | 378 | /* Check if a subchannel is newly available. */ |
379 | return s390_process_res_acc_new_sch(schid); | 379 | return s390_process_res_acc_new_sch(schid); |
380 | 380 | ||
381 | spin_lock_irq(&sch->lock); | 381 | spin_lock_irq(sch->lock); |
382 | 382 | ||
383 | chp_mask = s390_process_res_acc_sch(res_data, sch); | 383 | chp_mask = s390_process_res_acc_sch(res_data, sch); |
384 | 384 | ||
385 | if (chp_mask == 0) { | 385 | if (chp_mask == 0) { |
386 | spin_unlock_irq(&sch->lock); | 386 | spin_unlock_irq(sch->lock); |
387 | put_device(&sch->dev); | 387 | put_device(&sch->dev); |
388 | return 0; | 388 | return 0; |
389 | } | 389 | } |
@@ -397,7 +397,7 @@ __s390_process_res_acc(struct subchannel_id schid, void *data) | |||
397 | else if (sch->driver && sch->driver->verify) | 397 | else if (sch->driver && sch->driver->verify) |
398 | sch->driver->verify(&sch->dev); | 398 | sch->driver->verify(&sch->dev); |
399 | 399 | ||
400 | spin_unlock_irq(&sch->lock); | 400 | spin_unlock_irq(sch->lock); |
401 | put_device(&sch->dev); | 401 | put_device(&sch->dev); |
402 | return 0; | 402 | return 0; |
403 | } | 403 | } |
@@ -635,21 +635,21 @@ __chp_add(struct subchannel_id schid, void *data) | |||
635 | if (!sch) | 635 | if (!sch) |
636 | /* Check if the subchannel is now available. */ | 636 | /* Check if the subchannel is now available. */ |
637 | return __chp_add_new_sch(schid); | 637 | return __chp_add_new_sch(schid); |
638 | spin_lock_irq(&sch->lock); | 638 | spin_lock_irq(sch->lock); |
639 | for (i=0; i<8; i++) { | 639 | for (i=0; i<8; i++) { |
640 | mask = 0x80 >> i; | 640 | mask = 0x80 >> i; |
641 | if ((sch->schib.pmcw.pim & mask) && | 641 | if ((sch->schib.pmcw.pim & mask) && |
642 | (sch->schib.pmcw.chpid[i] == chp->id)) { | 642 | (sch->schib.pmcw.chpid[i] == chp->id)) { |
643 | if (stsch(sch->schid, &sch->schib) != 0) { | 643 | if (stsch(sch->schid, &sch->schib) != 0) { |
644 | /* Endgame. */ | 644 | /* Endgame. */ |
645 | spin_unlock_irq(&sch->lock); | 645 | spin_unlock_irq(sch->lock); |
646 | return -ENXIO; | 646 | return -ENXIO; |
647 | } | 647 | } |
648 | break; | 648 | break; |
649 | } | 649 | } |
650 | } | 650 | } |
651 | if (i==8) { | 651 | if (i==8) { |
652 | spin_unlock_irq(&sch->lock); | 652 | spin_unlock_irq(sch->lock); |
653 | return 0; | 653 | return 0; |
654 | } | 654 | } |
655 | sch->lpm = ((sch->schib.pmcw.pim & | 655 | sch->lpm = ((sch->schib.pmcw.pim & |
@@ -660,7 +660,7 @@ __chp_add(struct subchannel_id schid, void *data) | |||
660 | if (sch->driver && sch->driver->verify) | 660 | if (sch->driver && sch->driver->verify) |
661 | sch->driver->verify(&sch->dev); | 661 | sch->driver->verify(&sch->dev); |
662 | 662 | ||
663 | spin_unlock_irq(&sch->lock); | 663 | spin_unlock_irq(sch->lock); |
664 | put_device(&sch->dev); | 664 | put_device(&sch->dev); |
665 | return 0; | 665 | return 0; |
666 | } | 666 | } |
@@ -750,7 +750,7 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) | |||
750 | if (!sch->ssd_info.valid) | 750 | if (!sch->ssd_info.valid) |
751 | return; | 751 | return; |
752 | 752 | ||
753 | spin_lock_irqsave(&sch->lock, flags); | 753 | spin_lock_irqsave(sch->lock, flags); |
754 | old_lpm = sch->lpm; | 754 | old_lpm = sch->lpm; |
755 | for (chp = 0; chp < 8; chp++) { | 755 | for (chp = 0; chp < 8; chp++) { |
756 | if (sch->ssd_info.chpid[chp] != chpid) | 756 | if (sch->ssd_info.chpid[chp] != chpid) |
@@ -785,7 +785,7 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) | |||
785 | sch->driver->verify(&sch->dev); | 785 | sch->driver->verify(&sch->dev); |
786 | break; | 786 | break; |
787 | } | 787 | } |
788 | spin_unlock_irqrestore(&sch->lock, flags); | 788 | spin_unlock_irqrestore(sch->lock, flags); |
789 | } | 789 | } |
790 | 790 | ||
791 | static int | 791 | static int |
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 |
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index 4541c1af4b66..7e7369b21a93 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h | |||
@@ -87,7 +87,7 @@ struct orb { | |||
87 | /* subchannel data structure used by I/O subroutines */ | 87 | /* subchannel data structure used by I/O subroutines */ |
88 | struct subchannel { | 88 | struct subchannel { |
89 | struct subchannel_id schid; | 89 | struct subchannel_id schid; |
90 | spinlock_t lock; /* subchannel lock */ | 90 | spinlock_t *lock; /* subchannel lock */ |
91 | struct mutex reg_mutex; | 91 | struct mutex reg_mutex; |
92 | enum { | 92 | enum { |
93 | SUBCHANNEL_TYPE_IO = 0, | 93 | SUBCHANNEL_TYPE_IO = 0, |
@@ -137,9 +137,11 @@ extern struct subchannel *cio_probe_console(void); | |||
137 | extern void cio_release_console(void); | 137 | extern void cio_release_console(void); |
138 | extern int cio_is_console(struct subchannel_id); | 138 | extern int cio_is_console(struct subchannel_id); |
139 | extern struct subchannel *cio_get_console_subchannel(void); | 139 | extern struct subchannel *cio_get_console_subchannel(void); |
140 | extern spinlock_t * cio_get_console_lock(void); | ||
140 | #else | 141 | #else |
141 | #define cio_is_console(schid) 0 | 142 | #define cio_is_console(schid) 0 |
142 | #define cio_get_console_subchannel() NULL | 143 | #define cio_get_console_subchannel() NULL |
144 | #define cio_get_console_lock() NULL; | ||
143 | #endif | 145 | #endif |
144 | 146 | ||
145 | extern int cio_show_msg; | 147 | extern int cio_show_msg; |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 55895c83d499..65939e2eb415 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -91,9 +91,9 @@ css_free_subchannel(struct subchannel *sch) | |||
91 | /* Reset intparm to zeroes. */ | 91 | /* Reset intparm to zeroes. */ |
92 | sch->schib.pmcw.intparm = 0; | 92 | sch->schib.pmcw.intparm = 0; |
93 | cio_modify(sch); | 93 | cio_modify(sch); |
94 | kfree(sch->lock); | ||
94 | kfree(sch); | 95 | kfree(sch); |
95 | } | 96 | } |
96 | |||
97 | } | 97 | } |
98 | 98 | ||
99 | static void | 99 | static void |
@@ -102,8 +102,10 @@ css_subchannel_release(struct device *dev) | |||
102 | struct subchannel *sch; | 102 | struct subchannel *sch; |
103 | 103 | ||
104 | sch = to_subchannel(dev); | 104 | sch = to_subchannel(dev); |
105 | if (!cio_is_console(sch->schid)) | 105 | if (!cio_is_console(sch->schid)) { |
106 | kfree(sch->lock); | ||
106 | kfree(sch); | 107 | kfree(sch); |
108 | } | ||
107 | } | 109 | } |
108 | 110 | ||
109 | extern int css_get_ssd_info(struct subchannel *sch); | 111 | extern int css_get_ssd_info(struct subchannel *sch); |
@@ -206,18 +208,18 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow) | |||
206 | unsigned long flags; | 208 | unsigned long flags; |
207 | enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE } action; | 209 | enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE } action; |
208 | 210 | ||
209 | spin_lock_irqsave(&sch->lock, flags); | 211 | spin_lock_irqsave(sch->lock, flags); |
210 | disc = device_is_disconnected(sch); | 212 | disc = device_is_disconnected(sch); |
211 | if (disc && slow) { | 213 | if (disc && slow) { |
212 | /* Disconnected devices are evaluated directly only.*/ | 214 | /* Disconnected devices are evaluated directly only.*/ |
213 | spin_unlock_irqrestore(&sch->lock, flags); | 215 | spin_unlock_irqrestore(sch->lock, flags); |
214 | return 0; | 216 | return 0; |
215 | } | 217 | } |
216 | /* No interrupt after machine check - kill pending timers. */ | 218 | /* No interrupt after machine check - kill pending timers. */ |
217 | device_kill_pending_timer(sch); | 219 | device_kill_pending_timer(sch); |
218 | if (!disc && !slow) { | 220 | if (!disc && !slow) { |
219 | /* Non-disconnected devices are evaluated on the slow path. */ | 221 | /* Non-disconnected devices are evaluated on the slow path. */ |
220 | spin_unlock_irqrestore(&sch->lock, flags); | 222 | spin_unlock_irqrestore(sch->lock, flags); |
221 | return -EAGAIN; | 223 | return -EAGAIN; |
222 | } | 224 | } |
223 | event = css_get_subchannel_status(sch); | 225 | event = css_get_subchannel_status(sch); |
@@ -242,9 +244,9 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow) | |||
242 | /* Ask driver what to do with device. */ | 244 | /* Ask driver what to do with device. */ |
243 | action = UNREGISTER; | 245 | action = UNREGISTER; |
244 | if (sch->driver && sch->driver->notify) { | 246 | if (sch->driver && sch->driver->notify) { |
245 | spin_unlock_irqrestore(&sch->lock, flags); | 247 | spin_unlock_irqrestore(sch->lock, flags); |
246 | ret = sch->driver->notify(&sch->dev, event); | 248 | ret = sch->driver->notify(&sch->dev, event); |
247 | spin_lock_irqsave(&sch->lock, flags); | 249 | spin_lock_irqsave(sch->lock, flags); |
248 | if (ret) | 250 | if (ret) |
249 | action = NONE; | 251 | action = NONE; |
250 | } | 252 | } |
@@ -269,9 +271,9 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow) | |||
269 | case UNREGISTER: | 271 | case UNREGISTER: |
270 | case UNREGISTER_PROBE: | 272 | case UNREGISTER_PROBE: |
271 | /* Unregister device (will use subchannel lock). */ | 273 | /* Unregister device (will use subchannel lock). */ |
272 | spin_unlock_irqrestore(&sch->lock, flags); | 274 | spin_unlock_irqrestore(sch->lock, flags); |
273 | css_sch_device_unregister(sch); | 275 | css_sch_device_unregister(sch); |
274 | spin_lock_irqsave(&sch->lock, flags); | 276 | spin_lock_irqsave(sch->lock, flags); |
275 | 277 | ||
276 | /* Reset intparm to zeroes. */ | 278 | /* Reset intparm to zeroes. */ |
277 | sch->schib.pmcw.intparm = 0; | 279 | sch->schib.pmcw.intparm = 0; |
@@ -283,7 +285,7 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow) | |||
283 | default: | 285 | default: |
284 | break; | 286 | break; |
285 | } | 287 | } |
286 | spin_unlock_irqrestore(&sch->lock, flags); | 288 | spin_unlock_irqrestore(sch->lock, flags); |
287 | /* Probe if necessary. */ | 289 | /* Probe if necessary. */ |
288 | if (action == UNREGISTER_PROBE) | 290 | if (action == UNREGISTER_PROBE) |
289 | ret = css_probe_device(sch->schid); | 291 | ret = css_probe_device(sch->schid); |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index e644fd6905ee..9a31239fe028 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -774,9 +774,9 @@ io_subchannel_register(struct work_struct *work) | |||
774 | printk (KERN_WARNING "%s: could not register %s\n", | 774 | printk (KERN_WARNING "%s: could not register %s\n", |
775 | __func__, cdev->dev.bus_id); | 775 | __func__, cdev->dev.bus_id); |
776 | put_device(&cdev->dev); | 776 | put_device(&cdev->dev); |
777 | spin_lock_irqsave(&sch->lock, flags); | 777 | spin_lock_irqsave(sch->lock, flags); |
778 | sch->dev.driver_data = NULL; | 778 | sch->dev.driver_data = NULL; |
779 | spin_unlock_irqrestore(&sch->lock, flags); | 779 | spin_unlock_irqrestore(sch->lock, flags); |
780 | kfree (cdev->private); | 780 | kfree (cdev->private); |
781 | kfree (cdev); | 781 | kfree (cdev); |
782 | put_device(&sch->dev); | 782 | put_device(&sch->dev); |
@@ -860,7 +860,7 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch) | |||
860 | 860 | ||
861 | sch->dev.driver_data = cdev; | 861 | sch->dev.driver_data = cdev; |
862 | sch->driver = &io_subchannel_driver; | 862 | sch->driver = &io_subchannel_driver; |
863 | cdev->ccwlock = &sch->lock; | 863 | cdev->ccwlock = sch->lock; |
864 | 864 | ||
865 | /* Init private data. */ | 865 | /* Init private data. */ |
866 | priv = cdev->private; | 866 | priv = cdev->private; |
@@ -880,9 +880,9 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch) | |||
880 | atomic_inc(&ccw_device_init_count); | 880 | atomic_inc(&ccw_device_init_count); |
881 | 881 | ||
882 | /* Start async. device sensing. */ | 882 | /* Start async. device sensing. */ |
883 | spin_lock_irq(&sch->lock); | 883 | spin_lock_irq(sch->lock); |
884 | rc = ccw_device_recognition(cdev); | 884 | rc = ccw_device_recognition(cdev); |
885 | spin_unlock_irq(&sch->lock); | 885 | spin_unlock_irq(sch->lock); |
886 | if (rc) { | 886 | if (rc) { |
887 | if (atomic_dec_and_test(&ccw_device_init_count)) | 887 | if (atomic_dec_and_test(&ccw_device_init_count)) |
888 | wake_up(&ccw_device_init_wq); | 888 | wake_up(&ccw_device_init_wq); |
@@ -924,9 +924,9 @@ io_subchannel_probe (struct subchannel *sch) | |||
924 | 924 | ||
925 | rc = io_subchannel_recog(cdev, sch); | 925 | rc = io_subchannel_recog(cdev, sch); |
926 | if (rc) { | 926 | if (rc) { |
927 | spin_lock_irqsave(&sch->lock, flags); | 927 | spin_lock_irqsave(sch->lock, flags); |
928 | sch->dev.driver_data = NULL; | 928 | sch->dev.driver_data = NULL; |
929 | spin_unlock_irqrestore(&sch->lock, flags); | 929 | spin_unlock_irqrestore(sch->lock, flags); |
930 | if (cdev->dev.release) | 930 | if (cdev->dev.release) |
931 | cdev->dev.release(&cdev->dev); | 931 | cdev->dev.release(&cdev->dev); |
932 | } | 932 | } |
@@ -1036,6 +1036,13 @@ static struct ccw_device console_cdev; | |||
1036 | static struct ccw_device_private console_private; | 1036 | static struct ccw_device_private console_private; |
1037 | static int console_cdev_in_use; | 1037 | static int console_cdev_in_use; |
1038 | 1038 | ||
1039 | static DEFINE_SPINLOCK(ccw_console_lock); | ||
1040 | |||
1041 | spinlock_t * cio_get_console_lock(void) | ||
1042 | { | ||
1043 | return &ccw_console_lock; | ||
1044 | } | ||
1045 | |||
1039 | static int | 1046 | static int |
1040 | ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch) | 1047 | ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch) |
1041 | { | 1048 | { |
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index b39c1fa48acd..d269607336ec 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c | |||
@@ -316,9 +316,9 @@ __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, _ | |||
316 | ccw_device_set_timeout(cdev, 0); | 316 | ccw_device_set_timeout(cdev, 0); |
317 | if (ret == -EBUSY) { | 317 | if (ret == -EBUSY) { |
318 | /* Try again later. */ | 318 | /* Try again later. */ |
319 | spin_unlock_irq(&sch->lock); | 319 | spin_unlock_irq(sch->lock); |
320 | msleep(10); | 320 | msleep(10); |
321 | spin_lock_irq(&sch->lock); | 321 | spin_lock_irq(sch->lock); |
322 | continue; | 322 | continue; |
323 | } | 323 | } |
324 | if (ret != 0) | 324 | if (ret != 0) |
@@ -326,12 +326,12 @@ __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, _ | |||
326 | break; | 326 | break; |
327 | /* Wait for end of request. */ | 327 | /* Wait for end of request. */ |
328 | cdev->private->intparm = magic; | 328 | cdev->private->intparm = magic; |
329 | spin_unlock_irq(&sch->lock); | 329 | spin_unlock_irq(sch->lock); |
330 | wait_event(cdev->private->wait_q, | 330 | wait_event(cdev->private->wait_q, |
331 | (cdev->private->intparm == -EIO) || | 331 | (cdev->private->intparm == -EIO) || |
332 | (cdev->private->intparm == -EAGAIN) || | 332 | (cdev->private->intparm == -EAGAIN) || |
333 | (cdev->private->intparm == 0)); | 333 | (cdev->private->intparm == 0)); |
334 | spin_lock_irq(&sch->lock); | 334 | spin_lock_irq(sch->lock); |
335 | /* Check at least for channel end / device end */ | 335 | /* Check at least for channel end / device end */ |
336 | if (cdev->private->intparm == -EIO) { | 336 | if (cdev->private->intparm == -EIO) { |
337 | /* Non-retryable error. */ | 337 | /* Non-retryable error. */ |
@@ -342,9 +342,9 @@ __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, _ | |||
342 | /* Success. */ | 342 | /* Success. */ |
343 | break; | 343 | break; |
344 | /* Try again later. */ | 344 | /* Try again later. */ |
345 | spin_unlock_irq(&sch->lock); | 345 | spin_unlock_irq(sch->lock); |
346 | msleep(10); | 346 | msleep(10); |
347 | spin_lock_irq(&sch->lock); | 347 | spin_lock_irq(sch->lock); |
348 | } while (1); | 348 | } while (1); |
349 | 349 | ||
350 | return ret; | 350 | return ret; |
@@ -389,7 +389,7 @@ read_dev_chars (struct ccw_device *cdev, void **buffer, int length) | |||
389 | return ret; | 389 | return ret; |
390 | } | 390 | } |
391 | 391 | ||
392 | spin_lock_irq(&sch->lock); | 392 | spin_lock_irq(sch->lock); |
393 | /* Save interrupt handler. */ | 393 | /* Save interrupt handler. */ |
394 | handler = cdev->handler; | 394 | handler = cdev->handler; |
395 | /* Temporarily install own handler. */ | 395 | /* Temporarily install own handler. */ |
@@ -406,7 +406,7 @@ read_dev_chars (struct ccw_device *cdev, void **buffer, int length) | |||
406 | 406 | ||
407 | /* Restore interrupt handler. */ | 407 | /* Restore interrupt handler. */ |
408 | cdev->handler = handler; | 408 | cdev->handler = handler; |
409 | spin_unlock_irq(&sch->lock); | 409 | spin_unlock_irq(sch->lock); |
410 | 410 | ||
411 | clear_normalized_cda (rdc_ccw); | 411 | clear_normalized_cda (rdc_ccw); |
412 | kfree(rdc_ccw); | 412 | kfree(rdc_ccw); |
@@ -463,7 +463,7 @@ read_conf_data_lpm (struct ccw_device *cdev, void **buffer, int *length, __u8 lp | |||
463 | rcd_ccw->count = ciw->count; | 463 | rcd_ccw->count = ciw->count; |
464 | rcd_ccw->flags = CCW_FLAG_SLI; | 464 | rcd_ccw->flags = CCW_FLAG_SLI; |
465 | 465 | ||
466 | spin_lock_irq(&sch->lock); | 466 | spin_lock_irq(sch->lock); |
467 | /* Save interrupt handler. */ | 467 | /* Save interrupt handler. */ |
468 | handler = cdev->handler; | 468 | handler = cdev->handler; |
469 | /* Temporarily install own handler. */ | 469 | /* Temporarily install own handler. */ |
@@ -480,7 +480,7 @@ read_conf_data_lpm (struct ccw_device *cdev, void **buffer, int *length, __u8 lp | |||
480 | 480 | ||
481 | /* Restore interrupt handler. */ | 481 | /* Restore interrupt handler. */ |
482 | cdev->handler = handler; | 482 | cdev->handler = handler; |
483 | spin_unlock_irq(&sch->lock); | 483 | spin_unlock_irq(sch->lock); |
484 | 484 | ||
485 | /* | 485 | /* |
486 | * on success we update the user input parms | 486 | * on success we update the user input parms |
@@ -537,7 +537,7 @@ ccw_device_stlck(struct ccw_device *cdev) | |||
537 | kfree(buf); | 537 | kfree(buf); |
538 | return -ENOMEM; | 538 | return -ENOMEM; |
539 | } | 539 | } |
540 | spin_lock_irqsave(&sch->lock, flags); | 540 | spin_lock_irqsave(sch->lock, flags); |
541 | ret = cio_enable_subchannel(sch, 3); | 541 | ret = cio_enable_subchannel(sch, 3); |
542 | if (ret) | 542 | if (ret) |
543 | goto out_unlock; | 543 | goto out_unlock; |
@@ -559,9 +559,9 @@ ccw_device_stlck(struct ccw_device *cdev) | |||
559 | goto out_unlock; | 559 | goto out_unlock; |
560 | } | 560 | } |
561 | cdev->private->irb.scsw.actl |= SCSW_ACTL_START_PEND; | 561 | cdev->private->irb.scsw.actl |= SCSW_ACTL_START_PEND; |
562 | spin_unlock_irqrestore(&sch->lock, flags); | 562 | spin_unlock_irqrestore(sch->lock, flags); |
563 | wait_event(cdev->private->wait_q, cdev->private->irb.scsw.actl == 0); | 563 | wait_event(cdev->private->wait_q, cdev->private->irb.scsw.actl == 0); |
564 | spin_lock_irqsave(&sch->lock, flags); | 564 | spin_lock_irqsave(sch->lock, flags); |
565 | cio_disable_subchannel(sch); //FIXME: return code? | 565 | cio_disable_subchannel(sch); //FIXME: return code? |
566 | if ((cdev->private->irb.scsw.dstat != | 566 | if ((cdev->private->irb.scsw.dstat != |
567 | (DEV_STAT_CHN_END|DEV_STAT_DEV_END)) || | 567 | (DEV_STAT_CHN_END|DEV_STAT_DEV_END)) || |
@@ -572,7 +572,7 @@ ccw_device_stlck(struct ccw_device *cdev) | |||
572 | out_unlock: | 572 | out_unlock: |
573 | kfree(buf); | 573 | kfree(buf); |
574 | kfree(buf2); | 574 | kfree(buf2); |
575 | spin_unlock_irqrestore(&sch->lock, flags); | 575 | spin_unlock_irqrestore(sch->lock, flags); |
576 | return ret; | 576 | return ret; |
577 | } | 577 | } |
578 | 578 | ||