aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/net/qeth_core_main.c51
-rw-r--r--drivers/s390/net/qeth_l2_main.c52
-rw-r--r--drivers/s390/net/qeth_l3_main.c52
3 files changed, 152 insertions, 3 deletions
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 74c49d9a8db..d53621c4acb 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -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
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index ecd3d06c0d5..81d7f268418 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -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);
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 6f2386e9d6e..54872406864 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -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);