aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn
diff options
context:
space:
mode:
authorKarsten Keil <kkeil@linux-pingi.de>2012-05-15 19:51:05 -0400
committerDavid S. Miller <davem@davemloft.net>2012-05-16 15:23:28 -0400
commit7206e659f689558b41aa058c3040b081cb281d03 (patch)
tree2be5bdef5a0bbb9c5763b8c1b1e6fe04b7184cc5 /drivers/isdn
parent37952cfa3afdfa5cec39d9d76e80bc3a0e6a910c (diff)
mISDN: Reduce RX buffer allocation for transparent data
We did allways allocate maxsize buffers, but for transparent data we know the actual size. Use a common function to calculate size and detect overflows. 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.c18
-rw-r--r--drivers/isdn/hardware/mISDN/hfcmulti.c61
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c11
-rw-r--r--drivers/isdn/hardware/mISDN/hfcsusb.c52
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNipac.c20
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNisar.c37
-rw-r--r--drivers/isdn/hardware/mISDN/netjet.c79
-rw-r--r--drivers/isdn/hardware/mISDN/w6692.c20
-rw-r--r--drivers/isdn/mISDN/hwchannel.c75
9 files changed, 185 insertions, 188 deletions
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c
index cc782646886c..808136735f32 100644
--- a/drivers/isdn/hardware/mISDN/avmfritz.c
+++ b/drivers/isdn/hardware/mISDN/avmfritz.c
@@ -404,21 +404,14 @@ hdlc_empty_fifo(struct bchannel *bch, int count)
404 u32 *ptr; 404 u32 *ptr;
405 u8 *p; 405 u8 *p;
406 u32 val, addr; 406 u32 val, addr;
407 int cnt = 0; 407 int cnt;
408 struct fritzcard *fc = bch->hw; 408 struct fritzcard *fc = bch->hw;
409 409
410 pr_debug("%s: %s %d\n", fc->name, __func__, count); 410 pr_debug("%s: %s %d\n", fc->name, __func__, count);
411 if (!bch->rx_skb) { 411 cnt = bchannel_get_rxbuf(bch, count);
412 bch->rx_skb = mI_alloc_skb(bch->maxlen, GFP_ATOMIC); 412 if (cnt < 0) {
413 if (!bch->rx_skb) { 413 pr_warning("%s.B%d: No bufferspace for %d bytes\n",
414 pr_info("%s: B receive out of memory\n", 414 fc->name, bch->nr, count);
415 fc->name);
416 return;
417 }
418 }
419 if ((bch->rx_skb->len + count) > bch->maxlen) {
420 pr_debug("%s: overrun %d\n", fc->name,
421 bch->rx_skb->len + count);
422 return; 415 return;
423 } 416 }
424 p = skb_put(bch->rx_skb, count); 417 p = skb_put(bch->rx_skb, count);
@@ -430,6 +423,7 @@ hdlc_empty_fifo(struct bchannel *bch, int count)
430 addr = fc->addr + CHIP_WINDOW; 423 addr = fc->addr + CHIP_WINDOW;
431 outl(bch->nr == 2 ? AVM_HDLC_2 : AVM_HDLC_1, fc->addr); 424 outl(bch->nr == 2 ? AVM_HDLC_2 : AVM_HDLC_1, fc->addr);
432 } 425 }
426 cnt = 0;
433 while (cnt < count) { 427 while (cnt < count) {
434 val = le32_to_cpu(inl(addr)); 428 val = le32_to_cpu(inl(addr));
435 put_unaligned(val, ptr); 429 put_unaligned(val, ptr);
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index ab3d2983e3ad..60dd6efa1879 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -2196,24 +2196,20 @@ hfcmulti_rx(struct hfc_multi *hc, int ch)
2196 int f1 = 0, f2 = 0; /* = 0, to make GCC happy */ 2196 int f1 = 0, f2 = 0; /* = 0, to make GCC happy */
2197 int again = 0; 2197 int again = 0;
2198 struct bchannel *bch; 2198 struct bchannel *bch;
2199 struct dchannel *dch; 2199 struct dchannel *dch = NULL;
2200 struct sk_buff *skb, **sp = NULL; 2200 struct sk_buff *skb, **sp = NULL;
2201 int maxlen; 2201 int maxlen;
2202 2202
2203 bch = hc->chan[ch].bch; 2203 bch = hc->chan[ch].bch;
2204 dch = hc->chan[ch].dch; 2204 if (bch) {
2205 if ((!dch) && (!bch)) 2205 if (!test_bit(FLG_ACTIVE, &bch->Flags))
2206 return; 2206 return;
2207 if (dch) { 2207 } else if (hc->chan[ch].dch) {
2208 dch = hc->chan[ch].dch;
2208 if (!test_bit(FLG_ACTIVE, &dch->Flags)) 2209 if (!test_bit(FLG_ACTIVE, &dch->Flags))
2209 return; 2210 return;
2210 sp = &dch->rx_skb;
2211 maxlen = dch->maxlen;
2212 } else { 2211 } else {
2213 if (!test_bit(FLG_ACTIVE, &bch->Flags)) 2212 return;
2214 return;
2215 sp = &bch->rx_skb;
2216 maxlen = bch->maxlen;
2217 } 2213 }
2218next_frame: 2214next_frame:
2219 /* on first AND before getting next valid frame, R_FIFO must be written 2215 /* on first AND before getting next valid frame, R_FIFO must be written
@@ -2260,13 +2256,26 @@ next_frame:
2260 if (Zsize <= 0) 2256 if (Zsize <= 0)
2261 return; 2257 return;
2262 2258
2263 if (*sp == NULL) { 2259 if (bch) {
2264 *sp = mI_alloc_skb(maxlen + 3, GFP_ATOMIC); 2260 maxlen = bchannel_get_rxbuf(bch, Zsize);
2265 if (*sp == NULL) { 2261 if (maxlen < 0) {
2266 printk(KERN_DEBUG "%s: No mem for rx_skb\n", 2262 pr_warning("card%d.B%d: No bufferspace for %d bytes\n",
2267 __func__); 2263 hc->id + 1, bch->nr, Zsize);
2268 return; 2264 return;
2269 } 2265 }
2266 sp = &bch->rx_skb;
2267 maxlen = bch->maxlen;
2268 } else { /* Dchannel */
2269 sp = &dch->rx_skb;
2270 maxlen = dch->maxlen + 3;
2271 if (*sp == NULL) {
2272 *sp = mI_alloc_skb(maxlen, GFP_ATOMIC);
2273 if (*sp == NULL) {
2274 pr_warning("card%d: No mem for dch rx_skb\n",
2275 hc->id + 1);
2276 return;
2277 }
2278 }
2270 } 2279 }
2271 /* show activity */ 2280 /* show activity */
2272 if (dch) 2281 if (dch)
@@ -2281,7 +2290,7 @@ next_frame:
2281 Zsize, z1, z2, (f1 == f2) ? "fragment" : "COMPLETE", 2290 Zsize, z1, z2, (f1 == f2) ? "fragment" : "COMPLETE",
2282 f1, f2, Zsize + (*sp)->len, again); 2291 f1, f2, Zsize + (*sp)->len, again);
2283 /* HDLC */ 2292 /* HDLC */
2284 if ((Zsize + (*sp)->len) > (maxlen + 3)) { 2293 if ((Zsize + (*sp)->len) > maxlen) {
2285 if (debug & DEBUG_HFCMULTI_FIFO) 2294 if (debug & DEBUG_HFCMULTI_FIFO)
2286 printk(KERN_DEBUG 2295 printk(KERN_DEBUG
2287 "%s(card %d): hdlc-frame too large.\n", 2296 "%s(card %d): hdlc-frame too large.\n",
@@ -2351,24 +2360,7 @@ next_frame:
2351 /* there is an incomplete frame */ 2360 /* there is an incomplete frame */
2352 } else { 2361 } else {
2353 /* transparent */ 2362 /* transparent */
2354 if (Zsize > skb_tailroom(*sp))
2355 Zsize = skb_tailroom(*sp);
2356 hc->read_fifo(hc, skb_put(*sp, Zsize), Zsize); 2363 hc->read_fifo(hc, skb_put(*sp, Zsize), Zsize);
2357 if (((*sp)->len) < MISDN_COPY_SIZE) {
2358 skb = *sp;
2359 *sp = mI_alloc_skb(skb->len, GFP_ATOMIC);
2360 if (*sp) {
2361 memcpy(skb_put(*sp, skb->len),
2362 skb->data, skb->len);
2363 skb_trim(skb, 0);
2364 } else {
2365 printk(KERN_DEBUG "%s: No mem\n", __func__);
2366 *sp = skb;
2367 skb = NULL;
2368 }
2369 } else {
2370 skb = NULL;
2371 }
2372 if (debug & DEBUG_HFCMULTI_FIFO) 2364 if (debug & DEBUG_HFCMULTI_FIFO)
2373 printk(KERN_DEBUG 2365 printk(KERN_DEBUG
2374 "%s(card %d): fifo(%d) reading %d bytes " 2366 "%s(card %d): fifo(%d) reading %d bytes "
@@ -2376,7 +2368,6 @@ next_frame:
2376 __func__, hc->id + 1, ch, Zsize, z1, z2); 2368 __func__, hc->id + 1, ch, Zsize, z1, z2);
2377 /* only bch is transparent */ 2369 /* only bch is transparent */
2378 recv_Bchannel(bch, hc->chan[ch].Zfill); 2370 recv_Bchannel(bch, hc->chan[ch].Zfill);
2379 *sp = skb;
2380 } 2371 }
2381} 2372}
2382 2373
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index 123e8e5e57be..0622e05ae066 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -577,8 +577,11 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz,
577 fcnt_tx = B_FIFO_SIZE - fcnt_tx; 577 fcnt_tx = B_FIFO_SIZE - fcnt_tx;
578 /* remaining bytes to send (bytes in tx-fifo) */ 578 /* remaining bytes to send (bytes in tx-fifo) */
579 579
580 bch->rx_skb = mI_alloc_skb(fcnt_rx, GFP_ATOMIC); 580 maxlen = bchannel_get_rxbuf(bch, fcnt_rx);
581 if (bch->rx_skb) { 581 if (maxlen < 0) {
582 pr_warning("B%d: No bufferspace for %d bytes\n",
583 bch->nr, fcnt_rx);
584 } else {
582 ptr = skb_put(bch->rx_skb, fcnt_rx); 585 ptr = skb_put(bch->rx_skb, fcnt_rx);
583 if (le16_to_cpu(*z2r) + fcnt_rx <= B_FIFO_SIZE + B_SUB_VAL) 586 if (le16_to_cpu(*z2r) + fcnt_rx <= B_FIFO_SIZE + B_SUB_VAL)
584 maxlen = fcnt_rx; /* complete transfer */ 587 maxlen = fcnt_rx; /* complete transfer */
@@ -597,9 +600,7 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz,
597 memcpy(ptr, ptr1, fcnt_rx); /* rest */ 600 memcpy(ptr, ptr1, fcnt_rx); /* rest */
598 } 601 }
599 recv_Bchannel(bch, fcnt_tx); /* bch, id */ 602 recv_Bchannel(bch, fcnt_tx); /* bch, id */
600 } else 603 }
601 printk(KERN_WARNING "HFCPCI: receive out of memory\n");
602
603 *z2r = cpu_to_le16(new_z2); /* new position */ 604 *z2r = cpu_to_le16(new_z2); /* new position */
604} 605}
605 606
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c
index 919ecccb9939..6bb689b8d66f 100644
--- a/drivers/isdn/hardware/mISDN/hfcsusb.c
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -860,7 +860,16 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
860 hdlc = 1; 860 hdlc = 1;
861 } 861 }
862 if (fifo->bch) { 862 if (fifo->bch) {
863 maxlen = bchannel_get_rxbuf(fifo->bch, len);
863 rx_skb = fifo->bch->rx_skb; 864 rx_skb = fifo->bch->rx_skb;
865 if (maxlen < 0) {
866 if (rx_skb)
867 skb_trim(rx_skb, 0);
868 pr_warning("%s.B%d: No bufferspace for %d bytes\n",
869 hw->name, fifo->bch->nr, len);
870 spin_unlock(&hw->lock);
871 return;
872 }
864 maxlen = fifo->bch->maxlen; 873 maxlen = fifo->bch->maxlen;
865 hdlc = test_bit(FLG_HDLC, &fifo->bch->Flags); 874 hdlc = test_bit(FLG_HDLC, &fifo->bch->Flags);
866 } 875 }
@@ -870,25 +879,22 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
870 hdlc = 1; 879 hdlc = 1;
871 } 880 }
872 881
873 if (!rx_skb) {
874 rx_skb = mI_alloc_skb(maxlen, GFP_ATOMIC);
875 if (rx_skb) {
876 if (fifo->dch)
877 fifo->dch->rx_skb = rx_skb;
878 if (fifo->bch)
879 fifo->bch->rx_skb = rx_skb;
880 if (fifo->ech)
881 fifo->ech->rx_skb = rx_skb;
882 skb_trim(rx_skb, 0);
883 } else {
884 printk(KERN_DEBUG "%s: %s: No mem for rx_skb\n",
885 hw->name, __func__);
886 spin_unlock(&hw->lock);
887 return;
888 }
889 }
890
891 if (fifo->dch || fifo->ech) { 882 if (fifo->dch || fifo->ech) {
883 if (!rx_skb) {
884 rx_skb = mI_alloc_skb(maxlen, GFP_ATOMIC);
885 if (rx_skb) {
886 if (fifo->dch)
887 fifo->dch->rx_skb = rx_skb;
888 if (fifo->ech)
889 fifo->ech->rx_skb = rx_skb;
890 skb_trim(rx_skb, 0);
891 } else {
892 printk(KERN_DEBUG "%s: %s: No mem for rx_skb\n",
893 hw->name, __func__);
894 spin_unlock(&hw->lock);
895 return;
896 }
897 }
892 /* D/E-Channel SKB range check */ 898 /* D/E-Channel SKB range check */
893 if ((rx_skb->len + len) >= MAX_DFRAME_LEN_L1) { 899 if ((rx_skb->len + len) >= MAX_DFRAME_LEN_L1) {
894 printk(KERN_DEBUG "%s: %s: sbk mem exceeded " 900 printk(KERN_DEBUG "%s: %s: sbk mem exceeded "
@@ -898,16 +904,6 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
898 spin_unlock(&hw->lock); 904 spin_unlock(&hw->lock);
899 return; 905 return;
900 } 906 }
901 } else if (fifo->bch) {
902 /* B-Channel SKB range check */
903 if ((rx_skb->len + len) >= (MAX_BCH_SIZE + 3)) {
904 printk(KERN_DEBUG "%s: %s: sbk mem exceeded "
905 "for fifo(%d) HFCUSB_B_RX\n",
906 hw->name, __func__, fifon);
907 skb_trim(rx_skb, 0);
908 spin_unlock(&hw->lock);
909 return;
910 }
911 } 907 }
912 908
913 memcpy(skb_put(rx_skb, len), data, len); 909 memcpy(skb_put(rx_skb, len), data, len);
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
index e4b6d8d51aae..7d109ed35366 100644
--- a/drivers/isdn/hardware/mISDN/mISDNipac.c
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -933,22 +933,16 @@ static void
933hscx_empty_fifo(struct hscx_hw *hscx, u8 count) 933hscx_empty_fifo(struct hscx_hw *hscx, u8 count)
934{ 934{
935 u8 *p; 935 u8 *p;
936 int maxlen;
936 937
937 pr_debug("%s: B%1d %d\n", hscx->ip->name, hscx->bch.nr, count); 938 pr_debug("%s: B%1d %d\n", hscx->ip->name, hscx->bch.nr, count);
938 if (!hscx->bch.rx_skb) { 939 maxlen = bchannel_get_rxbuf(&hscx->bch, count);
939 hscx->bch.rx_skb = mI_alloc_skb(hscx->bch.maxlen, GFP_ATOMIC); 940 if (maxlen < 0) {
940 if (!hscx->bch.rx_skb) {
941 pr_info("%s: B receive out of memory\n",
942 hscx->ip->name);
943 hscx_cmdr(hscx, 0x80); /* RMC */
944 return;
945 }
946 }
947 if ((hscx->bch.rx_skb->len + count) > hscx->bch.maxlen) {
948 pr_debug("%s: overrun %d\n", hscx->ip->name,
949 hscx->bch.rx_skb->len + count);
950 skb_trim(hscx->bch.rx_skb, 0);
951 hscx_cmdr(hscx, 0x80); /* RMC */ 941 hscx_cmdr(hscx, 0x80); /* RMC */
942 if (hscx->bch.rx_skb)
943 skb_trim(hscx->bch.rx_skb, 0);
944 pr_warning("%s.B%d: No bufferspace for %d bytes\n",
945 hscx->ip->name, hscx->bch.nr, count);
952 return; 946 return;
953 } 947 }
954 p = skb_put(hscx->bch.rx_skb, count); 948 p = skb_put(hscx->bch.rx_skb, count);
diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c
index 9deea88c994e..4169bb2db19c 100644
--- a/drivers/isdn/hardware/mISDN/mISDNisar.c
+++ b/drivers/isdn/hardware/mISDN/mISDNisar.c
@@ -421,7 +421,8 @@ deliver_status(struct isar_ch *ch, int status)
421static inline void 421static inline void
422isar_rcv_frame(struct isar_ch *ch) 422isar_rcv_frame(struct isar_ch *ch)
423{ 423{
424 u8 *ptr; 424 u8 *ptr;
425 int maxlen;
425 426
426 if (!ch->is->clsb) { 427 if (!ch->is->clsb) {
427 pr_debug("%s; ISAR zero len frame\n", ch->is->name); 428 pr_debug("%s; ISAR zero len frame\n", ch->is->name);
@@ -437,36 +438,22 @@ isar_rcv_frame(struct isar_ch *ch)
437 case ISDN_P_B_RAW: 438 case ISDN_P_B_RAW:
438 case ISDN_P_B_L2DTMF: 439 case ISDN_P_B_L2DTMF:
439 case ISDN_P_B_MODEM_ASYNC: 440 case ISDN_P_B_MODEM_ASYNC:
440 if (!ch->bch.rx_skb) { 441 maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb);
441 ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen, 442 if (maxlen < 0) {
442 GFP_ATOMIC); 443 pr_warning("%s.B%d: No bufferspace for %d bytes\n",
443 if (unlikely(!ch->bch.rx_skb)) { 444 ch->is->name, ch->bch.nr, ch->is->clsb);
444 pr_info("%s: B receive out of memory\n", 445 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
445 ch->is->name); 446 break;
446 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
447 break;
448 }
449 } 447 }
450 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));
451 recv_Bchannel(&ch->bch, 0); 449 recv_Bchannel(&ch->bch, 0);
452 break; 450 break;
453 case ISDN_P_B_HDLC: 451 case ISDN_P_B_HDLC:
454 if (!ch->bch.rx_skb) { 452 maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb);
455 ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen, 453 if (maxlen < 0) {
456 GFP_ATOMIC); 454 pr_warning("%s.B%d: No bufferspace for %d bytes\n",
457 if (unlikely(!ch->bch.rx_skb)) { 455 ch->is->name, ch->bch.nr, ch->is->clsb);
458 pr_info("%s: B receive out of memory\n",
459 ch->is->name);
460 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
461 break;
462 }
463 }
464 if ((ch->bch.rx_skb->len + ch->is->clsb) >
465 (ch->bch.maxlen + 2)) {
466 pr_debug("%s: incoming packet too large\n",
467 ch->is->name);
468 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); 456 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
469 skb_trim(ch->bch.rx_skb, 0);
470 break; 457 break;
471 } 458 }
472 if (ch->is->cmsb & HDLC_ERROR) { 459 if (ch->is->cmsb & HDLC_ERROR) {
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c
index da13b07cd856..3f28057e725e 100644
--- a/drivers/isdn/hardware/mISDN/netjet.c
+++ b/drivers/isdn/hardware/mISDN/netjet.c
@@ -386,24 +386,16 @@ read_dma(struct tiger_ch *bc, u32 idx, int cnt)
386 bc->bch.nr, idx); 386 bc->bch.nr, idx);
387 } 387 }
388 bc->lastrx = idx; 388 bc->lastrx = idx;
389 if (!bc->bch.rx_skb) { 389 stat = bchannel_get_rxbuf(&bc->bch, cnt);
390 bc->bch.rx_skb = mI_alloc_skb(bc->bch.maxlen, GFP_ATOMIC); 390 /* only transparent use the count here, HDLC overun is detected later */
391 if (!bc->bch.rx_skb) { 391 if (stat == ENOMEM) {
392 pr_info("%s: B%1d receive out of memory\n", 392 pr_warning("%s.B%d: No memory for %d bytes\n",
393 card->name, bc->bch.nr); 393 card->name, bc->bch.nr, cnt);
394 return; 394 return;
395 }
396 } 395 }
397 396 if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags))
398 if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) {
399 if ((bc->bch.rx_skb->len + cnt) > bc->bch.maxlen) {
400 pr_debug("%s: B%1d overrun %d\n", card->name,
401 bc->bch.nr, bc->bch.rx_skb->len + cnt);
402 skb_trim(bc->bch.rx_skb, 0);
403 return;
404 }
405 p = skb_put(bc->bch.rx_skb, cnt); 397 p = skb_put(bc->bch.rx_skb, cnt);
406 } else 398 else
407 p = bc->hrbuf; 399 p = bc->hrbuf;
408 400
409 for (i = 0; i < cnt; i++) { 401 for (i = 0; i < cnt; i++) {
@@ -414,48 +406,45 @@ read_dma(struct tiger_ch *bc, u32 idx, int cnt)
414 idx = 0; 406 idx = 0;
415 p[i] = val & 0xff; 407 p[i] = val & 0xff;
416 } 408 }
409
410 if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) {
411 recv_Bchannel(&bc->bch, 0);
412 return;
413 }
414
417 pn = bc->hrbuf; 415 pn = bc->hrbuf;
418next_frame: 416 while (cnt > 0) {
419 if (test_bit(FLG_HDLC, &bc->bch.Flags)) {
420 stat = isdnhdlc_decode(&bc->hrecv, pn, cnt, &i, 417 stat = isdnhdlc_decode(&bc->hrecv, pn, cnt, &i,
421 bc->bch.rx_skb->data, bc->bch.maxlen); 418 bc->bch.rx_skb->data, bc->bch.maxlen);
422 if (stat > 0) /* valid frame received */ 419 if (stat > 0) { /* valid frame received */
423 p = skb_put(bc->bch.rx_skb, stat); 420 p = skb_put(bc->bch.rx_skb, stat);
424 else if (stat == -HDLC_CRC_ERROR) 421 if (debug & DEBUG_HW_BFIFO) {
422 snprintf(card->log, LOG_SIZE,
423 "B%1d-recv %s %d ", bc->bch.nr,
424 card->name, stat);
425 print_hex_dump_bytes(card->log,
426 DUMP_PREFIX_OFFSET, p,
427 stat);
428 }
429 recv_Bchannel(&bc->bch, 0);
430 stat = bchannel_get_rxbuf(&bc->bch, bc->bch.maxlen);
431 if (stat < 0) {
432 pr_warning("%s.B%d: No memory for %d bytes\n",
433 card->name, bc->bch.nr, cnt);
434 return;
435 }
436 } else if (stat == -HDLC_CRC_ERROR) {
425 pr_info("%s: B%1d receive frame CRC error\n", 437 pr_info("%s: B%1d receive frame CRC error\n",
426 card->name, bc->bch.nr); 438 card->name, bc->bch.nr);
427 else if (stat == -HDLC_FRAMING_ERROR) 439 } else if (stat == -HDLC_FRAMING_ERROR) {
428 pr_info("%s: B%1d receive framing error\n", 440 pr_info("%s: B%1d receive framing error\n",
429 card->name, bc->bch.nr); 441 card->name, bc->bch.nr);
430 else if (stat == -HDLC_LENGTH_ERROR) 442 } else if (stat == -HDLC_LENGTH_ERROR) {
431 pr_info("%s: B%1d receive frame too long (> %d)\n", 443 pr_info("%s: B%1d receive frame too long (> %d)\n",
432 card->name, bc->bch.nr, bc->bch.maxlen); 444 card->name, bc->bch.nr, bc->bch.maxlen);
433 } else
434 stat = cnt;
435
436 if (stat > 0) {
437 if (debug & DEBUG_HW_BFIFO) {
438 snprintf(card->log, LOG_SIZE, "B%1d-recv %s %d ",
439 bc->bch.nr, card->name, stat);
440 print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET,
441 p, stat);
442 } 445 }
443 recv_Bchannel(&bc->bch, 0);
444 }
445 if (test_bit(FLG_HDLC, &bc->bch.Flags)) {
446 pn += i; 446 pn += i;
447 cnt -= i; 447 cnt -= i;
448 if (!bc->bch.rx_skb) {
449 bc->bch.rx_skb = mI_alloc_skb(bc->bch.maxlen,
450 GFP_ATOMIC);
451 if (!bc->bch.rx_skb) {
452 pr_info("%s: B%1d receive out of memory\n",
453 card->name, bc->bch.nr);
454 return;
455 }
456 }
457 if (cnt > 0)
458 goto next_frame;
459 } 448 }
460} 449}
461 450
diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c
index f1c0bf1ac689..8324b20c7f16 100644
--- a/drivers/isdn/hardware/mISDN/w6692.c
+++ b/drivers/isdn/hardware/mISDN/w6692.c
@@ -465,6 +465,7 @@ W6692_empty_Bfifo(struct w6692_ch *wch, int count)
465{ 465{
466 struct w6692_hw *card = wch->bch.hw; 466 struct w6692_hw *card = wch->bch.hw;
467 u8 *ptr; 467 u8 *ptr;
468 int maxlen;
468 469
469 pr_debug("%s: empty_Bfifo %d\n", card->name, count); 470 pr_debug("%s: empty_Bfifo %d\n", card->name, count);
470 if (unlikely(wch->bch.state == ISDN_P_NONE)) { 471 if (unlikely(wch->bch.state == ISDN_P_NONE)) {
@@ -474,20 +475,13 @@ W6692_empty_Bfifo(struct w6692_ch *wch, int count)
474 skb_trim(wch->bch.rx_skb, 0); 475 skb_trim(wch->bch.rx_skb, 0);
475 return; 476 return;
476 } 477 }
477 if (!wch->bch.rx_skb) { 478 maxlen = bchannel_get_rxbuf(&wch->bch, count);
478 wch->bch.rx_skb = mI_alloc_skb(wch->bch.maxlen, GFP_ATOMIC); 479 if (maxlen < 0) {
479 if (unlikely(!wch->bch.rx_skb)) {
480 pr_info("%s: B receive out of memory\n", card->name);
481 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK |
482 W_B_CMDR_RACT);
483 return;
484 }
485 }
486 if (wch->bch.rx_skb->len + count > wch->bch.maxlen) {
487 pr_debug("%s: empty_Bfifo incoming packet too large\n",
488 card->name);
489 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); 480 WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
490 skb_trim(wch->bch.rx_skb, 0); 481 if (wch->bch.rx_skb)
482 skb_trim(wch->bch.rx_skb, 0);
483 pr_warning("%s.B%d: No bufferspace for %d bytes\n",
484 card->name, wch->bch.nr, count);
491 return; 485 return;
492 } 486 }
493 ptr = skb_put(wch->bch.rx_skb, count); 487 ptr = skb_put(wch->bch.rx_skb, count);
diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c
index 5c5ab478f66a..3c2145d8c3f8 100644
--- a/drivers/isdn/mISDN/hwchannel.c
+++ b/drivers/isdn/mISDN/hwchannel.c
@@ -201,20 +201,30 @@ recv_Bchannel(struct bchannel *bch, unsigned int id)
201{ 201{
202 struct mISDNhead *hh; 202 struct mISDNhead *hh;
203 203
204 hh = mISDN_HEAD_P(bch->rx_skb); 204 /* if allocation did fail upper functions still may call us */
205 hh->prim = PH_DATA_IND; 205 if (unlikely(!bch->rx_skb))
206 hh->id = id;
207 if (bch->rcount >= 64) {
208 printk(KERN_WARNING "B-channel %p receive queue overflow, "
209 "flushing!\n", bch);
210 skb_queue_purge(&bch->rqueue);
211 bch->rcount = 0;
212 return; 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);
213 } 227 }
214 bch->rcount++;
215 skb_queue_tail(&bch->rqueue, bch->rx_skb);
216 bch->rx_skb = NULL;
217 schedule_event(bch, FLG_RECVQUEUE);
218} 228}
219EXPORT_SYMBOL(recv_Bchannel); 229EXPORT_SYMBOL(recv_Bchannel);
220 230
@@ -399,3 +409,44 @@ bchannel_senddata(struct bchannel *ch, struct sk_buff *skb)
399 } 409 }
400} 410}
401EXPORT_SYMBOL(bchannel_senddata); 411EXPORT_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 */
417int
418bchannel_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}
452EXPORT_SYMBOL(bchannel_get_rxbuf);