kmem_cache_free(capidev_cachep, cdev);
}
-static struct capidev *capidev_find(u16 applid)
-{
- // FIXME this doesn't guarantee that the device won't go away shortly
- struct list_head *l;
- struct capidev *p = NULL;
-
- read_lock(&capidev_list_lock);
- list_for_each(l, &capidev_list) {
- p = list_entry(l, struct capidev, list);
- if (p->applid == applid)
- break;
- }
- read_unlock(&capidev_list_lock);
-
- if (l == &capidev_list)
- return NULL;
-
- return p;
-}
-
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
/* -------- handle data queue --------------------------------------- */
return;
}
+ BUG_ON(cdev->applid != applid);
+
+ if (CAPIMSG_COMMAND(skb->data) == CAPI_CONNECT_B3_CONF) {
+ u16 info = CAPIMSG_U16(skb->data, 12); // Info field
+ if (info == 0)
+ capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
+
+ }
+
if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) {
skb_queue_tail(&cdev->recvqueue, skb);
wake_up_interruptible(&cdev->recvwait);
}
CAPIMSG_SETAPPID(skb->data, cdev->applid);
+ if (CAPIMSG_COMMAND(skb->data) == CAPI_DISCONNECT_B3_RESP) {
+ capincci_free(cdev, CAPIMSG_NCCI(skb->data));
+
+ }
+
cdev->errcode = (*capifuncs->capi_put_message) (cdev->applid, skb);
if (cdev->errcode) {
return 0;
}
-static void lower_callback(unsigned int cmd, u32 contr, void *data)
-{
- struct capi_ncciinfo *np;
- struct capidev *cdev;
-
- switch (cmd) {
- case KCI_CONTRUP:
- printk(KERN_INFO "capi: controller %hu up\n", contr);
- break;
- case KCI_CONTRDOWN:
- printk(KERN_INFO "capi: controller %hu down\n", contr);
- break;
- case KCI_NCCIUP:
- np = (struct capi_ncciinfo *)data;
- if ((cdev = capidev_find(np->applid)) == 0)
- return;
- (void)capincci_alloc(cdev, np->ncci);
- break;
- case KCI_NCCIDOWN:
- np = (struct capi_ncciinfo *)data;
- if ((cdev = capidev_find(np->applid)) == 0)
- return;
- (void)capincci_free(cdev, np->ncci);
- break;
- }
-}
-
static struct capi_interface_user cuser = {
name: "capi20",
- callback: lower_callback,
};
static char rev[32];
spin_unlock(&users_lock);
}
-/* -------- KCI_NCCIUP ---------------------------------------- */
-
-static void notify_ncciup(u32 contr, u16 applid, u32 ncci)
-{
- struct list_head *l;
- struct capi_interface_user *p;
- struct capi_ncciinfo n;
-
- n.applid = applid;
- n.ncci = ncci;
- /*printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);*/
- spin_lock(&users_lock);
- list_for_each(l, &users) {
- p = list_entry(l, struct capi_interface_user, user_list);
- if (!p->callback) continue;
- (*p->callback) (KCI_NCCIUP, contr, &n);
- }
- spin_unlock(&users_lock);
-};
-
-/* -------- KCI_NCCIDOWN -------------------------------------- */
-
-static void notify_nccidown(u32 contr, u16 applid, u32 ncci)
-{
- struct list_head *l;
- struct capi_interface_user *p;
- struct capi_ncciinfo n;
-
- n.applid = applid;
- n.ncci = ncci;
- /*printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr);*/
- spin_lock(&users_lock);
- list_for_each(l, &users) {
- p = list_entry(l, struct capi_interface_user, user_list);
- if (!p->callback) continue;
- (*p->callback) (KCI_NCCIDOWN, contr, &n);
- }
- spin_unlock(&users_lock);
-};
-
/* ------------------------------------------------------------ */
static void inline notify_doit(struct capi_notifier *np)
case KCI_CONTRDOWN:
notify_down(np->controller);
break;
- case KCI_NCCIUP:
- notify_ncciup(np->controller, np->applid, np->ncci);
- break;
- case KCI_NCCIDOWN:
- notify_nccidown(np->controller, np->applid, np->ncci);
- break;
}
}
ap->nccilist = np;
ap->nncci++;
printk(KERN_INFO "kcapi: appl %d ncci 0x%x up\n", appl, ncci);
-
- notify_push(KCI_NCCIUP, card->cnr, appl, ncci);
}
static void controllercb_free_ncci(struct capi_ctr * card,
kfree(np);
ap->nncci--;
printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", appl, ncci);
- notify_push(KCI_NCCIDOWN, card->cnr, appl, ncci);
return;
}
}
struct capi_ncci *np = *pp;
*pp = np->next;
printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down!\n", appl, np->ncci);
- notify_push(KCI_NCCIDOWN, card->cnr, appl, np->ncci);
kfree(np);
nextpp = pp;
} else {