aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn
diff options
context:
space:
mode:
authorKarsten Keil <kkeil@linux-pingi.de>2012-05-15 19:51:06 -0400
committerDavid S. Miller <davem@davemloft.net>2012-05-16 15:23:46 -0400
commit034005a0119b9c2aabe0ac3953eb9a65ca937a69 (patch)
treea7ee0735f2a9f87eb0207c27930a3e3c748bc1fe /drivers/isdn
parent7206e659f689558b41aa058c3040b081cb281d03 (diff)
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>
Diffstat (limited to 'drivers/isdn')
-rw-r--r--drivers/isdn/hardware/mISDN/avmfritz.c35
-rw-r--r--drivers/isdn/hardware/mISDN/hfcmulti.c17
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c12
-rw-r--r--drivers/isdn/hardware/mISDN/hfcsusb.c14
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNipac.c27
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNisar.c25
-rw-r--r--drivers/isdn/hardware/mISDN/netjet.c23
-rw-r--r--drivers/isdn/hardware/mISDN/w6692.c25
-rw-r--r--drivers/isdn/mISDN/hwchannel.c65
-rw-r--r--drivers/isdn/mISDN/l1oip_core.c2
10 files changed, 117 insertions, 128 deletions
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c
index 808136735f32..7cd3a963ed2e 100644
--- a/drivers/isdn/hardware/mISDN/avmfritz.c
+++ b/drivers/isdn/hardware/mISDN/avmfritz.c
@@ -536,12 +536,12 @@ HDLC_irq(struct bchannel *bch, u32 stat)
536 hdlc_empty_fifo(bch, len); 536 hdlc_empty_fifo(bch, len);
537 if (!bch->rx_skb) 537 if (!bch->rx_skb)
538 goto handle_tx; 538 goto handle_tx;
539 if (test_bit(FLG_TRANSPARENT, &bch->Flags) || 539 if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
540 (stat & HDLC_STAT_RME)) { 540 recv_Bchannel(bch, 0, false);
541 if (((stat & HDLC_STAT_CRCVFRRAB) == 541 } else if (stat & HDLC_STAT_RME) {
542 HDLC_STAT_CRCVFR) || 542 if ((stat & HDLC_STAT_CRCVFRRAB) ==
543 test_bit(FLG_TRANSPARENT, &bch->Flags)) { 543 HDLC_STAT_CRCVFR) {
544 recv_Bchannel(bch, 0); 544 recv_Bchannel(bch, 0, false);
545 } else { 545 } else {
546 pr_warning("%s: got invalid frame\n", 546 pr_warning("%s: got invalid frame\n",
547 fc->name); 547 fc->name);
@@ -809,21 +809,7 @@ init_card(struct fritzcard *fc)
809static int 809static int
810channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) 810channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
811{ 811{
812 int ret = 0; 812 return mISDN_ctrl_bchannel(bch, cq);
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;
827} 813}
828 814
829static int 815static int
@@ -1019,6 +1005,7 @@ static int __devinit
1019setup_instance(struct fritzcard *card) 1005setup_instance(struct fritzcard *card)
1020{ 1006{
1021 int i, err; 1007 int i, err;
1008 unsigned short minsize;
1022 u_long flags; 1009 u_long flags;
1023 1010
1024 snprintf(card->name, MISDN_MAX_IDLEN - 1, "AVM.%d", AVM_cnt + 1); 1011 snprintf(card->name, MISDN_MAX_IDLEN - 1, "AVM.%d", AVM_cnt + 1);
@@ -1038,7 +1025,11 @@ setup_instance(struct fritzcard *card)
1038 for (i = 0; i < 2; i++) { 1025 for (i = 0; i < 2; i++) {
1039 card->bch[i].nr = i + 1; 1026 card->bch[i].nr = i + 1;
1040 set_channelmap(i + 1, card->isac.dch.dev.channelmap); 1027 set_channelmap(i + 1, card->isac.dch.dev.channelmap);
1041 mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM); 1028 if (AVM_FRITZ_PCIV2 == card->type)
1029 minsize = HDLC_FIFO_SIZE_V2;
1030 else
1031 minsize = HDLC_FIFO_SIZE_V1;
1032 mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM, minsize);
1042 card->bch[i].hw = card; 1033 card->bch[i].hw = card;
1043 card->bch[i].ch.send = avm_l2l1B; 1034 card->bch[i].ch.send = avm_l2l1B;
1044 card->bch[i].ch.ctrl = avm_bctrl; 1035 card->bch[i].ch.ctrl = avm_bctrl;
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index 60dd6efa1879..3d4b36d2a31a 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -2352,7 +2352,7 @@ next_frame:
2352 if (dch) 2352 if (dch)
2353 recv_Dchannel(dch); 2353 recv_Dchannel(dch);
2354 else 2354 else
2355 recv_Bchannel(bch, MISDN_ID_ANY); 2355 recv_Bchannel(bch, MISDN_ID_ANY, false);
2356 *sp = skb; 2356 *sp = skb;
2357 again++; 2357 again++;
2358 goto next_frame; 2358 goto next_frame;
@@ -2367,7 +2367,7 @@ next_frame:
2367 "(z1=%04x, z2=%04x) TRANS\n", 2367 "(z1=%04x, z2=%04x) TRANS\n",
2368 __func__, hc->id + 1, ch, Zsize, z1, z2); 2368 __func__, hc->id + 1, ch, Zsize, z1, z2);
2369 /* only bch is transparent */ 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,8 +3574,9 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
3574 3574
3575 switch (cq->op) { 3575 switch (cq->op) {
3576 case MISDN_CTRL_GETOP: 3576 case MISDN_CTRL_GETOP:
3577 cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP 3577 ret = mISDN_ctrl_bchannel(bch, cq);
3578 | MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY; 3578 cq->op |= MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP |
3579 MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY;
3579 break; 3580 break;
3580 case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */ 3581 case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */
3581 hc->chan[bch->slot].rx_off = !!cq->p1; 3582 hc->chan[bch->slot].rx_off = !!cq->p1;
@@ -3683,9 +3684,7 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
3683 ret = -EINVAL; 3684 ret = -EINVAL;
3684 break; 3685 break;
3685 default: 3686 default:
3686 printk(KERN_WARNING "%s: unknown Op %x\n", 3687 ret = mISDN_ctrl_bchannel(bch, cq);
3687 __func__, cq->op);
3688 ret = -EINVAL;
3689 break; 3688 break;
3690 } 3689 }
3691 return ret; 3690 return ret;
@@ -4855,7 +4854,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m, int pt)
4855 bch->nr = ch; 4854 bch->nr = ch;
4856 bch->slot = ch; 4855 bch->slot = ch;
4857 bch->debug = debug; 4856 bch->debug = debug;
4858 mISDN_initbchannel(bch, MAX_DATA_MEM); 4857 mISDN_initbchannel(bch, MAX_DATA_MEM, poll >> 1);
4859 bch->hw = hc; 4858 bch->hw = hc;
4860 bch->ch.send = handle_bmsg; 4859 bch->ch.send = handle_bmsg;
4861 bch->ch.ctrl = hfcm_bctrl; 4860 bch->ch.ctrl = hfcm_bctrl;
@@ -4928,7 +4927,7 @@ init_multi_port(struct hfc_multi *hc, int pt)
4928 bch->nr = ch + 1; 4927 bch->nr = ch + 1;
4929 bch->slot = i + ch; 4928 bch->slot = i + ch;
4930 bch->debug = debug; 4929 bch->debug = debug;
4931 mISDN_initbchannel(bch, MAX_DATA_MEM); 4930 mISDN_initbchannel(bch, MAX_DATA_MEM, poll >> 1);
4932 bch->hw = hc; 4931 bch->hw = hc;
4933 bch->ch.send = handle_bmsg; 4932 bch->ch.send = handle_bmsg;
4934 bch->ch.ctrl = hfcm_bctrl; 4933 bch->ch.ctrl = hfcm_bctrl;
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index 0622e05ae066..27743754ab81 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -453,7 +453,7 @@ hfcpci_empty_bfifo(struct bchannel *bch, struct bzfifo *bz,
453 } 453 }
454 bz->za[new_f2].z2 = cpu_to_le16(new_z2); 454 bz->za[new_f2].z2 = cpu_to_le16(new_z2);
455 bz->f2 = new_f2; /* next buffer */ 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,7 +599,7 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz,
599 ptr1 = bdata; /* start of buffer */ 599 ptr1 = bdata; /* start of buffer */
600 memcpy(ptr, ptr1, fcnt_rx); /* rest */ 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 *z2r = cpu_to_le16(new_z2); /* new position */ 604 *z2r = cpu_to_le16(new_z2); /* new position */
605} 605}
@@ -1535,7 +1535,8 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
1535 1535
1536 switch (cq->op) { 1536 switch (cq->op) {
1537 case MISDN_CTRL_GETOP: 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 break; 1540 break;
1540 case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */ 1541 case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
1541 test_and_set_bit(FLG_FILLEMPTY, &bch->Flags); 1542 test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
@@ -1544,8 +1545,7 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
1544 "off=%d)\n", __func__, bch->nr, !!cq->p1); 1545 "off=%d)\n", __func__, bch->nr, !!cq->p1);
1545 break; 1546 break;
1546 default: 1547 default:
1547 printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op); 1548 ret = mISDN_ctrl_bchannel(bch, cq);
1548 ret = -EINVAL;
1549 break; 1549 break;
1550 } 1550 }
1551 return ret; 1551 return ret;
@@ -2116,7 +2116,7 @@ setup_card(struct hfc_pci *card)
2116 card->bch[i].nr = i + 1; 2116 card->bch[i].nr = i + 1;
2117 set_channelmap(i + 1, card->dch.dev.channelmap); 2117 set_channelmap(i + 1, card->dch.dev.channelmap);
2118 card->bch[i].debug = debug; 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 card->bch[i].hw = card; 2120 card->bch[i].hw = card;
2121 card->bch[i].ch.send = hfcpci_l2l1B; 2121 card->bch[i].ch.send = hfcpci_l2l1B;
2122 card->bch[i].ch.ctrl = hfc_bctrl; 2122 card->bch[i].ch.ctrl = hfc_bctrl;
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c
index 6bb689b8d66f..9c17473da83b 100644
--- a/drivers/isdn/hardware/mISDN/hfcsusb.c
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -810,7 +810,8 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
810 810
811 switch (cq->op) { 811 switch (cq->op) {
812 case MISDN_CTRL_GETOP: 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 break; 815 break;
815 case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */ 816 case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
816 test_and_set_bit(FLG_FILLEMPTY, &bch->Flags); 817 test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
@@ -819,8 +820,7 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
819 "off=%d)\n", __func__, bch->nr, !!cq->p1); 820 "off=%d)\n", __func__, bch->nr, !!cq->p1);
820 break; 821 break;
821 default: 822 default:
822 printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op); 823 ret = mISDN_ctrl_bchannel(bch, cq);
823 ret = -EINVAL;
824 break; 824 break;
825 } 825 }
826 return ret; 826 return ret;
@@ -931,7 +931,8 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
931 if (fifo->dch) 931 if (fifo->dch)
932 recv_Dchannel(fifo->dch); 932 recv_Dchannel(fifo->dch);
933 if (fifo->bch) 933 if (fifo->bch)
934 recv_Bchannel(fifo->bch, MISDN_ID_ANY); 934 recv_Bchannel(fifo->bch, MISDN_ID_ANY,
935 0);
935 if (fifo->ech) 936 if (fifo->ech)
936 recv_Echannel(fifo->ech, 937 recv_Echannel(fifo->ech,
937 &hw->dch); 938 &hw->dch);
@@ -952,8 +953,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
952 } 953 }
953 } else { 954 } else {
954 /* deliver transparent data to layer2 */ 955 /* deliver transparent data to layer2 */
955 if (rx_skb->len >= poll) 956 recv_Bchannel(fifo->bch, MISDN_ID_ANY, false);
956 recv_Bchannel(fifo->bch, MISDN_ID_ANY);
957 } 957 }
958 spin_unlock(&hw->lock); 958 spin_unlock(&hw->lock);
959} 959}
@@ -1861,7 +1861,7 @@ setup_instance(struct hfcsusb *hw, struct device *parent)
1861 hw->bch[i].nr = i + 1; 1861 hw->bch[i].nr = i + 1;
1862 set_channelmap(i + 1, hw->dch.dev.channelmap); 1862 set_channelmap(i + 1, hw->dch.dev.channelmap);
1863 hw->bch[i].debug = debug; 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 hw->bch[i].hw = hw; 1865 hw->bch[i].hw = hw;
1866 hw->bch[i].ch.send = hfcusb_l2l1B; 1866 hw->bch[i].ch.send = hfcusb_l2l1B;
1867 hw->bch[i].ch.ctrl = hfc_bctrl; 1867 hw->bch[i].ch.ctrl = hfc_bctrl;
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
index 7d109ed35366..3e71a5ef4bbc 100644
--- a/drivers/isdn/hardware/mISDN/mISDNipac.c
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -1063,7 +1063,7 @@ ipac_rme(struct hscx_hw *hx)
1063 skb_trim(hx->bch.rx_skb, 0); 1063 skb_trim(hx->bch.rx_skb, 0);
1064 } else { 1064 } else {
1065 skb_trim(hx->bch.rx_skb, hx->bch.rx_skb->len - 1); 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,11 +1114,8 @@ ipac_irq(struct hscx_hw *hx, u8 ista)
1114 1114
1115 if (istab & IPACX_B_RPF) { 1115 if (istab & IPACX_B_RPF) {
1116 hscx_empty_fifo(hx, hx->fifo_size); 1116 hscx_empty_fifo(hx, hx->fifo_size);
1117 if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) { 1117 if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags))
1118 /* receive transparent audio data */ 1118 recv_Bchannel(&hx->bch, 0, false);
1119 if (hx->bch.rx_skb)
1120 recv_Bchannel(&hx->bch, 0);
1121 }
1122 } 1119 }
1123 1120
1124 if (istab & IPACX_B_RFO) { 1121 if (istab & IPACX_B_RFO) {
@@ -1377,20 +1374,7 @@ hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
1377static int 1374static int
1378channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) 1375channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
1379{ 1376{
1380 int ret = 0; 1377 return mISDN_ctrl_bchannel(bch, cq);
1381
1382 switch (cq->op) {
1383 case MISDN_CTRL_GETOP:
1384 cq->op = 0;
1385 break;
1386 /* Nothing implemented yet */
1387 case MISDN_CTRL_FILL_EMPTY:
1388 default:
1389 pr_info("%s: unknown Op %x\n", __func__, cq->op);
1390 ret = -EINVAL;
1391 break;
1392 }
1393 return ret;
1394} 1378}
1395 1379
1396static int 1380static int
@@ -1608,7 +1592,8 @@ mISDNipac_init(struct ipac_hw *ipac, void *hw)
1608 set_channelmap(i + 1, ipac->isac.dch.dev.channelmap); 1592 set_channelmap(i + 1, ipac->isac.dch.dev.channelmap);
1609 list_add(&ipac->hscx[i].bch.ch.list, 1593 list_add(&ipac->hscx[i].bch.ch.list,
1610 &ipac->isac.dch.dev.bchannels); 1594 &ipac->isac.dch.dev.bchannels);
1611 mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM); 1595 mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM,
1596 ipac->hscx[i].fifo_size);
1612 ipac->hscx[i].bch.ch.nr = i + 1; 1597 ipac->hscx[i].bch.ch.nr = i + 1;
1613 ipac->hscx[i].bch.ch.send = &hscx_l2l1; 1598 ipac->hscx[i].bch.ch.send = &hscx_l2l1;
1614 ipac->hscx[i].bch.ch.ctrl = hscx_bctrl; 1599 ipac->hscx[i].bch.ch.ctrl = hscx_bctrl;
diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c
index 4169bb2db19c..e74ad385e73f 100644
--- a/drivers/isdn/hardware/mISDN/mISDNisar.c
+++ b/drivers/isdn/hardware/mISDN/mISDNisar.c
@@ -446,7 +446,7 @@ isar_rcv_frame(struct isar_ch *ch)
446 break; 446 break;
447 } 447 }
448 rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb)); 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 break; 450 break;
451 case ISDN_P_B_HDLC: 451 case ISDN_P_B_HDLC:
452 maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb); 452 maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb);
@@ -481,7 +481,7 @@ isar_rcv_frame(struct isar_ch *ch)
481 break; 481 break;
482 } 482 }
483 skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2); 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 break; 486 break;
487 case ISDN_P_B_T30_FAX: 487 case ISDN_P_B_T30_FAX:
@@ -517,7 +517,7 @@ isar_rcv_frame(struct isar_ch *ch)
517 ch->state = STFAX_ESCAPE; 517 ch->state = STFAX_ESCAPE;
518 /* set_skb_flag(skb, DF_NOMOREDATA); */ 518 /* set_skb_flag(skb, DF_NOMOREDATA); */
519 } 519 }
520 recv_Bchannel(&ch->bch, 0); 520 recv_Bchannel(&ch->bch, 0, false);
521 if (ch->is->cmsb & SART_NMD) 521 if (ch->is->cmsb & SART_NMD)
522 deliver_status(ch, HW_MOD_NOCARR); 522 deliver_status(ch, HW_MOD_NOCARR);
523 break; 523 break;
@@ -557,7 +557,7 @@ isar_rcv_frame(struct isar_ch *ch)
557 break; 557 break;
558 } 558 }
559 skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2); 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 if (ch->is->cmsb & SART_NMD) { /* ABORT */ 562 if (ch->is->cmsb & SART_NMD) { /* ABORT */
563 pr_debug("%s: isar_rcv_frame: no more data\n", 563 pr_debug("%s: isar_rcv_frame: no more data\n",
@@ -1554,20 +1554,7 @@ isar_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
1554static int 1554static int
1555channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) 1555channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
1556{ 1556{
1557 int ret = 0; 1557 return mISDN_ctrl_bchannel(bch, cq);
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;
1571} 1558}
1572 1559
1573static int 1560static int
@@ -1665,7 +1652,7 @@ mISDNisar_init(struct isar_hw *isar, void *hw)
1665 isar->hw = hw; 1652 isar->hw = hw;
1666 for (i = 0; i < 2; i++) { 1653 for (i = 0; i < 2; i++) {
1667 isar->ch[i].bch.nr = i + 1; 1654 isar->ch[i].bch.nr = i + 1;
1668 mISDN_initbchannel(&isar->ch[i].bch, MAX_DATA_MEM); 1655 mISDN_initbchannel(&isar->ch[i].bch, MAX_DATA_MEM, 32);
1669 isar->ch[i].bch.ch.nr = i + 1; 1656 isar->ch[i].bch.ch.nr = i + 1;
1670 isar->ch[i].bch.ch.send = &isar_l2l1; 1657 isar->ch[i].bch.ch.send = &isar_l2l1;
1671 isar->ch[i].bch.ch.ctrl = isar_bctrl; 1658 isar->ch[i].bch.ch.ctrl = isar_bctrl;
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c
index 3f28057e725e..47d30749d8a7 100644
--- a/drivers/isdn/hardware/mISDN/netjet.c
+++ b/drivers/isdn/hardware/mISDN/netjet.c
@@ -408,7 +408,7 @@ read_dma(struct tiger_ch *bc, u32 idx, int cnt)
408 } 408 }
409 409
410 if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) { 410 if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) {
411 recv_Bchannel(&bc->bch, 0); 411 recv_Bchannel(&bc->bch, 0, false);
412 return; 412 return;
413 } 413 }
414 414
@@ -426,7 +426,7 @@ read_dma(struct tiger_ch *bc, u32 idx, int cnt)
426 DUMP_PREFIX_OFFSET, p, 426 DUMP_PREFIX_OFFSET, p,
427 stat); 427 stat);
428 } 428 }
429 recv_Bchannel(&bc->bch, 0); 429 recv_Bchannel(&bc->bch, 0, false);
430 stat = bchannel_get_rxbuf(&bc->bch, bc->bch.maxlen); 430 stat = bchannel_get_rxbuf(&bc->bch, bc->bch.maxlen);
431 if (stat < 0) { 431 if (stat < 0) {
432 pr_warning("%s.B%d: No memory for %d bytes\n", 432 pr_warning("%s.B%d: No memory for %d bytes\n",
@@ -758,21 +758,7 @@ nj_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
758static int 758static int
759channel_bctrl(struct tiger_ch *bc, struct mISDN_ctrl_req *cq) 759channel_bctrl(struct tiger_ch *bc, struct mISDN_ctrl_req *cq)
760{ 760{
761 int ret = 0; 761 return mISDN_ctrl_bchannel(&bc->bch, cq);
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;
776} 762}
777 763
778static int 764static int
@@ -1006,7 +992,8 @@ setup_instance(struct tiger_hw *card)
1006 for (i = 0; i < 2; i++) { 992 for (i = 0; i < 2; i++) {
1007 card->bc[i].bch.nr = i + 1; 993 card->bc[i].bch.nr = i + 1;
1008 set_channelmap(i + 1, card->isac.dch.dev.channelmap); 994 set_channelmap(i + 1, card->isac.dch.dev.channelmap);
1009 mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM); 995 mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM,
996 NJ_DMA_RXSIZE >> 1);
1010 card->bc[i].bch.hw = card; 997 card->bc[i].bch.hw = card;
1011 card->bc[i].bch.ch.send = nj_l2l1B; 998 card->bc[i].bch.ch.send = nj_l2l1B;
1012 card->bc[i].bch.ch.ctrl = nj_bctrl; 999 card->bc[i].bch.ch.ctrl = nj_bctrl;
diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c
index 8324b20c7f16..03fb4a34fd53 100644
--- a/drivers/isdn/hardware/mISDN/w6692.c
+++ b/drivers/isdn/hardware/mISDN/w6692.c
@@ -688,7 +688,7 @@ W6692B_interrupt(struct w6692_hw *card, int ch)
688 if (count == 0) 688 if (count == 0)
689 count = W_B_FIFO_THRESH; 689 count = W_B_FIFO_THRESH;
690 W6692_empty_Bfifo(wch, count); 690 W6692_empty_Bfifo(wch, count);
691 recv_Bchannel(&wch->bch, 0); 691 recv_Bchannel(&wch->bch, 0, false);
692 } 692 }
693 } 693 }
694 if (stat & W_B_EXI_RMR) { 694 if (stat & W_B_EXI_RMR) {
@@ -704,9 +704,8 @@ W6692B_interrupt(struct w6692_hw *card, int ch)
704 W_B_CMDR_RRST | W_B_CMDR_RACT); 704 W_B_CMDR_RRST | W_B_CMDR_RACT);
705 } else { 705 } else {
706 W6692_empty_Bfifo(wch, W_B_FIFO_THRESH); 706 W6692_empty_Bfifo(wch, W_B_FIFO_THRESH);
707 if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags) && 707 if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
708 wch->bch.rx_skb && (wch->bch.rx_skb->len > 0)) 708 recv_Bchannel(&wch->bch, 0, false);
709 recv_Bchannel(&wch->bch, 0);
710 } 709 }
711 } 710 }
712 if (stat & W_B_EXI_RDOV) { 711 if (stat & W_B_EXI_RDOV) {
@@ -979,20 +978,7 @@ w6692_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
979static int 978static int
980channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) 979channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
981{ 980{
982 int ret = 0; 981 return mISDN_ctrl_bchannel(bch, cq);
983
984 switch (cq->op) {
985 case MISDN_CTRL_GETOP:
986 cq->op = 0;
987 break;
988 /* Nothing implemented yet */
989 case MISDN_CTRL_FILL_EMPTY:
990 default:
991 pr_info("%s: unknown Op %x\n", __func__, cq->op);
992 ret = -EINVAL;
993 break;
994 }
995 return ret;
996} 982}
997 983
998static int 984static int
@@ -1303,7 +1289,8 @@ setup_instance(struct w6692_hw *card)
1303 card->dch.hw = card; 1289 card->dch.hw = card;
1304 card->dch.dev.nrbchan = 2; 1290 card->dch.dev.nrbchan = 2;
1305 for (i = 0; i < 2; i++) { 1291 for (i = 0; i < 2; i++) {
1306 mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM); 1292 mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM,
1293 W_B_FIFO_THRESH);
1307 card->bc[i].bch.hw = card; 1294 card->bc[i].bch.hw = card;
1308 card->bc[i].bch.nr = i + 1; 1295 card->bc[i].bch.nr = i + 1;
1309 card->bc[i].bch.ch.nr = i + 1; 1296 card->bc[i].bch.ch.nr = i + 1;
diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c
index 3c2145d8c3f8..d42ad0e98de3 100644
--- a/drivers/isdn/mISDN/hwchannel.c
+++ b/drivers/isdn/mISDN/hwchannel.c
@@ -81,10 +81,16 @@ mISDN_initdchannel(struct dchannel *ch, int maxlen, void *phf)
81EXPORT_SYMBOL(mISDN_initdchannel); 81EXPORT_SYMBOL(mISDN_initdchannel);
82 82
83int 83int
84mISDN_initbchannel(struct bchannel *ch, int maxlen) 84mISDN_initbchannel(struct bchannel *ch, unsigned short maxlen,
85 unsigned short minlen)
85{ 86{
86 ch->Flags = 0; 87 ch->Flags = 0;
88 ch->minlen = minlen;
89 ch->next_minlen = minlen;
90 ch->init_minlen = minlen;
87 ch->maxlen = maxlen; 91 ch->maxlen = maxlen;
92 ch->next_maxlen = maxlen;
93 ch->init_maxlen = maxlen;
88 ch->hw = NULL; 94 ch->hw = NULL;
89 ch->rx_skb = NULL; 95 ch->rx_skb = NULL;
90 ch->tx_skb = NULL; 96 ch->tx_skb = NULL;
@@ -134,6 +140,10 @@ mISDN_clear_bchannel(struct bchannel *ch)
134 test_and_clear_bit(FLG_TX_BUSY, &ch->Flags); 140 test_and_clear_bit(FLG_TX_BUSY, &ch->Flags);
135 test_and_clear_bit(FLG_TX_NEXT, &ch->Flags); 141 test_and_clear_bit(FLG_TX_NEXT, &ch->Flags);
136 test_and_clear_bit(FLG_ACTIVE, &ch->Flags); 142 test_and_clear_bit(FLG_ACTIVE, &ch->Flags);
143 ch->minlen = ch->init_minlen;
144 ch->next_minlen = ch->init_minlen;
145 ch->maxlen = ch->init_maxlen;
146 ch->next_maxlen = ch->init_maxlen;
137} 147}
138EXPORT_SYMBOL(mISDN_clear_bchannel); 148EXPORT_SYMBOL(mISDN_clear_bchannel);
139 149
@@ -148,6 +158,33 @@ mISDN_freebchannel(struct bchannel *ch)
148} 158}
149EXPORT_SYMBOL(mISDN_freebchannel); 159EXPORT_SYMBOL(mISDN_freebchannel);
150 160
161int
162mISDN_ctrl_bchannel(struct bchannel *bch, struct mISDN_ctrl_req *cq)
163{
164 int ret = 0;
165
166 switch (cq->op) {
167 case MISDN_CTRL_GETOP:
168 cq->op = MISDN_CTRL_RX_BUFFER;
169 break;
170 case MISDN_CTRL_RX_BUFFER:
171 if (cq->p2 > MISDN_CTRL_RX_SIZE_IGNORE)
172 bch->next_maxlen = cq->p2;
173 if (cq->p1 > MISDN_CTRL_RX_SIZE_IGNORE)
174 bch->next_minlen = cq->p1;
175 /* we return the old values */
176 cq->p1 = bch->minlen;
177 cq->p2 = bch->maxlen;
178 break;
179 default:
180 pr_info("mISDN unhandled control %x operation\n", cq->op);
181 ret = -EINVAL;
182 break;
183 }
184 return ret;
185}
186EXPORT_SYMBOL(mISDN_ctrl_bchannel);
187
151static inline u_int 188static inline u_int
152get_sapi_tei(u_char *p) 189get_sapi_tei(u_char *p)
153{ 190{
@@ -197,7 +234,7 @@ recv_Echannel(struct dchannel *ech, struct dchannel *dch)
197EXPORT_SYMBOL(recv_Echannel); 234EXPORT_SYMBOL(recv_Echannel);
198 235
199void 236void
200recv_Bchannel(struct bchannel *bch, unsigned int id) 237recv_Bchannel(struct bchannel *bch, unsigned int id, bool force)
201{ 238{
202 struct mISDNhead *hh; 239 struct mISDNhead *hh;
203 240
@@ -211,6 +248,9 @@ recv_Bchannel(struct bchannel *bch, unsigned int id)
211 dev_kfree_skb(bch->rx_skb); 248 dev_kfree_skb(bch->rx_skb);
212 bch->rx_skb = NULL; 249 bch->rx_skb = NULL;
213 } else { 250 } else {
251 if (test_bit(FLG_TRANSPARENT, &bch->Flags) &&
252 (bch->rx_skb->len < bch->minlen) && !force)
253 return;
214 hh = mISDN_HEAD_P(bch->rx_skb); 254 hh = mISDN_HEAD_P(bch->rx_skb);
215 hh->prim = PH_DATA_IND; 255 hh->prim = PH_DATA_IND;
216 hh->id = id; 256 hh->id = id;
@@ -426,7 +466,7 @@ bchannel_get_rxbuf(struct bchannel *bch, int reqlen)
426 bch->nr, reqlen, len); 466 bch->nr, reqlen, len);
427 if (test_bit(FLG_TRANSPARENT, &bch->Flags)) { 467 if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
428 /* send what we have now and try a new buffer */ 468 /* send what we have now and try a new buffer */
429 recv_Bchannel(bch, 0); 469 recv_Bchannel(bch, 0, true);
430 } else { 470 } else {
431 /* on HDLC we have to drop too big frames */ 471 /* on HDLC we have to drop too big frames */
432 return -EMSGSIZE; 472 return -EMSGSIZE;
@@ -435,12 +475,25 @@ bchannel_get_rxbuf(struct bchannel *bch, int reqlen)
435 return len; 475 return len;
436 } 476 }
437 } 477 }
478 /* update current min/max length first */
479 if (unlikely(bch->maxlen != bch->next_maxlen))
480 bch->maxlen = bch->next_maxlen;
481 if (unlikely(bch->minlen != bch->next_minlen))
482 bch->minlen = bch->next_minlen;
438 if (unlikely(reqlen > bch->maxlen)) 483 if (unlikely(reqlen > bch->maxlen))
439 return -EMSGSIZE; 484 return -EMSGSIZE;
440 if (test_bit(FLG_TRANSPARENT, &bch->Flags)) 485 if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
441 len = reqlen; 486 if (reqlen >= bch->minlen) {
442 else /* with HDLC we do not know the length yet */ 487 len = reqlen;
488 } else {
489 len = 2 * bch->minlen;
490 if (len > bch->maxlen)
491 len = bch->maxlen;
492 }
493 } else {
494 /* with HDLC we do not know the length yet */
443 len = bch->maxlen; 495 len = bch->maxlen;
496 }
444 bch->rx_skb = mI_alloc_skb(len, GFP_ATOMIC); 497 bch->rx_skb = mI_alloc_skb(len, GFP_ATOMIC);
445 if (!bch->rx_skb) { 498 if (!bch->rx_skb) {
446 pr_warning("B%d receive no memory for %d bytes\n", 499 pr_warning("B%d receive no memory for %d bytes\n",
diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c
index 0f88acf1185f..db50f788855d 100644
--- a/drivers/isdn/mISDN/l1oip_core.c
+++ b/drivers/isdn/mISDN/l1oip_core.c
@@ -1420,7 +1420,7 @@ init_card(struct l1oip *hc, int pri, int bundle)
1420 bch->nr = i + ch; 1420 bch->nr = i + ch;
1421 bch->slot = i + ch; 1421 bch->slot = i + ch;
1422 bch->debug = debug; 1422 bch->debug = debug;
1423 mISDN_initbchannel(bch, MAX_DATA_MEM); 1423 mISDN_initbchannel(bch, MAX_DATA_MEM, 0);
1424 bch->hw = hc; 1424 bch->hw = hc;
1425 bch->ch.send = handle_bmsg; 1425 bch->ch.send = handle_bmsg;
1426 bch->ch.ctrl = l1oip_bctrl; 1426 bch->ch.ctrl = l1oip_bctrl;