in nicstar.c [1733:1843]
static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd,
struct sk_buff *skb, bool may_sleep)
{
unsigned long flags;
ns_scqe tsr;
u32 scdi, scqi;
int scq_is_vbr;
u32 data;
int index;
spin_lock_irqsave(&scq->lock, flags);
while (scq->tail == scq->next) {
if (!may_sleep) {
spin_unlock_irqrestore(&scq->lock, flags);
printk("nicstar%d: Error pushing TBD.\n", card->index);
return 1;
}
scq->full = 1;
wait_event_interruptible_lock_irq_timeout(scq->scqfull_waitq,
scq->tail != scq->next,
scq->lock,
SCQFULL_TIMEOUT);
if (scq->full) {
spin_unlock_irqrestore(&scq->lock, flags);
printk("nicstar%d: Timeout pushing TBD.\n",
card->index);
return 1;
}
}
*scq->next = *tbd;
index = (int)(scq->next - scq->base);
scq->skb[index] = skb;
XPRINTK("nicstar%d: sending skb at 0x%p (pos %d).\n",
card->index, skb, index);
XPRINTK("nicstar%d: TBD written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%p.\n",
card->index, le32_to_cpu(tbd->word_1), le32_to_cpu(tbd->word_2),
le32_to_cpu(tbd->word_3), le32_to_cpu(tbd->word_4),
scq->next);
if (scq->next == scq->last)
scq->next = scq->base;
else
scq->next++;
vc->tbd_count++;
if (scq->num_entries == VBR_SCQ_NUM_ENTRIES) {
scq->tbd_count++;
scq_is_vbr = 1;
} else
scq_is_vbr = 0;
if (vc->tbd_count >= MAX_TBD_PER_VC
|| scq->tbd_count >= MAX_TBD_PER_SCQ) {
int has_run = 0;
while (scq->tail == scq->next) {
if (!may_sleep) {
data = scq_virt_to_bus(scq, scq->next);
ns_write_sram(card, scq->scd, &data, 1);
spin_unlock_irqrestore(&scq->lock, flags);
printk("nicstar%d: Error pushing TSR.\n",
card->index);
return 0;
}
scq->full = 1;
if (has_run++)
break;
wait_event_interruptible_lock_irq_timeout(scq->scqfull_waitq,
scq->tail != scq->next,
scq->lock,
SCQFULL_TIMEOUT);
}
if (!scq->full) {
tsr.word_1 = ns_tsr_mkword_1(NS_TSR_INTENABLE);
if (scq_is_vbr)
scdi = NS_TSR_SCDISVBR;
else
scdi = (vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE;
scqi = scq->next - scq->base;
tsr.word_2 = ns_tsr_mkword_2(scdi, scqi);
tsr.word_3 = 0x00000000;
tsr.word_4 = 0x00000000;
*scq->next = tsr;
index = (int)scqi;
scq->skb[index] = NULL;
XPRINTK
("nicstar%d: TSR written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%p.\n",
card->index, le32_to_cpu(tsr.word_1),
le32_to_cpu(tsr.word_2), le32_to_cpu(tsr.word_3),
le32_to_cpu(tsr.word_4), scq->next);
if (scq->next == scq->last)
scq->next = scq->base;
else
scq->next++;
vc->tbd_count = 0;
scq->tbd_count = 0;
} else
PRINTK("nicstar%d: Timeout pushing TSR.\n",
card->index);
}
data = scq_virt_to_bus(scq, scq->next);
ns_write_sram(card, scq->scd, &data, 1);
spin_unlock_irqrestore(&scq->lock, flags);
return 0;
}