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, int maxlen) 85 { 86 ch->Flags = 0; 87 ch->maxlen = maxlen; 88 ch->hw = NULL; 89 ch->rx_skb = NULL; 90 ch->tx_skb = NULL; 91 ch->tx_idx = 0; 92 skb_queue_head_init(&ch->rqueue); 93 ch->rcount = 0; 94 ch->next_skb = NULL; 95 INIT_WORK(&ch->workq, bchannel_bh); 96 return 0; 97 } 98 EXPORT_SYMBOL(mISDN_initbchannel); 99 100 int 101 mISDN_freedchannel(struct dchannel *ch) 102 { 103 if (ch->tx_skb) { 104 dev_kfree_skb(ch->tx_skb); 105 ch->tx_skb = NULL; 106 } 107 if (ch->rx_skb) { 108 dev_kfree_skb(ch->rx_skb); 109 ch->rx_skb = NULL; 110 } 111 skb_queue_purge(&ch->squeue); 112 skb_queue_purge(&ch->rqueue); 113 flush_work_sync(&ch->workq); 114 return 0; 115 } 116 EXPORT_SYMBOL(mISDN_freedchannel); 117 118 void 119 mISDN_clear_bchannel(struct bchannel *ch) 120 { 121 if (ch->tx_skb) { 122 dev_kfree_skb(ch->tx_skb); 123 ch->tx_skb = NULL; 124 } 125 ch->tx_idx = 0; 126 if (ch->rx_skb) { 127 dev_kfree_skb(ch->rx_skb); 128 ch->rx_skb = NULL; 129 } 130 if (ch->next_skb) { 131 dev_kfree_skb(ch->next_skb); 132 ch->next_skb = NULL; 133 } 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); 137 } 138 EXPORT_SYMBOL(mISDN_clear_bchannel); 139 140 int 141 mISDN_freebchannel(struct bchannel *ch) 142 { 143 mISDN_clear_bchannel(ch); 144 skb_queue_purge(&ch->rqueue); 145 ch->rcount = 0; 146 flush_work_sync(&ch->workq); 147 return 0; 148 } 149 EXPORT_SYMBOL(mISDN_freebchannel); 150 151 static inline u_int 152 get_sapi_tei(u_char *p) 153 { 154 u_int sapi, tei; 155 156 sapi = *p >> 2; 157 tei = p[1] >> 1; 158 return sapi | (tei << 8); 159 } 160 161 void 162 recv_Dchannel(struct dchannel *dch) 163 { 164 struct mISDNhead *hh; 165 166 if (dch->rx_skb->len < 2) { /* at least 2 for sapi / tei */ 167 dev_kfree_skb(dch->rx_skb); 168 dch->rx_skb = NULL; 169 return; 170 } 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); 175 dch->rx_skb = NULL; 176 schedule_event(dch, FLG_RECVQUEUE); 177 } 178 EXPORT_SYMBOL(recv_Dchannel); 179 180 void 181 recv_Echannel(struct dchannel *ech, struct dchannel *dch) 182 { 183 struct mISDNhead *hh; 184 185 if (ech->rx_skb->len < 2) { /* at least 2 for sapi / tei */ 186 dev_kfree_skb(ech->rx_skb); 187 ech->rx_skb = NULL; 188 return; 189 } 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); 194 ech->rx_skb = NULL; 195 schedule_event(dch, FLG_RECVQUEUE); 196 } 197 EXPORT_SYMBOL(recv_Echannel); 198 199 void 200 recv_Bchannel(struct bchannel *bch, unsigned int id) 201 { 202 struct mISDNhead *hh; 203 204 /* if allocation did fail upper functions still may call us */ 205 if (unlikely(!bch->rx_skb)) 206 return; 207 if (unlikely(!bch->rx_skb->len)) { 208 /* we have no data to send - this may happen after recovery 209 * from overflow or too small allocation. 210 * We need to free the buffer here */ 211 dev_kfree_skb(bch->rx_skb); 212 bch->rx_skb = NULL; 213 } else { 214 hh = mISDN_HEAD_P(bch->rx_skb); 215 hh->prim = PH_DATA_IND; 216 hh->id = id; 217 if (bch->rcount >= 64) { 218 printk(KERN_WARNING 219 "B%d receive queue overflow - flushing!\n", 220 bch->nr); 221 skb_queue_purge(&bch->rqueue); 222 } 223 bch->rcount++; 224 skb_queue_tail(&bch->rqueue, bch->rx_skb); 225 bch->rx_skb = NULL; 226 schedule_event(bch, FLG_RECVQUEUE); 227 } 228 } 229 EXPORT_SYMBOL(recv_Bchannel); 230 231 void 232 recv_Dchannel_skb(struct dchannel *dch, struct sk_buff *skb) 233 { 234 skb_queue_tail(&dch->rqueue, skb); 235 schedule_event(dch, FLG_RECVQUEUE); 236 } 237 EXPORT_SYMBOL(recv_Dchannel_skb); 238 239 void 240 recv_Bchannel_skb(struct bchannel *bch, struct sk_buff *skb) 241 { 242 if (bch->rcount >= 64) { 243 printk(KERN_WARNING "B-channel %p receive queue overflow, " 244 "flushing!\n", bch); 245 skb_queue_purge(&bch->rqueue); 246 bch->rcount = 0; 247 } 248 bch->rcount++; 249 skb_queue_tail(&bch->rqueue, skb); 250 schedule_event(bch, FLG_RECVQUEUE); 251 } 252 EXPORT_SYMBOL(recv_Bchannel_skb); 253 254 static void 255 confirm_Dsend(struct dchannel *dch) 256 { 257 struct sk_buff *skb; 258 259 skb = _alloc_mISDN_skb(PH_DATA_CNF, mISDN_HEAD_ID(dch->tx_skb), 260 0, NULL, GFP_ATOMIC); 261 if (!skb) { 262 printk(KERN_ERR "%s: no skb id %x\n", __func__, 263 mISDN_HEAD_ID(dch->tx_skb)); 264 return; 265 } 266 skb_queue_tail(&dch->rqueue, skb); 267 schedule_event(dch, FLG_RECVQUEUE); 268 } 269 270 int 271 get_next_dframe(struct dchannel *dch) 272 { 273 dch->tx_idx = 0; 274 dch->tx_skb = skb_dequeue(&dch->squeue); 275 if (dch->tx_skb) { 276 confirm_Dsend(dch); 277 return 1; 278 } 279 dch->tx_skb = NULL; 280 test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); 281 return 0; 282 } 283 EXPORT_SYMBOL(get_next_dframe); 284 285 static void 286 confirm_Bsend(struct bchannel *bch) 287 { 288 struct sk_buff *skb; 289 290 if (bch->rcount >= 64) { 291 printk(KERN_WARNING "B-channel %p receive queue overflow, " 292 "flushing!\n", bch); 293 skb_queue_purge(&bch->rqueue); 294 bch->rcount = 0; 295 } 296 skb = _alloc_mISDN_skb(PH_DATA_CNF, mISDN_HEAD_ID(bch->tx_skb), 297 0, NULL, GFP_ATOMIC); 298 if (!skb) { 299 printk(KERN_ERR "%s: no skb id %x\n", __func__, 300 mISDN_HEAD_ID(bch->tx_skb)); 301 return; 302 } 303 bch->rcount++; 304 skb_queue_tail(&bch->rqueue, skb); 305 schedule_event(bch, FLG_RECVQUEUE); 306 } 307 308 int 309 get_next_bframe(struct bchannel *bch) 310 { 311 bch->tx_idx = 0; 312 if (test_bit(FLG_TX_NEXT, &bch->Flags)) { 313 bch->tx_skb = bch->next_skb; 314 if (bch->tx_skb) { 315 bch->next_skb = NULL; 316 test_and_clear_bit(FLG_TX_NEXT, &bch->Flags); 317 /* confirm imediately to allow next data */ 318 confirm_Bsend(bch); 319 return 1; 320 } else { 321 test_and_clear_bit(FLG_TX_NEXT, &bch->Flags); 322 printk(KERN_WARNING "B TX_NEXT without skb\n"); 323 } 324 } 325 bch->tx_skb = NULL; 326 test_and_clear_bit(FLG_TX_BUSY, &bch->Flags); 327 return 0; 328 } 329 EXPORT_SYMBOL(get_next_bframe); 330 331 void 332 queue_ch_frame(struct mISDNchannel *ch, u_int pr, int id, struct sk_buff *skb) 333 { 334 struct mISDNhead *hh; 335 336 if (!skb) { 337 _queue_data(ch, pr, id, 0, NULL, GFP_ATOMIC); 338 } else { 339 if (ch->peer) { 340 hh = mISDN_HEAD_P(skb); 341 hh->prim = pr; 342 hh->id = id; 343 if (!ch->recv(ch->peer, skb)) 344 return; 345 } 346 dev_kfree_skb(skb); 347 } 348 } 349 EXPORT_SYMBOL(queue_ch_frame); 350 351 int 352 dchannel_senddata(struct dchannel *ch, struct sk_buff *skb) 353 { 354 /* check oversize */ 355 if (skb->len <= 0) { 356 printk(KERN_WARNING "%s: skb too small\n", __func__); 357 return -EINVAL; 358 } 359 if (skb->len > ch->maxlen) { 360 printk(KERN_WARNING "%s: skb too large(%d/%d)\n", 361 __func__, skb->len, ch->maxlen); 362 return -EINVAL; 363 } 364 /* HW lock must be obtained */ 365 if (test_and_set_bit(FLG_TX_BUSY, &ch->Flags)) { 366 skb_queue_tail(&ch->squeue, skb); 367 return 0; 368 } else { 369 /* write to fifo */ 370 ch->tx_skb = skb; 371 ch->tx_idx = 0; 372 return 1; 373 } 374 } 375 EXPORT_SYMBOL(dchannel_senddata); 376 377 int 378 bchannel_senddata(struct bchannel *ch, struct sk_buff *skb) 379 { 380 381 /* check oversize */ 382 if (skb->len <= 0) { 383 printk(KERN_WARNING "%s: skb too small\n", __func__); 384 return -EINVAL; 385 } 386 if (skb->len > ch->maxlen) { 387 printk(KERN_WARNING "%s: skb too large(%d/%d)\n", 388 __func__, skb->len, ch->maxlen); 389 return -EINVAL; 390 } 391 /* HW lock must be obtained */ 392 /* check for pending next_skb */ 393 if (ch->next_skb) { 394 printk(KERN_WARNING 395 "%s: next_skb exist ERROR (skb->len=%d next_skb->len=%d)\n", 396 __func__, skb->len, ch->next_skb->len); 397 return -EBUSY; 398 } 399 if (test_and_set_bit(FLG_TX_BUSY, &ch->Flags)) { 400 test_and_set_bit(FLG_TX_NEXT, &ch->Flags); 401 ch->next_skb = skb; 402 return 0; 403 } else { 404 /* write to fifo */ 405 ch->tx_skb = skb; 406 ch->tx_idx = 0; 407 confirm_Bsend(ch); 408 return 1; 409 } 410 } 411 EXPORT_SYMBOL(bchannel_senddata); 412 413 /* The function allocates a new receive skb on demand with a size for the 414 * requirements of the current protocol. It returns the tailroom of the 415 * receive skb or an error. 416 */ 417 int 418 bchannel_get_rxbuf(struct bchannel *bch, int reqlen) 419 { 420 int len; 421 422 if (bch->rx_skb) { 423 len = skb_tailroom(bch->rx_skb); 424 if (len < reqlen) { 425 pr_warning("B%d no space for %d (only %d) bytes\n", 426 bch->nr, reqlen, len); 427 if (test_bit(FLG_TRANSPARENT, &bch->Flags)) { 428 /* send what we have now and try a new buffer */ 429 recv_Bchannel(bch, 0); 430 } else { 431 /* on HDLC we have to drop too big frames */ 432 return -EMSGSIZE; 433 } 434 } else { 435 return len; 436 } 437 } 438 if (unlikely(reqlen > bch->maxlen)) 439 return -EMSGSIZE; 440 if (test_bit(FLG_TRANSPARENT, &bch->Flags)) 441 len = reqlen; 442 else /* with HDLC we do not know the length yet */ 443 len = bch->maxlen; 444 bch->rx_skb = mI_alloc_skb(len, GFP_ATOMIC); 445 if (!bch->rx_skb) { 446 pr_warning("B%d receive no memory for %d bytes\n", 447 bch->nr, len); 448 len = -ENOMEM; 449 } 450 return len; 451 } 452 EXPORT_SYMBOL(bchannel_get_rxbuf); 453