void hfc_fifo_put(struct hfc_chan_simplex *chan, void *data, int size) { struct hfc_card *card = chan->chan->card; int used_bytes = hfc_fifo_used_tx(chan); int free_bytes = hfc_fifo_free_tx(chan); if (!used_bytes && !chan->fifo_underrun++) { /* * print warning only once, to make timing not worse */ printk(KERN_WARNING hfc_DRIVER_PREFIX "card %d: " "chan %s: " "TX FIFO has become empty\n", card->cardnum, chan->chan->name); } if (free_bytes < size) { printk(KERN_CRIT hfc_DRIVER_PREFIX "card %d: " "chan %s: " "TX FIFO full!\n", chan->chan->card->cardnum, chan->chan->name); chan->fifo_full++; hfc_clear_fifo_tx(chan); } hfc_fifo_mem_write(chan, data, size); chan->bytes += size; *Z1_F1(chan) = Z_inc(chan, *Z1_F1(chan), size); }
static ssize_t hfc_sys_chan_write( struct visdn_leg *visdn_leg, const void *buf, size_t count) { struct hfc_sys_chan *chan = to_sys_chan(visdn_leg->chan); struct hfc_card *card = chan->port->card; int copied_octets; int available_octets; int used_octets; hfc_card_lock(card); hfc_fifo_select(&chan->tx_fifo); available_octets = hfc_fifo_free_tx(&chan->tx_fifo); copied_octets = available_octets > count ? count : available_octets; used_octets = hfc_fifo_used_tx(&chan->tx_fifo); chan->tx_fifo.stats_cycles++; if (chan->tx_fifo.stats_cycles >= 10) { if (chan->tx_fifo.stats_min < HFC_FIFO_JITTBUFF) { u8 foo = ((u8 *)buf)[0]; hfc_fifo_mem_write(&chan->tx_fifo, &foo, 1); // printk(KERN_DEBUG "Added one sample\n"); } chan->tx_fifo.stats_cycles = 0; chan->tx_fifo.stats_min = INT_MAX; chan->tx_fifo.stats_max = 0; } if (used_octets < chan->tx_fifo.stats_min) chan->tx_fifo.stats_min = used_octets; if (used_octets + copied_octets > chan->tx_fifo.stats_max) chan->tx_fifo.stats_max = used_octets + copied_octets; hfc_fifo_mem_write(&chan->tx_fifo, buf, copied_octets); hfc_card_unlock(card); return copied_octets; }
static int hfc_sys_chan_frame_xmit( struct visdn_leg *visdn_leg, struct sk_buff *skb) { struct hfc_sys_chan *chan = to_sys_chan(visdn_leg->chan); struct hfc_card *card = chan->port->card; struct hfc_fifo *fifo = &chan->tx_fifo; hfc_card_lock(card); hfc_fifo_select(fifo); /* * hfc_fifo_select() updates F/Z cache, so, * size calculations are allowed */ if (hfc_fifo_free_frames(fifo) <= 1) { hfc_debug_sys_chan(chan, 3, "TX FIFO frames full, throttling\n"); visdn_leg_stop_queue(&chan->visdn_chan.leg_b); } if (hfc_fifo_free_tx(fifo) < skb->len) { hfc_debug_sys_chan(chan, 3, "TX FIFO full (%d < %d), throttling\n", hfc_fifo_free_tx(fifo), skb->len); visdn_leg_stop_queue(&chan->visdn_chan.leg_b); visdn_leg_tx_error(&chan->visdn_chan.leg_b, VISDN_TX_ERROR_FIFO_FULL); goto err_no_free_tx; } #ifdef DEBUG_CODE if (debug_level == 3) { hfc_fifo_refresh_fz_cache(fifo); hfc_debug_sys_chan(chan, 3, "TX len %2d: ", skb->len); } else if (debug_level >= 4) { hfc_fifo_refresh_fz_cache(fifo); hfc_debug_sys_chan(chan, 4, "TX (f1=%02x, f2=%02x, z1(f1)=%04x, z2(f2)=%04x)" " len %2d: ", fifo->f1, fifo->f2, fifo->z1, fifo->z2, skb->len); } if (debug_level >= 3) { int i; for (i=0; i<skb->len; i++) printk("%02x",((u8 *)skb->data)[i]); printk("\n"); } #endif hfc_fifo_mem_write(fifo, skb->data, skb->len); hfc_fifo_next_frame(fifo); hfc_card_unlock(card); visdn_kfree_skb(skb); #if 0 if (chan->connected_e1_chan) { struct hfc_led *led = &card->leds[chan->connected_e1_chan->port->id]; led->alt_color = HFC_LED_OFF; led->flashing_freq = HZ / 10; led->flashes = 1; hfc_led_update(led); } #endif return VISDN_TX_OK; err_no_free_tx: hfc_card_unlock(card); return VISDN_TX_BUSY; }