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.c82
1 files changed, 36 insertions, 46 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 2d78f0f4a40f..dbfb77b03928 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -251,6 +251,8 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
251 cc = cio_clear(sch); 251 cc = cio_clear(sch);
252 if (cc == -ENODEV) 252 if (cc == -ENODEV)
253 goto out_unreg; 253 goto out_unreg;
254 /* Request retry of internal operation. */
255 device_set_intretry(sch);
254 /* Call handler. */ 256 /* Call handler. */
255 if (sch->driver && sch->driver->termination) 257 if (sch->driver && sch->driver->termination)
256 sch->driver->termination(&sch->dev); 258 sch->driver->termination(&sch->dev);
@@ -711,9 +713,6 @@ static inline int check_for_io_on_path(struct subchannel *sch, int index)
711{ 713{
712 int cc; 714 int cc;
713 715
714 if (!device_is_online(sch))
715 /* cio could be doing I/O. */
716 return 0;
717 cc = stsch(sch->schid, &sch->schib); 716 cc = stsch(sch->schid, &sch->schib);
718 if (cc) 717 if (cc)
719 return 0; 718 return 0;
@@ -722,6 +721,26 @@ static inline int check_for_io_on_path(struct subchannel *sch, int index)
722 return 0; 721 return 0;
723} 722}
724 723
724static void terminate_internal_io(struct subchannel *sch)
725{
726 if (cio_clear(sch)) {
727 /* Recheck device in case clear failed. */
728 sch->lpm = 0;
729 if (device_trigger_verify(sch) != 0) {
730 if(css_enqueue_subchannel_slow(sch->schid)) {
731 css_clear_subchannel_slow_list();
732 need_rescan = 1;
733 }
734 }
735 return;
736 }
737 /* Request retry of internal operation. */
738 device_set_intretry(sch);
739 /* Call handler. */
740 if (sch->driver && sch->driver->termination)
741 sch->driver->termination(&sch->dev);
742}
743
725static inline void 744static inline void
726__s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) 745__s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
727{ 746{
@@ -744,20 +763,26 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
744 device_trigger_reprobe(sch); 763 device_trigger_reprobe(sch);
745 else if (sch->driver && sch->driver->verify) 764 else if (sch->driver && sch->driver->verify)
746 sch->driver->verify(&sch->dev); 765 sch->driver->verify(&sch->dev);
747 } else { 766 break;
748 sch->opm &= ~(0x80 >> chp); 767 }
749 sch->lpm &= ~(0x80 >> chp); 768 sch->opm &= ~(0x80 >> chp);
750 if (check_for_io_on_path(sch, chp)) 769 sch->lpm &= ~(0x80 >> chp);
770 if (check_for_io_on_path(sch, chp)) {
771 if (device_is_online(sch))
751 /* Path verification is done after killing. */ 772 /* Path verification is done after killing. */
752 device_kill_io(sch); 773 device_kill_io(sch);
753 else if (!sch->lpm) { 774 else
775 /* Kill and retry internal I/O. */
776 terminate_internal_io(sch);
777 } else if (!sch->lpm) {
778 if (device_trigger_verify(sch) != 0) {
754 if (css_enqueue_subchannel_slow(sch->schid)) { 779 if (css_enqueue_subchannel_slow(sch->schid)) {
755 css_clear_subchannel_slow_list(); 780 css_clear_subchannel_slow_list();
756 need_rescan = 1; 781 need_rescan = 1;
757 } 782 }
758 } else if (sch->driver && sch->driver->verify) 783 }
759 sch->driver->verify(&sch->dev); 784 } else if (sch->driver && sch->driver->verify)
760 } 785 sch->driver->verify(&sch->dev);
761 break; 786 break;
762 } 787 }
763 spin_unlock_irqrestore(&sch->lock, flags); 788 spin_unlock_irqrestore(&sch->lock, flags);
@@ -1465,41 +1490,6 @@ chsc_get_chp_desc(struct subchannel *sch, int chp_no)
1465 return desc; 1490 return desc;
1466} 1491}
1467 1492
1468static int reset_channel_path(struct channel_path *chp)
1469{
1470 int cc;
1471
1472 cc = rchp(chp->id);
1473 switch (cc) {
1474 case 0:
1475 return 0;
1476 case 2:
1477 return -EBUSY;
1478 default:
1479 return -ENODEV;
1480 }
1481}
1482
1483static void reset_channel_paths_css(struct channel_subsystem *css)
1484{
1485 int i;
1486
1487 for (i = 0; i <= __MAX_CHPID; i++) {
1488 if (css->chps[i])
1489 reset_channel_path(css->chps[i]);
1490 }
1491}
1492
1493void cio_reset_channel_paths(void)
1494{
1495 int i;
1496
1497 for (i = 0; i <= __MAX_CSSID; i++) {
1498 if (css[i] && css[i]->valid)
1499 reset_channel_paths_css(css[i]);
1500 }
1501}
1502
1503static int __init 1493static int __init
1504chsc_alloc_sei_area(void) 1494chsc_alloc_sei_area(void)
1505{ 1495{