aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/device.c')
-rw-r--r--drivers/s390/cio/device.c260
1 files changed, 260 insertions, 0 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 35441fa16be1..3c57c1a18bb8 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -138,6 +138,19 @@ static struct css_device_id io_subchannel_ids[] = {
138}; 138};
139MODULE_DEVICE_TABLE(css, io_subchannel_ids); 139MODULE_DEVICE_TABLE(css, io_subchannel_ids);
140 140
141static int io_subchannel_prepare(struct subchannel *sch)
142{
143 struct ccw_device *cdev;
144 /*
145 * Don't allow suspend while a ccw device registration
146 * is still outstanding.
147 */
148 cdev = sch_get_cdev(sch);
149 if (cdev && !device_is_registered(&cdev->dev))
150 return -EAGAIN;
151 return 0;
152}
153
141static struct css_driver io_subchannel_driver = { 154static struct css_driver io_subchannel_driver = {
142 .owner = THIS_MODULE, 155 .owner = THIS_MODULE,
143 .subchannel_type = io_subchannel_ids, 156 .subchannel_type = io_subchannel_ids,
@@ -148,6 +161,7 @@ static struct css_driver io_subchannel_driver = {
148 .probe = io_subchannel_probe, 161 .probe = io_subchannel_probe,
149 .remove = io_subchannel_remove, 162 .remove = io_subchannel_remove,
150 .shutdown = io_subchannel_shutdown, 163 .shutdown = io_subchannel_shutdown,
164 .prepare = io_subchannel_prepare,
151}; 165};
152 166
153struct workqueue_struct *ccw_device_work; 167struct workqueue_struct *ccw_device_work;
@@ -1775,6 +1789,15 @@ ccw_device_probe_console(void)
1775 return &console_cdev; 1789 return &console_cdev;
1776} 1790}
1777 1791
1792static int ccw_device_pm_restore(struct device *dev);
1793
1794int ccw_device_force_console(void)
1795{
1796 if (!console_cdev_in_use)
1797 return -ENODEV;
1798 return ccw_device_pm_restore(&console_cdev.dev);
1799}
1800EXPORT_SYMBOL_GPL(ccw_device_force_console);
1778 1801
1779const char *cio_get_console_cdev_name(struct subchannel *sch) 1802const char *cio_get_console_cdev_name(struct subchannel *sch)
1780{ 1803{
@@ -1895,6 +1918,242 @@ static void ccw_device_shutdown(struct device *dev)
1895 disable_cmf(cdev); 1918 disable_cmf(cdev);
1896} 1919}
1897 1920
1921static int ccw_device_pm_prepare(struct device *dev)
1922{
1923 struct ccw_device *cdev = to_ccwdev(dev);
1924
1925 if (work_pending(&cdev->private->kick_work))
1926 return -EAGAIN;
1927 /* Fail while device is being set online/offline. */
1928 if (atomic_read(&cdev->private->onoff))
1929 return -EAGAIN;
1930
1931 if (cdev->online && cdev->drv && cdev->drv->prepare)
1932 return cdev->drv->prepare(cdev);
1933
1934 return 0;
1935}
1936
1937static void ccw_device_pm_complete(struct device *dev)
1938{
1939 struct ccw_device *cdev = to_ccwdev(dev);
1940
1941 if (cdev->online && cdev->drv && cdev->drv->complete)
1942 cdev->drv->complete(cdev);
1943}
1944
1945static int ccw_device_pm_freeze(struct device *dev)
1946{
1947 struct ccw_device *cdev = to_ccwdev(dev);
1948 struct subchannel *sch = to_subchannel(cdev->dev.parent);
1949 int ret, cm_enabled;
1950
1951 /* Fail suspend while device is in transistional state. */
1952 if (!dev_fsm_final_state(cdev))
1953 return -EAGAIN;
1954 if (!cdev->online)
1955 return 0;
1956 if (cdev->drv && cdev->drv->freeze) {
1957 ret = cdev->drv->freeze(cdev);
1958 if (ret)
1959 return ret;
1960 }
1961
1962 spin_lock_irq(sch->lock);
1963 cm_enabled = cdev->private->cmb != NULL;
1964 spin_unlock_irq(sch->lock);
1965 if (cm_enabled) {
1966 /* Don't have the css write on memory. */
1967 ret = ccw_set_cmf(cdev, 0);
1968 if (ret)
1969 return ret;
1970 }
1971 /* From here on, disallow device driver I/O. */
1972 spin_lock_irq(sch->lock);
1973 ret = cio_disable_subchannel(sch);
1974 spin_unlock_irq(sch->lock);
1975
1976 return ret;
1977}
1978
1979static int ccw_device_pm_thaw(struct device *dev)
1980{
1981 struct ccw_device *cdev = to_ccwdev(dev);
1982 struct subchannel *sch = to_subchannel(cdev->dev.parent);
1983 int ret, cm_enabled;
1984
1985 if (!cdev->online)
1986 return 0;
1987
1988 spin_lock_irq(sch->lock);
1989 /* Allow device driver I/O again. */
1990 ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
1991 cm_enabled = cdev->private->cmb != NULL;
1992 spin_unlock_irq(sch->lock);
1993 if (ret)
1994 return ret;
1995
1996 if (cm_enabled) {
1997 ret = ccw_set_cmf(cdev, 1);
1998 if (ret)
1999 return ret;
2000 }
2001
2002 if (cdev->drv && cdev->drv->thaw)
2003 ret = cdev->drv->thaw(cdev);
2004
2005 return ret;
2006}
2007
2008static void __ccw_device_pm_restore(struct ccw_device *cdev)
2009{
2010 struct subchannel *sch = to_subchannel(cdev->dev.parent);
2011 int ret;
2012
2013 if (cio_is_console(sch->schid))
2014 goto out;
2015 /*
2016 * While we were sleeping, devices may have gone or become
2017 * available again. Kick re-detection.
2018 */
2019 spin_lock_irq(sch->lock);
2020 cdev->private->flags.resuming = 1;
2021 ret = ccw_device_recognition(cdev);
2022 spin_unlock_irq(sch->lock);
2023 if (ret) {
2024 CIO_MSG_EVENT(0, "Couldn't start recognition for device "
2025 "%s (ret=%d)\n", dev_name(&cdev->dev), ret);
2026 spin_lock_irq(sch->lock);
2027 cdev->private->state = DEV_STATE_DISCONNECTED;
2028 spin_unlock_irq(sch->lock);
2029 /* notify driver after the resume cb */
2030 goto out;
2031 }
2032 wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev) ||
2033 cdev->private->state == DEV_STATE_DISCONNECTED);
2034
2035out:
2036 cdev->private->flags.resuming = 0;
2037}
2038
2039static int resume_handle_boxed(struct ccw_device *cdev)
2040{
2041 cdev->private->state = DEV_STATE_BOXED;
2042 if (ccw_device_notify(cdev, CIO_BOXED))
2043 return 0;
2044 ccw_device_schedule_sch_unregister(cdev);
2045 return -ENODEV;
2046}
2047
2048static int resume_handle_disc(struct ccw_device *cdev)
2049{
2050 cdev->private->state = DEV_STATE_DISCONNECTED;
2051 if (ccw_device_notify(cdev, CIO_GONE))
2052 return 0;
2053 ccw_device_schedule_sch_unregister(cdev);
2054 return -ENODEV;
2055}
2056
2057static int ccw_device_pm_restore(struct device *dev)
2058{
2059 struct ccw_device *cdev = to_ccwdev(dev);
2060 struct subchannel *sch = to_subchannel(cdev->dev.parent);
2061 int ret = 0, cm_enabled;
2062
2063 __ccw_device_pm_restore(cdev);
2064 spin_lock_irq(sch->lock);
2065 if (cio_is_console(sch->schid)) {
2066 cio_enable_subchannel(sch, (u32)(addr_t)sch);
2067 spin_unlock_irq(sch->lock);
2068 goto out_restore;
2069 }
2070 cdev->private->flags.donotify = 0;
2071 /* check recognition results */
2072 switch (cdev->private->state) {
2073 case DEV_STATE_OFFLINE:
2074 break;
2075 case DEV_STATE_BOXED:
2076 ret = resume_handle_boxed(cdev);
2077 spin_unlock_irq(sch->lock);
2078 if (ret)
2079 goto out;
2080 goto out_restore;
2081 case DEV_STATE_DISCONNECTED:
2082 goto out_disc_unlock;
2083 default:
2084 goto out_unreg_unlock;
2085 }
2086 /* check if the device id has changed */
2087 if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) {
2088 CIO_MSG_EVENT(0, "resume: sch %s: failed (devno changed from "
2089 "%04x to %04x)\n", dev_name(&sch->dev),
2090 cdev->private->dev_id.devno,
2091 sch->schib.pmcw.dev);
2092 goto out_unreg_unlock;
2093 }
2094 /* check if the device type has changed */
2095 if (!ccw_device_test_sense_data(cdev)) {
2096 ccw_device_update_sense_data(cdev);
2097 PREPARE_WORK(&cdev->private->kick_work,
2098 ccw_device_do_unbind_bind);
2099 queue_work(ccw_device_work, &cdev->private->kick_work);
2100 ret = -ENODEV;
2101 goto out_unlock;
2102 }
2103 if (!cdev->online) {
2104 ret = 0;
2105 goto out_unlock;
2106 }
2107 ret = ccw_device_online(cdev);
2108 if (ret)
2109 goto out_disc_unlock;
2110
2111 cm_enabled = cdev->private->cmb != NULL;
2112 spin_unlock_irq(sch->lock);
2113
2114 wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
2115 if (cdev->private->state != DEV_STATE_ONLINE) {
2116 spin_lock_irq(sch->lock);
2117 goto out_disc_unlock;
2118 }
2119 if (cm_enabled) {
2120 ret = ccw_set_cmf(cdev, 1);
2121 if (ret) {
2122 CIO_MSG_EVENT(2, "resume: cdev %s: cmf failed "
2123 "(rc=%d)\n", dev_name(&cdev->dev), ret);
2124 ret = 0;
2125 }
2126 }
2127
2128out_restore:
2129 if (cdev->online && cdev->drv && cdev->drv->restore)
2130 ret = cdev->drv->restore(cdev);
2131out:
2132 return ret;
2133
2134out_disc_unlock:
2135 ret = resume_handle_disc(cdev);
2136 spin_unlock_irq(sch->lock);
2137 if (ret)
2138 return ret;
2139 goto out_restore;
2140
2141out_unreg_unlock:
2142 ccw_device_schedule_sch_unregister(cdev);
2143 ret = -ENODEV;
2144out_unlock:
2145 spin_unlock_irq(sch->lock);
2146 return ret;
2147}
2148
2149static struct dev_pm_ops ccw_pm_ops = {
2150 .prepare = ccw_device_pm_prepare,
2151 .complete = ccw_device_pm_complete,
2152 .freeze = ccw_device_pm_freeze,
2153 .thaw = ccw_device_pm_thaw,
2154 .restore = ccw_device_pm_restore,
2155};
2156
1898struct bus_type ccw_bus_type = { 2157struct bus_type ccw_bus_type = {
1899 .name = "ccw", 2158 .name = "ccw",
1900 .match = ccw_bus_match, 2159 .match = ccw_bus_match,
@@ -1902,6 +2161,7 @@ struct bus_type ccw_bus_type = {
1902 .probe = ccw_device_probe, 2161 .probe = ccw_device_probe,
1903 .remove = ccw_device_remove, 2162 .remove = ccw_device_remove,
1904 .shutdown = ccw_device_shutdown, 2163 .shutdown = ccw_device_shutdown,
2164 .pm = &ccw_pm_ops,
1905}; 2165};
1906 2166
1907/** 2167/**