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 ?
        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);
 
        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);
        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 */
 
        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",
 
                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) {
 
        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 */
 
                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",
 
                        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) {
 
                        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);
 
        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;
 
        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) {
                        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;
 
 #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
        int                     err_crc;
        int                     err_tx;
        int                     err_rx;
+       int                     dropcnt;
 };
 
 extern int     mISDN_initdchannel(struct dchannel *, int, void *);