Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
•
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
isdn
mISDN
hwchannel.c
Go to the documentation of this file.
1
/*
2
*
3
* Author Karsten Keil <kkeil@novell.com>
4
*
5
* Copyright 2008 by Karsten Keil <kkeil@novell.com>
6
*
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.
10
*
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.
15
*
16
*/
17
18
#include <
linux/gfp.h
>
19
#include <linux/module.h>
20
#include <
linux/mISDNhw.h
>
21
22
static
void
23
dchannel_bh(
struct
work_struct
*
ws
)
24
{
25
struct
dchannel
*dch =
container_of
(ws,
struct
dchannel
,
workq
);
26
struct
sk_buff
*
skb
;
27
int
err
;
28
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);
33
if
(err)
34
dev_kfree_skb(skb);
35
}
else
36
dev_kfree_skb(skb);
37
}
38
}
39
if
(
test_and_clear_bit
(
FLG_PHCHANGE
, &dch->
Flags
)) {
40
if
(dch->
phfunc
)
41
dch->
phfunc
(dch);
42
}
43
}
44
45
static
void
46
bchannel_bh(
struct
work_struct
*ws)
47
{
48
struct
bchannel
*bch =
container_of
(ws,
struct
bchannel
,
workq
);
49
struct
sk_buff
*
skb
;
50
int
err
;
51
52
if
(
test_and_clear_bit
(
FLG_RECVQUEUE
, &bch->
Flags
)) {
53
while
((skb =
skb_dequeue
(&bch->
rqueue
))) {
54
bch->
rcount
--;
55
if
(
likely
(bch->
ch
.peer)) {
56
err = bch->
ch
.recv(bch->
ch
.peer, skb);
57
if
(err)
58
dev_kfree_skb(skb);
59
}
else
60
dev_kfree_skb(skb);
61
}
62
}
63
}
64
65
int
66
mISDN_initdchannel
(
struct
dchannel
*ch,
int
maxlen,
void
*phf)
67
{
68
test_and_set_bit
(
FLG_HDLC
, &ch->
Flags
);
69
ch->
maxlen
= maxlen;
70
ch->
hw
=
NULL
;
71
ch->
rx_skb
=
NULL
;
72
ch->
tx_skb
=
NULL
;
73
ch->
tx_idx
= 0;
74
ch->
phfunc
= phf;
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);
79
return
0;
80
}
81
EXPORT_SYMBOL
(
mISDN_initdchannel
);
82
83
int
84
mISDN_initbchannel
(
struct
bchannel
*ch,
unsigned
short
maxlen,
85
unsigned
short
minlen)
86
{
87
ch->
Flags
= 0;
88
ch->
minlen
= minlen;
89
ch->
next_minlen
= minlen;
90
ch->
init_minlen
= minlen;
91
ch->
maxlen
= maxlen;
92
ch->
next_maxlen
= maxlen;
93
ch->
init_maxlen
= maxlen;
94
ch->
hw
=
NULL
;
95
ch->
rx_skb
=
NULL
;
96
ch->
tx_skb
=
NULL
;
97
ch->
tx_idx
= 0;
98
skb_queue_head_init(&ch->
rqueue
);
99
ch->
rcount
= 0;
100
ch->
next_skb
=
NULL
;
101
INIT_WORK
(&ch->
workq
, bchannel_bh);
102
return
0;
103
}
104
EXPORT_SYMBOL
(
mISDN_initbchannel
);
105
106
int
107
mISDN_freedchannel
(
struct
dchannel
*ch)
108
{
109
if
(ch->
tx_skb
) {
110
dev_kfree_skb(ch->
tx_skb
);
111
ch->
tx_skb
=
NULL
;
112
}
113
if
(ch->
rx_skb
) {
114
dev_kfree_skb(ch->
rx_skb
);
115
ch->
rx_skb
=
NULL
;
116
}
117
skb_queue_purge
(&ch->
squeue
);
118
skb_queue_purge
(&ch->
rqueue
);
119
flush_work
(&ch->
workq
);
120
return
0;
121
}
122
EXPORT_SYMBOL
(
mISDN_freedchannel
);
123
124
void
125
mISDN_clear_bchannel
(
struct
bchannel
*ch)
126
{
127
if
(ch->
tx_skb
) {
128
dev_kfree_skb(ch->
tx_skb
);
129
ch->
tx_skb
=
NULL
;
130
}
131
ch->
tx_idx
= 0;
132
if
(ch->
rx_skb
) {
133
dev_kfree_skb(ch->
rx_skb
);
134
ch->
rx_skb
=
NULL
;
135
}
136
if
(ch->
next_skb
) {
137
dev_kfree_skb(ch->
next_skb
);
138
ch->
next_skb
=
NULL
;
139
}
140
test_and_clear_bit
(
FLG_TX_BUSY
, &ch->
Flags
);
141
test_and_clear_bit
(
FLG_TX_NEXT
, &ch->
Flags
);
142
test_and_clear_bit
(
FLG_ACTIVE
, &ch->
Flags
);
143
test_and_clear_bit
(
FLG_FILLEMPTY
, &ch->
Flags
);
144
test_and_clear_bit
(
FLG_TX_EMPTY
, &ch->
Flags
);
145
test_and_clear_bit
(
FLG_RX_OFF
, &ch->
Flags
);
146
ch->
dropcnt
= 0;
147
ch->
minlen
= ch->
init_minlen
;
148
ch->
next_minlen
= ch->
init_minlen
;
149
ch->
maxlen
= ch->
init_maxlen
;
150
ch->
next_maxlen
= ch->
init_maxlen
;
151
skb_queue_purge
(&ch->
rqueue
);
152
ch->
rcount
= 0;
153
}
154
EXPORT_SYMBOL
(
mISDN_clear_bchannel
);
155
156
void
157
mISDN_freebchannel
(
struct
bchannel
*ch)
158
{
159
cancel_work_sync
(&ch->
workq
);
160
mISDN_clear_bchannel
(ch);
161
}
162
EXPORT_SYMBOL
(
mISDN_freebchannel
);
163
164
int
165
mISDN_ctrl_bchannel
(
struct
bchannel
*bch,
struct
mISDN_ctrl_req
*cq)
166
{
167
int
ret
= 0;
168
169
switch
(cq->
op
) {
170
case
MISDN_CTRL_GETOP
:
171
cq->
op
=
MISDN_CTRL_RX_BUFFER
|
MISDN_CTRL_FILL_EMPTY
|
172
MISDN_CTRL_RX_OFF
;
173
break
;
174
case
MISDN_CTRL_FILL_EMPTY
:
175
if
(cq->
p1
) {
176
memset
(bch->
fill
, cq->
p2
& 0xff,
MISDN_BCH_FILL_SIZE
);
177
test_and_set_bit
(
FLG_FILLEMPTY
, &bch->
Flags
);
178
}
else
{
179
test_and_clear_bit
(
FLG_FILLEMPTY
, &bch->
Flags
);
180
}
181
break
;
182
case
MISDN_CTRL_RX_OFF
:
183
/* read back dropped byte count */
184
cq->
p2
= bch->
dropcnt
;
185
if
(cq->
p1
)
186
test_and_set_bit
(
FLG_RX_OFF
, &bch->
Flags
);
187
else
188
test_and_clear_bit
(
FLG_RX_OFF
, &bch->
Flags
);
189
bch->
dropcnt
= 0;
190
break
;
191
case
MISDN_CTRL_RX_BUFFER
:
192
if
(cq->
p2
>
MISDN_CTRL_RX_SIZE_IGNORE
)
193
bch->
next_maxlen
= cq->
p2
;
194
if
(cq->
p1
>
MISDN_CTRL_RX_SIZE_IGNORE
)
195
bch->
next_minlen
= cq->
p1
;
196
/* we return the old values */
197
cq->
p1
= bch->
minlen
;
198
cq->
p2
= bch->
maxlen
;
199
break
;
200
default
:
201
pr_info
(
"mISDN unhandled control %x operation\n"
, cq->
op
);
202
ret = -
EINVAL
;
203
break
;
204
}
205
return
ret
;
206
}
207
EXPORT_SYMBOL
(
mISDN_ctrl_bchannel
);
208
209
static
inline
u_int
210
get_sapi_tei(
u_char
*
p
)
211
{
212
u_int
sapi, tei;
213
214
sapi = *p >> 2;
215
tei = p[1] >> 1;
216
return
sapi | (tei << 8);
217
}
218
219
void
220
recv_Dchannel
(
struct
dchannel
*dch)
221
{
222
struct
mISDNhead
*
hh
;
223
224
if
(dch->
rx_skb
->len < 2) {
/* at least 2 for sapi / tei */
225
dev_kfree_skb(dch->
rx_skb
);
226
dch->
rx_skb
=
NULL
;
227
return
;
228
}
229
hh = mISDN_HEAD_P(dch->
rx_skb
);
230
hh->
prim
=
PH_DATA_IND
;
231
hh->
id
= get_sapi_tei(dch->
rx_skb
->data);
232
skb_queue_tail
(&dch->
rqueue
, dch->
rx_skb
);
233
dch->
rx_skb
=
NULL
;
234
schedule_event
(dch,
FLG_RECVQUEUE
);
235
}
236
EXPORT_SYMBOL
(
recv_Dchannel
);
237
238
void
239
recv_Echannel
(
struct
dchannel
*ech,
struct
dchannel
*dch)
240
{
241
struct
mISDNhead
*
hh
;
242
243
if
(ech->
rx_skb
->len < 2) {
/* at least 2 for sapi / tei */
244
dev_kfree_skb(ech->
rx_skb
);
245
ech->
rx_skb
=
NULL
;
246
return
;
247
}
248
hh = mISDN_HEAD_P(ech->
rx_skb
);
249
hh->
prim
=
PH_DATA_E_IND
;
250
hh->
id
= get_sapi_tei(ech->
rx_skb
->data);
251
skb_queue_tail
(&dch->
rqueue
, ech->
rx_skb
);
252
ech->
rx_skb
=
NULL
;
253
schedule_event
(dch,
FLG_RECVQUEUE
);
254
}
255
EXPORT_SYMBOL
(
recv_Echannel
);
256
257
void
258
recv_Bchannel
(
struct
bchannel
*bch,
unsigned
int
id
,
bool
force
)
259
{
260
struct
mISDNhead
*
hh
;
261
262
/* if allocation did fail upper functions still may call us */
263
if
(
unlikely
(!bch->
rx_skb
))
264
return
;
265
if
(
unlikely
(!bch->
rx_skb
->len)) {
266
/* we have no data to send - this may happen after recovery
267
* from overflow or too small allocation.
268
* We need to free the buffer here */
269
dev_kfree_skb(bch->
rx_skb
);
270
bch->
rx_skb
=
NULL
;
271
}
else
{
272
if
(
test_bit
(
FLG_TRANSPARENT
, &bch->
Flags
) &&
273
(bch->
rx_skb
->len < bch->
minlen
) && !force)
274
return
;
275
hh = mISDN_HEAD_P(bch->
rx_skb
);
276
hh->
prim
=
PH_DATA_IND
;
277
hh->
id
=
id
;
278
if
(bch->
rcount
>= 64) {
279
printk
(
KERN_WARNING
280
"B%d receive queue overflow - flushing!\n"
,
281
bch->
nr
);
282
skb_queue_purge
(&bch->
rqueue
);
283
}
284
bch->
rcount
++;
285
skb_queue_tail
(&bch->
rqueue
, bch->
rx_skb
);
286
bch->
rx_skb
=
NULL
;
287
schedule_event
(bch,
FLG_RECVQUEUE
);
288
}
289
}
290
EXPORT_SYMBOL
(
recv_Bchannel
);
291
292
void
293
recv_Dchannel_skb
(
struct
dchannel
*dch,
struct
sk_buff
*skb)
294
{
295
skb_queue_tail
(&dch->
rqueue
, skb);
296
schedule_event
(dch,
FLG_RECVQUEUE
);
297
}
298
EXPORT_SYMBOL
(
recv_Dchannel_skb
);
299
300
void
301
recv_Bchannel_skb
(
struct
bchannel
*bch,
struct
sk_buff
*skb)
302
{
303
if
(bch->
rcount
>= 64) {
304
printk
(
KERN_WARNING
"B-channel %p receive queue overflow, "
305
"flushing!\n"
, bch);
306
skb_queue_purge
(&bch->
rqueue
);
307
bch->
rcount
= 0;
308
}
309
bch->
rcount
++;
310
skb_queue_tail
(&bch->
rqueue
, skb);
311
schedule_event
(bch,
FLG_RECVQUEUE
);
312
}
313
EXPORT_SYMBOL
(
recv_Bchannel_skb
);
314
315
static
void
316
confirm_Dsend(
struct
dchannel
*dch)
317
{
318
struct
sk_buff
*
skb
;
319
320
skb = _alloc_mISDN_skb(
PH_DATA_CNF
, mISDN_HEAD_ID(dch->
tx_skb
),
321
0,
NULL
,
GFP_ATOMIC
);
322
if
(!skb) {
323
printk
(
KERN_ERR
"%s: no skb id %x\n"
, __func__,
324
mISDN_HEAD_ID(dch->
tx_skb
));
325
return
;
326
}
327
skb_queue_tail
(&dch->
rqueue
, skb);
328
schedule_event
(dch,
FLG_RECVQUEUE
);
329
}
330
331
int
332
get_next_dframe
(
struct
dchannel
*dch)
333
{
334
dch->
tx_idx
= 0;
335
dch->
tx_skb
=
skb_dequeue
(&dch->
squeue
);
336
if
(dch->
tx_skb
) {
337
confirm_Dsend(dch);
338
return
1;
339
}
340
dch->
tx_skb
=
NULL
;
341
test_and_clear_bit
(
FLG_TX_BUSY
, &dch->
Flags
);
342
return
0;
343
}
344
EXPORT_SYMBOL
(
get_next_dframe
);
345
346
static
void
347
confirm_Bsend(
struct
bchannel
*bch)
348
{
349
struct
sk_buff
*
skb
;
350
351
if
(bch->
rcount
>= 64) {
352
printk
(
KERN_WARNING
"B-channel %p receive queue overflow, "
353
"flushing!\n"
, bch);
354
skb_queue_purge
(&bch->
rqueue
);
355
bch->
rcount
= 0;
356
}
357
skb = _alloc_mISDN_skb(
PH_DATA_CNF
, mISDN_HEAD_ID(bch->
tx_skb
),
358
0,
NULL
,
GFP_ATOMIC
);
359
if
(!skb) {
360
printk
(
KERN_ERR
"%s: no skb id %x\n"
, __func__,
361
mISDN_HEAD_ID(bch->
tx_skb
));
362
return
;
363
}
364
bch->
rcount
++;
365
skb_queue_tail
(&bch->
rqueue
, skb);
366
schedule_event
(bch,
FLG_RECVQUEUE
);
367
}
368
369
int
370
get_next_bframe
(
struct
bchannel
*bch)
371
{
372
bch->
tx_idx
= 0;
373
if
(
test_bit
(
FLG_TX_NEXT
, &bch->
Flags
)) {
374
bch->
tx_skb
= bch->
next_skb
;
375
if
(bch->
tx_skb
) {
376
bch->
next_skb
=
NULL
;
377
test_and_clear_bit
(
FLG_TX_NEXT
, &bch->
Flags
);
378
/* confirm imediately to allow next data */
379
confirm_Bsend(bch);
380
return
1;
381
}
else
{
382
test_and_clear_bit
(
FLG_TX_NEXT
, &bch->
Flags
);
383
printk
(
KERN_WARNING
"B TX_NEXT without skb\n"
);
384
}
385
}
386
bch->
tx_skb
=
NULL
;
387
test_and_clear_bit
(
FLG_TX_BUSY
, &bch->
Flags
);
388
return
0;
389
}
390
EXPORT_SYMBOL
(
get_next_bframe
);
391
392
void
393
queue_ch_frame
(
struct
mISDNchannel *ch,
u_int
pr
,
int
id
,
struct
sk_buff
*skb)
394
{
395
struct
mISDNhead
*
hh
;
396
397
if
(!skb) {
398
_queue_data(ch, pr,
id
, 0,
NULL
,
GFP_ATOMIC
);
399
}
else
{
400
if
(ch->peer) {
401
hh = mISDN_HEAD_P(skb);
402
hh->
prim
=
pr
;
403
hh->
id
=
id
;
404
if
(!ch->recv(ch->peer, skb))
405
return
;
406
}
407
dev_kfree_skb(skb);
408
}
409
}
410
EXPORT_SYMBOL
(
queue_ch_frame
);
411
412
int
413
dchannel_senddata
(
struct
dchannel
*ch,
struct
sk_buff
*skb)
414
{
415
/* check oversize */
416
if
(skb->
len
<= 0) {
417
printk
(
KERN_WARNING
"%s: skb too small\n"
, __func__);
418
return
-
EINVAL
;
419
}
420
if
(skb->
len
> ch->
maxlen
) {
421
printk
(
KERN_WARNING
"%s: skb too large(%d/%d)\n"
,
422
__func__, skb->
len
, ch->
maxlen
);
423
return
-
EINVAL
;
424
}
425
/* HW lock must be obtained */
426
if
(
test_and_set_bit
(
FLG_TX_BUSY
, &ch->
Flags
)) {
427
skb_queue_tail
(&ch->
squeue
, skb);
428
return
0;
429
}
else
{
430
/* write to fifo */
431
ch->
tx_skb
=
skb
;
432
ch->
tx_idx
= 0;
433
return
1;
434
}
435
}
436
EXPORT_SYMBOL
(
dchannel_senddata
);
437
438
int
439
bchannel_senddata
(
struct
bchannel
*ch,
struct
sk_buff
*skb)
440
{
441
442
/* check oversize */
443
if
(skb->
len
<= 0) {
444
printk
(
KERN_WARNING
"%s: skb too small\n"
, __func__);
445
return
-
EINVAL
;
446
}
447
if
(skb->
len
> ch->
maxlen
) {
448
printk
(
KERN_WARNING
"%s: skb too large(%d/%d)\n"
,
449
__func__, skb->
len
, ch->
maxlen
);
450
return
-
EINVAL
;
451
}
452
/* HW lock must be obtained */
453
/* check for pending next_skb */
454
if
(ch->
next_skb
) {
455
printk
(
KERN_WARNING
456
"%s: next_skb exist ERROR (skb->len=%d next_skb->len=%d)\n"
,
457
__func__, skb->
len
, ch->
next_skb
->len);
458
return
-
EBUSY
;
459
}
460
if
(
test_and_set_bit
(
FLG_TX_BUSY
, &ch->
Flags
)) {
461
test_and_set_bit
(
FLG_TX_NEXT
, &ch->
Flags
);
462
ch->
next_skb
=
skb
;
463
return
0;
464
}
else
{
465
/* write to fifo */
466
ch->
tx_skb
=
skb
;
467
ch->
tx_idx
= 0;
468
confirm_Bsend(ch);
469
return
1;
470
}
471
}
472
EXPORT_SYMBOL
(
bchannel_senddata
);
473
474
/* The function allocates a new receive skb on demand with a size for the
475
* requirements of the current protocol. It returns the tailroom of the
476
* receive skb or an error.
477
*/
478
int
479
bchannel_get_rxbuf
(
struct
bchannel
*bch,
int
reqlen)
480
{
481
int
len
;
482
483
if
(bch->
rx_skb
) {
484
len = skb_tailroom(bch->
rx_skb
);
485
if
(len < reqlen) {
486
pr_warning
(
"B%d no space for %d (only %d) bytes\n"
,
487
bch->
nr
, reqlen, len);
488
if
(
test_bit
(
FLG_TRANSPARENT
, &bch->
Flags
)) {
489
/* send what we have now and try a new buffer */
490
recv_Bchannel
(bch, 0,
true
);
491
}
else
{
492
/* on HDLC we have to drop too big frames */
493
return
-
EMSGSIZE
;
494
}
495
}
else
{
496
return
len;
497
}
498
}
499
/* update current min/max length first */
500
if
(
unlikely
(bch->
maxlen
!= bch->
next_maxlen
))
501
bch->
maxlen
= bch->
next_maxlen
;
502
if
(
unlikely
(bch->
minlen
!= bch->
next_minlen
))
503
bch->
minlen
= bch->
next_minlen
;
504
if
(
unlikely
(reqlen > bch->
maxlen
))
505
return
-
EMSGSIZE
;
506
if
(
test_bit
(
FLG_TRANSPARENT
, &bch->
Flags
)) {
507
if
(reqlen >= bch->
minlen
) {
508
len = reqlen;
509
}
else
{
510
len = 2 * bch->
minlen
;
511
if
(len > bch->
maxlen
)
512
len = bch->
maxlen
;
513
}
514
}
else
{
515
/* with HDLC we do not know the length yet */
516
len = bch->
maxlen
;
517
}
518
bch->
rx_skb
= mI_alloc_skb(len,
GFP_ATOMIC
);
519
if
(!bch->
rx_skb
) {
520
pr_warning
(
"B%d receive no memory for %d bytes\n"
,
521
bch->
nr
, len);
522
len = -
ENOMEM
;
523
}
524
return
len;
525
}
526
EXPORT_SYMBOL
(
bchannel_get_rxbuf
);
Generated on Thu Jan 10 2013 13:42:31 for Linux Kernel by
1.8.2