diff options
Diffstat (limited to 'drivers/s390/net/lcs.c')
-rw-r--r-- | drivers/s390/net/lcs.c | 94 |
1 files changed, 75 insertions, 19 deletions
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index a45bc24eb5f9..8c675905448b 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -1,15 +1,12 @@ /* - * linux/drivers/s390/net/lcs.c - * * Linux for S/390 Lan Channel Station Network Driver * - * Copyright (C) 1999-2001 IBM Deutschland Entwicklung GmbH, - * IBM Corporation - * Author(s): Original Code written by - * DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) - * Rewritten by - * Frank Pavlic (fpavlic@de.ibm.com) and - * Martin Schwidefsky <schwidefsky@de.ibm.com> + * Copyright IBM Corp. 1999, 2009 + * Author(s): Original Code written by + * DJ Barrow <djbarrow@de.ibm.com,barrow_dj@yahoo.com> + * Rewritten by + * Frank Pavlic <fpavlic@de.ibm.com> and + * Martin Schwidefsky <schwidefsky@de.ibm.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1939,7 +1936,7 @@ lcs_portno_show (struct device *dev, struct device_attribute *attr, char *buf) { struct lcs_card *card; - card = (struct lcs_card *)dev->driver_data; + card = dev_get_drvdata(dev); if (!card) return 0; @@ -1956,7 +1953,7 @@ lcs_portno_store (struct device *dev, struct device_attribute *attr, const char struct lcs_card *card; int value; - card = (struct lcs_card *)dev->driver_data; + card = dev_get_drvdata(dev); if (!card) return 0; @@ -1990,7 +1987,7 @@ lcs_timeout_show(struct device *dev, struct device_attribute *attr, char *buf) { struct lcs_card *card; - card = (struct lcs_card *)dev->driver_data; + card = dev_get_drvdata(dev); return card ? sprintf(buf, "%u\n", card->lancmd_timeout) : 0; } @@ -2001,7 +1998,7 @@ lcs_timeout_store (struct device *dev, struct device_attribute *attr, const char struct lcs_card *card; int value; - card = (struct lcs_card *)dev->driver_data; + card = dev_get_drvdata(dev); if (!card) return 0; @@ -2020,7 +2017,7 @@ static ssize_t lcs_dev_recover_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct lcs_card *card = dev->driver_data; + struct lcs_card *card = dev_get_drvdata(dev); char *tmp; int i; @@ -2073,7 +2070,7 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev) put_device(&ccwgdev->dev); return ret; } - ccwgdev->dev.driver_data = card; + dev_set_drvdata(&ccwgdev->dev, card); ccwgdev->cdev[0]->handler = lcs_irq; ccwgdev->cdev[1]->handler = lcs_irq; card->gdev = ccwgdev; @@ -2090,7 +2087,7 @@ lcs_register_netdev(struct ccwgroup_device *ccwgdev) struct lcs_card *card; LCS_DBF_TEXT(2, setup, "regnetdv"); - card = (struct lcs_card *)ccwgdev->dev.driver_data; + card = dev_get_drvdata(&ccwgdev->dev); if (card->dev->reg_state != NETREG_UNINITIALIZED) return 0; SET_NETDEV_DEV(card->dev, &ccwgdev->dev); @@ -2123,7 +2120,7 @@ lcs_new_device(struct ccwgroup_device *ccwgdev) enum lcs_dev_states recover_state; int rc; - card = (struct lcs_card *)ccwgdev->dev.driver_data; + card = dev_get_drvdata(&ccwgdev->dev); if (!card) return -ENODEV; @@ -2229,7 +2226,7 @@ __lcs_shutdown_device(struct ccwgroup_device *ccwgdev, int recovery_mode) int ret; LCS_DBF_TEXT(3, setup, "shtdndev"); - card = (struct lcs_card *)ccwgdev->dev.driver_data; + card = dev_get_drvdata(&ccwgdev->dev); if (!card) return -ENODEV; if (recovery_mode == 0) { @@ -2296,7 +2293,7 @@ lcs_remove_device(struct ccwgroup_device *ccwgdev) { struct lcs_card *card; - card = (struct lcs_card *)ccwgdev->dev.driver_data; + card = dev_get_drvdata(&ccwgdev->dev); if (!card) return; @@ -2313,6 +2310,60 @@ lcs_remove_device(struct ccwgroup_device *ccwgdev) put_device(&ccwgdev->dev); } +static int lcs_pm_suspend(struct lcs_card *card) +{ + if (card->dev) + netif_device_detach(card->dev); + lcs_set_allowed_threads(card, 0); + lcs_wait_for_threads(card, 0xffffffff); + if (card->state != DEV_STATE_DOWN) + __lcs_shutdown_device(card->gdev, 1); + return 0; +} + +static int lcs_pm_resume(struct lcs_card *card) +{ + int rc = 0; + + if (card->state == DEV_STATE_RECOVER) + rc = lcs_new_device(card->gdev); + if (card->dev) + netif_device_attach(card->dev); + if (rc) { + dev_warn(&card->gdev->dev, "The lcs device driver " + "failed to recover the device\n"); + } + return rc; +} + +static int lcs_prepare(struct ccwgroup_device *gdev) +{ + return 0; +} + +static void lcs_complete(struct ccwgroup_device *gdev) +{ + return; +} + +static int lcs_freeze(struct ccwgroup_device *gdev) +{ + struct lcs_card *card = dev_get_drvdata(&gdev->dev); + return lcs_pm_suspend(card); +} + +static int lcs_thaw(struct ccwgroup_device *gdev) +{ + struct lcs_card *card = dev_get_drvdata(&gdev->dev); + return lcs_pm_resume(card); +} + +static int lcs_restore(struct ccwgroup_device *gdev) +{ + struct lcs_card *card = dev_get_drvdata(&gdev->dev); + return lcs_pm_resume(card); +} + /** * LCS ccwgroup driver registration */ @@ -2325,6 +2376,11 @@ static struct ccwgroup_driver lcs_group_driver = { .remove = lcs_remove_device, .set_online = lcs_new_device, .set_offline = lcs_shutdown_device, + .prepare = lcs_prepare, + .complete = lcs_complete, + .freeze = lcs_freeze, + .thaw = lcs_thaw, + .restore = lcs_restore, }; /** |