summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/isdn/hardware/mISDN/avmfritz.c25
-rw-r--r--drivers/isdn/hardware/mISDN/hfcmulti.c9
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c5
-rw-r--r--drivers/isdn/hardware/mISDN/hfcsusb.c5
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNipac.c5
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNisar.c5
-rw-r--r--drivers/isdn/hardware/mISDN/netjet.c4
-rw-r--r--drivers/isdn/hardware/mISDN/w6692.c5
-rw-r--r--drivers/isdn/mISDN/hwchannel.c14
-rw-r--r--include/linux/mISDNhw.h3
10 files changed, 67 insertions, 13 deletions
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c
index c6fa505a1d1b..c08fc605e56b 100644
--- a/drivers/isdn/hardware/mISDN/avmfritz.c
+++ b/drivers/isdn/hardware/mISDN/avmfritz.c
@@ -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 ?
@@ -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);
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index db9b04519829..5e402cf2e795 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -2224,8 +2224,11 @@ next_frame:
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);
@@ -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 */
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index 1bd8bc7eb5c7..81363ffa5357 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -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",
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c
index b539b10d6f3e..83206e453d4e 100644
--- a/drivers/isdn/hardware/mISDN/hfcsusb.c
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -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) {
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
index 374a17751ffb..752e0825591f 100644
--- a/drivers/isdn/hardware/mISDN/mISDNipac.c
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -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 */
diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c
index 901be3257a7b..be5973ded6d6 100644
--- a/drivers/isdn/hardware/mISDN/mISDNisar.c
+++ b/drivers/isdn/hardware/mISDN/mISDNisar.c
@@ -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",
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c
index aa95cc7d32f9..c3e3e7686273 100644
--- a/drivers/isdn/hardware/mISDN/netjet.c
+++ b/drivers/isdn/hardware/mISDN/netjet.c
@@ -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) {
diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c
index 183181f01927..26a86b846099 100644
--- a/drivers/isdn/hardware/mISDN/w6692.c
+++ b/drivers/isdn/hardware/mISDN/w6692.c
@@ -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);
diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c
index e541b65f68ba..ef34fd40867c 100644
--- a/drivers/isdn/mISDN/hwchannel.c
+++ b/drivers/isdn/mISDN/hwchannel.c
@@ -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;
@@ -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) {
@@ -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;
diff --git a/include/linux/mISDNhw.h b/include/linux/mISDNhw.h
index 621184216566..d0752eca9b44 100644
--- a/include/linux/mISDNhw.h
+++ b/include/linux/mISDNhw.h
@@ -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
@@ -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 *);