]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.25/patches.arch/s390-10-10-ccwgroup_fix_unbind.patch
Reenabled linux-xen and xen-image build
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.arch / s390-10-10-ccwgroup_fix_unbind.patch
CommitLineData
00e5a55c
BS
1From: Gerald Schaefer <geraldsc@de.ibm.com>
2Subject: cio: ccwgroup - fix unbind behaviour
3References: bnc#482818,LTC#52098
4
5Symptom: Oops after unbinding a ccwgroup device.
6Problem: There is no special callback to tell a driver to unbind
7 a device - the normal remove is called. In this case
8 the device remains partly registered in the driver core.
9Solution: Use a bus notifier function to handle this special case
10 and call ungroup since this virtual device can not exist
11 without a driver.
12
13Acked-by: John Jolly <jjolly@suse.de>
14---
15 drivers/s390/cio/ccwgroup.c | 73 +++++++++++++++++++++++++++++++++-----------
16 1 file changed, 56 insertions(+), 17 deletions(-)
17
18Index: linux-sles11/drivers/s390/cio/ccwgroup.c
19===================================================================
20--- linux-sles11.orig/drivers/s390/cio/ccwgroup.c 2009-03-09 15:36:56.000000000 +0100
21+++ linux-sles11/drivers/s390/cio/ccwgroup.c 2009-03-09 15:53:56.000000000 +0100
22@@ -313,16 +313,32 @@ error:
23 }
24 EXPORT_SYMBOL(ccwgroup_create_from_string);
25
26-static int __init
27-init_ccwgroup (void)
28+static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
29+ void *data);
30+
31+static struct notifier_block ccwgroup_nb = {
32+ .notifier_call = ccwgroup_notifier
33+};
34+
35+static int __init init_ccwgroup(void)
36 {
37- return bus_register (&ccwgroup_bus_type);
38+ int ret;
39+
40+ ret = bus_register(&ccwgroup_bus_type);
41+ if (ret)
42+ return ret;
43+
44+ ret = bus_register_notifier(&ccwgroup_bus_type, &ccwgroup_nb);
45+ if (ret)
46+ bus_unregister(&ccwgroup_bus_type);
47+
48+ return ret;
49 }
50
51-static void __exit
52-cleanup_ccwgroup (void)
53+static void __exit cleanup_ccwgroup(void)
54 {
55- bus_unregister (&ccwgroup_bus_type);
56+ bus_unregister_notifier(&ccwgroup_bus_type, &ccwgroup_nb);
57+ bus_unregister(&ccwgroup_bus_type);
58 }
59
60 module_init(init_ccwgroup);
61@@ -390,27 +406,28 @@ ccwgroup_online_store (struct device *de
62 unsigned long value;
63 int ret;
64
65- gdev = to_ccwgroupdev(dev);
66 if (!dev->driver)
67- return count;
68+ return -ENODEV;
69+
70+ gdev = to_ccwgroupdev(dev);
71+ gdrv = to_ccwgroupdrv(dev->driver);
72
73- gdrv = to_ccwgroupdrv (gdev->dev.driver);
74 if (!try_module_get(gdrv->owner))
75 return -EINVAL;
76
77 ret = strict_strtoul(buf, 0, &value);
78 if (ret)
79 goto out;
80- ret = count;
81+
82 if (value == 1)
83- ccwgroup_set_online(gdev);
84+ ret = ccwgroup_set_online(gdev);
85 else if (value == 0)
86- ccwgroup_set_offline(gdev);
87+ ret = ccwgroup_set_offline(gdev);
88 else
89 ret = -EINVAL;
90 out:
91 module_put(gdrv->owner);
92- return ret;
93+ return (ret == 0) ? count : ret;
94 }
95
96 static ssize_t
97@@ -452,13 +469,18 @@ ccwgroup_remove (struct device *dev)
98 struct ccwgroup_device *gdev;
99 struct ccwgroup_driver *gdrv;
100
101+ device_remove_file(dev, &dev_attr_online);
102+ device_remove_file(dev, &dev_attr_ungroup);
103+
104+ if (!dev->driver)
105+ return 0;
106+
107 gdev = to_ccwgroupdev(dev);
108 gdrv = to_ccwgroupdrv(dev->driver);
109
110- device_remove_file(dev, &dev_attr_online);
111-
112- if (gdrv && gdrv->remove)
113+ if (gdrv->remove)
114 gdrv->remove(gdev);
115+
116 return 0;
117 }
118
119@@ -467,9 +489,13 @@ static void ccwgroup_shutdown(struct dev
120 struct ccwgroup_device *gdev;
121 struct ccwgroup_driver *gdrv;
122
123+ if (!dev->driver)
124+ return;
125+
126 gdev = to_ccwgroupdev(dev);
127 gdrv = to_ccwgroupdrv(dev->driver);
128- if (gdrv && gdrv->shutdown)
129+
130+ if (gdrv->shutdown)
131 gdrv->shutdown(gdev);
132 }
133
134@@ -482,6 +508,19 @@ static struct bus_type ccwgroup_bus_type
135 .shutdown = ccwgroup_shutdown,
136 };
137
138+
139+static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
140+ void *data)
141+{
142+ struct device *dev = data;
143+
144+ if (action == BUS_NOTIFY_UNBIND_DRIVER)
145+ device_schedule_callback(dev, ccwgroup_ungroup_callback);
146+
147+ return NOTIFY_OK;
148+}
149+
150+
151 /**
152 * ccwgroup_driver_register() - register a ccw group driver
153 * @cdriver: driver to be registered