blob: 4754f440ed5bd655690c2f87b58e13b56738c06c [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
27static int check_id(int id)
28{
29 return (id < OCMEM_CLIENT_MAX && id >= OCMEM_GRAPHICS);
30}
31
32int check_notifier(int id)
33{
34 int ret = 0;
35
36 if (!check_id(id))
37 return 0;
38
39 mutex_lock(&nc_lock);
40 ret = notifiers[id].listeners;
41 mutex_unlock(&nc_lock);
42 return ret;
43}
44
45int ocmem_notifier_init(void)
46{
47 int id;
48 /* Maximum notifiers for each subsystem */
49 notifier_threshold = 1;
50 mutex_lock(&nc_lock);
51 for (id = 0; id < OCMEM_CLIENT_MAX; id++) {
52 notifiers[id].owner = id;
53 ATOMIC_INIT_NOTIFIER_HEAD(&notifiers[id].nc);
54 notifiers[id].listeners = 0;
55 }
56 mutex_unlock(&nc_lock);
57 return 0;
58}
59
60/* Broadcast a notification to listeners */
61int dispatch_notification(int id, enum ocmem_notif_type notif,
62 struct ocmem_buf *buf)
63{
64 int ret = 0;
65 struct ocmem_notifier *nc_hndl = NULL;
66 mutex_lock(&nc_lock);
67 nc_hndl = &notifiers[id];
68 if (nc_hndl->listeners == 0) {
69 /* Send an error so that the scheduler can clean up */
70 mutex_unlock(&nc_lock);
71 return -EINVAL;
72 }
73 ret = atomic_notifier_call_chain(&notifiers[id].nc, notif, buf);
74 mutex_unlock(&nc_lock);
75 return ret;
76}
77
Naveen Ramaraj6b882652012-06-28 16:07:09 -070078struct ocmem_notifier *ocmem_notifier_register(int client_id,
79 struct notifier_block *nb)
Naveen Ramarajbdf4dfe2012-04-23 14:09:50 -070080{
81
82 int ret = 0;
83 struct ocmem_notifier *nc_hndl = NULL;
84
85 if (!check_id(client_id)) {
86 pr_err("ocmem: Invalid Client id\n");
87 return NULL;
88 }
89
90 if (!nb) {
91 pr_err("ocmem: Invalid Notifier Block\n");
92 return NULL;
93 }
94
95 mutex_lock(&nc_lock);
96
97 nc_hndl = &notifiers[client_id];
98
99 if (nc_hndl->listeners >= notifier_threshold) {
100 pr_err("ocmem: Max notifiers already registered\n");
101 mutex_unlock(&nc_lock);
102 return NULL;
103 }
104
105 ret = atomic_notifier_chain_register(&nc_hndl->nc, nb);
106
107 if (ret < 0) {
108 mutex_unlock(&nc_lock);
109 return NULL;
110 }
111
112 nc_hndl->listeners++;
113 pr_info("ocmem: Notifier registered for %d\n", client_id);
114 mutex_unlock(&nc_lock);
115 return nc_hndl;
116}
117EXPORT_SYMBOL(ocmem_notifier_register);
118
Naveen Ramaraj6b882652012-06-28 16:07:09 -0700119int ocmem_notifier_unregister(struct ocmem_notifier *nc_hndl,
120 struct notifier_block *nb)
Naveen Ramarajbdf4dfe2012-04-23 14:09:50 -0700121{
122
123 int ret = 0;
124
Naveen Ramarajbdf4dfe2012-04-23 14:09:50 -0700125 if (!nc_hndl) {
126 pr_err("ocmem: Invalid notification handle\n");
127 return -EINVAL;
128 }
129
130 mutex_lock(&nc_lock);
131 ret = atomic_notifier_chain_unregister(&nc_hndl->nc, nb);
132 nc_hndl->listeners--;
133 mutex_unlock(&nc_lock);
134
135 return ret;
136}
137EXPORT_SYMBOL(ocmem_notifier_unregister);