1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/slab.h>
4 #include <linux/kernel.h>
5 #include <linux/module.h>
6 #include <linux/isdn/capilli.h>
8 #define DBG(format, arg...) do { \
9 printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \
12 struct capilib_msgidqueue
{
13 struct capilib_msgidqueue
*next
;
18 struct list_head list
;
23 struct capilib_msgidqueue
*msgidqueue
;
24 struct capilib_msgidqueue
*msgidlast
;
25 struct capilib_msgidqueue
*msgidfree
;
26 struct capilib_msgidqueue msgidpool
[CAPI_MAXDATAWINDOW
];
29 // ---------------------------------------------------------------------------
32 static inline void mq_init(struct capilib_ncci
*np
)
35 np
->msgidqueue
= NULL
;
38 memset(np
->msgidpool
, 0, sizeof(np
->msgidpool
));
39 np
->msgidfree
= &np
->msgidpool
[0];
40 for (i
= 1; i
< np
->winsize
; i
++) {
41 np
->msgidpool
[i
].next
= np
->msgidfree
;
42 np
->msgidfree
= &np
->msgidpool
[i
];
46 static inline int mq_enqueue(struct capilib_ncci
*np
, u16 msgid
)
48 struct capilib_msgidqueue
*mq
;
49 if ((mq
= np
->msgidfree
) == NULL
)
51 np
->msgidfree
= mq
->next
;
55 np
->msgidlast
->next
= mq
;
63 static inline int mq_dequeue(struct capilib_ncci
*np
, u16 msgid
)
65 struct capilib_msgidqueue
**pp
;
66 for (pp
= &np
->msgidqueue
; *pp
; pp
= &(*pp
)->next
) {
67 if ((*pp
)->msgid
== msgid
) {
68 struct capilib_msgidqueue
*mq
= *pp
;
70 if (mq
== np
->msgidlast
)
72 mq
->next
= np
->msgidfree
;
81 void capilib_new_ncci(struct list_head
*head
, u16 applid
, u32 ncci
, u32 winsize
)
83 struct capilib_ncci
*np
;
85 np
= kmalloc(sizeof(*np
), GFP_ATOMIC
);
87 printk(KERN_WARNING
"capilib_new_ncci: no memory.\n");
90 if (winsize
> CAPI_MAXDATAWINDOW
) {
91 printk(KERN_ERR
"capi_new_ncci: winsize %d too big\n",
93 winsize
= CAPI_MAXDATAWINDOW
;
97 np
->winsize
= winsize
;
99 list_add_tail(&np
->list
, head
);
100 DBG("kcapi: appl %d ncci 0x%x up", applid
, ncci
);
103 EXPORT_SYMBOL(capilib_new_ncci
);
105 void capilib_free_ncci(struct list_head
*head
, u16 applid
, u32 ncci
)
108 struct capilib_ncci
*np
;
110 list_for_each(l
, head
) {
111 np
= list_entry(l
, struct capilib_ncci
, list
);
112 if (np
->applid
!= applid
)
114 if (np
->ncci
!= ncci
)
116 printk(KERN_INFO
"kcapi: appl %d ncci 0x%x down\n", applid
, ncci
);
121 printk(KERN_ERR
"capilib_free_ncci: ncci 0x%x not found\n", ncci
);
124 EXPORT_SYMBOL(capilib_free_ncci
);
126 void capilib_release_appl(struct list_head
*head
, u16 applid
)
128 struct list_head
*l
, *n
;
129 struct capilib_ncci
*np
;
131 list_for_each_safe(l
, n
, head
) {
132 np
= list_entry(l
, struct capilib_ncci
, list
);
133 if (np
->applid
!= applid
)
135 printk(KERN_INFO
"kcapi: appl %d ncci 0x%x forced down\n", applid
, np
->ncci
);
141 EXPORT_SYMBOL(capilib_release_appl
);
143 void capilib_release(struct list_head
*head
)
145 struct list_head
*l
, *n
;
146 struct capilib_ncci
*np
;
148 list_for_each_safe(l
, n
, head
) {
149 np
= list_entry(l
, struct capilib_ncci
, list
);
150 printk(KERN_INFO
"kcapi: appl %d ncci 0x%x forced down\n", np
->applid
, np
->ncci
);
156 EXPORT_SYMBOL(capilib_release
);
158 u16
capilib_data_b3_req(struct list_head
*head
, u16 applid
, u32 ncci
, u16 msgid
)
161 struct capilib_ncci
*np
;
163 list_for_each(l
, head
) {
164 np
= list_entry(l
, struct capilib_ncci
, list
);
165 if (np
->applid
!= applid
)
167 if (np
->ncci
!= ncci
)
170 if (mq_enqueue(np
, msgid
) == 0)
171 return CAPI_SENDQUEUEFULL
;
175 printk(KERN_ERR
"capilib_data_b3_req: ncci 0x%x not found\n", ncci
);
179 EXPORT_SYMBOL(capilib_data_b3_req
);
181 void capilib_data_b3_conf(struct list_head
*head
, u16 applid
, u32 ncci
, u16 msgid
)
184 struct capilib_ncci
*np
;
186 list_for_each(l
, head
) {
187 np
= list_entry(l
, struct capilib_ncci
, list
);
188 if (np
->applid
!= applid
)
190 if (np
->ncci
!= ncci
)
193 if (mq_dequeue(np
, msgid
) == 0) {
194 printk(KERN_ERR
"kcapi: msgid %hu ncci 0x%x not on queue\n",
199 printk(KERN_ERR
"capilib_data_b3_conf: ncci 0x%x not found\n", ncci
);
202 EXPORT_SYMBOL(capilib_data_b3_conf
);