Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=387b734fc2b55f776b192c7afdfd892ba42347d4
Commit:     387b734fc2b55f776b192c7afdfd892ba42347d4
Parent:     cfbe9bb2fb5de1da58d351432a9465c22d6d3ee5
Author:     Stefan Bader <[EMAIL PROTECTED]>
AuthorDate: Fri Apr 27 16:01:33 2007 +0200
Committer:  Martin Schwidefsky <[EMAIL PROTECTED]>
CommitDate: Fri Apr 27 16:01:40 2007 +0200

    [S390] cio: Re-start path verification after aborting internal I/O.
    
    Path verification triggered by changes to the available CHPIDs will be
    interrupted by another change but not re-started. This results in an
    invalid path mask.
    To solve this make sure to completely re-start path verification when
    changing the available paths.
    
    Signed-off-by: Stefan Bader <[EMAIL PROTECTED]>
    Signed-off-by: Heiko Carstens <[EMAIL PROTECTED]>
    Signed-off-by: Martin Schwidefsky <[EMAIL PROTECTED]>
---
 drivers/s390/cio/chsc.c |  108 +++++++++++++++++++++++-----------------------
 1 files changed, 54 insertions(+), 54 deletions(-)

diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 3dec460..02615eb 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -178,6 +178,38 @@ css_get_ssd_info(struct subchannel *sch)
        return ret;
 }
 
+static int check_for_io_on_path(struct subchannel *sch, int mask)
+{
+       int cc;
+
+       cc = stsch(sch->schid, &sch->schib);
+       if (cc)
+               return 0;
+       if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == mask)
+               return 1;
+       return 0;
+}
+
+static void terminate_internal_io(struct subchannel *sch)
+{
+       if (cio_clear(sch)) {
+               /* Recheck device in case clear failed. */
+               sch->lpm = 0;
+               if (device_trigger_verify(sch) != 0) {
+                       if(css_enqueue_subchannel_slow(sch->schid)) {
+                               css_clear_subchannel_slow_list();
+                               need_rescan = 1;
+                       }
+               }
+               return;
+       }
+       /* Request retry of internal operation. */
+       device_set_intretry(sch);
+       /* Call handler. */
+       if (sch->driver && sch->driver->termination)
+               sch->driver->termination(&sch->dev);
+}
+
 static int
 s390_subchannel_remove_chpid(struct device *dev, void *data)
 {
@@ -208,37 +240,33 @@ s390_subchannel_remove_chpid(struct device *dev, void 
*data)
        if (sch->schib.pmcw.pim == 0x80)
                goto out_unreg;
 
-       if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) &&
-           (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) &&
-           (sch->schib.pmcw.lpum == mask)) {
-               int cc;
-
-               cc = cio_clear(sch);
-               if (cc == -ENODEV)
+       if (check_for_io_on_path(sch, mask)) {
+               if (device_is_online(sch))
+                       device_kill_io(sch);
+               else {
+                       terminate_internal_io(sch);
+                       /* Re-start path verification. */
+                       if (sch->driver && sch->driver->verify)
+                               sch->driver->verify(&sch->dev);
+               }
+       } else {
+               /* trigger path verification. */
+               if (sch->driver && sch->driver->verify)
+                       sch->driver->verify(&sch->dev);
+               else if (sch->lpm == mask)
                        goto out_unreg;
-               /* Request retry of internal operation. */
-               device_set_intretry(sch);
-               /* Call handler. */
-               if (sch->driver && sch->driver->termination)
-                       sch->driver->termination(&sch->dev);
-               goto out_unlock;
        }
 
-       /* trigger path verification. */
-       if (sch->driver && sch->driver->verify)
-               sch->driver->verify(&sch->dev);
-       else if (sch->lpm == mask)
-               goto out_unreg;
-out_unlock:
        spin_unlock_irq(sch->lock);
        return 0;
+
 out_unreg:
-       spin_unlock_irq(sch->lock);
        sch->lpm = 0;
        if (css_enqueue_subchannel_slow(sch->schid)) {
                css_clear_subchannel_slow_list();
                need_rescan = 1;
        }
+       spin_unlock_irq(sch->lock);
        return 0;
 }
 
@@ -683,38 +711,6 @@ int chsc_chp_online(struct chp_id chpid)
        return rc;
 }
 
-static int check_for_io_on_path(struct subchannel *sch, int index)
-{
-       int cc;
-
-       cc = stsch(sch->schid, &sch->schib);
-       if (cc)
-               return 0;
-       if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index))
-               return 1;
-       return 0;
-}
-
-static void terminate_internal_io(struct subchannel *sch)
-{
-       if (cio_clear(sch)) {
-               /* Recheck device in case clear failed. */
-               sch->lpm = 0;
-               if (device_trigger_verify(sch) != 0) {
-                       if(css_enqueue_subchannel_slow(sch->schid)) {
-                               css_clear_subchannel_slow_list();
-                               need_rescan = 1;
-                       }
-               }
-               return;
-       }
-       /* Request retry of internal operation. */
-       device_set_intretry(sch);
-       /* Call handler. */
-       if (sch->driver && sch->driver->termination)
-               sch->driver->termination(&sch->dev);
-}
-
 static void __s390_subchannel_vary_chpid(struct subchannel *sch,
                                         struct chp_id chpid, int on)
 {
@@ -741,13 +737,17 @@ static void __s390_subchannel_vary_chpid(struct 
subchannel *sch,
                }
                sch->opm &= ~(0x80 >> chp);
                sch->lpm &= ~(0x80 >> chp);
-               if (check_for_io_on_path(sch, chp)) {
+               if (check_for_io_on_path(sch, (0x80 >> chp))) {
                        if (device_is_online(sch))
                                /* Path verification is done after killing. */
                                device_kill_io(sch);
-                       else
+                       else {
                                /* Kill and retry internal I/O. */
                                terminate_internal_io(sch);
+                               /* Re-start path verification. */
+                               if (sch->driver && sch->driver->verify)
+                                       sch->driver->verify(&sch->dev);
+                       }
                } else if (!sch->lpm) {
                        if (device_trigger_verify(sch) != 0) {
                                if (css_enqueue_subchannel_slow(sch->schid)) {
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to