Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mISDN: Allow to set a minimum length for transparent data

If the FIFO of the card is small, many short messages are queued up to
the upper layers and the userspace. This change allows the applications
to set a minimum datalen they want from the drivers.
Create a common control function to avoid code duplication in each
driver.

Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Karsten Keil and committed by
David S. Miller
034005a0 7206e659

+135 -132
+13 -22
drivers/isdn/hardware/mISDN/avmfritz.c
··· 536 536 hdlc_empty_fifo(bch, len); 537 537 if (!bch->rx_skb) 538 538 goto handle_tx; 539 - if (test_bit(FLG_TRANSPARENT, &bch->Flags) || 540 - (stat & HDLC_STAT_RME)) { 541 - if (((stat & HDLC_STAT_CRCVFRRAB) == 542 - HDLC_STAT_CRCVFR) || 543 - test_bit(FLG_TRANSPARENT, &bch->Flags)) { 544 - recv_Bchannel(bch, 0); 539 + if (test_bit(FLG_TRANSPARENT, &bch->Flags)) { 540 + recv_Bchannel(bch, 0, false); 541 + } else if (stat & HDLC_STAT_RME) { 542 + if ((stat & HDLC_STAT_CRCVFRRAB) == 543 + HDLC_STAT_CRCVFR) { 544 + recv_Bchannel(bch, 0, false); 545 545 } else { 546 546 pr_warning("%s: got invalid frame\n", 547 547 fc->name); ··· 809 809 static int 810 810 channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) 811 811 { 812 - int ret = 0; 813 - struct fritzcard *fc = bch->hw; 814 - 815 - switch (cq->op) { 816 - case MISDN_CTRL_GETOP: 817 - cq->op = 0; 818 - break; 819 - /* Nothing implemented yet */ 820 - case MISDN_CTRL_FILL_EMPTY: 821 - default: 822 - pr_info("%s: %s unknown Op %x\n", fc->name, __func__, cq->op); 823 - ret = -EINVAL; 824 - break; 825 - } 826 - return ret; 812 + return mISDN_ctrl_bchannel(bch, cq); 827 813 } 828 814 829 815 static int ··· 1005 1019 setup_instance(struct fritzcard *card) 1006 1020 { 1007 1021 int i, err; 1022 + unsigned short minsize; 1008 1023 u_long flags; 1009 1024 1010 1025 snprintf(card->name, MISDN_MAX_IDLEN - 1, "AVM.%d", AVM_cnt + 1); ··· 1025 1038 for (i = 0; i < 2; i++) { 1026 1039 card->bch[i].nr = i + 1; 1027 1040 set_channelmap(i + 1, card->isac.dch.dev.channelmap); 1028 - mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM); 1041 + if (AVM_FRITZ_PCIV2 == card->type) 1042 + minsize = HDLC_FIFO_SIZE_V2; 1043 + else 1044 + minsize = HDLC_FIFO_SIZE_V1; 1045 + mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM, minsize); 1029 1046 card->bch[i].hw = card; 1030 1047 card->bch[i].ch.send = avm_l2l1B; 1031 1048 card->bch[i].ch.ctrl = avm_bctrl;
+8 -9
drivers/isdn/hardware/mISDN/hfcmulti.c
··· 2352 2352 if (dch) 2353 2353 recv_Dchannel(dch); 2354 2354 else 2355 - recv_Bchannel(bch, MISDN_ID_ANY); 2355 + recv_Bchannel(bch, MISDN_ID_ANY, false); 2356 2356 *sp = skb; 2357 2357 again++; 2358 2358 goto next_frame; ··· 2367 2367 "(z1=%04x, z2=%04x) TRANS\n", 2368 2368 __func__, hc->id + 1, ch, Zsize, z1, z2); 2369 2369 /* only bch is transparent */ 2370 - recv_Bchannel(bch, hc->chan[ch].Zfill); 2370 + recv_Bchannel(bch, hc->chan[ch].Zfill, false); 2371 2371 } 2372 2372 } 2373 2373 ··· 3574 3574 3575 3575 switch (cq->op) { 3576 3576 case MISDN_CTRL_GETOP: 3577 - cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP 3578 - | MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY; 3577 + ret = mISDN_ctrl_bchannel(bch, cq); 3578 + cq->op |= MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP | 3579 + MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY; 3579 3580 break; 3580 3581 case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */ 3581 3582 hc->chan[bch->slot].rx_off = !!cq->p1; ··· 3684 3683 ret = -EINVAL; 3685 3684 break; 3686 3685 default: 3687 - printk(KERN_WARNING "%s: unknown Op %x\n", 3688 - __func__, cq->op); 3689 - ret = -EINVAL; 3686 + ret = mISDN_ctrl_bchannel(bch, cq); 3690 3687 break; 3691 3688 } 3692 3689 return ret; ··· 4854 4855 bch->nr = ch; 4855 4856 bch->slot = ch; 4856 4857 bch->debug = debug; 4857 - mISDN_initbchannel(bch, MAX_DATA_MEM); 4858 + mISDN_initbchannel(bch, MAX_DATA_MEM, poll >> 1); 4858 4859 bch->hw = hc; 4859 4860 bch->ch.send = handle_bmsg; 4860 4861 bch->ch.ctrl = hfcm_bctrl; ··· 4927 4928 bch->nr = ch + 1; 4928 4929 bch->slot = i + ch; 4929 4930 bch->debug = debug; 4930 - mISDN_initbchannel(bch, MAX_DATA_MEM); 4931 + mISDN_initbchannel(bch, MAX_DATA_MEM, poll >> 1); 4931 4932 bch->hw = hc; 4932 4933 bch->ch.send = handle_bmsg; 4933 4934 bch->ch.ctrl = hfcm_bctrl;
+6 -6
drivers/isdn/hardware/mISDN/hfcpci.c
··· 453 453 } 454 454 bz->za[new_f2].z2 = cpu_to_le16(new_z2); 455 455 bz->f2 = new_f2; /* next buffer */ 456 - recv_Bchannel(bch, MISDN_ID_ANY); 456 + recv_Bchannel(bch, MISDN_ID_ANY, false); 457 457 } 458 458 } 459 459 ··· 599 599 ptr1 = bdata; /* start of buffer */ 600 600 memcpy(ptr, ptr1, fcnt_rx); /* rest */ 601 601 } 602 - recv_Bchannel(bch, fcnt_tx); /* bch, id */ 602 + recv_Bchannel(bch, fcnt_tx, false); /* bch, id, !force */ 603 603 } 604 604 *z2r = cpu_to_le16(new_z2); /* new position */ 605 605 } ··· 1535 1535 1536 1536 switch (cq->op) { 1537 1537 case MISDN_CTRL_GETOP: 1538 - cq->op = MISDN_CTRL_FILL_EMPTY; 1538 + ret = mISDN_ctrl_bchannel(bch, cq); 1539 + cq->op |= MISDN_CTRL_FILL_EMPTY; 1539 1540 break; 1540 1541 case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */ 1541 1542 test_and_set_bit(FLG_FILLEMPTY, &bch->Flags); ··· 1545 1544 "off=%d)\n", __func__, bch->nr, !!cq->p1); 1546 1545 break; 1547 1546 default: 1548 - printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op); 1549 - ret = -EINVAL; 1547 + ret = mISDN_ctrl_bchannel(bch, cq); 1550 1548 break; 1551 1549 } 1552 1550 return ret; ··· 2116 2116 card->bch[i].nr = i + 1; 2117 2117 set_channelmap(i + 1, card->dch.dev.channelmap); 2118 2118 card->bch[i].debug = debug; 2119 - mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM); 2119 + mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM, poll >> 1); 2120 2120 card->bch[i].hw = card; 2121 2121 card->bch[i].ch.send = hfcpci_l2l1B; 2122 2122 card->bch[i].ch.ctrl = hfc_bctrl;
+7 -7
drivers/isdn/hardware/mISDN/hfcsusb.c
··· 810 810 811 811 switch (cq->op) { 812 812 case MISDN_CTRL_GETOP: 813 - cq->op = MISDN_CTRL_FILL_EMPTY; 813 + ret = mISDN_ctrl_bchannel(bch, cq); 814 + cq->op |= MISDN_CTRL_FILL_EMPTY; 814 815 break; 815 816 case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */ 816 817 test_and_set_bit(FLG_FILLEMPTY, &bch->Flags); ··· 820 819 "off=%d)\n", __func__, bch->nr, !!cq->p1); 821 820 break; 822 821 default: 823 - printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op); 824 - ret = -EINVAL; 822 + ret = mISDN_ctrl_bchannel(bch, cq); 825 823 break; 826 824 } 827 825 return ret; ··· 931 931 if (fifo->dch) 932 932 recv_Dchannel(fifo->dch); 933 933 if (fifo->bch) 934 - recv_Bchannel(fifo->bch, MISDN_ID_ANY); 934 + recv_Bchannel(fifo->bch, MISDN_ID_ANY, 935 + 0); 935 936 if (fifo->ech) 936 937 recv_Echannel(fifo->ech, 937 938 &hw->dch); ··· 953 952 } 954 953 } else { 955 954 /* deliver transparent data to layer2 */ 956 - if (rx_skb->len >= poll) 957 - recv_Bchannel(fifo->bch, MISDN_ID_ANY); 955 + recv_Bchannel(fifo->bch, MISDN_ID_ANY, false); 958 956 } 959 957 spin_unlock(&hw->lock); 960 958 } ··· 1861 1861 hw->bch[i].nr = i + 1; 1862 1862 set_channelmap(i + 1, hw->dch.dev.channelmap); 1863 1863 hw->bch[i].debug = debug; 1864 - mISDN_initbchannel(&hw->bch[i], MAX_DATA_MEM); 1864 + mISDN_initbchannel(&hw->bch[i], MAX_DATA_MEM, poll >> 1); 1865 1865 hw->bch[i].hw = hw; 1866 1866 hw->bch[i].ch.send = hfcusb_l2l1B; 1867 1867 hw->bch[i].ch.ctrl = hfc_bctrl;
+6 -21
drivers/isdn/hardware/mISDN/mISDNipac.c
··· 1063 1063 skb_trim(hx->bch.rx_skb, 0); 1064 1064 } else { 1065 1065 skb_trim(hx->bch.rx_skb, hx->bch.rx_skb->len - 1); 1066 - recv_Bchannel(&hx->bch, 0); 1066 + recv_Bchannel(&hx->bch, 0, false); 1067 1067 } 1068 1068 } 1069 1069 ··· 1114 1114 1115 1115 if (istab & IPACX_B_RPF) { 1116 1116 hscx_empty_fifo(hx, hx->fifo_size); 1117 - if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) { 1118 - /* receive transparent audio data */ 1119 - if (hx->bch.rx_skb) 1120 - recv_Bchannel(&hx->bch, 0); 1121 - } 1117 + if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) 1118 + recv_Bchannel(&hx->bch, 0, false); 1122 1119 } 1123 1120 1124 1121 if (istab & IPACX_B_RFO) { ··· 1374 1377 static int 1375 1378 channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) 1376 1379 { 1377 - int ret = 0; 1378 - 1379 - switch (cq->op) { 1380 - case MISDN_CTRL_GETOP: 1381 - cq->op = 0; 1382 - break; 1383 - /* Nothing implemented yet */ 1384 - case MISDN_CTRL_FILL_EMPTY: 1385 - default: 1386 - pr_info("%s: unknown Op %x\n", __func__, cq->op); 1387 - ret = -EINVAL; 1388 - break; 1389 - } 1390 - return ret; 1380 + return mISDN_ctrl_bchannel(bch, cq); 1391 1381 } 1392 1382 1393 1383 static int ··· 1592 1608 set_channelmap(i + 1, ipac->isac.dch.dev.channelmap); 1593 1609 list_add(&ipac->hscx[i].bch.ch.list, 1594 1610 &ipac->isac.dch.dev.bchannels); 1595 - mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM); 1611 + mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM, 1612 + ipac->hscx[i].fifo_size); 1596 1613 ipac->hscx[i].bch.ch.nr = i + 1; 1597 1614 ipac->hscx[i].bch.ch.send = &hscx_l2l1; 1598 1615 ipac->hscx[i].bch.ch.ctrl = hscx_bctrl;
+6 -19
drivers/isdn/hardware/mISDN/mISDNisar.c
··· 446 446 break; 447 447 } 448 448 rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb)); 449 - recv_Bchannel(&ch->bch, 0); 449 + recv_Bchannel(&ch->bch, 0, false); 450 450 break; 451 451 case ISDN_P_B_HDLC: 452 452 maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb); ··· 481 481 break; 482 482 } 483 483 skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2); 484 - recv_Bchannel(&ch->bch, 0); 484 + recv_Bchannel(&ch->bch, 0, false); 485 485 } 486 486 break; 487 487 case ISDN_P_B_T30_FAX: ··· 517 517 ch->state = STFAX_ESCAPE; 518 518 /* set_skb_flag(skb, DF_NOMOREDATA); */ 519 519 } 520 - recv_Bchannel(&ch->bch, 0); 520 + recv_Bchannel(&ch->bch, 0, false); 521 521 if (ch->is->cmsb & SART_NMD) 522 522 deliver_status(ch, HW_MOD_NOCARR); 523 523 break; ··· 557 557 break; 558 558 } 559 559 skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2); 560 - recv_Bchannel(&ch->bch, 0); 560 + recv_Bchannel(&ch->bch, 0, false); 561 561 } 562 562 if (ch->is->cmsb & SART_NMD) { /* ABORT */ 563 563 pr_debug("%s: isar_rcv_frame: no more data\n", ··· 1554 1554 static int 1555 1555 channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) 1556 1556 { 1557 - int ret = 0; 1558 - 1559 - switch (cq->op) { 1560 - case MISDN_CTRL_GETOP: 1561 - cq->op = 0; 1562 - break; 1563 - /* Nothing implemented yet */ 1564 - case MISDN_CTRL_FILL_EMPTY: 1565 - default: 1566 - pr_info("%s: unknown Op %x\n", __func__, cq->op); 1567 - ret = -EINVAL; 1568 - break; 1569 - } 1570 - return ret; 1557 + return mISDN_ctrl_bchannel(bch, cq); 1571 1558 } 1572 1559 1573 1560 static int ··· 1652 1665 isar->hw = hw; 1653 1666 for (i = 0; i < 2; i++) { 1654 1667 isar->ch[i].bch.nr = i + 1; 1655 - mISDN_initbchannel(&isar->ch[i].bch, MAX_DATA_MEM); 1668 + mISDN_initbchannel(&isar->ch[i].bch, MAX_DATA_MEM, 32); 1656 1669 isar->ch[i].bch.ch.nr = i + 1; 1657 1670 isar->ch[i].bch.ch.send = &isar_l2l1; 1658 1671 isar->ch[i].bch.ch.ctrl = isar_bctrl;
+5 -18
drivers/isdn/hardware/mISDN/netjet.c
··· 408 408 } 409 409 410 410 if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) { 411 - recv_Bchannel(&bc->bch, 0); 411 + recv_Bchannel(&bc->bch, 0, false); 412 412 return; 413 413 } 414 414 ··· 426 426 DUMP_PREFIX_OFFSET, p, 427 427 stat); 428 428 } 429 - recv_Bchannel(&bc->bch, 0); 429 + recv_Bchannel(&bc->bch, 0, false); 430 430 stat = bchannel_get_rxbuf(&bc->bch, bc->bch.maxlen); 431 431 if (stat < 0) { 432 432 pr_warning("%s.B%d: No memory for %d bytes\n", ··· 758 758 static int 759 759 channel_bctrl(struct tiger_ch *bc, struct mISDN_ctrl_req *cq) 760 760 { 761 - int ret = 0; 762 - struct tiger_hw *card = bc->bch.hw; 763 - 764 - switch (cq->op) { 765 - case MISDN_CTRL_GETOP: 766 - cq->op = 0; 767 - break; 768 - /* Nothing implemented yet */ 769 - case MISDN_CTRL_FILL_EMPTY: 770 - default: 771 - pr_info("%s: %s unknown Op %x\n", card->name, __func__, cq->op); 772 - ret = -EINVAL; 773 - break; 774 - } 775 - return ret; 761 + return mISDN_ctrl_bchannel(&bc->bch, cq); 776 762 } 777 763 778 764 static int ··· 992 1006 for (i = 0; i < 2; i++) { 993 1007 card->bc[i].bch.nr = i + 1; 994 1008 set_channelmap(i + 1, card->isac.dch.dev.channelmap); 995 - mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM); 1009 + mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM, 1010 + NJ_DMA_RXSIZE >> 1); 996 1011 card->bc[i].bch.hw = card; 997 1012 card->bc[i].bch.ch.send = nj_l2l1B; 998 1013 card->bc[i].bch.ch.ctrl = nj_bctrl;
+6 -19
drivers/isdn/hardware/mISDN/w6692.c
··· 688 688 if (count == 0) 689 689 count = W_B_FIFO_THRESH; 690 690 W6692_empty_Bfifo(wch, count); 691 - recv_Bchannel(&wch->bch, 0); 691 + recv_Bchannel(&wch->bch, 0, false); 692 692 } 693 693 } 694 694 if (stat & W_B_EXI_RMR) { ··· 704 704 W_B_CMDR_RRST | W_B_CMDR_RACT); 705 705 } else { 706 706 W6692_empty_Bfifo(wch, W_B_FIFO_THRESH); 707 - if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags) && 708 - wch->bch.rx_skb && (wch->bch.rx_skb->len > 0)) 709 - recv_Bchannel(&wch->bch, 0); 707 + if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags)) 708 + recv_Bchannel(&wch->bch, 0, false); 710 709 } 711 710 } 712 711 if (stat & W_B_EXI_RDOV) { ··· 978 979 static int 979 980 channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) 980 981 { 981 - int ret = 0; 982 - 983 - switch (cq->op) { 984 - case MISDN_CTRL_GETOP: 985 - cq->op = 0; 986 - break; 987 - /* Nothing implemented yet */ 988 - case MISDN_CTRL_FILL_EMPTY: 989 - default: 990 - pr_info("%s: unknown Op %x\n", __func__, cq->op); 991 - ret = -EINVAL; 992 - break; 993 - } 994 - return ret; 982 + return mISDN_ctrl_bchannel(bch, cq); 995 983 } 996 984 997 985 static int ··· 1289 1303 card->dch.hw = card; 1290 1304 card->dch.dev.nrbchan = 2; 1291 1305 for (i = 0; i < 2; i++) { 1292 - mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM); 1306 + mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM, 1307 + W_B_FIFO_THRESH); 1293 1308 card->bc[i].bch.hw = card; 1294 1309 card->bc[i].bch.nr = i + 1; 1295 1310 card->bc[i].bch.ch.nr = i + 1;
+59 -6
drivers/isdn/mISDN/hwchannel.c
··· 81 81 EXPORT_SYMBOL(mISDN_initdchannel); 82 82 83 83 int 84 - mISDN_initbchannel(struct bchannel *ch, int maxlen) 84 + mISDN_initbchannel(struct bchannel *ch, unsigned short maxlen, 85 + unsigned short minlen) 85 86 { 86 87 ch->Flags = 0; 88 + ch->minlen = minlen; 89 + ch->next_minlen = minlen; 90 + ch->init_minlen = minlen; 87 91 ch->maxlen = maxlen; 92 + ch->next_maxlen = maxlen; 93 + ch->init_maxlen = maxlen; 88 94 ch->hw = NULL; 89 95 ch->rx_skb = NULL; 90 96 ch->tx_skb = NULL; ··· 140 134 test_and_clear_bit(FLG_TX_BUSY, &ch->Flags); 141 135 test_and_clear_bit(FLG_TX_NEXT, &ch->Flags); 142 136 test_and_clear_bit(FLG_ACTIVE, &ch->Flags); 137 + ch->minlen = ch->init_minlen; 138 + ch->next_minlen = ch->init_minlen; 139 + ch->maxlen = ch->init_maxlen; 140 + ch->next_maxlen = ch->init_maxlen; 143 141 } 144 142 EXPORT_SYMBOL(mISDN_clear_bchannel); 145 143 ··· 157 147 return 0; 158 148 } 159 149 EXPORT_SYMBOL(mISDN_freebchannel); 150 + 151 + int 152 + mISDN_ctrl_bchannel(struct bchannel *bch, struct mISDN_ctrl_req *cq) 153 + { 154 + int ret = 0; 155 + 156 + switch (cq->op) { 157 + case MISDN_CTRL_GETOP: 158 + cq->op = MISDN_CTRL_RX_BUFFER; 159 + break; 160 + case MISDN_CTRL_RX_BUFFER: 161 + if (cq->p2 > MISDN_CTRL_RX_SIZE_IGNORE) 162 + bch->next_maxlen = cq->p2; 163 + if (cq->p1 > MISDN_CTRL_RX_SIZE_IGNORE) 164 + bch->next_minlen = cq->p1; 165 + /* we return the old values */ 166 + cq->p1 = bch->minlen; 167 + cq->p2 = bch->maxlen; 168 + break; 169 + default: 170 + pr_info("mISDN unhandled control %x operation\n", cq->op); 171 + ret = -EINVAL; 172 + break; 173 + } 174 + return ret; 175 + } 176 + EXPORT_SYMBOL(mISDN_ctrl_bchannel); 160 177 161 178 static inline u_int 162 179 get_sapi_tei(u_char *p) ··· 234 197 EXPORT_SYMBOL(recv_Echannel); 235 198 236 199 void 237 - recv_Bchannel(struct bchannel *bch, unsigned int id) 200 + recv_Bchannel(struct bchannel *bch, unsigned int id, bool force) 238 201 { 239 202 struct mISDNhead *hh; 240 203 ··· 248 211 dev_kfree_skb(bch->rx_skb); 249 212 bch->rx_skb = NULL; 250 213 } else { 214 + if (test_bit(FLG_TRANSPARENT, &bch->Flags) && 215 + (bch->rx_skb->len < bch->minlen) && !force) 216 + return; 251 217 hh = mISDN_HEAD_P(bch->rx_skb); 252 218 hh->prim = PH_DATA_IND; 253 219 hh->id = id; ··· 466 426 bch->nr, reqlen, len); 467 427 if (test_bit(FLG_TRANSPARENT, &bch->Flags)) { 468 428 /* send what we have now and try a new buffer */ 469 - recv_Bchannel(bch, 0); 429 + recv_Bchannel(bch, 0, true); 470 430 } else { 471 431 /* on HDLC we have to drop too big frames */ 472 432 return -EMSGSIZE; ··· 475 435 return len; 476 436 } 477 437 } 438 + /* update current min/max length first */ 439 + if (unlikely(bch->maxlen != bch->next_maxlen)) 440 + bch->maxlen = bch->next_maxlen; 441 + if (unlikely(bch->minlen != bch->next_minlen)) 442 + bch->minlen = bch->next_minlen; 478 443 if (unlikely(reqlen > bch->maxlen)) 479 444 return -EMSGSIZE; 480 - if (test_bit(FLG_TRANSPARENT, &bch->Flags)) 481 - len = reqlen; 482 - else /* with HDLC we do not know the length yet */ 445 + if (test_bit(FLG_TRANSPARENT, &bch->Flags)) { 446 + if (reqlen >= bch->minlen) { 447 + len = reqlen; 448 + } else { 449 + len = 2 * bch->minlen; 450 + if (len > bch->maxlen) 451 + len = bch->maxlen; 452 + } 453 + } else { 454 + /* with HDLC we do not know the length yet */ 483 455 len = bch->maxlen; 456 + } 484 457 bch->rx_skb = mI_alloc_skb(len, GFP_ATOMIC); 485 458 if (!bch->rx_skb) { 486 459 pr_warning("B%d receive no memory for %d bytes\n",
+1 -1
drivers/isdn/mISDN/l1oip_core.c
··· 1420 1420 bch->nr = i + ch; 1421 1421 bch->slot = i + ch; 1422 1422 bch->debug = debug; 1423 - mISDN_initbchannel(bch, MAX_DATA_MEM); 1423 + mISDN_initbchannel(bch, MAX_DATA_MEM, 0); 1424 1424 bch->hw = hc; 1425 1425 bch->ch.send = handle_bmsg; 1426 1426 bch->ch.ctrl = l1oip_bctrl;
+10 -3
include/linux/mISDNhw.h
··· 154 154 struct timer_list timer; 155 155 /* receive data */ 156 156 struct sk_buff *rx_skb; 157 - int maxlen; 157 + unsigned short maxlen; 158 + unsigned short init_maxlen; /* initial value */ 159 + unsigned short next_maxlen; /* pending value */ 160 + unsigned short minlen; /* for transparent data */ 161 + unsigned short init_minlen; /* initial value */ 162 + unsigned short next_minlen; /* pending value */ 158 163 /* send data */ 159 164 struct sk_buff *next_skb; 160 165 struct sk_buff *tx_skb; ··· 174 169 }; 175 170 176 171 extern int mISDN_initdchannel(struct dchannel *, int, void *); 177 - extern int mISDN_initbchannel(struct bchannel *, int); 172 + extern int mISDN_initbchannel(struct bchannel *, unsigned short, 173 + unsigned short); 178 174 extern int mISDN_freedchannel(struct dchannel *); 179 175 extern void mISDN_clear_bchannel(struct bchannel *); 180 176 extern int mISDN_freebchannel(struct bchannel *); 177 + extern int mISDN_ctrl_bchannel(struct bchannel *, struct mISDN_ctrl_req *); 181 178 extern void queue_ch_frame(struct mISDNchannel *, u_int, 182 179 int, struct sk_buff *); 183 180 extern int dchannel_senddata(struct dchannel *, struct sk_buff *); ··· 187 180 extern int bchannel_get_rxbuf(struct bchannel *, int); 188 181 extern void recv_Dchannel(struct dchannel *); 189 182 extern void recv_Echannel(struct dchannel *, struct dchannel *); 190 - extern void recv_Bchannel(struct bchannel *, unsigned int id); 183 + extern void recv_Bchannel(struct bchannel *, unsigned int, bool); 191 184 extern void recv_Dchannel_skb(struct dchannel *, struct sk_buff *); 192 185 extern void recv_Bchannel_skb(struct bchannel *, struct sk_buff *); 193 186 extern int get_next_bframe(struct bchannel *);
+8 -1
include/linux/mISDNif.h
··· 37 37 */ 38 38 #define MISDN_MAJOR_VERSION 1 39 39 #define MISDN_MINOR_VERSION 1 40 - #define MISDN_RELEASE 28 40 + #define MISDN_RELEASE 29 41 41 42 42 /* primitives for information exchange 43 43 * generell format ··· 365 365 #define MISDN_CTRL_LOOP 0x0001 366 366 #define MISDN_CTRL_CONNECT 0x0002 367 367 #define MISDN_CTRL_DISCONNECT 0x0004 368 + #define MISDN_CTRL_RX_BUFFER 0x0008 368 369 #define MISDN_CTRL_PCMCONNECT 0x0010 369 370 #define MISDN_CTRL_PCMDISCONNECT 0x0020 370 371 #define MISDN_CTRL_SETPEER 0x0040 ··· 387 386 #define MISDN_CTRL_HFC_ECHOCAN_OFF 0x4008 388 387 #define MISDN_CTRL_HFC_WD_INIT 0x4009 389 388 #define MISDN_CTRL_HFC_WD_RESET 0x400A 389 + 390 + /* special RX buffer value for MISDN_CTRL_RX_BUFFER request.p1 is the minimum 391 + * buffer size request.p2 the maximum. Using MISDN_CTRL_RX_SIZE_IGNORE will 392 + * not change the value, but still read back the actual stetting. 393 + */ 394 + #define MISDN_CTRL_RX_SIZE_IGNORE -1 390 395 391 396 /* socket options */ 392 397 #define MISDN_TIME_STAMP 0x0001