summaryrefslogtreecommitdiffstats
path: root/drivers/isdn/hardware/mISDN/hfcsusb.c
diff options
context:
space:
mode:
authorKarsten Keil <kkeil@linux-pingi.de>2012-05-15 23:51:05 +0000
committerDavid S. Miller <davem@davemloft.net>2012-05-16 15:23:28 -0400
commit7206e659f689558b41aa058c3040b081cb281d03 (patch)
tree2be5bdef5a0bbb9c5763b8c1b1e6fe04b7184cc5 /drivers/isdn/hardware/mISDN/hfcsusb.c
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/hardware/mISDN/hfcsusb.c')
-rw-r--r--drivers/isdn/hardware/mISDN/hfcsusb.c52
1 files changed, 24 insertions, 28 deletions
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c
index 919ecccb993..6bb689b8d66 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,
hdlc = 1;
}
if (fifo->bch) {
+ maxlen = bchannel_get_rxbuf(fifo->bch, len);
rx_skb = fifo->bch->rx_skb;
+ if (maxlen < 0) {
+ if (rx_skb)
+ skb_trim(rx_skb, 0);
+ pr_warning("%s.B%d: No bufferspace for %d bytes\n",
+ hw->name, fifo->bch->nr, len);
+ spin_unlock(&hw->lock);
+ return;
+ }
maxlen = fifo->bch->maxlen;
hdlc = test_bit(FLG_HDLC, &fifo->bch->Flags);
}
@@ -870,25 +879,22 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
hdlc = 1;
}
- if (!rx_skb) {
- rx_skb = mI_alloc_skb(maxlen, GFP_ATOMIC);
- if (rx_skb) {
- if (fifo->dch)
- fifo->dch->rx_skb = rx_skb;
- if (fifo->bch)
- fifo->bch->rx_skb = rx_skb;
- if (fifo->ech)
- fifo->ech->rx_skb = rx_skb;
- skb_trim(rx_skb, 0);
- } else {
- printk(KERN_DEBUG "%s: %s: No mem for rx_skb\n",
- hw->name, __func__);
- spin_unlock(&hw->lock);
- return;
- }
- }
-
if (fifo->dch || fifo->ech) {
+ if (!rx_skb) {
+ rx_skb = mI_alloc_skb(maxlen, GFP_ATOMIC);
+ if (rx_skb) {
+ if (fifo->dch)
+ fifo->dch->rx_skb = rx_skb;
+ if (fifo->ech)
+ fifo->ech->rx_skb = rx_skb;
+ skb_trim(rx_skb, 0);
+ } else {
+ printk(KERN_DEBUG "%s: %s: No mem for rx_skb\n",
+ hw->name, __func__);
+ spin_unlock(&hw->lock);
+ return;
+ }
+ }
/* D/E-Channel SKB range check */
if ((rx_skb->len + len) >= MAX_DFRAME_LEN_L1) {
printk(KERN_DEBUG "%s: %s: sbk mem exceeded "
@@ -898,16 +904,6 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
spin_unlock(&hw->lock);
return;
}
- } else if (fifo->bch) {
- /* B-Channel SKB range check */
- if ((rx_skb->len + len) >= (MAX_BCH_SIZE + 3)) {
- printk(KERN_DEBUG "%s: %s: sbk mem exceeded "
- "for fifo(%d) HFCUSB_B_RX\n",
- hw->name, __func__, fifon);
- skb_trim(rx_skb, 0);
- spin_unlock(&hw->lock);
- return;
- }
}
memcpy(skb_put(rx_skb, len), data, len);