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_Bchannel(struct bchannel
*bch
)
171 struct mISDNhead
*hh
;
173 hh
= mISDN_HEAD_P(bch
->rx_skb
);
174 hh
->prim
= PH_DATA_IND
;
175 hh
->id
= MISDN_ID_ANY
;
176 if (bch
->rcount
>= 64) {
177 printk(KERN_WARNING
"B-channel %p receive queue overflow, "
179 skb_queue_purge(&bch
->rqueue
);
184 skb_queue_tail(&bch
->rqueue
, bch
->rx_skb
);
186 schedule_event(bch
, FLG_RECVQUEUE
);
188 EXPORT_SYMBOL(recv_Bchannel
);
191 recv_Dchannel_skb(struct dchannel
*dch
, struct sk_buff
*skb
)
193 skb_queue_tail(&dch
->rqueue
, skb
);
194 schedule_event(dch
, FLG_RECVQUEUE
);
196 EXPORT_SYMBOL(recv_Dchannel_skb
);
199 recv_Bchannel_skb(struct bchannel
*bch
, struct sk_buff
*skb
)
201 if (bch
->rcount
>= 64) {
202 printk(KERN_WARNING
"B-channel %p receive queue overflow, "
204 skb_queue_purge(&bch
->rqueue
);
208 skb_queue_tail(&bch
->rqueue
, skb
);
209 schedule_event(bch
, FLG_RECVQUEUE
);
211 EXPORT_SYMBOL(recv_Bchannel_skb
);
214 confirm_Dsend(struct dchannel
*dch
)
218 skb
= _alloc_mISDN_skb(PH_DATA_CNF
, mISDN_HEAD_ID(dch
->tx_skb
),
219 0, NULL
, GFP_ATOMIC
);
221 printk(KERN_ERR
"%s: no skb id %x\n", __func__
,
222 mISDN_HEAD_ID(dch
->tx_skb
));
225 skb_queue_tail(&dch
->rqueue
, skb
);
226 schedule_event(dch
, FLG_RECVQUEUE
);
230 get_next_dframe(struct dchannel
*dch
)
233 dch
->tx_skb
= skb_dequeue(&dch
->squeue
);
239 test_and_clear_bit(FLG_TX_BUSY
, &dch
->Flags
);
242 EXPORT_SYMBOL(get_next_dframe
);
245 confirm_Bsend(struct bchannel
*bch
)
249 if (bch
->rcount
>= 64) {
250 printk(KERN_WARNING
"B-channel %p receive queue overflow, "
252 skb_queue_purge(&bch
->rqueue
);
255 skb
= _alloc_mISDN_skb(PH_DATA_CNF
, mISDN_HEAD_ID(bch
->tx_skb
),
256 0, NULL
, GFP_ATOMIC
);
258 printk(KERN_ERR
"%s: no skb id %x\n", __func__
,
259 mISDN_HEAD_ID(bch
->tx_skb
));
263 skb_queue_tail(&bch
->rqueue
, skb
);
264 schedule_event(bch
, FLG_RECVQUEUE
);
266 EXPORT_SYMBOL(confirm_Bsend
);
269 get_next_bframe(struct bchannel
*bch
)
272 if (test_bit(FLG_TX_NEXT
, &bch
->Flags
)) {
273 bch
->tx_skb
= bch
->next_skb
;
275 bch
->next_skb
= NULL
;
276 test_and_clear_bit(FLG_TX_NEXT
, &bch
->Flags
);
277 if (!test_bit(FLG_TRANSPARENT
, &bch
->Flags
))
278 confirm_Bsend(bch
); /* not for transparent */
281 test_and_clear_bit(FLG_TX_NEXT
, &bch
->Flags
);
282 printk(KERN_WARNING
"B TX_NEXT without skb\n");
286 test_and_clear_bit(FLG_TX_BUSY
, &bch
->Flags
);
289 EXPORT_SYMBOL(get_next_bframe
);
292 queue_ch_frame(struct mISDNchannel
*ch
, u_int pr
, int id
, struct sk_buff
*skb
)
294 struct mISDNhead
*hh
;
297 _queue_data(ch
, pr
, id
, 0, NULL
, GFP_ATOMIC
);
300 hh
= mISDN_HEAD_P(skb
);
303 if (!ch
->recv(ch
->peer
, skb
))
309 EXPORT_SYMBOL(queue_ch_frame
);
312 dchannel_senddata(struct dchannel
*ch
, struct sk_buff
*skb
)
316 printk(KERN_WARNING
"%s: skb too small\n", __func__
);
319 if (skb
->len
> ch
->maxlen
) {
320 printk(KERN_WARNING
"%s: skb too large(%d/%d)\n",
321 __func__
, skb
->len
, ch
->maxlen
);
324 /* HW lock must be obtained */
325 if (test_and_set_bit(FLG_TX_BUSY
, &ch
->Flags
)) {
326 skb_queue_tail(&ch
->squeue
, skb
);
335 EXPORT_SYMBOL(dchannel_senddata
);
338 bchannel_senddata(struct bchannel
*ch
, struct sk_buff
*skb
)
343 printk(KERN_WARNING
"%s: skb too small\n", __func__
);
346 if (skb
->len
> ch
->maxlen
) {
347 printk(KERN_WARNING
"%s: skb too large(%d/%d)\n",
348 __func__
, skb
->len
, ch
->maxlen
);
351 /* HW lock must be obtained */
352 /* check for pending next_skb */
355 "%s: next_skb exist ERROR (skb->len=%d next_skb->len=%d)\n",
356 __func__
, skb
->len
, ch
->next_skb
->len
);
359 if (test_and_set_bit(FLG_TX_BUSY
, &ch
->Flags
)) {
360 test_and_set_bit(FLG_TX_NEXT
, &ch
->Flags
);
370 EXPORT_SYMBOL(bchannel_senddata
);