static void push_rxbufs()

in nicstar.c [946:1058]


static void push_rxbufs(ns_dev * card, struct sk_buff *skb)
{
	struct sk_buff *handle1, *handle2;
	int id1, id2;
	u32 addr1, addr2;
	u32 stat;
	unsigned long flags;

	/* *BARF* */
	handle2 = NULL;
	addr2 = 0;
	handle1 = skb;
	addr1 = dma_map_single(&card->pcidev->dev,
			       skb->data,
			       (NS_PRV_BUFTYPE(skb) == BUF_SM
				? NS_SMSKBSIZE : NS_LGSKBSIZE),
			       DMA_TO_DEVICE);
	NS_PRV_DMA(skb) = addr1; /* save so we can unmap later */

#ifdef GENERAL_DEBUG
	if (!addr1)
		printk("nicstar%d: push_rxbufs called with addr1 = 0.\n",
		       card->index);
#endif /* GENERAL_DEBUG */

	stat = readl(card->membase + STAT);
	card->sbfqc = ns_stat_sfbqc_get(stat);
	card->lbfqc = ns_stat_lfbqc_get(stat);
	if (NS_PRV_BUFTYPE(skb) == BUF_SM) {
		if (!addr2) {
			if (card->sm_addr) {
				addr2 = card->sm_addr;
				handle2 = card->sm_handle;
				card->sm_addr = 0x00000000;
				card->sm_handle = NULL;
			} else {	/* (!sm_addr) */

				card->sm_addr = addr1;
				card->sm_handle = handle1;
			}
		}
	} else {		/* buf_type == BUF_LG */

		if (!addr2) {
			if (card->lg_addr) {
				addr2 = card->lg_addr;
				handle2 = card->lg_handle;
				card->lg_addr = 0x00000000;
				card->lg_handle = NULL;
			} else {	/* (!lg_addr) */

				card->lg_addr = addr1;
				card->lg_handle = handle1;
			}
		}
	}

	if (addr2) {
		if (NS_PRV_BUFTYPE(skb) == BUF_SM) {
			if (card->sbfqc >= card->sbnr.max) {
				skb_unlink(handle1, &card->sbpool.queue);
				dev_kfree_skb_any(handle1);
				skb_unlink(handle2, &card->sbpool.queue);
				dev_kfree_skb_any(handle2);
				return;
			} else
				card->sbfqc += 2;
		} else {	/* (buf_type == BUF_LG) */

			if (card->lbfqc >= card->lbnr.max) {
				skb_unlink(handle1, &card->lbpool.queue);
				dev_kfree_skb_any(handle1);
				skb_unlink(handle2, &card->lbpool.queue);
				dev_kfree_skb_any(handle2);
				return;
			} else
				card->lbfqc += 2;
		}

		id1 = idr_alloc(&card->idr, handle1, 0, 0, GFP_ATOMIC);
		if (id1 < 0)
			goto out;

		id2 = idr_alloc(&card->idr, handle2, 0, 0, GFP_ATOMIC);
		if (id2 < 0)
			goto out;

		spin_lock_irqsave(&card->res_lock, flags);
		while (CMD_BUSY(card)) ;
		writel(addr2, card->membase + DR3);
		writel(id2, card->membase + DR2);
		writel(addr1, card->membase + DR1);
		writel(id1, card->membase + DR0);
		writel(NS_CMD_WRITE_FREEBUFQ | NS_PRV_BUFTYPE(skb),
		       card->membase + CMD);
		spin_unlock_irqrestore(&card->res_lock, flags);

		XPRINTK("nicstar%d: Pushing %s buffers at 0x%x and 0x%x.\n",
			card->index,
			(NS_PRV_BUFTYPE(skb) == BUF_SM ? "small" : "large"),
			addr1, addr2);
	}

	if (!card->efbie && card->sbfqc >= card->sbnr.min &&
	    card->lbfqc >= card->lbnr.min) {
		card->efbie = 1;
		writel((readl(card->membase + CFG) | NS_CFG_EFBIE),
		       card->membase + CFG);
	}

out:
	return;
}