aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2006-12-08 09:54:26 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2006-12-08 09:54:26 -0500
commit2ec2298412e1ab4674b3780005058d4f0b8bd858 (patch)
tree7d48542e666636de17ac18e50ed33b4639be43fb
parent7674da77cb2d27ae6559c55151da171ceb02beb4 (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>
-rw-r--r--drivers/s390/cio/chsc.c28
-rw-r--r--drivers/s390/cio/cio.c58
-rw-r--r--drivers/s390/cio/cio.h4
-rw-r--r--drivers/s390/cio/css.c22
-rw-r--r--drivers/s390/cio/device.c21
-rw-r--r--drivers/s390/cio/device_ops.c28
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;
267out_unlock: 267out_unlock:
268 spin_unlock_irq(&sch->lock); 268 spin_unlock_irq(sch->lock);
269 return 0; 269 return 0;
270out_unreg: 270out_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
791static int 791static 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
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
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 */
88struct subchannel { 88struct 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);
137extern void cio_release_console(void); 137extern void cio_release_console(void);
138extern int cio_is_console(struct subchannel_id); 138extern int cio_is_console(struct subchannel_id);
139extern struct subchannel *cio_get_console_subchannel(void); 139extern struct subchannel *cio_get_console_subchannel(void);
140extern 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
145extern int cio_show_msg; 147extern 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
99static void 99static 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
109extern int css_get_ssd_info(struct subchannel *sch); 111extern 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;
1036static struct ccw_device_private console_private; 1036static struct ccw_device_private console_private;
1037static int console_cdev_in_use; 1037static int console_cdev_in_use;
1038 1038
1039static DEFINE_SPINLOCK(ccw_console_lock);
1040
1041spinlock_t * cio_get_console_lock(void)
1042{
1043 return &ccw_console_lock;
1044}
1045
1039static int 1046static int
1040ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch) 1047ccw_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)
572out_unlock: 572out_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