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>
This commit is contained in:
@@ -81,10 +81,16 @@ mISDN_initdchannel(struct dchannel *ch, int maxlen, void *phf)
|
||||
EXPORT_SYMBOL(mISDN_initdchannel);
|
||||
|
||||
int
|
||||
mISDN_initbchannel(struct bchannel *ch, int maxlen)
|
||||
mISDN_initbchannel(struct bchannel *ch, unsigned short maxlen,
|
||||
unsigned short minlen)
|
||||
{
|
||||
ch->Flags = 0;
|
||||
ch->minlen = minlen;
|
||||
ch->next_minlen = minlen;
|
||||
ch->init_minlen = minlen;
|
||||
ch->maxlen = maxlen;
|
||||
ch->next_maxlen = maxlen;
|
||||
ch->init_maxlen = maxlen;
|
||||
ch->hw = NULL;
|
||||
ch->rx_skb = NULL;
|
||||
ch->tx_skb = NULL;
|
||||
@@ -134,6 +140,10 @@ mISDN_clear_bchannel(struct bchannel *ch)
|
||||
test_and_clear_bit(FLG_TX_BUSY, &ch->Flags);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &ch->Flags);
|
||||
test_and_clear_bit(FLG_ACTIVE, &ch->Flags);
|
||||
ch->minlen = ch->init_minlen;
|
||||
ch->next_minlen = ch->init_minlen;
|
||||
ch->maxlen = ch->init_maxlen;
|
||||
ch->next_maxlen = ch->init_maxlen;
|
||||
}
|
||||
EXPORT_SYMBOL(mISDN_clear_bchannel);
|
||||
|
||||
@@ -148,6 +158,33 @@ mISDN_freebchannel(struct bchannel *ch)
|
||||
}
|
||||
EXPORT_SYMBOL(mISDN_freebchannel);
|
||||
|
||||
int
|
||||
mISDN_ctrl_bchannel(struct bchannel *bch, struct mISDN_ctrl_req *cq)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = MISDN_CTRL_RX_BUFFER;
|
||||
break;
|
||||
case MISDN_CTRL_RX_BUFFER:
|
||||
if (cq->p2 > MISDN_CTRL_RX_SIZE_IGNORE)
|
||||
bch->next_maxlen = cq->p2;
|
||||
if (cq->p1 > MISDN_CTRL_RX_SIZE_IGNORE)
|
||||
bch->next_minlen = cq->p1;
|
||||
/* we return the old values */
|
||||
cq->p1 = bch->minlen;
|
||||
cq->p2 = bch->maxlen;
|
||||
break;
|
||||
default:
|
||||
pr_info("mISDN unhandled control %x operation\n", cq->op);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(mISDN_ctrl_bchannel);
|
||||
|
||||
static inline u_int
|
||||
get_sapi_tei(u_char *p)
|
||||
{
|
||||
@@ -197,7 +234,7 @@ recv_Echannel(struct dchannel *ech, struct dchannel *dch)
|
||||
EXPORT_SYMBOL(recv_Echannel);
|
||||
|
||||
void
|
||||
recv_Bchannel(struct bchannel *bch, unsigned int id)
|
||||
recv_Bchannel(struct bchannel *bch, unsigned int id, bool force)
|
||||
{
|
||||
struct mISDNhead *hh;
|
||||
|
||||
@@ -211,6 +248,9 @@ recv_Bchannel(struct bchannel *bch, unsigned int id)
|
||||
dev_kfree_skb(bch->rx_skb);
|
||||
bch->rx_skb = NULL;
|
||||
} else {
|
||||
if (test_bit(FLG_TRANSPARENT, &bch->Flags) &&
|
||||
(bch->rx_skb->len < bch->minlen) && !force)
|
||||
return;
|
||||
hh = mISDN_HEAD_P(bch->rx_skb);
|
||||
hh->prim = PH_DATA_IND;
|
||||
hh->id = id;
|
||||
@@ -426,7 +466,7 @@ bchannel_get_rxbuf(struct bchannel *bch, int reqlen)
|
||||
bch->nr, reqlen, len);
|
||||
if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
|
||||
/* send what we have now and try a new buffer */
|
||||
recv_Bchannel(bch, 0);
|
||||
recv_Bchannel(bch, 0, true);
|
||||
} else {
|
||||
/* on HDLC we have to drop too big frames */
|
||||
return -EMSGSIZE;
|
||||
@@ -435,12 +475,25 @@ bchannel_get_rxbuf(struct bchannel *bch, int reqlen)
|
||||
return len;
|
||||
}
|
||||
}
|
||||
/* update current min/max length first */
|
||||
if (unlikely(bch->maxlen != bch->next_maxlen))
|
||||
bch->maxlen = bch->next_maxlen;
|
||||
if (unlikely(bch->minlen != bch->next_minlen))
|
||||
bch->minlen = bch->next_minlen;
|
||||
if (unlikely(reqlen > bch->maxlen))
|
||||
return -EMSGSIZE;
|
||||
if (test_bit(FLG_TRANSPARENT, &bch->Flags))
|
||||
len = reqlen;
|
||||
else /* with HDLC we do not know the length yet */
|
||||
if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
|
||||
if (reqlen >= bch->minlen) {
|
||||
len = reqlen;
|
||||
} else {
|
||||
len = 2 * bch->minlen;
|
||||
if (len > bch->maxlen)
|
||||
len = bch->maxlen;
|
||||
}
|
||||
} else {
|
||||
/* with HDLC we do not know the length yet */
|
||||
len = bch->maxlen;
|
||||
}
|
||||
bch->rx_skb = mI_alloc_skb(len, GFP_ATOMIC);
|
||||
if (!bch->rx_skb) {
|
||||
pr_warning("B%d receive no memory for %d bytes\n",
|
||||
|
Reference in New Issue
Block a user