3 * Author Karsten Keil <kkeil@novell.com>
5 * Copyright 2008 by Karsten Keil <kkeil@novell.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
18 #include <linux/gfp.h>
19 #include <linux/module.h>
20 #include <linux/mISDNhw.h>
23 dchannel_bh(struct work_struct
*ws
)
25 struct dchannel
*dch
= container_of(ws
, struct dchannel
, workq
);
29 if (test_and_clear_bit(FLG_RECVQUEUE
, &dch
->Flags
)) {
30 while ((skb
= skb_dequeue(&dch
->rqueue
))) {
31 if (likely(dch
->dev
.D
.peer
)) {
32 err
= dch
->dev
.D
.recv(dch
->dev
.D
.peer
, skb
);
39 if (test_and_clear_bit(FLG_PHCHANGE
, &dch
->Flags
)) {
46 bchannel_bh(struct work_struct
*ws
)
48 struct bchannel
*bch
= container_of(ws
, struct bchannel
, workq
);
52 if (test_and_clear_bit(FLG_RECVQUEUE
, &bch
->Flags
)) {
53 while ((skb
= skb_dequeue(&bch
->rqueue
))) {
55 if (likely(bch
->ch
.peer
)) {
56 err
= bch
->ch
.recv(bch
->ch
.peer
, skb
);
66 mISDN_initdchannel(struct dchannel
*ch
, int maxlen
, void *phf
)
68 test_and_set_bit(FLG_HDLC
, &ch
->Flags
);
75 skb_queue_head_init(&ch
->squeue
);
76 skb_queue_head_init(&ch
->rqueue
);
77 INIT_LIST_HEAD(&ch
->dev
.bchannels
);
78 INIT_WORK(&ch
->workq
, dchannel_bh
);
81 EXPORT_SYMBOL(mISDN_initdchannel
);
84 mISDN_initbchannel(struct bchannel
*ch
, int maxlen
)
92 skb_queue_head_init(&ch
->rqueue
);
95 INIT_WORK(&ch
->workq
, bchannel_bh
);
98 EXPORT_SYMBOL(mISDN_initbchannel
);
101 mISDN_freedchannel(struct dchannel
*ch
)
104 dev_kfree_skb(ch
->tx_skb
);
108 dev_kfree_skb(ch
->rx_skb
);
111 skb_queue_purge(&ch
->squeue
);
112 skb_queue_purge(&ch
->rqueue
);
113 flush_work_sync(&ch
->workq
);
116 EXPORT_SYMBOL(mISDN_freedchannel
);
119 mISDN_clear_bchannel(struct bchannel
*ch
)
122 dev_kfree_skb(ch
->tx_skb
);
127 dev_kfree_skb(ch
->rx_skb
);
131 dev_kfree_skb(ch
->next_skb
);
134 test_and_clear_bit(FLG_TX_BUSY
, &ch
->Flags
);
135 test_and_clear_bit(FLG_TX_NEXT
, &ch
->Flags
);
136 test_and_clear_bit(FLG_ACTIVE
, &ch
->Flags
);
138 EXPORT_SYMBOL(mISDN_clear_bchannel
);
141 mISDN_freebchannel(struct bchannel
*ch
)
143 mISDN_clear_bchannel(ch
);
144 skb_queue_purge(&ch
->rqueue
);
146 flush_work_sync(&ch
->workq
);
149 EXPORT_SYMBOL(mISDN_freebchannel
);
152 get_sapi_tei(u_char
*p
)
158 return sapi
| (tei
<< 8);
162 recv_Dchannel(struct dchannel
*dch
)
164 struct mISDNhead
*hh
;
166 if (dch
->rx_skb
->len
< 2) { /* at least 2 for sapi / tei */
167 dev_kfree_skb(dch
->rx_skb
);
171 hh
= mISDN_HEAD_P(dch
->rx_skb
);
172 hh
->prim
= PH_DATA_IND
;
173 hh
->id
= get_sapi_tei(dch
->rx_skb
->data
);
174 skb_queue_tail(&dch
->rqueue
, dch
->rx_skb
);
176 schedule_event(dch
, FLG_RECVQUEUE
);
178 EXPORT_SYMBOL(recv_Dchannel
);
181 recv_Echannel(struct dchannel
*ech
, struct dchannel
*dch
)
183 struct mISDNhead
*hh
;
185 if (ech
->rx_skb
->len
< 2) { /* at least 2 for sapi / tei */
186 dev_kfree_skb(ech
->rx_skb
);
190 hh
= mISDN_HEAD_P(ech
->rx_skb
);
191 hh
->prim
= PH_DATA_E_IND
;
192 hh
->id
= get_sapi_tei(ech
->rx_skb
->data
);
193 skb_queue_tail(&dch
->rqueue
, ech
->rx_skb
);
195 schedule_event(dch
, FLG_RECVQUEUE
);
197 EXPORT_SYMBOL(recv_Echannel
);
200 recv_Bchannel(struct bchannel
*bch
, unsigned int id
)
202 struct mISDNhead
*hh
;
204 hh
= mISDN_HEAD_P(bch
->rx_skb
);
205 hh
->prim
= PH_DATA_IND
;
207 if (bch
->rcount
>= 64) {
208 printk(KERN_WARNING
"B-channel %p receive queue overflow, "
210 skb_queue_purge(&bch
->rqueue
);
215 skb_queue_tail(&bch
->rqueue
, bch
->rx_skb
);
217 schedule_event(bch
, FLG_RECVQUEUE
);
219 EXPORT_SYMBOL(recv_Bchannel
);
222 recv_Dchannel_skb(struct dchannel
*dch
, struct sk_buff
*skb
)
224 skb_queue_tail(&dch
->rqueue
, skb
);
225 schedule_event(dch
, FLG_RECVQUEUE
);
227 EXPORT_SYMBOL(recv_Dchannel_skb
);
230 recv_Bchannel_skb(struct bchannel
*bch
, struct sk_buff
*skb
)
232 if (bch
->rcount
>= 64) {
233 printk(KERN_WARNING
"B-channel %p receive queue overflow, "
235 skb_queue_purge(&bch
->rqueue
);
239 skb_queue_tail(&bch
->rqueue
, skb
);
240 schedule_event(bch
, FLG_RECVQUEUE
);
242 EXPORT_SYMBOL(recv_Bchannel_skb
);
245 confirm_Dsend(struct dchannel
*dch
)
249 skb
= _alloc_mISDN_skb(PH_DATA_CNF
, mISDN_HEAD_ID(dch
->tx_skb
),
250 0, NULL
, GFP_ATOMIC
);
252 printk(KERN_ERR
"%s: no skb id %x\n", __func__
,
253 mISDN_HEAD_ID(dch
->tx_skb
));
256 skb_queue_tail(&dch
->rqueue
, skb
);
257 schedule_event(dch
, FLG_RECVQUEUE
);
261 get_next_dframe(struct dchannel
*dch
)
264 dch
->tx_skb
= skb_dequeue(&dch
->squeue
);
270 test_and_clear_bit(FLG_TX_BUSY
, &dch
->Flags
);
273 EXPORT_SYMBOL(get_next_dframe
);
276 confirm_Bsend(struct bchannel
*bch
)
280 if (bch
->rcount
>= 64) {
281 printk(KERN_WARNING
"B-channel %p receive queue overflow, "
283 skb_queue_purge(&bch
->rqueue
);
286 skb
= _alloc_mISDN_skb(PH_DATA_CNF
, mISDN_HEAD_ID(bch
->tx_skb
),
287 0, NULL
, GFP_ATOMIC
);
289 printk(KERN_ERR
"%s: no skb id %x\n", __func__
,
290 mISDN_HEAD_ID(bch
->tx_skb
));
294 skb_queue_tail(&bch
->rqueue
, skb
);
295 schedule_event(bch
, FLG_RECVQUEUE
);
297 EXPORT_SYMBOL(confirm_Bsend
);
300 get_next_bframe(struct bchannel
*bch
)
303 if (test_bit(FLG_TX_NEXT
, &bch
->Flags
)) {
304 bch
->tx_skb
= bch
->next_skb
;
306 bch
->next_skb
= NULL
;
307 test_and_clear_bit(FLG_TX_NEXT
, &bch
->Flags
);
308 if (!test_bit(FLG_TRANSPARENT
, &bch
->Flags
))
309 confirm_Bsend(bch
); /* not for transparent */
312 test_and_clear_bit(FLG_TX_NEXT
, &bch
->Flags
);
313 printk(KERN_WARNING
"B TX_NEXT without skb\n");
317 test_and_clear_bit(FLG_TX_BUSY
, &bch
->Flags
);
320 EXPORT_SYMBOL(get_next_bframe
);
323 queue_ch_frame(struct mISDNchannel
*ch
, u_int pr
, int id
, struct sk_buff
*skb
)
325 struct mISDNhead
*hh
;
328 _queue_data(ch
, pr
, id
, 0, NULL
, GFP_ATOMIC
);
331 hh
= mISDN_HEAD_P(skb
);
334 if (!ch
->recv(ch
->peer
, skb
))
340 EXPORT_SYMBOL(queue_ch_frame
);
343 dchannel_senddata(struct dchannel
*ch
, struct sk_buff
*skb
)
347 printk(KERN_WARNING
"%s: skb too small\n", __func__
);
350 if (skb
->len
> ch
->maxlen
) {
351 printk(KERN_WARNING
"%s: skb too large(%d/%d)\n",
352 __func__
, skb
->len
, ch
->maxlen
);
355 /* HW lock must be obtained */
356 if (test_and_set_bit(FLG_TX_BUSY
, &ch
->Flags
)) {
357 skb_queue_tail(&ch
->squeue
, skb
);
366 EXPORT_SYMBOL(dchannel_senddata
);
369 bchannel_senddata(struct bchannel
*ch
, struct sk_buff
*skb
)
374 printk(KERN_WARNING
"%s: skb too small\n", __func__
);
377 if (skb
->len
> ch
->maxlen
) {
378 printk(KERN_WARNING
"%s: skb too large(%d/%d)\n",
379 __func__
, skb
->len
, ch
->maxlen
);
382 /* HW lock must be obtained */
383 /* check for pending next_skb */
386 "%s: next_skb exist ERROR (skb->len=%d next_skb->len=%d)\n",
387 __func__
, skb
->len
, ch
->next_skb
->len
);
390 if (test_and_set_bit(FLG_TX_BUSY
, &ch
->Flags
)) {
391 test_and_set_bit(FLG_TX_NEXT
, &ch
->Flags
);
401 EXPORT_SYMBOL(bchannel_senddata
);