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/module.h>
19 #include <linux/mISDNhw.h>
22 dchannel_bh(struct work_struct
*ws
)
24 struct dchannel
*dch
= container_of(ws
, struct dchannel
, workq
);
28 if (test_and_clear_bit(FLG_RECVQUEUE
, &dch
->Flags
)) {
29 while ((skb
= skb_dequeue(&dch
->rqueue
))) {
30 if (likely(dch
->dev
.D
.peer
)) {
31 err
= dch
->dev
.D
.recv(dch
->dev
.D
.peer
, skb
);
38 if (test_and_clear_bit(FLG_PHCHANGE
, &dch
->Flags
)) {
45 bchannel_bh(struct work_struct
*ws
)
47 struct bchannel
*bch
= container_of(ws
, struct bchannel
, workq
);
51 if (test_and_clear_bit(FLG_RECVQUEUE
, &bch
->Flags
)) {
52 while ((skb
= skb_dequeue(&bch
->rqueue
))) {
54 if (likely(bch
->ch
.peer
)) {
55 err
= bch
->ch
.recv(bch
->ch
.peer
, skb
);
65 mISDN_initdchannel(struct dchannel
*ch
, int maxlen
, void *phf
)
67 test_and_set_bit(FLG_HDLC
, &ch
->Flags
);
74 skb_queue_head_init(&ch
->squeue
);
75 skb_queue_head_init(&ch
->rqueue
);
76 INIT_LIST_HEAD(&ch
->dev
.bchannels
);
77 INIT_WORK(&ch
->workq
, dchannel_bh
);
80 EXPORT_SYMBOL(mISDN_initdchannel
);
83 mISDN_initbchannel(struct bchannel
*ch
, int maxlen
)
91 skb_queue_head_init(&ch
->rqueue
);
94 INIT_WORK(&ch
->workq
, bchannel_bh
);
97 EXPORT_SYMBOL(mISDN_initbchannel
);
100 mISDN_freedchannel(struct dchannel
*ch
)
103 dev_kfree_skb(ch
->tx_skb
);
107 dev_kfree_skb(ch
->rx_skb
);
110 skb_queue_purge(&ch
->squeue
);
111 skb_queue_purge(&ch
->rqueue
);
112 flush_scheduled_work();
115 EXPORT_SYMBOL(mISDN_freedchannel
);
118 mISDN_freebchannel(struct bchannel
*ch
)
121 dev_kfree_skb(ch
->tx_skb
);
125 dev_kfree_skb(ch
->rx_skb
);
129 dev_kfree_skb(ch
->next_skb
);
132 skb_queue_purge(&ch
->rqueue
);
134 flush_scheduled_work();
137 EXPORT_SYMBOL(mISDN_freebchannel
);
140 get_sapi_tei(u_char
*p
)
146 return sapi
| (tei
<< 8);
150 recv_Dchannel(struct dchannel
*dch
)
152 struct mISDNhead
*hh
;
154 if (dch
->rx_skb
->len
< 2) { /* at least 2 for sapi / tei */
155 dev_kfree_skb(dch
->rx_skb
);
159 hh
= mISDN_HEAD_P(dch
->rx_skb
);
160 hh
->prim
= PH_DATA_IND
;
161 hh
->id
= get_sapi_tei(dch
->rx_skb
->data
);
162 skb_queue_tail(&dch
->rqueue
, dch
->rx_skb
);
164 schedule_event(dch
, FLG_RECVQUEUE
);
166 EXPORT_SYMBOL(recv_Dchannel
);
169 recv_Echannel(struct dchannel
*ech
, struct dchannel
*dch
)
171 struct mISDNhead
*hh
;
173 if (ech
->rx_skb
->len
< 2) { /* at least 2 for sapi / tei */
174 dev_kfree_skb(ech
->rx_skb
);
178 hh
= mISDN_HEAD_P(ech
->rx_skb
);
179 hh
->prim
= PH_DATA_E_IND
;
180 hh
->id
= get_sapi_tei(ech
->rx_skb
->data
);
181 skb_queue_tail(&dch
->rqueue
, ech
->rx_skb
);
183 schedule_event(dch
, FLG_RECVQUEUE
);
185 EXPORT_SYMBOL(recv_Echannel
);
188 recv_Bchannel(struct bchannel
*bch
, unsigned int id
)
190 struct mISDNhead
*hh
;
192 hh
= mISDN_HEAD_P(bch
->rx_skb
);
193 hh
->prim
= PH_DATA_IND
;
195 if (bch
->rcount
>= 64) {
196 printk(KERN_WARNING
"B-channel %p receive queue overflow, "
198 skb_queue_purge(&bch
->rqueue
);
203 skb_queue_tail(&bch
->rqueue
, bch
->rx_skb
);
205 schedule_event(bch
, FLG_RECVQUEUE
);
207 EXPORT_SYMBOL(recv_Bchannel
);
210 recv_Dchannel_skb(struct dchannel
*dch
, struct sk_buff
*skb
)
212 skb_queue_tail(&dch
->rqueue
, skb
);
213 schedule_event(dch
, FLG_RECVQUEUE
);
215 EXPORT_SYMBOL(recv_Dchannel_skb
);
218 recv_Bchannel_skb(struct bchannel
*bch
, struct sk_buff
*skb
)
220 if (bch
->rcount
>= 64) {
221 printk(KERN_WARNING
"B-channel %p receive queue overflow, "
223 skb_queue_purge(&bch
->rqueue
);
227 skb_queue_tail(&bch
->rqueue
, skb
);
228 schedule_event(bch
, FLG_RECVQUEUE
);
230 EXPORT_SYMBOL(recv_Bchannel_skb
);
233 confirm_Dsend(struct dchannel
*dch
)
237 skb
= _alloc_mISDN_skb(PH_DATA_CNF
, mISDN_HEAD_ID(dch
->tx_skb
),
238 0, NULL
, GFP_ATOMIC
);
240 printk(KERN_ERR
"%s: no skb id %x\n", __func__
,
241 mISDN_HEAD_ID(dch
->tx_skb
));
244 skb_queue_tail(&dch
->rqueue
, skb
);
245 schedule_event(dch
, FLG_RECVQUEUE
);
249 get_next_dframe(struct dchannel
*dch
)
252 dch
->tx_skb
= skb_dequeue(&dch
->squeue
);
258 test_and_clear_bit(FLG_TX_BUSY
, &dch
->Flags
);
261 EXPORT_SYMBOL(get_next_dframe
);
264 confirm_Bsend(struct bchannel
*bch
)
268 if (bch
->rcount
>= 64) {
269 printk(KERN_WARNING
"B-channel %p receive queue overflow, "
271 skb_queue_purge(&bch
->rqueue
);
274 skb
= _alloc_mISDN_skb(PH_DATA_CNF
, mISDN_HEAD_ID(bch
->tx_skb
),
275 0, NULL
, GFP_ATOMIC
);
277 printk(KERN_ERR
"%s: no skb id %x\n", __func__
,
278 mISDN_HEAD_ID(bch
->tx_skb
));
282 skb_queue_tail(&bch
->rqueue
, skb
);
283 schedule_event(bch
, FLG_RECVQUEUE
);
285 EXPORT_SYMBOL(confirm_Bsend
);
288 get_next_bframe(struct bchannel
*bch
)
291 if (test_bit(FLG_TX_NEXT
, &bch
->Flags
)) {
292 bch
->tx_skb
= bch
->next_skb
;
294 bch
->next_skb
= NULL
;
295 test_and_clear_bit(FLG_TX_NEXT
, &bch
->Flags
);
296 if (!test_bit(FLG_TRANSPARENT
, &bch
->Flags
))
297 confirm_Bsend(bch
); /* not for transparent */
300 test_and_clear_bit(FLG_TX_NEXT
, &bch
->Flags
);
301 printk(KERN_WARNING
"B TX_NEXT without skb\n");
305 test_and_clear_bit(FLG_TX_BUSY
, &bch
->Flags
);
308 EXPORT_SYMBOL(get_next_bframe
);
311 queue_ch_frame(struct mISDNchannel
*ch
, u_int pr
, int id
, struct sk_buff
*skb
)
313 struct mISDNhead
*hh
;
316 _queue_data(ch
, pr
, id
, 0, NULL
, GFP_ATOMIC
);
319 hh
= mISDN_HEAD_P(skb
);
322 if (!ch
->recv(ch
->peer
, skb
))
328 EXPORT_SYMBOL(queue_ch_frame
);
331 dchannel_senddata(struct dchannel
*ch
, struct sk_buff
*skb
)
335 printk(KERN_WARNING
"%s: skb too small\n", __func__
);
338 if (skb
->len
> ch
->maxlen
) {
339 printk(KERN_WARNING
"%s: skb too large(%d/%d)\n",
340 __func__
, skb
->len
, ch
->maxlen
);
343 /* HW lock must be obtained */
344 if (test_and_set_bit(FLG_TX_BUSY
, &ch
->Flags
)) {
345 skb_queue_tail(&ch
->squeue
, skb
);
354 EXPORT_SYMBOL(dchannel_senddata
);
357 bchannel_senddata(struct bchannel
*ch
, struct sk_buff
*skb
)
362 printk(KERN_WARNING
"%s: skb too small\n", __func__
);
365 if (skb
->len
> ch
->maxlen
) {
366 printk(KERN_WARNING
"%s: skb too large(%d/%d)\n",
367 __func__
, skb
->len
, ch
->maxlen
);
370 /* HW lock must be obtained */
371 /* check for pending next_skb */
374 "%s: next_skb exist ERROR (skb->len=%d next_skb->len=%d)\n",
375 __func__
, skb
->len
, ch
->next_skb
->len
);
378 if (test_and_set_bit(FLG_TX_BUSY
, &ch
->Flags
)) {
379 test_and_set_bit(FLG_TX_NEXT
, &ch
->Flags
);
389 EXPORT_SYMBOL(bchannel_senddata
);