Re: [PATCH v5] net: ethernet: add driver for Aurora VLSI NB8800 Ethernet controller

From: Eric Dumazet
Date: Tue Nov 10 2015 - 13:04:20 EST


On Tue, 2015-11-10 at 16:14 +0000, Mans Rullgard wrote:
> This adds a driver for the Aurora VLSI NB8800 Ethernet controller.
> It is an almost complete rewrite of a driver originally found in
> a Sigma Designs 2.6.22 tree.

...

> +
> +static int nb8800_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> + struct nb8800_priv *priv = netdev_priv(dev);
> + struct nb8800_tx_desc *txd;
> + struct nb8800_tx_buf *txb;
> + struct nb8800_dma_desc *dma;
> + dma_addr_t dma_addr;
> + unsigned int dma_len;
> + unsigned long flags;
> + int align;
> + int next;
> +
> + if (atomic_read(&priv->tx_free) <= NB8800_DESC_LOW) {
> + netif_stop_queue(dev);
> + return NETDEV_TX_BUSY;
> + }
> +
> + align = (8 - (uintptr_t)skb->data) & 7;
> +
> + dma_len = skb->len - align;
> + dma_addr = dma_map_single(&dev->dev, skb->data + align,
> + dma_len, DMA_TO_DEVICE);
> +
> + if (dma_mapping_error(&dev->dev, dma_addr)) {
> + netdev_err(dev, "tx dma mapping error\n");
> + kfree_skb(skb);
> + dev->stats.tx_dropped++;
> + return NETDEV_TX_OK;
> + }
> +
> + if (atomic_dec_return(&priv->tx_free) <= NB8800_DESC_LOW)
> + netif_stop_queue(dev);


You probably also want to clear skb->xmit_more or risk a stall

xmit_more is tricky ;)

> +
> + next = priv->tx_next;
> + txb = &priv->tx_bufs[next];
> + txd = &priv->tx_descs[next];
> + dma = &txd->desc[0];
> +
> + next = (next + 1) % TX_DESC_COUNT;
> +
> + if (align) {
> + memcpy(txd->buf, skb->data, align);
> +
> + dma->s_addr =
> + txb->dma_desc + offsetof(struct nb8800_tx_desc, buf);
> + dma->n_addr = txb->dma_desc + sizeof(txd->desc[0]);
> + dma->config = DESC_BTS(2) | DESC_DS | align;
> +
> + dma++;
> + }
> +
> + dma->s_addr = dma_addr;
> + dma->n_addr = priv->tx_bufs[next].dma_desc;
> + dma->config = DESC_BTS(2) | DESC_DS | DESC_EOF | dma_len;
> +
> + if (!skb->xmit_more)
> + dma->config |= DESC_EOC;
> +
> + txb->skb = skb;
> + txb->dma_addr = dma_addr;
> + txb->dma_len = dma_len;
> +
> + if (!priv->tx_chain) {
> + txb->chain_len = 1;
> + priv->tx_chain = txb;
> + } else {
> + priv->tx_chain->chain_len++;
> + }
> +
> + netdev_sent_queue(dev, skb->len);
> +
> + smp_mb__before_spinlock();
> + spin_lock_irqsave(&priv->tx_lock, flags);
> +
> + if (!skb->xmit_more) {
> + priv->tx_chain->ready = true;
> + priv->tx_chain = NULL;
> + nb8800_tx_dma_start(dev);
> + }
> +
> + spin_unlock_irqrestore(&priv->tx_lock, flags);
> +
> + priv->tx_next = next;
> +
> + return NETDEV_TX_OK;
> +}
> +

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/