aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/mISDN
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/mISDN
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/mISDN')
-rw-r--r--drivers/isdn/mISDN/hwchannel.c65
-rw-r--r--drivers/isdn/mISDN/l1oip_core.c2
2 files changed, 60 insertions, 7 deletions
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;