Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / s390 / cio / device_pgid.c
index 0adac8a..85b1020 100644 (file)
@@ -3,7 +3,7 @@
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *                      IBM Corporation
- *    Author(s): Cornelia Huck(cohuck@de.ibm.com)
+ *    Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
  * Path Group ID functions.
@@ -22,6 +22,7 @@
 #include "cio_debug.h"
 #include "css.h"
 #include "device.h"
+#include "ioasm.h"
 
 /*
  * Start Sense Path Group ID helper function. Used in ccw_device_recog
@@ -56,10 +57,10 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev)
                        if (ret != -EACCES)
                                return ret;
                        CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
-                                     "%04x, lpm %02X, became 'not "
+                                     "0.%x.%04x, lpm %02X, became 'not "
                                      "operational'\n",
-                                     cdev->private->devno, sch->irq,
-                                     cdev->private->imask);
+                                     cdev->private->devno, sch->schid.ssid,
+                                     sch->schid.sch_no, cdev->private->imask);
 
                }
                cdev->private->imask >>= 1;
@@ -105,10 +106,10 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
                return -EOPNOTSUPP;
        }
        if (irb->esw.esw0.erw.cons) {
-               CIO_MSG_EVENT(2, "SNID - device %04x, unit check, "
+               CIO_MSG_EVENT(2, "SNID - device 0.%x.%04x, unit check, "
                              "lpum %02X, cnt %02d, sns : "
                              "%02X%02X%02X%02X %02X%02X%02X%02X ...\n",
-                             cdev->private->devno,
+                             cdev->private->ssid, cdev->private->devno,
                              irb->esw.esw0.sublog.lpum,
                              irb->esw.esw0.erw.scnt,
                              irb->ecw[0], irb->ecw[1],
@@ -118,15 +119,17 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
                return -EAGAIN;
        }
        if (irb->scsw.cc == 3) {
-               CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
-                             "%04x, lpm %02X, became 'not operational'\n",
-                             cdev->private->devno, sch->irq, sch->orb.lpm);
+               CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x,"
+                             " lpm %02X, became 'not operational'\n",
+                             cdev->private->devno, sch->schid.ssid,
+                             sch->schid.sch_no, sch->orb.lpm);
                return -EACCES;
        }
        if (cdev->private->pgid.inf.ps.state2 == SNID_STATE2_RESVD_ELSE) {
-               CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel %04x "
+               CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x "
                              "is reserved by someone else\n",
-                             cdev->private->devno, sch->irq);
+                             cdev->private->devno, sch->schid.ssid,
+                             sch->schid.sch_no);
                return -EUSERS;
        }
        return 0;
@@ -162,7 +165,7 @@ ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event)
        /* 0, -ETIME, -EOPNOTSUPP, -EAGAIN, -EACCES or -EUSERS */
        case 0:                 /* Sense Path Group ID successful. */
                if (cdev->private->pgid.inf.ps.state1 == SNID_STATE1_RESET)
-                       memcpy(&cdev->private->pgid, &global_pgid,
+                       memcpy(&cdev->private->pgid, &css[0]->global_pgid,
                               sizeof(struct pgid));
                ccw_device_sense_pgid_done(cdev, 0);
                break;
@@ -235,8 +238,9 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func)
        sch->lpm &= ~cdev->private->imask;
        sch->vpm &= ~cdev->private->imask;
        CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
-                     "%04x, lpm %02X, became 'not operational'\n",
-                     cdev->private->devno, sch->irq, cdev->private->imask);
+                     "0.%x.%04x, lpm %02X, became 'not operational'\n",
+                     cdev->private->devno, sch->schid.ssid,
+                     sch->schid.sch_no, cdev->private->imask);
        return ret;
 }
 
@@ -258,8 +262,10 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
                if (irb->ecw[0] & SNS0_CMD_REJECT)
                        return -EOPNOTSUPP;
                /* Hmm, whatever happened, try again. */
-               CIO_MSG_EVENT(2, "SPID - device %04x, unit check, cnt %02d, "
+               CIO_MSG_EVENT(2, "SPID - device 0.%x.%04x, unit check, "
+                             "cnt %02d, "
                              "sns : %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
+                             cdev->private->ssid,
                              cdev->private->devno, irb->esw.esw0.erw.scnt,
                              irb->ecw[0], irb->ecw[1],
                              irb->ecw[2], irb->ecw[3],
@@ -268,10 +274,10 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
                return -EAGAIN;
        }
        if (irb->scsw.cc == 3) {
-               CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
-                             "%04x, lpm %02X, became 'not operational'\n",
-                             cdev->private->devno, sch->irq,
-                             cdev->private->imask);
+               CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel 0.%x.%04x,"
+                             " lpm %02X, became 'not operational'\n",
+                             cdev->private->devno, sch->schid.ssid,
+                             sch->schid.sch_no, cdev->private->imask);
                return -EACCES;
        }
        return 0;
@@ -364,8 +370,22 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event)
 void
 ccw_device_verify_start(struct ccw_device *cdev)
 {
+       struct subchannel *sch = to_subchannel(cdev->dev.parent);
+
        cdev->private->flags.pgid_single = 0;
        cdev->private->iretry = 5;
+       /*
+        * Update sch->lpm with current values to catch paths becoming
+        * available again.
+        */
+       if (stsch(sch->schid, &sch->schib)) {
+               ccw_device_verify_done(cdev, -ENODEV);
+               return;
+       }
+       sch->lpm = sch->schib.pmcw.pim &
+               sch->schib.pmcw.pam &
+               sch->schib.pmcw.pom &
+               sch->opm;
        __ccw_device_verify_start(cdev);
 }
 
@@ -385,7 +405,7 @@ __ccw_device_disband_start(struct ccw_device *cdev)
                cdev->private->iretry = 5;
                cdev->private->imask >>= 1;
        }
-       ccw_device_verify_done(cdev, (sch->lpm != 0) ? 0 : -ENODEV);
+       ccw_device_disband_done(cdev, (sch->lpm != 0) ? 0 : -ENODEV);
 }
 
 /*