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.c48
1 files changed, 25 insertions, 23 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 3bb4e472d73d..2d78f0f4a40f 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -200,11 +200,13 @@ css_get_ssd_info(struct subchannel *sch)
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; 203 int j, chpid, mask;
204 /* Allocate channel path structures, if needed. */ 204 /* Allocate channel path structures, if needed. */
205 for (j = 0; j < 8; j++) { 205 for (j = 0; j < 8; j++) {
206 mask = 0x80 >> j;
206 chpid = sch->ssd_info.chpid[j]; 207 chpid = sch->ssd_info.chpid[j];
207 if (chpid && (get_chp_status(chpid) < 0)) 208 if ((sch->schib.pmcw.pim & mask) &&
209 (get_chp_status(chpid) < 0))
208 new_channel_path(chpid); 210 new_channel_path(chpid);
209 } 211 }
210 } 212 }
@@ -222,13 +224,15 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
222 224
223 sch = to_subchannel(dev); 225 sch = to_subchannel(dev);
224 chpid = data; 226 chpid = data;
225 for (j = 0; j < 8; j++) 227 for (j = 0; j < 8; j++) {
226 if (sch->schib.pmcw.chpid[j] == chpid->id) 228 mask = 0x80 >> j;
229 if ((sch->schib.pmcw.pim & mask) &&
230 (sch->schib.pmcw.chpid[j] == chpid->id))
227 break; 231 break;
232 }
228 if (j >= 8) 233 if (j >= 8)
229 return 0; 234 return 0;
230 235
231 mask = 0x80 >> j;
232 spin_lock_irq(&sch->lock); 236 spin_lock_irq(&sch->lock);
233 237
234 stsch(sch->schid, &schib); 238 stsch(sch->schid, &schib);
@@ -366,7 +370,7 @@ __s390_process_res_acc(struct subchannel_id schid, void *data)
366 struct res_acc_data *res_data; 370 struct res_acc_data *res_data;
367 struct subchannel *sch; 371 struct subchannel *sch;
368 372
369 res_data = (struct res_acc_data *)data; 373 res_data = data;
370 sch = get_subchannel_by_schid(schid); 374 sch = get_subchannel_by_schid(schid);
371 if (!sch) 375 if (!sch)
372 /* Check if a subchannel is newly available. */ 376 /* Check if a subchannel is newly available. */
@@ -440,7 +444,7 @@ __get_chpid_from_lir(void *data)
440 u32 isinfo[28]; 444 u32 isinfo[28];
441 } *lir; 445 } *lir;
442 446
443 lir = (struct lir*) data; 447 lir = data;
444 if (!(lir->iq&0x80)) 448 if (!(lir->iq&0x80))
445 /* NULL link incident record */ 449 /* NULL link incident record */
446 return -EINVAL; 450 return -EINVAL;
@@ -620,18 +624,20 @@ __chp_add_new_sch(struct subchannel_id schid)
620static int 624static int
621__chp_add(struct subchannel_id schid, void *data) 625__chp_add(struct subchannel_id schid, void *data)
622{ 626{
623 int i; 627 int i, mask;
624 struct channel_path *chp; 628 struct channel_path *chp;
625 struct subchannel *sch; 629 struct subchannel *sch;
626 630
627 chp = (struct channel_path *)data; 631 chp = data;
628 sch = get_subchannel_by_schid(schid); 632 sch = get_subchannel_by_schid(schid);
629 if (!sch) 633 if (!sch)
630 /* Check if the subchannel is now available. */ 634 /* Check if the subchannel is now available. */
631 return __chp_add_new_sch(schid); 635 return __chp_add_new_sch(schid);
632 spin_lock_irq(&sch->lock); 636 spin_lock_irq(&sch->lock);
633 for (i=0; i<8; i++) 637 for (i=0; i<8; i++) {
634 if (sch->schib.pmcw.chpid[i] == chp->id) { 638 mask = 0x80 >> i;
639 if ((sch->schib.pmcw.pim & mask) &&
640 (sch->schib.pmcw.chpid[i] == chp->id)) {
635 if (stsch(sch->schid, &sch->schib) != 0) { 641 if (stsch(sch->schid, &sch->schib) != 0) {
636 /* Endgame. */ 642 /* Endgame. */
637 spin_unlock_irq(&sch->lock); 643 spin_unlock_irq(&sch->lock);
@@ -639,6 +645,7 @@ __chp_add(struct subchannel_id schid, void *data)
639 } 645 }
640 break; 646 break;
641 } 647 }
648 }
642 if (i==8) { 649 if (i==8) {
643 spin_unlock_irq(&sch->lock); 650 spin_unlock_irq(&sch->lock);
644 return 0; 651 return 0;
@@ -646,7 +653,7 @@ __chp_add(struct subchannel_id schid, void *data)
646 sch->lpm = ((sch->schib.pmcw.pim & 653 sch->lpm = ((sch->schib.pmcw.pim &
647 sch->schib.pmcw.pam & 654 sch->schib.pmcw.pam &
648 sch->schib.pmcw.pom) 655 sch->schib.pmcw.pom)
649 | 0x80 >> i) & sch->opm; 656 | mask) & sch->opm;
650 657
651 if (sch->driver && sch->driver->verify) 658 if (sch->driver && sch->driver->verify)
652 sch->driver->verify(&sch->dev); 659 sch->driver->verify(&sch->dev);
@@ -700,8 +707,7 @@ chp_process_crw(int chpid, int on)
700 return chp_add(chpid); 707 return chp_add(chpid);
701} 708}
702 709
703static inline int 710static inline int check_for_io_on_path(struct subchannel *sch, int index)
704__check_for_io_and_kill(struct subchannel *sch, int index)
705{ 711{
706 int cc; 712 int cc;
707 713
@@ -711,10 +717,8 @@ __check_for_io_and_kill(struct subchannel *sch, int index)
711 cc = stsch(sch->schid, &sch->schib); 717 cc = stsch(sch->schid, &sch->schib);
712 if (cc) 718 if (cc)
713 return 0; 719 return 0;
714 if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index)) { 720 if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index))
715 device_set_waiting(sch);
716 return 1; 721 return 1;
717 }
718 return 0; 722 return 0;
719} 723}
720 724
@@ -743,12 +747,10 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
743 } else { 747 } else {
744 sch->opm &= ~(0x80 >> chp); 748 sch->opm &= ~(0x80 >> chp);
745 sch->lpm &= ~(0x80 >> chp); 749 sch->lpm &= ~(0x80 >> chp);
746 /* 750 if (check_for_io_on_path(sch, chp))
747 * Give running I/O a grace period in which it 751 /* Path verification is done after killing. */
748 * can successfully terminate, even using the 752 device_kill_io(sch);
749 * just varied off path. Then kill it. 753 else if (!sch->lpm) {
750 */
751 if (!__check_for_io_and_kill(sch, chp) && !sch->lpm) {
752 if (css_enqueue_subchannel_slow(sch->schid)) { 754 if (css_enqueue_subchannel_slow(sch->schid)) {
753 css_clear_subchannel_slow_list(); 755 css_clear_subchannel_slow_list();
754 need_rescan = 1; 756 need_rescan = 1;