int bchannel_senddata(struct bchannel *ch, struct sk_buff *skb) { /* check oversize */ if (skb->len <= 0) { printk(KERN_WARNING "%s: skb too small\n", __func__); return -EINVAL; } if (skb->len > ch->maxlen) { printk(KERN_WARNING "%s: skb too large(%d/%d)\n", __func__, skb->len, ch->maxlen); return -EINVAL; } /* HW lock must be obtained */ /* check for pending next_skb */ if (ch->next_skb) { printk(KERN_WARNING "%s: next_skb exist ERROR (skb->len=%d next_skb->len=%d)\n", __func__, skb->len, ch->next_skb->len); return -EBUSY; } if (test_and_set_bit(FLG_TX_BUSY, &ch->Flags)) { test_and_set_bit(FLG_TX_NEXT, &ch->Flags); ch->next_skb = skb; return 0; } else { /* write to fifo */ ch->tx_skb = skb; ch->tx_idx = 0; confirm_Bsend(ch); return 1; } }
static void send_next(struct w6692_ch *wch) { if (wch->bch.tx_skb && wch->bch.tx_idx < wch->bch.tx_skb->len) W6692_fill_Bfifo(wch); else { if (wch->bch.tx_skb) { if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags)) confirm_Bsend(&wch->bch); dev_kfree_skb(wch->bch.tx_skb); } if (get_next_bframe(&wch->bch)) W6692_fill_Bfifo(wch); } }
static void send_next(struct isar_ch *ch) { pr_debug("%s: %s ch%d tx_skb %p tx_idx %d\n", ch->is->name, __func__, ch->bch.nr, ch->bch.tx_skb, ch->bch.tx_idx); if (ch->bch.state == ISDN_P_B_T30_FAX) { if (ch->cmd == PCTRL_CMD_FTH) { if (test_bit(FLG_LASTDATA, &ch->bch.Flags)) { pr_debug("set NMD_DATA\n"); test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags); } } else if (ch->cmd == PCTRL_CMD_FTM) { if (test_bit(FLG_DLEETX, &ch->bch.Flags)) { test_and_set_bit(FLG_LASTDATA, &ch->bch.Flags); test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags); } } } if (ch->bch.tx_skb) { /* send confirm, on trans, free on hdlc. */ if (test_bit(FLG_TRANSPARENT, &ch->bch.Flags)) confirm_Bsend(&ch->bch); dev_kfree_skb(ch->bch.tx_skb); } if (get_next_bframe(&ch->bch)) isar_fill_fifo(ch); else { if (test_and_clear_bit(FLG_DLEETX, &ch->bch.Flags)) { if (test_and_clear_bit(FLG_LASTDATA, &ch->bch.Flags)) { if (test_and_clear_bit(FLG_NMD_DATA, &ch->bch.Flags)) { u8 zd = 0; send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, 0x01, 1, &zd); } test_and_set_bit(FLG_LL_OK, &ch->bch.Flags); } else { deliver_status(ch, HW_MOD_CONNECT); } } } }
int get_next_bframe(struct bchannel *bch) { bch->tx_idx = 0; if (test_bit(FLG_TX_NEXT, &bch->Flags)) { bch->tx_skb = bch->next_skb; if (bch->tx_skb) { bch->next_skb = NULL; test_and_clear_bit(FLG_TX_NEXT, &bch->Flags); if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) confirm_Bsend(bch); /* not for transparent */ return 1; } else { test_and_clear_bit(FLG_TX_NEXT, &bch->Flags); printk(KERN_WARNING "B TX_NEXT without skb\n"); } } bch->tx_skb = NULL; test_and_clear_bit(FLG_TX_BUSY, &bch->Flags); return 0; }
int get_next_bframe(struct bchannel *bch) { bch->tx_idx = 0; if (test_bit(FLG_TX_NEXT, &bch->Flags)) { bch->tx_skb = bch->next_skb; if (bch->tx_skb) { bch->next_skb = NULL; test_and_clear_bit(FLG_TX_NEXT, &bch->Flags); /* confirm imediately to allow next data */ confirm_Bsend(bch); return 1; } else { test_and_clear_bit(FLG_TX_NEXT, &bch->Flags); printk(KERN_WARNING "B TX_NEXT without skb\n"); } } bch->tx_skb = NULL; test_and_clear_bit(FLG_TX_BUSY, &bch->Flags); return 0; }