aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hsi
diff options
context:
space:
mode:
authorCarlos Chinea <carlos.chinea@nokia.com>2012-04-04 07:11:45 -0400
committerCarlos Chinea <carlos.chinea@nokia.com>2012-04-23 07:23:31 -0400
commit5a218ceba7b64f506bf4f004b04bb457c1805a62 (patch)
treef1f123391bbebd8c6136e9118bf8a2f6b0c49734 /drivers/hsi
parent66f75a5d028beaf67c931435fdc3e7823125730c (diff)
HSI: hsi: Rework hsi_controller release
Use the proper release mechanism for hsi_controller and hsi_ports structures. Free the structures through their associated device release callbacks. Signed-off-by: Carlos Chinea <carlos.chinea@nokia.com> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Acked-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/hsi')
-rw-r--r--drivers/hsi/hsi.c108
1 files changed, 66 insertions, 42 deletions
diff --git a/drivers/hsi/hsi.c b/drivers/hsi/hsi.c
index 4e2d79b79334..c17d12ca8e7f 100644
--- a/drivers/hsi/hsi.c
+++ b/drivers/hsi/hsi.c
@@ -140,12 +140,17 @@ static int hsi_remove_port(struct device *dev, void *data __maybe_unused)
140 return 0; 140 return 0;
141} 141}
142 142
143static void hsi_controller_release(struct device *dev __maybe_unused) 143static void hsi_controller_release(struct device *dev)
144{ 144{
145 struct hsi_controller *hsi = to_hsi_controller(dev);
146
147 kfree(hsi->port);
148 kfree(hsi);
145} 149}
146 150
147static void hsi_port_release(struct device *dev __maybe_unused) 151static void hsi_port_release(struct device *dev)
148{ 152{
153 kfree(to_hsi_port(dev));
149} 154}
150 155
151/** 156/**
@@ -172,18 +177,14 @@ int hsi_register_controller(struct hsi_controller *hsi)
172 177
173 hsi->device.type = &hsi_ctrl; 178 hsi->device.type = &hsi_ctrl;
174 hsi->device.bus = &hsi_bus_type; 179 hsi->device.bus = &hsi_bus_type;
175 hsi->device.release = hsi_controller_release; 180 err = device_add(&hsi->device);
176 err = device_register(&hsi->device);
177 if (err < 0) 181 if (err < 0)
178 return err; 182 return err;
179 for (i = 0; i < hsi->num_ports; i++) { 183 for (i = 0; i < hsi->num_ports; i++) {
180 hsi->port[i].device.parent = &hsi->device; 184 hsi->port[i]->device.parent = &hsi->device;
181 hsi->port[i].device.bus = &hsi_bus_type; 185 hsi->port[i]->device.bus = &hsi_bus_type;
182 hsi->port[i].device.release = hsi_port_release; 186 hsi->port[i]->device.type = &hsi_port;
183 hsi->port[i].device.type = &hsi_port; 187 err = device_add(&hsi->port[i]->device);
184 INIT_LIST_HEAD(&hsi->port[i].clients);
185 spin_lock_init(&hsi->port[i].clock);
186 err = device_register(&hsi->port[i].device);
187 if (err < 0) 188 if (err < 0)
188 goto out; 189 goto out;
189 } 190 }
@@ -192,7 +193,9 @@ int hsi_register_controller(struct hsi_controller *hsi)
192 193
193 return 0; 194 return 0;
194out: 195out:
195 hsi_unregister_controller(hsi); 196 while (i-- > 0)
197 device_del(&hsi->port[i]->device);
198 device_del(&hsi->device);
196 199
197 return err; 200 return err;
198} 201}
@@ -223,6 +226,29 @@ static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused)
223} 226}
224 227
225/** 228/**
229 * hsi_put_controller - Free an HSI controller
230 *
231 * @hsi: Pointer to the HSI controller to freed
232 *
233 * HSI controller drivers should only use this function if they need
234 * to free their allocated hsi_controller structures before a successful
235 * call to hsi_register_controller. Other use is not allowed.
236 */
237void hsi_put_controller(struct hsi_controller *hsi)
238{
239 unsigned int i;
240
241 if (!hsi)
242 return;
243
244 for (i = 0; i < hsi->num_ports; i++)
245 if (hsi->port && hsi->port[i])
246 put_device(&hsi->port[i]->device);
247 put_device(&hsi->device);
248}
249EXPORT_SYMBOL_GPL(hsi_put_controller);
250
251/**
226 * hsi_alloc_controller - Allocate an HSI controller and its ports 252 * hsi_alloc_controller - Allocate an HSI controller and its ports
227 * @n_ports: Number of ports on the HSI controller 253 * @n_ports: Number of ports on the HSI controller
228 * @flags: Kernel allocation flags 254 * @flags: Kernel allocation flags
@@ -232,55 +258,53 @@ static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused)
232struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags) 258struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags)
233{ 259{
234 struct hsi_controller *hsi; 260 struct hsi_controller *hsi;
235 struct hsi_port *port; 261 struct hsi_port **port;
236 unsigned int i; 262 unsigned int i;
237 263
238 if (!n_ports) 264 if (!n_ports)
239 return NULL; 265 return NULL;
240 266
241 port = kzalloc(sizeof(*port)*n_ports, flags);
242 if (!port)
243 return NULL;
244 hsi = kzalloc(sizeof(*hsi), flags); 267 hsi = kzalloc(sizeof(*hsi), flags);
245 if (!hsi) 268 if (!hsi)
246 goto out; 269 return NULL;
247 for (i = 0; i < n_ports; i++) { 270 port = kzalloc(sizeof(*port)*n_ports, flags);
248 dev_set_name(&port[i].device, "port%d", i); 271 if (!port) {
249 port[i].num = i; 272 kfree(hsi);
250 port[i].async = hsi_dummy_msg; 273 return NULL;
251 port[i].setup = hsi_dummy_cl;
252 port[i].flush = hsi_dummy_cl;
253 port[i].start_tx = hsi_dummy_cl;
254 port[i].stop_tx = hsi_dummy_cl;
255 port[i].release = hsi_dummy_cl;
256 mutex_init(&port[i].lock);
257 } 274 }
258 hsi->num_ports = n_ports; 275 hsi->num_ports = n_ports;
259 hsi->port = port; 276 hsi->port = port;
277 hsi->device.release = hsi_controller_release;
278 device_initialize(&hsi->device);
279
280 for (i = 0; i < n_ports; i++) {
281 port[i] = kzalloc(sizeof(**port), flags);
282 if (port[i] == NULL)
283 goto out;
284 port[i]->num = i;
285 port[i]->async = hsi_dummy_msg;
286 port[i]->setup = hsi_dummy_cl;
287 port[i]->flush = hsi_dummy_cl;
288 port[i]->start_tx = hsi_dummy_cl;
289 port[i]->stop_tx = hsi_dummy_cl;
290 port[i]->release = hsi_dummy_cl;
291 mutex_init(&port[i]->lock);
292 INIT_LIST_HEAD(&hsi->port[i]->clients);
293 spin_lock_init(&hsi->port[i]->clock);
294 dev_set_name(&port[i]->device, "port%d", i);
295 hsi->port[i]->device.release = hsi_port_release;
296 device_initialize(&hsi->port[i]->device);
297 }
260 298
261 return hsi; 299 return hsi;
262out: 300out:
263 kfree(port); 301 hsi_put_controller(hsi);
264 302
265 return NULL; 303 return NULL;
266} 304}
267EXPORT_SYMBOL_GPL(hsi_alloc_controller); 305EXPORT_SYMBOL_GPL(hsi_alloc_controller);
268 306
269/** 307/**
270 * hsi_free_controller - Free an HSI controller
271 * @hsi: Pointer to HSI controller
272 */
273void hsi_free_controller(struct hsi_controller *hsi)
274{
275 if (!hsi)
276 return;
277
278 kfree(hsi->port);
279 kfree(hsi);
280}
281EXPORT_SYMBOL_GPL(hsi_free_controller);
282
283/**
284 * hsi_free_msg - Free an HSI message 308 * hsi_free_msg - Free an HSI message
285 * @msg: Pointer to the HSI message 309 * @msg: Pointer to the HSI message
286 * 310 *