aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/capi/kcapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn/capi/kcapi.c')
-rw-r--r--drivers/isdn/capi/kcapi.c112
1 files changed, 51 insertions, 61 deletions
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index 9362a7a66aa1..e08914d33be1 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -44,12 +44,10 @@ module_param(showcapimsgs, uint, 0);
44 44
45/* ------------------------------------------------------------- */ 45/* ------------------------------------------------------------- */
46 46
47struct capi_notifier { 47struct capictr_event {
48 struct work_struct work; 48 struct work_struct work;
49 unsigned int cmd; 49 unsigned int type;
50 u32 controller; 50 u32 controller;
51 u16 applid;
52 u32 ncci;
53}; 51};
54 52
55/* ------------------------------------------------------------- */ 53/* ------------------------------------------------------------- */
@@ -71,6 +69,8 @@ struct capi_ctr *capi_controller[CAPI_MAXCONTR];
71 69
72static int ncontrollers; 70static int ncontrollers;
73 71
72static BLOCKING_NOTIFIER_HEAD(ctr_notifier_list);
73
74/* -------- controller ref counting -------------------------------------- */ 74/* -------- controller ref counting -------------------------------------- */
75 75
76static inline struct capi_ctr * 76static inline struct capi_ctr *
@@ -165,8 +165,6 @@ static void release_appl(struct capi_ctr *ctr, u16 applid)
165 capi_ctr_put(ctr); 165 capi_ctr_put(ctr);
166} 166}
167 167
168/* -------- KCI_CONTRUP --------------------------------------- */
169
170static void notify_up(u32 contr) 168static void notify_up(u32 contr)
171{ 169{
172 struct capi20_appl *ap; 170 struct capi20_appl *ap;
@@ -188,16 +186,11 @@ static void notify_up(u32 contr)
188 if (!ap || ap->release_in_progress) 186 if (!ap || ap->release_in_progress)
189 continue; 187 continue;
190 register_appl(ctr, applid, &ap->rparam); 188 register_appl(ctr, applid, &ap->rparam);
191 if (ap->callback && !ap->release_in_progress)
192 ap->callback(KCI_CONTRUP, contr,
193 &ctr->profile);
194 } 189 }
195 } else 190 } else
196 printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); 191 printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
197} 192}
198 193
199/* -------- KCI_CONTRDOWN ------------------------------------- */
200
201static void ctr_down(struct capi_ctr *ctr) 194static void ctr_down(struct capi_ctr *ctr)
202{ 195{
203 struct capi20_appl *ap; 196 struct capi20_appl *ap;
@@ -215,11 +208,8 @@ static void ctr_down(struct capi_ctr *ctr)
215 208
216 for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { 209 for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
217 ap = get_capi_appl_by_nr(applid); 210 ap = get_capi_appl_by_nr(applid);
218 if (ap && !ap->release_in_progress) { 211 if (ap && !ap->release_in_progress)
219 if (ap->callback)
220 ap->callback(KCI_CONTRDOWN, ctr->cnr, NULL);
221 capi_ctr_put(ctr); 212 capi_ctr_put(ctr);
222 }
223 } 213 }
224} 214}
225 215
@@ -237,45 +227,63 @@ static void notify_down(u32 contr)
237 printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); 227 printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
238} 228}
239 229
240static void notify_handler(struct work_struct *work) 230static int
231notify_handler(struct notifier_block *nb, unsigned long val, void *v)
241{ 232{
242 struct capi_notifier *np = 233 u32 contr = (long)v;
243 container_of(work, struct capi_notifier, work);
244 234
245 switch (np->cmd) { 235 switch (val) {
246 case KCI_CONTRUP: 236 case CAPICTR_UP:
247 notify_up(np->controller); 237 notify_up(contr);
248 break; 238 break;
249 case KCI_CONTRDOWN: 239 case CAPICTR_DOWN:
250 notify_down(np->controller); 240 notify_down(contr);
251 break; 241 break;
252 } 242 }
243 return NOTIFY_OK;
244}
245
246static void do_notify_work(struct work_struct *work)
247{
248 struct capictr_event *event =
249 container_of(work, struct capictr_event, work);
253 250
254 kfree(np); 251 blocking_notifier_call_chain(&ctr_notifier_list, event->type,
252 (void *)(long)event->controller);
253 kfree(event);
255} 254}
256 255
257/* 256/*
258 * The notifier will result in adding/deleteing of devices. Devices can 257 * The notifier will result in adding/deleteing of devices. Devices can
259 * only removed in user process, not in bh. 258 * only removed in user process, not in bh.
260 */ 259 */
261static int notify_push(unsigned int cmd, u32 controller, u16 applid, u32 ncci) 260static int notify_push(unsigned int event_type, u32 controller)
262{ 261{
263 struct capi_notifier *np = kmalloc(sizeof(*np), GFP_ATOMIC); 262 struct capictr_event *event = kmalloc(sizeof(*event), GFP_ATOMIC);
264 263
265 if (!np) 264 if (!event)
266 return -ENOMEM; 265 return -ENOMEM;
267 266
268 INIT_WORK(&np->work, notify_handler); 267 INIT_WORK(&event->work, do_notify_work);
269 np->cmd = cmd; 268 event->type = event_type;
270 np->controller = controller; 269 event->controller = controller;
271 np->applid = applid;
272 np->ncci = ncci;
273 270
274 schedule_work(&np->work); 271 schedule_work(&event->work);
275 return 0; 272 return 0;
276} 273}
277 274
278 275int register_capictr_notifier(struct notifier_block *nb)
276{
277 return blocking_notifier_chain_register(&ctr_notifier_list, nb);
278}
279EXPORT_SYMBOL_GPL(register_capictr_notifier);
280
281int unregister_capictr_notifier(struct notifier_block *nb)
282{
283 return blocking_notifier_chain_unregister(&ctr_notifier_list, nb);
284}
285EXPORT_SYMBOL_GPL(unregister_capictr_notifier);
286
279/* -------- Receiver ------------------------------------------ */ 287/* -------- Receiver ------------------------------------------ */
280 288
281static void recv_handler(struct work_struct *work) 289static void recv_handler(struct work_struct *work)
@@ -401,7 +409,7 @@ void capi_ctr_ready(struct capi_ctr *ctr)
401 printk(KERN_NOTICE "kcapi: controller [%03d] \"%s\" ready.\n", 409 printk(KERN_NOTICE "kcapi: controller [%03d] \"%s\" ready.\n",
402 ctr->cnr, ctr->name); 410 ctr->cnr, ctr->name);
403 411
404 notify_push(KCI_CONTRUP, ctr->cnr, 0, 0); 412 notify_push(CAPICTR_UP, ctr->cnr);
405} 413}
406 414
407EXPORT_SYMBOL(capi_ctr_ready); 415EXPORT_SYMBOL(capi_ctr_ready);
@@ -418,7 +426,7 @@ void capi_ctr_down(struct capi_ctr *ctr)
418{ 426{
419 printk(KERN_NOTICE "kcapi: controller [%03d] down.\n", ctr->cnr); 427 printk(KERN_NOTICE "kcapi: controller [%03d] down.\n", ctr->cnr);
420 428
421 notify_push(KCI_CONTRDOWN, ctr->cnr, 0, 0); 429 notify_push(CAPICTR_DOWN, ctr->cnr);
422} 430}
423 431
424EXPORT_SYMBOL(capi_ctr_down); 432EXPORT_SYMBOL(capi_ctr_down);
@@ -633,7 +641,6 @@ u16 capi20_register(struct capi20_appl *ap)
633 ap->nrecvdatapkt = 0; 641 ap->nrecvdatapkt = 0;
634 ap->nsentctlpkt = 0; 642 ap->nsentctlpkt = 0;
635 ap->nsentdatapkt = 0; 643 ap->nsentdatapkt = 0;
636 ap->callback = NULL;
637 mutex_init(&ap->recv_mtx); 644 mutex_init(&ap->recv_mtx);
638 skb_queue_head_init(&ap->recv_queue); 645 skb_queue_head_init(&ap->recv_queue);
639 INIT_WORK(&ap->recv_work, recv_handler); 646 INIT_WORK(&ap->recv_work, recv_handler);
@@ -1137,30 +1144,6 @@ int capi20_manufacturer(unsigned int cmd, void __user *data)
1137 1144
1138EXPORT_SYMBOL(capi20_manufacturer); 1145EXPORT_SYMBOL(capi20_manufacturer);
1139 1146
1140/* temporary hack */
1141
1142/**
1143 * capi20_set_callback() - set CAPI application notification callback function
1144 * @ap: CAPI application descriptor structure.
1145 * @callback: callback function (NULL to remove).
1146 *
1147 * If not NULL, the callback function will be called to notify the
1148 * application of the addition or removal of a controller.
1149 * The first argument (cmd) will tell whether the controller was added
1150 * (KCI_CONTRUP) or removed (KCI_CONTRDOWN).
1151 * The second argument (contr) will be the controller number.
1152 * For cmd==KCI_CONTRUP the third argument (data) will be a pointer to the
1153 * new controller's capability profile structure.
1154 */
1155
1156void capi20_set_callback(struct capi20_appl *ap,
1157 void (*callback) (unsigned int cmd, __u32 contr, void *data))
1158{
1159 ap->callback = callback;
1160}
1161
1162EXPORT_SYMBOL(capi20_set_callback);
1163
1164/* ------------------------------------------------------------- */ 1147/* ------------------------------------------------------------- */
1165/* -------- Init & Cleanup ------------------------------------- */ 1148/* -------- Init & Cleanup ------------------------------------- */
1166/* ------------------------------------------------------------- */ 1149/* ------------------------------------------------------------- */
@@ -1169,10 +1152,17 @@ EXPORT_SYMBOL(capi20_set_callback);
1169 * init / exit functions 1152 * init / exit functions
1170 */ 1153 */
1171 1154
1155static struct notifier_block capictr_nb = {
1156 .notifier_call = notify_handler,
1157 .priority = INT_MAX,
1158};
1159
1172static int __init kcapi_init(void) 1160static int __init kcapi_init(void)
1173{ 1161{
1174 int err; 1162 int err;
1175 1163
1164 register_capictr_notifier(&capictr_nb);
1165
1176 err = cdebug_init(); 1166 err = cdebug_init();
1177 if (!err) 1167 if (!err)
1178 kcapi_proc_init(); 1168 kcapi_proc_init();