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.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 11900de94cb3..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{
@@ -748,10 +767,14 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
748 } 767 }
749 sch->opm &= ~(0x80 >> chp); 768 sch->opm &= ~(0x80 >> chp);
750 sch->lpm &= ~(0x80 >> chp); 769 sch->lpm &= ~(0x80 >> chp);
751 if (check_for_io_on_path(sch, chp)) 770 if (check_for_io_on_path(sch, chp)) {
752 /* Path verification is done after killing. */ 771 if (device_is_online(sch))
753 device_kill_io(sch); 772 /* Path verification is done after killing. */
754 else if (!sch->lpm) { 773 device_kill_io(sch);
774 else
775 /* Kill and retry internal I/O. */
776 terminate_internal_io(sch);
777 } else if (!sch->lpm) {
755 if (device_trigger_verify(sch) != 0) { 778 if (device_trigger_verify(sch) != 0) {
756 if (css_enqueue_subchannel_slow(sch->schid)) { 779 if (css_enqueue_subchannel_slow(sch->schid)) {
757 css_clear_subchannel_slow_list(); 780 css_clear_subchannel_slow_list();