diff options
Diffstat (limited to 'arch/ppc64/kernel/vio.c')
-rw-r--r-- | arch/ppc64/kernel/vio.c | 73 |
1 files changed, 27 insertions, 46 deletions
diff --git a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c index 3b790bafcaad..c90e1dd875ce 100644 --- a/arch/ppc64/kernel/vio.c +++ b/arch/ppc64/kernel/vio.c | |||
@@ -32,14 +32,13 @@ struct vio_dev vio_bus_device = { /* fake "parent" device */ | |||
32 | .dev.bus = &vio_bus_type, | 32 | .dev.bus = &vio_bus_type, |
33 | }; | 33 | }; |
34 | 34 | ||
35 | static int (*is_match)(const struct vio_device_id *id, | 35 | static struct vio_bus_ops vio_bus_ops; |
36 | const struct vio_dev *dev); | ||
37 | static void (*unregister_device_callback)(struct vio_dev *dev); | ||
38 | static void (*release_device_callback)(struct device *dev); | ||
39 | 36 | ||
40 | /* convert from struct device to struct vio_dev and pass to driver. | 37 | /* |
38 | * Convert from struct device to struct vio_dev and pass to driver. | ||
41 | * dev->driver has already been set by generic code because vio_bus_match | 39 | * dev->driver has already been set by generic code because vio_bus_match |
42 | * succeeded. */ | 40 | * succeeded. |
41 | */ | ||
43 | static int vio_bus_probe(struct device *dev) | 42 | static int vio_bus_probe(struct device *dev) |
44 | { | 43 | { |
45 | struct vio_dev *viodev = to_vio_dev(dev); | 44 | struct vio_dev *viodev = to_vio_dev(dev); |
@@ -51,9 +50,8 @@ static int vio_bus_probe(struct device *dev) | |||
51 | return error; | 50 | return error; |
52 | 51 | ||
53 | id = vio_match_device(viodrv->id_table, viodev); | 52 | id = vio_match_device(viodrv->id_table, viodev); |
54 | if (id) { | 53 | if (id) |
55 | error = viodrv->probe(viodev, id); | 54 | error = viodrv->probe(viodev, id); |
56 | } | ||
57 | 55 | ||
58 | return error; | 56 | return error; |
59 | } | 57 | } |
@@ -64,9 +62,8 @@ static int vio_bus_remove(struct device *dev) | |||
64 | struct vio_dev *viodev = to_vio_dev(dev); | 62 | struct vio_dev *viodev = to_vio_dev(dev); |
65 | struct vio_driver *viodrv = to_vio_driver(dev->driver); | 63 | struct vio_driver *viodrv = to_vio_driver(dev->driver); |
66 | 64 | ||
67 | if (viodrv->remove) { | 65 | if (viodrv->remove) |
68 | return viodrv->remove(viodev); | 66 | return viodrv->remove(viodev); |
69 | } | ||
70 | 67 | ||
71 | /* driver can't remove */ | 68 | /* driver can't remove */ |
72 | return 1; | 69 | return 1; |
@@ -102,19 +99,20 @@ void vio_unregister_driver(struct vio_driver *viodrv) | |||
102 | EXPORT_SYMBOL(vio_unregister_driver); | 99 | EXPORT_SYMBOL(vio_unregister_driver); |
103 | 100 | ||
104 | /** | 101 | /** |
105 | * vio_match_device: - Tell if a VIO device has a matching VIO device id structure. | 102 | * vio_match_device: - Tell if a VIO device has a matching |
106 | * @ids: array of VIO device id structures to search in | 103 | * VIO device id structure. |
107 | * @dev: the VIO device structure to match against | 104 | * @ids: array of VIO device id structures to search in |
105 | * @dev: the VIO device structure to match against | ||
108 | * | 106 | * |
109 | * Used by a driver to check whether a VIO device present in the | 107 | * Used by a driver to check whether a VIO device present in the |
110 | * system is in its list of supported devices. Returns the matching | 108 | * system is in its list of supported devices. Returns the matching |
111 | * vio_device_id structure or NULL if there is no match. | 109 | * vio_device_id structure or NULL if there is no match. |
112 | */ | 110 | */ |
113 | static const struct vio_device_id * vio_match_device(const struct vio_device_id *ids, | 111 | static const struct vio_device_id *vio_match_device( |
114 | const struct vio_dev *dev) | 112 | const struct vio_device_id *ids, const struct vio_dev *dev) |
115 | { | 113 | { |
116 | while (ids->type) { | 114 | while (ids->type[0] != '\0') { |
117 | if (is_match(ids, dev)) | 115 | if (vio_bus_ops.match(ids, dev)) |
118 | return ids; | 116 | return ids; |
119 | ids++; | 117 | ids++; |
120 | } | 118 | } |
@@ -124,16 +122,11 @@ static const struct vio_device_id * vio_match_device(const struct vio_device_id | |||
124 | /** | 122 | /** |
125 | * vio_bus_init: - Initialize the virtual IO bus | 123 | * vio_bus_init: - Initialize the virtual IO bus |
126 | */ | 124 | */ |
127 | int __init vio_bus_init(int (*match_func)(const struct vio_device_id *id, | 125 | int __init vio_bus_init(struct vio_bus_ops *ops) |
128 | const struct vio_dev *dev), | ||
129 | void (*unregister_dev)(struct vio_dev *), | ||
130 | void (*release_dev)(struct device *)) | ||
131 | { | 126 | { |
132 | int err; | 127 | int err; |
133 | 128 | ||
134 | is_match = match_func; | 129 | vio_bus_ops = *ops; |
135 | unregister_device_callback = unregister_dev; | ||
136 | release_device_callback = release_dev; | ||
137 | 130 | ||
138 | err = bus_register(&vio_bus_type); | 131 | err = bus_register(&vio_bus_type); |
139 | if (err) { | 132 | if (err) { |
@@ -141,7 +134,8 @@ int __init vio_bus_init(int (*match_func)(const struct vio_device_id *id, | |||
141 | return err; | 134 | return err; |
142 | } | 135 | } |
143 | 136 | ||
144 | /* the fake parent of all vio devices, just to give us | 137 | /* |
138 | * The fake parent of all vio devices, just to give us | ||
145 | * a nice directory | 139 | * a nice directory |
146 | */ | 140 | */ |
147 | err = device_register(&vio_bus_device.dev); | 141 | err = device_register(&vio_bus_device.dev); |
@@ -157,25 +151,20 @@ int __init vio_bus_init(int (*match_func)(const struct vio_device_id *id, | |||
157 | /* vio_dev refcount hit 0 */ | 151 | /* vio_dev refcount hit 0 */ |
158 | static void __devinit vio_dev_release(struct device *dev) | 152 | static void __devinit vio_dev_release(struct device *dev) |
159 | { | 153 | { |
160 | if (release_device_callback) | 154 | if (vio_bus_ops.release_device) |
161 | release_device_callback(dev); | 155 | vio_bus_ops.release_device(dev); |
162 | kfree(to_vio_dev(dev)); | 156 | kfree(to_vio_dev(dev)); |
163 | } | 157 | } |
164 | 158 | ||
165 | static ssize_t viodev_show_name(struct device *dev, struct device_attribute *attr, char *buf) | 159 | static ssize_t viodev_show_name(struct device *dev, |
160 | struct device_attribute *attr, char *buf) | ||
166 | { | 161 | { |
167 | return sprintf(buf, "%s\n", to_vio_dev(dev)->name); | 162 | return sprintf(buf, "%s\n", to_vio_dev(dev)->name); |
168 | } | 163 | } |
169 | DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL); | 164 | DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL); |
170 | 165 | ||
171 | struct vio_dev * __devinit vio_register_device_common( | 166 | struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev) |
172 | struct vio_dev *viodev, char *name, char *type, | ||
173 | uint32_t unit_address, struct iommu_table *iommu_table) | ||
174 | { | 167 | { |
175 | viodev->name = name; | ||
176 | viodev->type = type; | ||
177 | viodev->unit_address = unit_address; | ||
178 | viodev->iommu_table = iommu_table; | ||
179 | /* init generic 'struct device' fields: */ | 168 | /* init generic 'struct device' fields: */ |
180 | viodev->dev.parent = &vio_bus_device.dev; | 169 | viodev->dev.parent = &vio_bus_device.dev; |
181 | viodev->dev.bus = &vio_bus_type; | 170 | viodev->dev.bus = &vio_bus_type; |
@@ -194,8 +183,8 @@ struct vio_dev * __devinit vio_register_device_common( | |||
194 | 183 | ||
195 | void __devinit vio_unregister_device(struct vio_dev *viodev) | 184 | void __devinit vio_unregister_device(struct vio_dev *viodev) |
196 | { | 185 | { |
197 | if (unregister_device_callback) | 186 | if (vio_bus_ops.unregister_device) |
198 | unregister_device_callback(viodev); | 187 | vio_bus_ops.unregister_device(viodev); |
199 | device_remove_file(&viodev->dev, &dev_attr_name); | 188 | device_remove_file(&viodev->dev, &dev_attr_name); |
200 | device_unregister(&viodev->dev); | 189 | device_unregister(&viodev->dev); |
201 | } | 190 | } |
@@ -262,16 +251,8 @@ static int vio_bus_match(struct device *dev, struct device_driver *drv) | |||
262 | const struct vio_dev *vio_dev = to_vio_dev(dev); | 251 | const struct vio_dev *vio_dev = to_vio_dev(dev); |
263 | struct vio_driver *vio_drv = to_vio_driver(drv); | 252 | struct vio_driver *vio_drv = to_vio_driver(drv); |
264 | const struct vio_device_id *ids = vio_drv->id_table; | 253 | const struct vio_device_id *ids = vio_drv->id_table; |
265 | const struct vio_device_id *found_id; | ||
266 | |||
267 | if (!ids) | ||
268 | return 0; | ||
269 | 254 | ||
270 | found_id = vio_match_device(ids, vio_dev); | 255 | return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL); |
271 | if (found_id) | ||
272 | return 1; | ||
273 | |||
274 | return 0; | ||
275 | } | 256 | } |
276 | 257 | ||
277 | struct bus_type vio_bus_type = { | 258 | struct bus_type vio_bus_type = { |