Skip to content

Commit

Permalink
mISDN: Implement MISDN_CTRL_RX_OFF for more drivers
Browse files Browse the repository at this point in the history
MISDN_CTRL_RX_OFF is a meachanism to discard RX data in the driver if
the data is not needed by the application. It can be used when playing
mesages, but not recording or with unidirectional protocols.

Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Karsten Keil authored and David S. Miller committed May 16, 2012
1 parent 6d1ee48 commit c27b46e
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 13 deletions.
25 changes: 16 additions & 9 deletions drivers/isdn/hardware/mISDN/avmfritz.c
Original file line number Diff line number Diff line change
Expand Up @@ -408,13 +408,18 @@ hdlc_empty_fifo(struct bchannel *bch, int count)
struct fritzcard *fc = bch->hw;

pr_debug("%s: %s %d\n", fc->name, __func__, count);
cnt = bchannel_get_rxbuf(bch, count);
if (cnt < 0) {
pr_warning("%s.B%d: No bufferspace for %d bytes\n",
fc->name, bch->nr, count);
return;
if (test_bit(FLG_RX_OFF, &bch->Flags)) {
p = NULL;
bch->dropcnt += count;
} else {
cnt = bchannel_get_rxbuf(bch, count);
if (cnt < 0) {
pr_warning("%s.B%d: No bufferspace for %d bytes\n",
fc->name, bch->nr, count);
return;
}
p = skb_put(bch->rx_skb, count);
}
p = skb_put(bch->rx_skb, count);
ptr = (u32 *)p;
if (fc->type == AVM_FRITZ_PCIV2)
addr = fc->addr + (bch->nr == 2 ?
Expand All @@ -426,11 +431,13 @@ hdlc_empty_fifo(struct bchannel *bch, int count)
cnt = 0;
while (cnt < count) {
val = le32_to_cpu(inl(addr));
put_unaligned(val, ptr);
ptr++;
if (p) {
put_unaligned(val, ptr);
ptr++;
}
cnt += 4;
}
if (debug & DEBUG_HW_BFIFO) {
if (p && (debug & DEBUG_HW_BFIFO)) {
snprintf(fc->log, LOG_SIZE, "B%1d-recv %s %d ",
bch->nr, fc->name, count);
print_hex_dump_bytes(fc->log, DUMP_PREFIX_OFFSET, p, count);
Expand Down
9 changes: 6 additions & 3 deletions drivers/isdn/hardware/mISDN/hfcmulti.c
Original file line number Diff line number Diff line change
Expand Up @@ -2224,8 +2224,11 @@ hfcmulti_rx(struct hfc_multi *hc, int ch)
HFC_wait_nodebug(hc);

/* ignore if rx is off BUT change fifo (above) to start pending TX */
if (hc->chan[ch].rx_off)
if (hc->chan[ch].rx_off) {
if (bch)
bch->dropcnt += poll; /* not exact but fair enough */
return;
}

if (dch || test_bit(FLG_HDLC, &bch->Flags)) {
f1 = HFC_inb_nodebug(hc, A_F1);
Expand Down Expand Up @@ -3575,10 +3578,10 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
ret = mISDN_ctrl_bchannel(bch, cq);
cq->op |= MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP |
MISDN_CTRL_RX_OFF;
cq->op |= MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP;
break;
case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */
ret = mISDN_ctrl_bchannel(bch, cq);
hc->chan[bch->slot].rx_off = !!cq->p1;
if (!hc->chan[bch->slot].rx_off) {
/* reset fifo on rx on */
Expand Down
5 changes: 5 additions & 0 deletions drivers/isdn/hardware/mISDN/hfcpci.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,11 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz,
fcnt_tx = B_FIFO_SIZE - fcnt_tx;
/* remaining bytes to send (bytes in tx-fifo) */

if (test_bit(FLG_RX_OFF, &bch->Flags)) {
bch->dropcnt += fcnt_rx;
*z2r = cpu_to_le16(new_z2);
return;
}
maxlen = bchannel_get_rxbuf(bch, fcnt_rx);
if (maxlen < 0) {
pr_warning("B%d: No bufferspace for %d bytes\n",
Expand Down
5 changes: 5 additions & 0 deletions drivers/isdn/hardware/mISDN/hfcsusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,11 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
hdlc = 1;
}
if (fifo->bch) {
if (test_bit(FLG_RX_OFF, &fifo->bch->Flags)) {
fifo->bch->dropcnt += len;
spin_unlock(&hw->lock);
return;
}
maxlen = bchannel_get_rxbuf(fifo->bch, len);
rx_skb = fifo->bch->rx_skb;
if (maxlen < 0) {
Expand Down
5 changes: 5 additions & 0 deletions drivers/isdn/hardware/mISDN/mISDNipac.c
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,11 @@ hscx_empty_fifo(struct hscx_hw *hscx, u8 count)
int maxlen;

pr_debug("%s: B%1d %d\n", hscx->ip->name, hscx->bch.nr, count);
if (test_bit(FLG_RX_OFF, &hscx->bch.Flags)) {
hscx->bch.dropcnt += count;
hscx_cmdr(hscx, 0x80); /* RMC */
return;
}
maxlen = bchannel_get_rxbuf(&hscx->bch, count);
if (maxlen < 0) {
hscx_cmdr(hscx, 0x80); /* RMC */
Expand Down
5 changes: 5 additions & 0 deletions drivers/isdn/hardware/mISDN/mISDNisar.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,11 @@ isar_rcv_frame(struct isar_ch *ch)
ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
return;
}
if (test_bit(FLG_RX_OFF, &ch->bch.Flags)) {
ch->bch.dropcnt += ch->is->clsb;
ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
return;
}
switch (ch->bch.state) {
case ISDN_P_NONE:
pr_debug("%s: ISAR protocol 0 spurious IIS_RDATA %x/%x/%x\n",
Expand Down
4 changes: 4 additions & 0 deletions drivers/isdn/hardware/mISDN/netjet.c
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,10 @@ read_dma(struct tiger_ch *bc, u32 idx, int cnt)
bc->bch.nr, idx);
}
bc->lastrx = idx;
if (test_bit(FLG_RX_OFF, &bc->bch.Flags)) {
bc->bch.dropcnt += cnt;
return;
}
stat = bchannel_get_rxbuf(&bc->bch, cnt);
/* only transparent use the count here, HDLC overun is detected later */
if (stat == ENOMEM) {
Expand Down
5 changes: 5 additions & 0 deletions drivers/isdn/hardware/mISDN/w6692.c
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,11 @@ W6692_empty_Bfifo(struct w6692_ch *wch, int count)
skb_trim(wch->bch.rx_skb, 0);
return;
}
if (test_bit(FLG_RX_OFF, &wch->bch.Flags)) {
wch->bch.dropcnt += count;
WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
return;
}
maxlen = bchannel_get_rxbuf(&wch->bch, count);
if (maxlen < 0) {
WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
Expand Down
14 changes: 13 additions & 1 deletion drivers/isdn/mISDN/hwchannel.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ mISDN_clear_bchannel(struct bchannel *ch)
test_and_clear_bit(FLG_ACTIVE, &ch->Flags);
test_and_clear_bit(FLG_FILLEMPTY, &ch->Flags);
test_and_clear_bit(FLG_TX_EMPTY, &ch->Flags);
test_and_clear_bit(FLG_RX_OFF, &ch->Flags);
ch->dropcnt = 0;
ch->minlen = ch->init_minlen;
ch->next_minlen = ch->init_minlen;
ch->maxlen = ch->init_maxlen;
Expand All @@ -167,7 +169,8 @@ mISDN_ctrl_bchannel(struct bchannel *bch, struct mISDN_ctrl_req *cq)

switch (cq->op) {
case MISDN_CTRL_GETOP:
cq->op = MISDN_CTRL_RX_BUFFER | MISDN_CTRL_FILL_EMPTY;
cq->op = MISDN_CTRL_RX_BUFFER | MISDN_CTRL_FILL_EMPTY |
MISDN_CTRL_RX_OFF;
break;
case MISDN_CTRL_FILL_EMPTY:
if (cq->p1) {
Expand All @@ -177,6 +180,15 @@ mISDN_ctrl_bchannel(struct bchannel *bch, struct mISDN_ctrl_req *cq)
test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
}
break;
case MISDN_CTRL_RX_OFF:
/* read back dropped byte count */
cq->p2 = bch->dropcnt;
if (cq->p1)
test_and_set_bit(FLG_RX_OFF, &bch->Flags);
else
test_and_clear_bit(FLG_RX_OFF, &bch->Flags);
bch->dropcnt = 0;
break;
case MISDN_CTRL_RX_BUFFER:
if (cq->p2 > MISDN_CTRL_RX_SIZE_IGNORE)
bch->next_maxlen = cq->p2;
Expand Down
3 changes: 3 additions & 0 deletions include/linux/mISDNhw.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@
#define FLG_LL_CONN 25
#define FLG_DTMFSEND 26
#define FLG_TX_EMPTY 27
/* stop sending received data upstream */
#define FLG_RX_OFF 28
/* workq events */
#define FLG_RECVQUEUE 30
#define FLG_PHCHANGE 31
Expand Down Expand Up @@ -173,6 +175,7 @@ struct bchannel {
int err_crc;
int err_tx;
int err_rx;
int dropcnt;
};

extern int mISDN_initdchannel(struct dchannel *, int, void *);
Expand Down

0 comments on commit c27b46e

Please sign in to comment.