aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/chsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/chsc.c')
-rw-r--r--drivers/s390/cio/chsc.c98
1 files changed, 32 insertions, 66 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 12a344c66b46..93e6f74187ee 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -136,17 +136,13 @@ static void terminate_internal_io(struct subchannel *sch)
136 sch->driver->termination(sch); 136 sch->driver->termination(sch);
137} 137}
138 138
139static int 139static int s390_subchannel_remove_chpid(struct subchannel *sch, void *data)
140s390_subchannel_remove_chpid(struct device *dev, void *data)
141{ 140{
142 int j; 141 int j;
143 int mask; 142 int mask;
144 struct subchannel *sch; 143 struct chp_id *chpid = data;
145 struct chp_id *chpid;
146 struct schib schib; 144 struct schib schib;
147 145
148 sch = to_subchannel(dev);
149 chpid = data;
150 for (j = 0; j < 8; j++) { 146 for (j = 0; j < 8; j++) {
151 mask = 0x80 >> j; 147 mask = 0x80 >> j;
152 if ((sch->schib.pmcw.pim & mask) && 148 if ((sch->schib.pmcw.pim & mask) &&
@@ -202,12 +198,10 @@ void chsc_chp_offline(struct chp_id chpid)
202 198
203 if (chp_get_status(chpid) <= 0) 199 if (chp_get_status(chpid) <= 0)
204 return; 200 return;
205 bus_for_each_dev(&css_bus_type, NULL, &chpid, 201 for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &chpid);
206 s390_subchannel_remove_chpid);
207} 202}
208 203
209static int 204static int s390_process_res_acc_new_sch(struct subchannel_id schid, void *data)
210s390_process_res_acc_new_sch(struct subchannel_id schid)
211{ 205{
212 struct schib schib; 206 struct schib schib;
213 /* 207 /*
@@ -253,18 +247,10 @@ static int get_res_chpid_mask(struct chsc_ssd_info *ssd,
253 return 0; 247 return 0;
254} 248}
255 249
256static int 250static int __s390_process_res_acc(struct subchannel *sch, void *data)
257__s390_process_res_acc(struct subchannel_id schid, void *data)
258{ 251{
259 int chp_mask, old_lpm; 252 int chp_mask, old_lpm;
260 struct res_acc_data *res_data; 253 struct res_acc_data *res_data = data;
261 struct subchannel *sch;
262
263 res_data = data;
264 sch = get_subchannel_by_schid(schid);
265 if (!sch)
266 /* Check if a subchannel is newly available. */
267 return s390_process_res_acc_new_sch(schid);
268 254
269 spin_lock_irq(sch->lock); 255 spin_lock_irq(sch->lock);
270 chp_mask = get_res_chpid_mask(&sch->ssd_info, res_data); 256 chp_mask = get_res_chpid_mask(&sch->ssd_info, res_data);
@@ -283,7 +269,7 @@ __s390_process_res_acc(struct subchannel_id schid, void *data)
283 sch->driver->verify(sch); 269 sch->driver->verify(sch);
284out: 270out:
285 spin_unlock_irq(sch->lock); 271 spin_unlock_irq(sch->lock);
286 put_device(&sch->dev); 272
287 return 0; 273 return 0;
288} 274}
289 275
@@ -306,7 +292,8 @@ static void s390_process_res_acc (struct res_acc_data *res_data)
306 * The more information we have (info), the less scanning 292 * The more information we have (info), the less scanning
307 * will we have to do. 293 * will we have to do.
308 */ 294 */
309 for_each_subchannel(__s390_process_res_acc, res_data); 295 for_each_subchannel_staged(__s390_process_res_acc,
296 s390_process_res_acc_new_sch, res_data);
310} 297}
311 298
312static int 299static int
@@ -500,8 +487,7 @@ void chsc_process_crw(void)
500 } while (sei_area->flags & 0x80); 487 } while (sei_area->flags & 0x80);
501} 488}
502 489
503static int 490static int __chp_add_new_sch(struct subchannel_id schid, void *data)
504__chp_add_new_sch(struct subchannel_id schid)
505{ 491{
506 struct schib schib; 492 struct schib schib;
507 493
@@ -515,35 +501,27 @@ __chp_add_new_sch(struct subchannel_id schid)
515} 501}
516 502
517 503
518static int 504static int __chp_add(struct subchannel *sch, void *data)
519__chp_add(struct subchannel_id schid, void *data)
520{ 505{
521 int i, mask; 506 int i, mask;
522 struct chp_id *chpid; 507 struct chp_id *chpid = data;
523 struct subchannel *sch; 508
524
525 chpid = data;
526 sch = get_subchannel_by_schid(schid);
527 if (!sch)
528 /* Check if the subchannel is now available. */
529 return __chp_add_new_sch(schid);
530 spin_lock_irq(sch->lock); 509 spin_lock_irq(sch->lock);
531 for (i=0; i<8; i++) { 510 for (i=0; i<8; i++) {
532 mask = 0x80 >> i; 511 mask = 0x80 >> i;
533 if ((sch->schib.pmcw.pim & mask) && 512 if ((sch->schib.pmcw.pim & mask) &&
534 (sch->schib.pmcw.chpid[i] == chpid->id)) { 513 (sch->schib.pmcw.chpid[i] == chpid->id))
535 if (stsch(sch->schid, &sch->schib) != 0) {
536 /* Endgame. */
537 spin_unlock_irq(sch->lock);
538 return -ENXIO;
539 }
540 break; 514 break;
541 }
542 } 515 }
543 if (i==8) { 516 if (i==8) {
544 spin_unlock_irq(sch->lock); 517 spin_unlock_irq(sch->lock);
545 return 0; 518 return 0;
546 } 519 }
520 if (stsch(sch->schid, &sch->schib)) {
521 spin_unlock_irq(sch->lock);
522 css_schedule_eval(sch->schid);
523 return 0;
524 }
547 sch->lpm = ((sch->schib.pmcw.pim & 525 sch->lpm = ((sch->schib.pmcw.pim &
548 sch->schib.pmcw.pam & 526 sch->schib.pmcw.pam &
549 sch->schib.pmcw.pom) 527 sch->schib.pmcw.pom)
@@ -553,7 +531,7 @@ __chp_add(struct subchannel_id schid, void *data)
553 sch->driver->verify(sch); 531 sch->driver->verify(sch);
554 532
555 spin_unlock_irq(sch->lock); 533 spin_unlock_irq(sch->lock);
556 put_device(&sch->dev); 534
557 return 0; 535 return 0;
558} 536}
559 537
@@ -565,7 +543,8 @@ void chsc_chp_online(struct chp_id chpid)
565 CIO_TRACE_EVENT(2, dbf_txt); 543 CIO_TRACE_EVENT(2, dbf_txt);
566 544
567 if (chp_get_status(chpid) != 0) 545 if (chp_get_status(chpid) != 0)
568 for_each_subchannel(__chp_add, &chpid); 546 for_each_subchannel_staged(__chp_add, __chp_add_new_sch,
547 &chpid);
569} 548}
570 549
571static void __s390_subchannel_vary_chpid(struct subchannel *sch, 550static void __s390_subchannel_vary_chpid(struct subchannel *sch,
@@ -616,25 +595,17 @@ static void __s390_subchannel_vary_chpid(struct subchannel *sch,
616 spin_unlock_irqrestore(sch->lock, flags); 595 spin_unlock_irqrestore(sch->lock, flags);
617} 596}
618 597
619static int s390_subchannel_vary_chpid_off(struct device *dev, void *data) 598static int s390_subchannel_vary_chpid_off(struct subchannel *sch, void *data)
620{ 599{
621 struct subchannel *sch; 600 struct chp_id *chpid = data;
622 struct chp_id *chpid;
623
624 sch = to_subchannel(dev);
625 chpid = data;
626 601
627 __s390_subchannel_vary_chpid(sch, *chpid, 0); 602 __s390_subchannel_vary_chpid(sch, *chpid, 0);
628 return 0; 603 return 0;
629} 604}
630 605
631static int s390_subchannel_vary_chpid_on(struct device *dev, void *data) 606static int s390_subchannel_vary_chpid_on(struct subchannel *sch, void *data)
632{ 607{
633 struct subchannel *sch; 608 struct chp_id *chpid = data;
634 struct chp_id *chpid;
635
636 sch = to_subchannel(dev);
637 chpid = data;
638 609
639 __s390_subchannel_vary_chpid(sch, *chpid, 1); 610 __s390_subchannel_vary_chpid(sch, *chpid, 1);
640 return 0; 611 return 0;
@@ -644,13 +615,7 @@ static int
644__s390_vary_chpid_on(struct subchannel_id schid, void *data) 615__s390_vary_chpid_on(struct subchannel_id schid, void *data)
645{ 616{
646 struct schib schib; 617 struct schib schib;
647 struct subchannel *sch;
648 618
649 sch = get_subchannel_by_schid(schid);
650 if (sch) {
651 put_device(&sch->dev);
652 return 0;
653 }
654 if (stsch_err(schid, &schib)) 619 if (stsch_err(schid, &schib))
655 /* We're through */ 620 /* We're through */
656 return -ENXIO; 621 return -ENXIO;
@@ -670,12 +635,13 @@ int chsc_chp_vary(struct chp_id chpid, int on)
670 * Redo PathVerification on the devices the chpid connects to 635 * Redo PathVerification on the devices the chpid connects to
671 */ 636 */
672 637
673 bus_for_each_dev(&css_bus_type, NULL, &chpid, on ?
674 s390_subchannel_vary_chpid_on :
675 s390_subchannel_vary_chpid_off);
676 if (on) 638 if (on)
677 /* Scan for new devices on varied on path. */ 639 for_each_subchannel_staged(s390_subchannel_vary_chpid_on,
678 for_each_subchannel(__s390_vary_chpid_on, NULL); 640 __s390_vary_chpid_on, &chpid);
641 else
642 for_each_subchannel_staged(s390_subchannel_vary_chpid_off,
643 NULL, &chpid);
644
679 return 0; 645 return 0;
680} 646}
681 647