[S390] pm: qeth driver power management callbacks
authorFrank Blaschka <frank.blaschka@de.ibm.com>
Tue, 16 Jun 2009 08:30:31 +0000 (10:30 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 16 Jun 2009 08:31:13 +0000 (10:31 +0200)
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c

index 74c49d9..d53621c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/net/qeth_core_main.c
  *
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2009
  *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
  *              Frank Pavlic <fpavlic@de.ibm.com>,
  *              Thomas Spatzier <tspat@de.ibm.com>,
@@ -4195,6 +4195,50 @@ static void qeth_core_shutdown(struct ccwgroup_device *gdev)
                card->discipline.ccwgdriver->shutdown(gdev);
 }
 
+static int qeth_core_prepare(struct ccwgroup_device *gdev)
+{
+       struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+       if (card->discipline.ccwgdriver &&
+           card->discipline.ccwgdriver->prepare)
+               return card->discipline.ccwgdriver->prepare(gdev);
+       return 0;
+}
+
+static void qeth_core_complete(struct ccwgroup_device *gdev)
+{
+       struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+       if (card->discipline.ccwgdriver &&
+           card->discipline.ccwgdriver->complete)
+               card->discipline.ccwgdriver->complete(gdev);
+}
+
+static int qeth_core_freeze(struct ccwgroup_device *gdev)
+{
+       struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+       if (card->discipline.ccwgdriver &&
+           card->discipline.ccwgdriver->freeze)
+               return card->discipline.ccwgdriver->freeze(gdev);
+       return 0;
+}
+
+static int qeth_core_thaw(struct ccwgroup_device *gdev)
+{
+       struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+       if (card->discipline.ccwgdriver &&
+           card->discipline.ccwgdriver->thaw)
+               return card->discipline.ccwgdriver->thaw(gdev);
+       return 0;
+}
+
+static int qeth_core_restore(struct ccwgroup_device *gdev)
+{
+       struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+       if (card->discipline.ccwgdriver &&
+           card->discipline.ccwgdriver->restore)
+               return card->discipline.ccwgdriver->restore(gdev);
+       return 0;
+}
+
 static struct ccwgroup_driver qeth_core_ccwgroup_driver = {
        .owner = THIS_MODULE,
        .name = "qeth",
@@ -4204,6 +4248,11 @@ static struct ccwgroup_driver qeth_core_ccwgroup_driver = {
        .set_online = qeth_core_set_online,
        .set_offline = qeth_core_set_offline,
        .shutdown = qeth_core_shutdown,
+       .prepare = qeth_core_prepare,
+       .complete = qeth_core_complete,
+       .freeze = qeth_core_freeze,
+       .thaw = qeth_core_thaw,
+       .restore = qeth_core_restore,
 };
 
 static ssize_t
index ecd3d06..81d7f26 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/net/qeth_l2_main.c
  *
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2009
  *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
  *              Frank Pavlic <fpavlic@de.ibm.com>,
  *              Thomas Spatzier <tspat@de.ibm.com>,
@@ -1141,12 +1141,62 @@ static void qeth_l2_shutdown(struct ccwgroup_device *gdev)
        qeth_clear_qdio_buffers(card);
 }
 
+static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev)
+{
+       struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+
+       if (card->dev)
+               netif_device_detach(card->dev);
+       qeth_set_allowed_threads(card, 0, 1);
+       wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
+       if (gdev->state == CCWGROUP_OFFLINE)
+               return 0;
+       if (card->state == CARD_STATE_UP) {
+               card->use_hard_stop = 1;
+               __qeth_l2_set_offline(card->gdev, 1);
+       } else
+               __qeth_l2_set_offline(card->gdev, 0);
+       return 0;
+}
+
+static int qeth_l2_pm_resume(struct ccwgroup_device *gdev)
+{
+       struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+       int rc = 0;
+
+       if (gdev->state == CCWGROUP_OFFLINE)
+               goto out;
+
+       if (card->state == CARD_STATE_RECOVER) {
+               rc = __qeth_l2_set_online(card->gdev, 1);
+               if (rc) {
+                       if (card->dev) {
+                               rtnl_lock();
+                               dev_close(card->dev);
+                               rtnl_unlock();
+                       }
+               }
+       } else
+               rc = __qeth_l2_set_online(card->gdev, 0);
+out:
+       qeth_set_allowed_threads(card, 0xffffffff, 0);
+       if (card->dev)
+               netif_device_attach(card->dev);
+       if (rc)
+               dev_warn(&card->gdev->dev, "The qeth device driver "
+                       "failed to recover an error on the device\n");
+       return rc;
+}
+
 struct ccwgroup_driver qeth_l2_ccwgroup_driver = {
        .probe = qeth_l2_probe_device,
        .remove = qeth_l2_remove_device,
        .set_online = qeth_l2_set_online,
        .set_offline = qeth_l2_set_offline,
        .shutdown = qeth_l2_shutdown,
+       .freeze = qeth_l2_pm_suspend,
+       .thaw = qeth_l2_pm_resume,
+       .restore = qeth_l2_pm_resume,
 };
 EXPORT_SYMBOL_GPL(qeth_l2_ccwgroup_driver);
 
index 6f2386e..5487240 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/net/qeth_l3_main.c
  *
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2009
  *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
  *              Frank Pavlic <fpavlic@de.ibm.com>,
  *              Thomas Spatzier <tspat@de.ibm.com>,
@@ -3283,12 +3283,62 @@ static void qeth_l3_shutdown(struct ccwgroup_device *gdev)
        qeth_clear_qdio_buffers(card);
 }
 
+static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev)
+{
+       struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+
+       if (card->dev)
+               netif_device_detach(card->dev);
+       qeth_set_allowed_threads(card, 0, 1);
+       wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
+       if (gdev->state == CCWGROUP_OFFLINE)
+               return 0;
+       if (card->state == CARD_STATE_UP) {
+               card->use_hard_stop = 1;
+               __qeth_l3_set_offline(card->gdev, 1);
+       } else
+               __qeth_l3_set_offline(card->gdev, 0);
+       return 0;
+}
+
+static int qeth_l3_pm_resume(struct ccwgroup_device *gdev)
+{
+       struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+       int rc = 0;
+
+       if (gdev->state == CCWGROUP_OFFLINE)
+               goto out;
+
+       if (card->state == CARD_STATE_RECOVER) {
+               rc = __qeth_l3_set_online(card->gdev, 1);
+               if (rc) {
+                       if (card->dev) {
+                               rtnl_lock();
+                               dev_close(card->dev);
+                               rtnl_unlock();
+                       }
+               }
+       } else
+               rc = __qeth_l3_set_online(card->gdev, 0);
+out:
+       qeth_set_allowed_threads(card, 0xffffffff, 0);
+       if (card->dev)
+               netif_device_attach(card->dev);
+       if (rc)
+               dev_warn(&card->gdev->dev, "The qeth device driver "
+                       "failed to recover an error on the device\n");
+       return rc;
+}
+
 struct ccwgroup_driver qeth_l3_ccwgroup_driver = {
        .probe = qeth_l3_probe_device,
        .remove = qeth_l3_remove_device,
        .set_online = qeth_l3_set_online,
        .set_offline = qeth_l3_set_offline,
        .shutdown = qeth_l3_shutdown,
+       .freeze = qeth_l3_pm_suspend,
+       .thaw = qeth_l3_pm_resume,
+       .restore = qeth_l3_pm_resume,
 };
 EXPORT_SYMBOL_GPL(qeth_l3_ccwgroup_driver);