blob: 9fbcd7355b6b804d945a59d5f097186d0efe2b72 [file] [log] [blame]
Naveen Ramarajbdf4dfe2012-04-23 14:09:50 -07001/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <mach/ocmem_priv.h>
14#include <linux/hardirq.h>
15
16static unsigned notifier_threshold;
17
18/* Protect the notifier structure below */
19DEFINE_MUTEX(nc_lock);
20
21struct ocmem_notifier {
22 int owner;
23 struct atomic_notifier_head nc;
24 unsigned listeners;
25} notifiers[OCMEM_CLIENT_MAX];
26
Naveen Ramarajbdf4dfe2012-04-23 14:09:50 -070027int check_notifier(int id)
28{
29 int ret = 0;
30
31 if (!check_id(id))
32 return 0;
33
34 mutex_lock(&nc_lock);
35 ret = notifiers[id].listeners;
36 mutex_unlock(&nc_lock);
37 return ret;
38}
39
40int ocmem_notifier_init(void)
41{
42 int id;
43 /* Maximum notifiers for each subsystem */
44 notifier_threshold = 1;
45 mutex_lock(&nc_lock);
46 for (id = 0; id < OCMEM_CLIENT_MAX; id++) {
47 notifiers[id].owner = id;
48 ATOMIC_INIT_NOTIFIER_HEAD(&notifiers[id].nc);
49 notifiers[id].listeners = 0;
50 }
51 mutex_unlock(&nc_lock);
52 return 0;
53}
54
55/* Broadcast a notification to listeners */
56int dispatch_notification(int id, enum ocmem_notif_type notif,
57 struct ocmem_buf *buf)
58{
59 int ret = 0;
60 struct ocmem_notifier *nc_hndl = NULL;
61 mutex_lock(&nc_lock);
62 nc_hndl = &notifiers[id];
63 if (nc_hndl->listeners == 0) {
64 /* Send an error so that the scheduler can clean up */
65 mutex_unlock(&nc_lock);
66 return -EINVAL;
67 }
68 ret = atomic_notifier_call_chain(&notifiers[id].nc, notif, buf);
69 mutex_unlock(&nc_lock);
70 return ret;
71}
72
Naveen Ramaraj6b882652012-06-28 16:07:09 -070073struct ocmem_notifier *ocmem_notifier_register(int client_id,
74 struct notifier_block *nb)
Naveen Ramarajbdf4dfe2012-04-23 14:09:50 -070075{
76
77 int ret = 0;
78 struct ocmem_notifier *nc_hndl = NULL;
79
80 if (!check_id(client_id)) {
81 pr_err("ocmem: Invalid Client id\n");
82 return NULL;
83 }
84
85 if (!nb) {
86 pr_err("ocmem: Invalid Notifier Block\n");
87 return NULL;
88 }
89
90 mutex_lock(&nc_lock);
91
92 nc_hndl = &notifiers[client_id];
93
94 if (nc_hndl->listeners >= notifier_threshold) {
95 pr_err("ocmem: Max notifiers already registered\n");
96 mutex_unlock(&nc_lock);
97 return NULL;
98 }
99
100 ret = atomic_notifier_chain_register(&nc_hndl->nc, nb);
101
102 if (ret < 0) {
103 mutex_unlock(&nc_lock);
104 return NULL;
105 }
106
107 nc_hndl->listeners++;
108 pr_info("ocmem: Notifier registered for %d\n", client_id);
109 mutex_unlock(&nc_lock);
110 return nc_hndl;
111}
112EXPORT_SYMBOL(ocmem_notifier_register);
113
Naveen Ramaraj6b882652012-06-28 16:07:09 -0700114int ocmem_notifier_unregister(struct ocmem_notifier *nc_hndl,
115 struct notifier_block *nb)
Naveen Ramarajbdf4dfe2012-04-23 14:09:50 -0700116{
117
118 int ret = 0;
119
Naveen Ramarajbdf4dfe2012-04-23 14:09:50 -0700120 if (!nc_hndl) {
121 pr_err("ocmem: Invalid notification handle\n");
122 return -EINVAL;
123 }
124
125 mutex_lock(&nc_lock);
126 ret = atomic_notifier_chain_unregister(&nc_hndl->nc, nb);
127 nc_hndl->listeners--;
128 mutex_unlock(&nc_lock);
129
130 return ret;
131}
132EXPORT_SYMBOL(ocmem_notifier_unregister);