static int push_scqe()

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;
}