HSI: hsi: Fix error path cleanup on client registration
[linux-2.6-block.git] / drivers / hsi / hsi.c
CommitLineData
a056ab8c
CC
1/*
2 * HSI core.
3 *
4 * Copyright (C) 2010 Nokia Corporation. All rights reserved.
5 *
6 * Contact: Carlos Chinea <carlos.chinea@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 */
22#include <linux/hsi/hsi.h>
23#include <linux/compiler.h>
24#include <linux/rwsem.h>
25#include <linux/list.h>
26#include <linux/spinlock.h>
27#include <linux/kobject.h>
28#include <linux/slab.h>
29#include <linux/string.h>
30#include "hsi_core.h"
31
32static struct device_type hsi_ctrl = {
33 .name = "hsi_controller",
34};
35
36static struct device_type hsi_cl = {
37 .name = "hsi_client",
38};
39
40static struct device_type hsi_port = {
41 .name = "hsi_port",
42};
43
44static ssize_t modalias_show(struct device *dev,
45 struct device_attribute *a __maybe_unused, char *buf)
46{
47 return sprintf(buf, "hsi:%s\n", dev_name(dev));
48}
49
50static struct device_attribute hsi_bus_dev_attrs[] = {
51 __ATTR_RO(modalias),
52 __ATTR_NULL,
53};
54
55static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
56{
57 if (dev->type == &hsi_cl)
58 add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev));
59
60 return 0;
61}
62
63static int hsi_bus_match(struct device *dev, struct device_driver *driver)
64{
65 return strcmp(dev_name(dev), driver->name) == 0;
66}
67
68static struct bus_type hsi_bus_type = {
69 .name = "hsi",
70 .dev_attrs = hsi_bus_dev_attrs,
71 .match = hsi_bus_match,
72 .uevent = hsi_bus_uevent,
73};
74
75static void hsi_client_release(struct device *dev)
76{
77 kfree(to_hsi_client(dev));
78}
79
80static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info)
81{
82 struct hsi_client *cl;
83 unsigned long flags;
84
85 cl = kzalloc(sizeof(*cl), GFP_KERNEL);
86 if (!cl)
87 return;
88 cl->device.type = &hsi_cl;
89 cl->tx_cfg = info->tx_cfg;
90 cl->rx_cfg = info->rx_cfg;
91 cl->device.bus = &hsi_bus_type;
92 cl->device.parent = &port->device;
93 cl->device.release = hsi_client_release;
94 dev_set_name(&cl->device, info->name);
95 cl->device.platform_data = info->platform_data;
96 spin_lock_irqsave(&port->clock, flags);
97 list_add_tail(&cl->link, &port->clients);
98 spin_unlock_irqrestore(&port->clock, flags);
99 if (info->archdata)
100 cl->device.archdata = *info->archdata;
101 if (device_register(&cl->device) < 0) {
102 pr_err("hsi: failed to register client: %s\n", info->name);
90e41f9d 103 put_device(&cl->device);
a056ab8c
CC
104 }
105}
106
107static void hsi_scan_board_info(struct hsi_controller *hsi)
108{
109 struct hsi_cl_info *cl_info;
110 struct hsi_port *p;
111
112 list_for_each_entry(cl_info, &hsi_board_list, list)
113 if (cl_info->info.hsi_id == hsi->id) {
114 p = hsi_find_port_num(hsi, cl_info->info.port);
115 if (!p)
116 continue;
117 hsi_new_client(p, &cl_info->info);
118 }
119}
120
121static int hsi_remove_client(struct device *dev, void *data __maybe_unused)
122{
123 struct hsi_client *cl = to_hsi_client(dev);
124 struct hsi_port *port = to_hsi_port(dev->parent);
125 unsigned long flags;
126
127 spin_lock_irqsave(&port->clock, flags);
128 list_del(&cl->link);
129 spin_unlock_irqrestore(&port->clock, flags);
130 device_unregister(dev);
131
132 return 0;
133}
134
135static int hsi_remove_port(struct device *dev, void *data __maybe_unused)
136{
137 device_for_each_child(dev, NULL, hsi_remove_client);
138 device_unregister(dev);
139
140 return 0;
141}
142
5a218ceb 143static void hsi_controller_release(struct device *dev)
a056ab8c 144{
5a218ceb
CC
145 struct hsi_controller *hsi = to_hsi_controller(dev);
146
147 kfree(hsi->port);
148 kfree(hsi);
a056ab8c
CC
149}
150
5a218ceb 151static void hsi_port_release(struct device *dev)
a056ab8c 152{
5a218ceb 153 kfree(to_hsi_port(dev));
a056ab8c
CC
154}
155
156/**
157 * hsi_unregister_controller - Unregister an HSI controller
158 * @hsi: The HSI controller to register
159 */
160void hsi_unregister_controller(struct hsi_controller *hsi)
161{
162 device_for_each_child(&hsi->device, NULL, hsi_remove_port);
163 device_unregister(&hsi->device);
164}
165EXPORT_SYMBOL_GPL(hsi_unregister_controller);
166
167/**
168 * hsi_register_controller - Register an HSI controller and its ports
169 * @hsi: The HSI controller to register
170 *
171 * Returns -errno on failure, 0 on success.
172 */
173int hsi_register_controller(struct hsi_controller *hsi)
174{
175 unsigned int i;
176 int err;
177
178 hsi->device.type = &hsi_ctrl;
179 hsi->device.bus = &hsi_bus_type;
5a218ceb 180 err = device_add(&hsi->device);
a056ab8c
CC
181 if (err < 0)
182 return err;
183 for (i = 0; i < hsi->num_ports; i++) {
5a218ceb
CC
184 hsi->port[i]->device.parent = &hsi->device;
185 hsi->port[i]->device.bus = &hsi_bus_type;
186 hsi->port[i]->device.type = &hsi_port;
187 err = device_add(&hsi->port[i]->device);
a056ab8c
CC
188 if (err < 0)
189 goto out;
190 }
191 /* Populate HSI bus with HSI clients */
192 hsi_scan_board_info(hsi);
193
194 return 0;
195out:
5a218ceb
CC
196 while (i-- > 0)
197 device_del(&hsi->port[i]->device);
198 device_del(&hsi->device);
a056ab8c
CC
199
200 return err;
201}
202EXPORT_SYMBOL_GPL(hsi_register_controller);
203
204/**
205 * hsi_register_client_driver - Register an HSI client to the HSI bus
206 * @drv: HSI client driver to register
207 *
208 * Returns -errno on failure, 0 on success.
209 */
210int hsi_register_client_driver(struct hsi_client_driver *drv)
211{
212 drv->driver.bus = &hsi_bus_type;
213
214 return driver_register(&drv->driver);
215}
216EXPORT_SYMBOL_GPL(hsi_register_client_driver);
217
218static inline int hsi_dummy_msg(struct hsi_msg *msg __maybe_unused)
219{
220 return 0;
221}
222
223static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused)
224{
225 return 0;
226}
227
5a218ceb
CC
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
a056ab8c
CC
251/**
252 * hsi_alloc_controller - Allocate an HSI controller and its ports
253 * @n_ports: Number of ports on the HSI controller
254 * @flags: Kernel allocation flags
255 *
256 * Return NULL on failure or a pointer to an hsi_controller on success.
257 */
258struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags)
259{
260 struct hsi_controller *hsi;
5a218ceb 261 struct hsi_port **port;
a056ab8c
CC
262 unsigned int i;
263
264 if (!n_ports)
265 return NULL;
266
a056ab8c
CC
267 hsi = kzalloc(sizeof(*hsi), flags);
268 if (!hsi)
5a218ceb
CC
269 return NULL;
270 port = kzalloc(sizeof(*port)*n_ports, flags);
271 if (!port) {
272 kfree(hsi);
273 return NULL;
a056ab8c
CC
274 }
275 hsi->num_ports = n_ports;
276 hsi->port = port;
5a218ceb
CC
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 }
a056ab8c
CC
298
299 return hsi;
300out:
5a218ceb 301 hsi_put_controller(hsi);
a056ab8c
CC
302
303 return NULL;
304}
305EXPORT_SYMBOL_GPL(hsi_alloc_controller);
306
a056ab8c
CC
307/**
308 * hsi_free_msg - Free an HSI message
309 * @msg: Pointer to the HSI message
310 *
311 * Client is responsible to free the buffers pointed by the scatterlists.
312 */
313void hsi_free_msg(struct hsi_msg *msg)
314{
315 if (!msg)
316 return;
317 sg_free_table(&msg->sgt);
318 kfree(msg);
319}
320EXPORT_SYMBOL_GPL(hsi_free_msg);
321
322/**
323 * hsi_alloc_msg - Allocate an HSI message
324 * @nents: Number of memory entries
325 * @flags: Kernel allocation flags
326 *
327 * nents can be 0. This mainly makes sense for read transfer.
328 * In that case, HSI drivers will call the complete callback when
329 * there is data to be read without consuming it.
330 *
331 * Return NULL on failure or a pointer to an hsi_msg on success.
332 */
333struct hsi_msg *hsi_alloc_msg(unsigned int nents, gfp_t flags)
334{
335 struct hsi_msg *msg;
336 int err;
337
338 msg = kzalloc(sizeof(*msg), flags);
339 if (!msg)
340 return NULL;
341
342 if (!nents)
343 return msg;
344
345 err = sg_alloc_table(&msg->sgt, nents, flags);
346 if (unlikely(err)) {
347 kfree(msg);
348 msg = NULL;
349 }
350
351 return msg;
352}
353EXPORT_SYMBOL_GPL(hsi_alloc_msg);
354
355/**
356 * hsi_async - Submit an HSI transfer to the controller
357 * @cl: HSI client sending the transfer
358 * @msg: The HSI transfer passed to controller
359 *
360 * The HSI message must have the channel, ttype, complete and destructor
361 * fields set beforehand. If nents > 0 then the client has to initialize
362 * also the scatterlists to point to the buffers to write to or read from.
363 *
364 * HSI controllers relay on pre-allocated buffers from their clients and they
365 * do not allocate buffers on their own.
366 *
367 * Once the HSI message transfer finishes, the HSI controller calls the
368 * complete callback with the status and actual_len fields of the HSI message
369 * updated. The complete callback can be called before returning from
370 * hsi_async.
371 *
372 * Returns -errno on failure or 0 on success
373 */
374int hsi_async(struct hsi_client *cl, struct hsi_msg *msg)
375{
376 struct hsi_port *port = hsi_get_port(cl);
377
378 if (!hsi_port_claimed(cl))
379 return -EACCES;
380
381 WARN_ON_ONCE(!msg->destructor || !msg->complete);
382 msg->cl = cl;
383
384 return port->async(msg);
385}
386EXPORT_SYMBOL_GPL(hsi_async);
387
388/**
389 * hsi_claim_port - Claim the HSI client's port
390 * @cl: HSI client that wants to claim its port
391 * @share: Flag to indicate if the client wants to share the port or not.
392 *
393 * Returns -errno on failure, 0 on success.
394 */
395int hsi_claim_port(struct hsi_client *cl, unsigned int share)
396{
397 struct hsi_port *port = hsi_get_port(cl);
398 int err = 0;
399
400 mutex_lock(&port->lock);
401 if ((port->claimed) && (!port->shared || !share)) {
402 err = -EBUSY;
403 goto out;
404 }
405 if (!try_module_get(to_hsi_controller(port->device.parent)->owner)) {
406 err = -ENODEV;
407 goto out;
408 }
409 port->claimed++;
410 port->shared = !!share;
411 cl->pclaimed = 1;
412out:
413 mutex_unlock(&port->lock);
414
415 return err;
416}
417EXPORT_SYMBOL_GPL(hsi_claim_port);
418
419/**
420 * hsi_release_port - Release the HSI client's port
421 * @cl: HSI client which previously claimed its port
422 */
423void hsi_release_port(struct hsi_client *cl)
424{
425 struct hsi_port *port = hsi_get_port(cl);
426
427 mutex_lock(&port->lock);
428 /* Allow HW driver to do some cleanup */
429 port->release(cl);
430 if (cl->pclaimed)
431 port->claimed--;
432 BUG_ON(port->claimed < 0);
433 cl->pclaimed = 0;
434 if (!port->claimed)
435 port->shared = 0;
436 module_put(to_hsi_controller(port->device.parent)->owner);
437 mutex_unlock(&port->lock);
438}
439EXPORT_SYMBOL_GPL(hsi_release_port);
440
441static int hsi_start_rx(struct hsi_client *cl, void *data __maybe_unused)
442{
443 if (cl->hsi_start_rx)
444 (*cl->hsi_start_rx)(cl);
445
446 return 0;
447}
448
449static int hsi_stop_rx(struct hsi_client *cl, void *data __maybe_unused)
450{
451 if (cl->hsi_stop_rx)
452 (*cl->hsi_stop_rx)(cl);
453
454 return 0;
455}
456
457static int hsi_port_for_each_client(struct hsi_port *port, void *data,
458 int (*fn)(struct hsi_client *cl, void *data))
459{
460 struct hsi_client *cl;
461
462 spin_lock(&port->clock);
463 list_for_each_entry(cl, &port->clients, link) {
464 spin_unlock(&port->clock);
465 (*fn)(cl, data);
466 spin_lock(&port->clock);
467 }
468 spin_unlock(&port->clock);
469
470 return 0;
471}
472
473/**
474 * hsi_event -Notifies clients about port events
475 * @port: Port where the event occurred
476 * @event: The event type
477 *
478 * Clients should not be concerned about wake line behavior. However, due
479 * to a race condition in HSI HW protocol, clients need to be notified
480 * about wake line changes, so they can implement a workaround for it.
481 *
482 * Events:
483 * HSI_EVENT_START_RX - Incoming wake line high
484 * HSI_EVENT_STOP_RX - Incoming wake line down
485 */
486void hsi_event(struct hsi_port *port, unsigned int event)
487{
488 int (*fn)(struct hsi_client *cl, void *data);
489
490 switch (event) {
491 case HSI_EVENT_START_RX:
492 fn = hsi_start_rx;
493 break;
494 case HSI_EVENT_STOP_RX:
495 fn = hsi_stop_rx;
496 break;
497 default:
498 return;
499 }
500 hsi_port_for_each_client(port, NULL, fn);
501}
502EXPORT_SYMBOL_GPL(hsi_event);
503
504static int __init hsi_init(void)
505{
506 return bus_register(&hsi_bus_type);
507}
508postcore_initcall(hsi_init);
509
510static void __exit hsi_exit(void)
511{
512 bus_unregister(&hsi_bus_type);
513}
514module_exit(hsi_exit);
515
516MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
517MODULE_DESCRIPTION("High-speed Synchronous Serial Interface (HSI) framework");
518MODULE_LICENSE("GPL v2");