static void W6692_empty_Dfifo(struct w6692_hw *card, int count) { struct dchannel *dch = &card->dch; u8 *ptr; pr_debug("%s: empty_Dfifo %d\n", card->name, count); if (!dch->rx_skb) { dch->rx_skb = mI_alloc_skb(card->dch.maxlen, GFP_ATOMIC); if (!dch->rx_skb) { pr_info("%s: D receive out of memory\n", card->name); WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK); return; } } if ((dch->rx_skb->len + count) >= dch->maxlen) { pr_debug("%s: empty_Dfifo overrun %d\n", card->name, dch->rx_skb->len + count); WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK); return; } ptr = skb_put(dch->rx_skb, count); insb(card->addr + W_D_RFIFO, ptr, count); WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK); if (debug & DEBUG_HW_DFIFO) { snprintf(card->log, 63, "D-recv %s %d ", card->name, count); print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count); } }
void isac_empty_fifo(struct isac_hw *isac, int count) { u8 *ptr; pr_debug("%s: %s %d\n", isac->name, __func__, count); if (!isac->dch.rx_skb) { isac->dch.rx_skb = mI_alloc_skb(isac->dch.maxlen, GFP_ATOMIC); if (!isac->dch.rx_skb) { pr_info("%s: D receive out of memory\n", isac->name); WriteISAC(isac, ISAC_CMDR, 0x80); return; } } if ((isac->dch.rx_skb->len + count) >= isac->dch.maxlen) { pr_debug("%s: %s overrun %d\n", isac->name, __func__, isac->dch.rx_skb->len + count); WriteISAC(isac, ISAC_CMDR, 0x80); return; } ptr = skb_put(isac->dch.rx_skb, count); isac->read_fifo(isac->dch.hw, isac->off, ptr, count); WriteISAC(isac, ISAC_CMDR, 0x80); if (isac->dch.debug & DEBUG_HW_DFIFO) { char pfx[MISDN_MAX_IDLEN + 16]; snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-recv %s %d ", isac->name, count); print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count); } }
/* The function allocates a new receive skb on demand with a size for the * requirements of the current protocol. It returns the tailroom of the * receive skb or an error. */ int bchannel_get_rxbuf(struct bchannel *bch, int reqlen) { int len; if (bch->rx_skb) { len = skb_tailroom(bch->rx_skb); if (len < reqlen) { pr_warning("B%d no space for %d (only %d) bytes\n", 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, true); } else { /* on HDLC we have to drop too big frames */ return -EMSGSIZE; } } else { 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)) { 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", bch->nr, len); len = -ENOMEM; } return len; }
static int l2down_create(struct layer2 *l2, u_int prim, u_int id, int len, void *arg) { struct sk_buff *skb; int err; struct mISDNhead *hh; skb = mI_alloc_skb(len, GFP_ATOMIC); if (!skb) return -ENOMEM; hh = mISDN_HEAD_P(skb); hh->prim = prim; hh->id = id; if (len) memcpy(skb_put(skb, len), arg, len); err = l2down_raw(l2, skb); if (err) dev_kfree_skb(skb); return err; }
static void send_uframe(struct layer2 *l2, struct sk_buff *skb, u_char cmd, u_char cr) { u_char tmp[MAX_L2HEADER_LEN]; int i; i = sethdraddr(l2, tmp, cr); tmp[i++] = cmd; if (skb) skb_trim(skb, 0); else { skb = mI_alloc_skb(i, GFP_ATOMIC); if (!skb) { printk(KERN_WARNING "%s: can't alloc skbuff\n", __func__); return; } } memcpy(skb_put(skb, i), tmp, i); enqueue_super(l2, skb); }
static void enquiry_cr(struct layer2 *l2, u_char typ, u_char cr, u_char pf) { struct sk_buff *skb; u_char tmp[MAX_L2HEADER_LEN]; int i; i = sethdraddr(l2, tmp, cr); if (test_bit(FLG_MOD128, &l2->flag)) { tmp[i++] = typ; tmp[i++] = (l2->vr << 1) | (pf ? 1 : 0); } else tmp[i++] = (l2->vr << 5) | typ | (pf ? 0x10 : 0); skb = mI_alloc_skb(i, GFP_ATOMIC); if (!skb) { printk(KERN_WARNING "isdnl2 can't alloc sbbuff for enquiry_cr\n"); return; } memcpy(skb_put(skb, i), tmp, i); enqueue_super(l2, skb); }
static void W6692_empty_Bfifo(struct w6692_ch *wch, int count) { struct w6692_hw *card = wch->bch.hw; u8 *ptr; pr_debug("%s: empty_Bfifo %d\n", card->name, count); if (unlikely(wch->bch.state == ISDN_P_NONE)) { pr_debug("%s: empty_Bfifo ISDN_P_NONE\n", card->name); WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); if (wch->bch.rx_skb) skb_trim(wch->bch.rx_skb, 0); return; } if (!wch->bch.rx_skb) { wch->bch.rx_skb = mI_alloc_skb(wch->bch.maxlen, GFP_ATOMIC); if (unlikely(!wch->bch.rx_skb)) { pr_info("%s: B receive out of memory\n", card->name); WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); return; } } if (wch->bch.rx_skb->len + count > wch->bch.maxlen) { pr_debug("%s: empty_Bfifo incoming packet too large\n", card->name); WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); skb_trim(wch->bch.rx_skb, 0); return; } ptr = skb_put(wch->bch.rx_skb, count); insb(wch->addr + W_B_RFIFO, ptr, count); WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); if (debug & DEBUG_HW_DFIFO) { snprintf(card->log, 63, "B%1d-recv %s %d ", wch->bch.nr, card->name, count); print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count); } }
static void l2up_create(struct layer2 *l2, u_int prim, int len, void *arg) { struct sk_buff *skb; struct mISDNhead *hh; int err; if (!l2->up) return; skb = mI_alloc_skb(len, GFP_ATOMIC); if (!skb) return; hh = mISDN_HEAD_P(skb); hh->prim = prim; hh->id = (l2->ch.nr << 16) | l2->ch.addr; if (len) memcpy(skb_put(skb, len), arg, len); err = l2->up->send(l2->up, skb); if (err) { printk(KERN_WARNING "%s: err=%d\n", __func__, err); dev_kfree_skb(skb); } }
static void hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len, int finish) { struct hfcsusb *hw = fifo->hw; struct sk_buff *rx_skb = NULL; int maxlen = 0; int fifon = fifo->fifonum; int i; int hdlc = 0; if (debug & DBG_HFC_CALL_TRACE) printk(KERN_DEBUG "%s: %s: fifo(%i) len(%i) " "dch(%p) bch(%p) ech(%p)\n", hw->name, __func__, fifon, len, fifo->dch, fifo->bch, fifo->ech); if (!len) return; if ((!!fifo->dch + !!fifo->bch + !!fifo->ech) != 1) { printk(KERN_DEBUG "%s: %s: undefined channel\n", hw->name, __func__); return; } spin_lock(&hw->lock); if (fifo->dch) { rx_skb = fifo->dch->rx_skb; maxlen = fifo->dch->maxlen; hdlc = 1; } if (fifo->bch) { rx_skb = fifo->bch->rx_skb; maxlen = fifo->bch->maxlen; hdlc = test_bit(FLG_HDLC, &fifo->bch->Flags); } if (fifo->ech) { rx_skb = fifo->ech->rx_skb; maxlen = fifo->ech->maxlen; hdlc = 1; } if (!rx_skb) { rx_skb = mI_alloc_skb(maxlen, GFP_ATOMIC); if (rx_skb) { if (fifo->dch) fifo->dch->rx_skb = rx_skb; if (fifo->bch) fifo->bch->rx_skb = rx_skb; if (fifo->ech) fifo->ech->rx_skb = rx_skb; skb_trim(rx_skb, 0); } else { printk(KERN_DEBUG "%s: %s: No mem for rx_skb\n", hw->name, __func__); spin_unlock(&hw->lock); return; } } if (fifo->dch || fifo->ech) { if ((rx_skb->len + len) >= MAX_DFRAME_LEN_L1) { printk(KERN_DEBUG "%s: %s: sbk mem exceeded " "for fifo(%d) HFCUSB_D_RX\n", hw->name, __func__, fifon); skb_trim(rx_skb, 0); spin_unlock(&hw->lock); return; } } else if (fifo->bch) { if ((rx_skb->len + len) >= (MAX_BCH_SIZE + 3)) { printk(KERN_DEBUG "%s: %s: sbk mem exceeded " "for fifo(%d) HFCUSB_B_RX\n", hw->name, __func__, fifon); skb_trim(rx_skb, 0); spin_unlock(&hw->lock); return; } } memcpy(skb_put(rx_skb, len), data, len); if (hdlc) { if (finish) { if ((rx_skb->len > 3) && (!(rx_skb->data[rx_skb->len - 1]))) { if (debug & DBG_HFC_FIFO_VERBOSE) { printk(KERN_DEBUG "%s: %s: fifon(%i)" " new RX len(%i): ", hw->name, __func__, fifon, rx_skb->len); i = 0; while (i < rx_skb->len) printk("%02x ", rx_skb->data[i++]); printk("\n"); } skb_trim(rx_skb, rx_skb->len - 3); if (fifo->dch) recv_Dchannel(fifo->dch); if (fifo->bch) recv_Bchannel(fifo->bch, MISDN_ID_ANY); if (fifo->ech) recv_Echannel(fifo->ech, &hw->dch); } else { if (debug & DBG_HFC_FIFO_VERBOSE) { printk(KERN_DEBUG "%s: CRC or minlen ERROR fifon(%i) " "RX len(%i): ", hw->name, fifon, rx_skb->len); i = 0; while (i < rx_skb->len) printk("%02x ", rx_skb->data[i++]); printk("\n"); } skb_trim(rx_skb, 0); } } } else { if (rx_skb->len >= poll) recv_Bchannel(fifo->bch, MISDN_ID_ANY); } spin_unlock(&hw->lock); }
static inline void isar_rcv_frame(struct isar_ch *ch) { u8 *ptr; if (!ch->is->clsb) { pr_debug("%s; ISAR zero len frame\n", ch->is->name); 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", ch->is->name, ch->is->iis, ch->is->cmsb, ch->is->clsb); ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); break; case ISDN_P_B_RAW: case ISDN_P_B_L2DTMF: case ISDN_P_B_MODEM_ASYNC: if (!ch->bch.rx_skb) { ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen, GFP_ATOMIC); if (unlikely(!ch->bch.rx_skb)) { pr_info("%s: B receive out of memory\n", ch->is->name); ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); break; } } rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb)); recv_Bchannel(&ch->bch, 0); break; case ISDN_P_B_HDLC: if (!ch->bch.rx_skb) { ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen, GFP_ATOMIC); if (unlikely(!ch->bch.rx_skb)) { pr_info("%s: B receive out of memory\n", ch->is->name); ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); break; } } if ((ch->bch.rx_skb->len + ch->is->clsb) > (ch->bch.maxlen + 2)) { pr_debug("%s: incoming packet too large\n", ch->is->name); ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); skb_trim(ch->bch.rx_skb, 0); break; } if (ch->is->cmsb & HDLC_ERROR) { pr_debug("%s: ISAR frame error %x len %d\n", ch->is->name, ch->is->cmsb, ch->is->clsb); #ifdef ERROR_STATISTIC if (ch->is->cmsb & HDLC_ERR_RER) ch->bch.err_inv++; if (ch->is->cmsb & HDLC_ERR_CER) ch->bch.err_crc++; #endif skb_trim(ch->bch.rx_skb, 0); ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); break; } if (ch->is->cmsb & HDLC_FSD) skb_trim(ch->bch.rx_skb, 0); ptr = skb_put(ch->bch.rx_skb, ch->is->clsb); rcv_mbox(ch->is, ptr); if (ch->is->cmsb & HDLC_FED) { if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */ pr_debug("%s: ISAR frame to short %d\n", ch->is->name, ch->bch.rx_skb->len); skb_trim(ch->bch.rx_skb, 0); break; } skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2); recv_Bchannel(&ch->bch, 0); } break; case ISDN_P_B_T30_FAX: if (ch->state != STFAX_ACTIV) { pr_debug("%s: isar_rcv_frame: not ACTIV\n", ch->is->name); ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); if (ch->bch.rx_skb) skb_trim(ch->bch.rx_skb, 0); break; } if (!ch->bch.rx_skb) { ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen, GFP_ATOMIC); if (unlikely(!ch->bch.rx_skb)) { pr_info("%s: B receive out of memory\n", __func__); ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); break; } } if (ch->cmd == PCTRL_CMD_FRM) { rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb)); pr_debug("%s: isar_rcv_frame: %d\n", ch->is->name, ch->bch.rx_skb->len); if (ch->is->cmsb & SART_NMD) { /* ABORT */ pr_debug("%s: isar_rcv_frame: no more data\n", ch->is->name); ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL); ch->state = STFAX_ESCAPE; /* set_skb_flag(skb, DF_NOMOREDATA); */ } recv_Bchannel(&ch->bch, 0); if (ch->is->cmsb & SART_NMD) deliver_status(ch, HW_MOD_NOCARR); break; } if (ch->cmd != PCTRL_CMD_FRH) { pr_debug("%s: isar_rcv_frame: unknown fax mode %x\n", ch->is->name, ch->cmd); ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); if (ch->bch.rx_skb) skb_trim(ch->bch.rx_skb, 0); break; } /* PCTRL_CMD_FRH */ if ((ch->bch.rx_skb->len + ch->is->clsb) > (ch->bch.maxlen + 2)) { pr_info("%s: %s incoming packet too large\n", ch->is->name, __func__); ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); skb_trim(ch->bch.rx_skb, 0); break; } else if (ch->is->cmsb & HDLC_ERROR) { pr_info("%s: ISAR frame error %x len %d\n", ch->is->name, ch->is->cmsb, ch->is->clsb); skb_trim(ch->bch.rx_skb, 0); ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); break; } if (ch->is->cmsb & HDLC_FSD) skb_trim(ch->bch.rx_skb, 0); ptr = skb_put(ch->bch.rx_skb, ch->is->clsb); rcv_mbox(ch->is, ptr); if (ch->is->cmsb & HDLC_FED) { if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */ pr_info("%s: ISAR frame to short %d\n", ch->is->name, ch->bch.rx_skb->len); skb_trim(ch->bch.rx_skb, 0); break; } skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2); recv_Bchannel(&ch->bch, 0); } if (ch->is->cmsb & SART_NMD) { /* ABORT */ pr_debug("%s: isar_rcv_frame: no more data\n", ch->is->name); ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); if (ch->bch.rx_skb) skb_trim(ch->bch.rx_skb, 0); send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL); ch->state = STFAX_ESCAPE; deliver_status(ch, HW_MOD_NOCARR); } break; default: pr_info("isar_rcv_frame protocol (%x)error\n", ch->bch.state); ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); break; } }