static int ag71xx_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct ag71xx *ag = netdev_priv(dev); struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); struct ag71xx_ring *ring = &ag->tx_ring; struct ag71xx_desc *desc; unsigned long flags; int i; i = ring->curr % AG71XX_TX_RING_SIZE; desc = &ring->descs[i]; spin_lock_irqsave(&ag->lock, flags); pdata->ddr_flush(); spin_unlock_irqrestore(&ag->lock, flags); if (!ag71xx_desc_empty(desc)) goto err_drop; ag71xx_add_ar8216_header(ag, skb); if (skb->len <= 0) { DBG("%s: packet len is too small\n", ag->dev->name); goto err_drop; } dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE); ring->buf[i].skb = skb; /* setup descriptor fields */ desc->data = virt_to_phys(skb->data); desc->ctrl = (skb->len & DESC_PKTLEN_M); /* flush descriptor */ wmb(); ring->curr++; if (ring->curr == (ring->dirty + AG71XX_TX_THRES_STOP)) { DBG("%s: tx queue full\n", ag->dev->name); netif_stop_queue(dev); } DBG("%s: packet injected into TX queue\n", ag->dev->name); /* enable TX engine */ ag71xx_wr(ag, AG71XX_REG_TX_CTRL, TX_CTRL_TXE); dev->trans_start = jiffies; return 0; err_drop: dev->stats.tx_dropped++; dev_kfree_skb(skb); return 0; }
static netdev_tx_t ag71xx_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct ag71xx *ag = netdev_priv(dev); struct ag71xx_ring *ring = &ag->tx_ring; struct ag71xx_desc *desc; dma_addr_t dma_addr; int i; i = ring->curr % AG71XX_TX_RING_SIZE; desc = ring->buf[i].desc; if (!ag71xx_desc_empty(desc)) goto err_drop; if (ag71xx_has_ar8216(ag)) ag71xx_add_ar8216_header(ag, skb); if (skb->len <= 0) { DBG("%s: packet len is too small\n", ag->dev->name); goto err_drop; } dma_addr = dma_map_single(&dev->dev, skb->data, skb->len, DMA_TO_DEVICE); ring->buf[i].skb = skb; /* setup descriptor fields */ desc->data = (u32) dma_addr; desc->ctrl = (skb->len & DESC_PKTLEN_M); /* flush descriptor */ wmb(); ring->curr++; if (ring->curr == (ring->dirty + AG71XX_TX_THRES_STOP)) { DBG("%s: tx queue full\n", ag->dev->name); netif_stop_queue(dev); } DBG("%s: packet injected into TX queue\n", ag->dev->name); /* enable TX engine */ ag71xx_wr(ag, AG71XX_REG_TX_CTRL, TX_CTRL_TXE); return NETDEV_TX_OK; err_drop: dev->stats.tx_dropped++; dev_kfree_skb(skb); return NETDEV_TX_OK; }