static netdev_tx_t greth_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct greth_private *greth = netdev_priv(dev); struct greth_bd *bdp; int err = NETDEV_TX_OK; u32 status, dma_addr, ctrl; unsigned long flags; /* Clean TX Ring */ greth_clean_tx(greth->netdev); if (unlikely(greth->tx_free <= 0)) { spin_lock_irqsave(&greth->devlock, flags);/*save from poll/irq*/ ctrl = GRETH_REGLOAD(greth->regs->control); /* Enable TX IRQ only if not already in poll() routine */ if (ctrl & GRETH_RXI) GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI); netif_stop_queue(dev); spin_unlock_irqrestore(&greth->devlock, flags); return NETDEV_TX_BUSY; } if (netif_msg_pktdata(greth)) greth_print_tx_packet(skb); if (unlikely(skb->len > MAX_FRAME_SIZE)) { dev->stats.tx_errors++; goto out; } bdp = greth->tx_bd_base + greth->tx_next; dma_addr = greth_read_bd(&bdp->addr); memcpy((unsigned char *) phys_to_virt(dma_addr), skb->data, skb->len); dma_sync_single_for_device(greth->dev, dma_addr, skb->len, DMA_TO_DEVICE); status = GRETH_BD_EN | GRETH_BD_IE | (skb->len & GRETH_BD_LEN); greth->tx_bufs_length[greth->tx_next] = skb->len & GRETH_BD_LEN; /* Wrap around descriptor ring */ if (greth->tx_next == GRETH_TXBD_NUM_MASK) { status |= GRETH_BD_WR; } greth->tx_next = NEXT_TX(greth->tx_next); greth->tx_free--; /* Write descriptor control word and enable transmission */ greth_write_bd(&bdp->stat, status); spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/ greth_enable_tx(greth); spin_unlock_irqrestore(&greth->devlock, flags); out: dev_kfree_skb(skb); return err; }
static inline void kick_tx(struct net_device *dev, struct sgiseeq_private *sp, struct hpc3_ethregs *hregs) { struct sgiseeq_tx_desc *td; int i = sp->tx_old; /* If the HPC aint doin nothin, and there are more packets * with ETXD cleared and XIU set we must make very certain * that we restart the HPC else we risk locking up the * adapter. The following code is only safe iff the HPCDMA * is not active! */ td = &sp->tx_desc[i]; dma_sync_desc_cpu(dev, td); while ((td->tdma.cntinfo & (HPCDMA_XIU | HPCDMA_ETXD)) == (HPCDMA_XIU | HPCDMA_ETXD)) { i = NEXT_TX(i); td = &sp->tx_desc[i]; dma_sync_desc_cpu(dev, td); } if (td->tdma.cntinfo & HPCDMA_XIU) { hregs->tx_ndptr = VIRT_TO_DMA(sp, td); hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE; } }
static void b44_tx(struct b44 *bp) { u32 cur, cons; cur = br32(bp, B44_DMATX_STAT) & DMATX_STAT_CDMASK; cur /= sizeof(struct dma_desc); /* XXX needs updating when NETIF_F_SG is supported */ for (cons = bp->tx_cons; cons != cur; cons = NEXT_TX(cons)) { struct ring_info *rp = &bp->tx_buffers[cons]; struct sk_buff *skb = rp->skb; if (unlikely(skb == NULL)) BUG(); pci_unmap_single(bp->pdev, pci_unmap_addr(rp, mapping), skb->len, PCI_DMA_TODEVICE); rp->skb = NULL; dev_kfree_skb_irq(skb); } bp->tx_cons = cons; if (netif_queue_stopped(bp->dev) && TX_BUFFS_AVAIL(bp) > B44_TX_WAKEUP_THRESH) netif_wake_queue(bp->dev); bw32(bp, B44_GPTIMER, 0); }
static inline void sgiseeq_tx(struct net_device *dev, struct sgiseeq_private *sp, struct hpc3_ethregs *hregs, struct sgiseeq_regs *sregs) { struct sgiseeq_tx_desc *td; unsigned long status = hregs->tx_ctrl; int j; tx_maybe_reset_collisions(sp, sregs); if (!(status & (HPC3_ETXCTRL_ACTIVE | SEEQ_TSTAT_PTRANS))) { /* Oops, HPC detected some sort of error. */ if (status & SEEQ_TSTAT_R16) dev->stats.tx_aborted_errors++; if (status & SEEQ_TSTAT_UFLOW) dev->stats.tx_fifo_errors++; if (status & SEEQ_TSTAT_LCLS) dev->stats.collisions++; } /* Ack 'em... */ for (j = sp->tx_old; j != sp->tx_new; j = NEXT_TX(j)) { td = &sp->tx_desc[j]; dma_sync_desc_cpu(dev, td); if (!(td->tdma.cntinfo & (HPCDMA_XIU))) break; if (!(td->tdma.cntinfo & (HPCDMA_ETXD))) { if (!(status & HPC3_ETXCTRL_ACTIVE)) { hregs->tx_ndptr = VIRT_TO_DMA(sp, td); hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE; } break; } dev->stats.tx_packets++; sp->tx_old = NEXT_TX(sp->tx_old); td->tdma.cntinfo &= ~(HPCDMA_XIU | HPCDMA_XIE); td->tdma.cntinfo |= HPCDMA_EOX; if (td->skb) { dev_kfree_skb_any(td->skb); td->skb = NULL; } dma_sync_desc_dev(dev, td); } }
static void cp_tx (struct cp_private *cp) { unsigned tx_head = cp->tx_head; unsigned tx_tail = cp->tx_tail; while (tx_tail != tx_head) { struct sk_buff *skb; u32 status; rmb(); status = le32_to_cpu(cp->tx_ring[tx_tail].opts1); if (status & DescOwn) break; skb = cp->tx_skb[tx_tail].skb; if (!skb) BUG(); pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping, skb->len, PCI_DMA_TODEVICE); if (status & LastFrag) { if (status & (TxError | TxFIFOUnder)) { if (netif_msg_tx_err(cp)) printk(KERN_DEBUG "%s: tx err, status 0x%x\n", cp->dev->name, status); cp->net_stats.tx_errors++; if (status & TxOWC) cp->net_stats.tx_window_errors++; if (status & TxMaxCol) cp->net_stats.tx_aborted_errors++; if (status & TxLinkFail) cp->net_stats.tx_carrier_errors++; if (status & TxFIFOUnder) cp->net_stats.tx_fifo_errors++; } else { cp->net_stats.collisions += ((status >> TxColCntShift) & TxColCntMask); cp->net_stats.tx_packets++; cp->net_stats.tx_bytes += skb->len; if (netif_msg_tx_done(cp)) printk(KERN_DEBUG "%s: tx done, slot %d\n", cp->dev->name, tx_tail); } dev_kfree_skb_irq(skb); } cp->tx_skb[tx_tail].skb = NULL; tx_tail = NEXT_TX(tx_tail); } cp->tx_tail = tx_tail; if (TX_BUFFS_AVAIL(cp) > (MAX_SKB_FRAGS + 1)) netif_wake_queue(cp->dev); }
static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct b44 *bp = netdev_priv(dev); dma_addr_t mapping; u32 len, entry, ctrl; len = skb->len; spin_lock_irq(&bp->lock); /* This is a hard error, log it. */ if (unlikely(TX_BUFFS_AVAIL(bp) < 1)) { netif_stop_queue(dev); spin_unlock_irq(&bp->lock); printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", dev->name); return 1; } entry = bp->tx_prod; mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE); bp->tx_buffers[entry].skb = skb; pci_unmap_addr_set(&bp->tx_buffers[entry], mapping, mapping); ctrl = (len & DESC_CTRL_LEN); ctrl |= DESC_CTRL_IOC | DESC_CTRL_SOF | DESC_CTRL_EOF; if (entry == (B44_TX_RING_SIZE - 1)) ctrl |= DESC_CTRL_EOT; bp->tx_ring[entry].ctrl = cpu_to_le32(ctrl); bp->tx_ring[entry].addr = cpu_to_le32((u32) mapping+bp->dma_offset); entry = NEXT_TX(entry); bp->tx_prod = entry; wmb(); bw32(bp, B44_DMATX_PTR, entry * sizeof(struct dma_desc)); if (bp->flags & B44_FLAG_BUGGY_TXPTR) bw32(bp, B44_DMATX_PTR, entry * sizeof(struct dma_desc)); if (bp->flags & B44_FLAG_REORDER_BUG) br32(bp, B44_DMATX_PTR); if (TX_BUFFS_AVAIL(bp) < 1) netif_stop_queue(dev); spin_unlock_irq(&bp->lock); dev->trans_start = jiffies; return 0; }
/* Get a packet queued to go onto the wire. */ static int qe_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct sunqe *qep = netdev_priv(dev); struct sunqe_buffers *qbufs = qep->buffers; __u32 txbuf_dvma, qbufs_dvma = qep->buffers_dvma; unsigned char *txbuf; int len, entry; spin_lock_irq(&qep->lock); qe_tx_reclaim(qep); len = skb->len; entry = qep->tx_new; txbuf = &qbufs->tx_buf[entry & (TX_RING_SIZE - 1)][0]; txbuf_dvma = qbufs_dvma + qebuf_offset(tx_buf, (entry & (TX_RING_SIZE - 1))); /* Avoid a race... */ qep->qe_block->qe_txd[entry].tx_flags = TXD_UPDATE; skb_copy_from_linear_data(skb, txbuf, len); qep->qe_block->qe_txd[entry].tx_addr = txbuf_dvma; qep->qe_block->qe_txd[entry].tx_flags = (TXD_OWN | TXD_SOP | TXD_EOP | (len & TXD_LENGTH)); qep->tx_new = NEXT_TX(entry); /* Get it going. */ dev->trans_start = jiffies; sbus_writel(CREG_CTRL_TWAKEUP, qep->qcregs + CREG_CTRL); dev->stats.tx_packets++; dev->stats.tx_bytes += len; if (TX_BUFFS_AVAIL(qep) <= 0) { /* Halt the net queue and enable tx interrupts. * When the tx queue empties the tx irq handler * will wake up the queue and return us back to * the lazy tx reclaim scheme. */ netif_stop_queue(dev); sbus_writel(0, qep->qcregs + CREG_TIMASK); } spin_unlock_irq(&qep->lock); dev_kfree_skb(skb); return NETDEV_TX_OK; }
/* Reclaim TX'd frames from the ring. This must always run under * the IRQ protected qep->lock. */ static void qe_tx_reclaim(struct sunqe *qep) { struct qe_txd *txbase = &qep->qe_block->qe_txd[0]; int elem = qep->tx_old; while (elem != qep->tx_new) { u32 flags = txbase[elem].tx_flags; if (flags & TXD_OWN) break; elem = NEXT_TX(elem); } qep->tx_old = elem; }
static void greth_clean_tx(struct net_device *dev) { struct greth_private *greth; struct greth_bd *bdp; u32 stat; greth = netdev_priv(dev); while (1) { bdp = greth->tx_bd_base + greth->tx_last; GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX); mb(); stat = greth_read_bd(&bdp->stat); if (unlikely(stat & GRETH_BD_EN)) break; if (greth->tx_free == GRETH_TXBD_NUM) break; /* Check status for errors */ if (unlikely(stat & GRETH_TXBD_STATUS)) { dev->stats.tx_errors++; if (stat & GRETH_TXBD_ERR_AL) dev->stats.tx_aborted_errors++; if (stat & GRETH_TXBD_ERR_UE) dev->stats.tx_fifo_errors++; } dev->stats.tx_packets++; dev->stats.tx_bytes += greth->tx_bufs_length[greth->tx_last]; greth->tx_last = NEXT_TX(greth->tx_last); greth->tx_free++; } if (greth->tx_free > 0) { netif_wake_queue(dev); } }
static void myri_tx(struct myri_eth *mp, struct net_device *dev) { struct sendq *sq = mp->sq; int entry = mp->tx_old; int limit = sbus_readl(&sq->head); DTX(("entry[%d] limit[%d] ", entry, limit)); if (entry == limit) return; while (entry != limit) { struct sk_buff *skb = mp->tx_skbs[entry]; u32 dma_addr; DTX(("SKB[%d] ", entry)); dma_addr = sbus_readl(&sq->myri_txd[entry].myri_gathers[0].addr); sbus_unmap_single(mp->myri_sdev, dma_addr, skb->len, SBUS_DMA_TODEVICE); dev_kfree_skb(skb); mp->tx_skbs[entry] = NULL; mp->enet_stats.tx_packets++; entry = NEXT_TX(entry); } mp->tx_old = entry; }
static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct myri_eth *mp = netdev_priv(dev); struct sendq __iomem *sq = mp->sq; struct myri_txd __iomem *txd; unsigned long flags; unsigned int head, tail; int len, entry; u32 dma_addr; DTX(("myri_start_xmit: ")); myri_tx(mp, dev); netif_stop_queue(dev); /* This is just to prevent multiple PIO reads for TX_BUFFS_AVAIL. */ head = sbus_readl(&sq->head); tail = sbus_readl(&sq->tail); if (!TX_BUFFS_AVAIL(head, tail)) { DTX(("no buffs available, returning 1\n")); return NETDEV_TX_BUSY; } spin_lock_irqsave(&mp->irq_lock, flags); DHDR(("xmit[skbdata(%p)]\n", skb->data)); #ifdef DEBUG_HEADER dump_ehdr_and_myripad(((unsigned char *) skb->data)); #endif /* XXX Maybe this can go as well. */ len = skb->len; if (len & 3) { DTX(("len&3 ")); len = (len + 4) & (~3); } entry = sbus_readl(&sq->tail); txd = &sq->myri_txd[entry]; mp->tx_skbs[entry] = skb; /* Must do this before we sbus map it. */ if (skb->data[MYRI_PAD_LEN] & 0x1) { sbus_writew(0xffff, &txd->addr[0]); sbus_writew(0xffff, &txd->addr[1]); sbus_writew(0xffff, &txd->addr[2]); sbus_writew(0xffff, &txd->addr[3]); } else { sbus_writew(0xffff, &txd->addr[0]); sbus_writew((skb->data[0] << 8) | skb->data[1], &txd->addr[1]); sbus_writew((skb->data[2] << 8) | skb->data[3], &txd->addr[2]); sbus_writew((skb->data[4] << 8) | skb->data[5], &txd->addr[3]); } dma_addr = dma_map_single(&mp->myri_op->dev, skb->data, len, DMA_TO_DEVICE); sbus_writel(dma_addr, &txd->myri_gathers[0].addr); sbus_writel(len, &txd->myri_gathers[0].len); sbus_writel(1, &txd->num_sg); sbus_writel(KERNEL_CHANNEL, &txd->chan); sbus_writel(len, &txd->len); sbus_writel((u32)-1, &txd->csum_off); sbus_writel(0, &txd->csum_field); sbus_writel(NEXT_TX(entry), &sq->tail); DTX(("BangTheChip ")); bang_the_chip(mp); DTX(("tbusy=0, returning 0\n")); netif_start_queue(dev); spin_unlock_irqrestore(&mp->irq_lock, flags); return NETDEV_TX_OK; }
static void greth_clean_tx_gbit(struct net_device *dev) { struct greth_private *greth; struct greth_bd *bdp, *bdp_last_frag; struct sk_buff *skb = NULL; u32 stat; int nr_frags, i; u16 tx_last; greth = netdev_priv(dev); tx_last = greth->tx_last; while (tx_last != greth->tx_next) { skb = greth->tx_skbuff[tx_last]; nr_frags = skb_shinfo(skb)->nr_frags; /* We only clean fully completed SKBs */ bdp_last_frag = greth->tx_bd_base + SKIP_TX(tx_last, nr_frags); GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX); mb(); stat = greth_read_bd(&bdp_last_frag->stat); if (stat & GRETH_BD_EN) break; greth->tx_skbuff[tx_last] = NULL; greth_update_tx_stats(dev, stat); dev->stats.tx_bytes += skb->len; bdp = greth->tx_bd_base + tx_last; tx_last = NEXT_TX(tx_last); dma_unmap_single(greth->dev, greth_read_bd(&bdp->addr), skb_headlen(skb), DMA_TO_DEVICE); for (i = 0; i < nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; bdp = greth->tx_bd_base + tx_last; dma_unmap_page(greth->dev, greth_read_bd(&bdp->addr), skb_frag_size(frag), DMA_TO_DEVICE); tx_last = NEXT_TX(tx_last); } dev_kfree_skb(skb); } if (skb) { /* skb is set only if the above while loop was entered */ wmb(); greth->tx_last = tx_last; if (netif_queue_stopped(dev) && (greth_num_free_bds(tx_last, greth->tx_next) > (MAX_SKB_FRAGS+1))) netif_wake_queue(dev); } }
static void greth_clean_rings(struct greth_private *greth) { int i; struct greth_bd *rx_bdp = greth->rx_bd_base; struct greth_bd *tx_bdp = greth->tx_bd_base; if (greth->gbit_mac) { /* Free and unmap RX buffers */ for (i = 0; i < GRETH_RXBD_NUM; i++, rx_bdp++) { if (greth->rx_skbuff[i] != NULL) { dev_kfree_skb(greth->rx_skbuff[i]); dma_unmap_single(greth->dev, greth_read_bd(&rx_bdp->addr), MAX_FRAME_SIZE+NET_IP_ALIGN, DMA_FROM_DEVICE); } } /* TX buffers */ while (greth->tx_free < GRETH_TXBD_NUM) { struct sk_buff *skb = greth->tx_skbuff[greth->tx_last]; int nr_frags = skb_shinfo(skb)->nr_frags; tx_bdp = greth->tx_bd_base + greth->tx_last; greth->tx_last = NEXT_TX(greth->tx_last); dma_unmap_single(greth->dev, greth_read_bd(&tx_bdp->addr), skb_headlen(skb), DMA_TO_DEVICE); for (i = 0; i < nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; tx_bdp = greth->tx_bd_base + greth->tx_last; dma_unmap_page(greth->dev, greth_read_bd(&tx_bdp->addr), skb_frag_size(frag), DMA_TO_DEVICE); greth->tx_last = NEXT_TX(greth->tx_last); } greth->tx_free += nr_frags+1; dev_kfree_skb(skb); } } else { /* 10/100 Mbps MAC */ for (i = 0; i < GRETH_RXBD_NUM; i++, rx_bdp++) { kfree(greth->rx_bufs[i]); dma_unmap_single(greth->dev, greth_read_bd(&rx_bdp->addr), MAX_FRAME_SIZE, DMA_FROM_DEVICE); } for (i = 0; i < GRETH_TXBD_NUM; i++, tx_bdp++) { kfree(greth->tx_bufs[i]); dma_unmap_single(greth->dev, greth_read_bd(&tx_bdp->addr), MAX_FRAME_SIZE, DMA_TO_DEVICE); } } }
static netdev_tx_t greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) { struct greth_private *greth = netdev_priv(dev); struct greth_bd *bdp; u32 status, dma_addr; int curr_tx, nr_frags, i, err = NETDEV_TX_OK; unsigned long flags; u16 tx_last; nr_frags = skb_shinfo(skb)->nr_frags; tx_last = greth->tx_last; rmb(); /* tx_last is updated by the poll task */ if (greth_num_free_bds(tx_last, greth->tx_next) < nr_frags + 1) { netif_stop_queue(dev); err = NETDEV_TX_BUSY; goto out; } if (netif_msg_pktdata(greth)) greth_print_tx_packet(skb); if (unlikely(skb->len > MAX_FRAME_SIZE)) { dev->stats.tx_errors++; goto out; } /* Save skb pointer. */ greth->tx_skbuff[greth->tx_next] = skb; /* Linear buf */ if (nr_frags != 0) status = GRETH_TXBD_MORE; else status = GRETH_BD_IE; if (skb->ip_summed == CHECKSUM_PARTIAL) status |= GRETH_TXBD_CSALL; status |= skb_headlen(skb) & GRETH_BD_LEN; if (greth->tx_next == GRETH_TXBD_NUM_MASK) status |= GRETH_BD_WR; bdp = greth->tx_bd_base + greth->tx_next; greth_write_bd(&bdp->stat, status); dma_addr = dma_map_single(greth->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); if (unlikely(dma_mapping_error(greth->dev, dma_addr))) goto map_error; greth_write_bd(&bdp->addr, dma_addr); curr_tx = NEXT_TX(greth->tx_next); /* Frags */ for (i = 0; i < nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; greth->tx_skbuff[curr_tx] = NULL; bdp = greth->tx_bd_base + curr_tx; status = GRETH_BD_EN; if (skb->ip_summed == CHECKSUM_PARTIAL) status |= GRETH_TXBD_CSALL; status |= skb_frag_size(frag) & GRETH_BD_LEN; /* Wrap around descriptor ring */ if (curr_tx == GRETH_TXBD_NUM_MASK) status |= GRETH_BD_WR; /* More fragments left */ if (i < nr_frags - 1) status |= GRETH_TXBD_MORE; else status |= GRETH_BD_IE; /* enable IRQ on last fragment */ greth_write_bd(&bdp->stat, status); dma_addr = skb_frag_dma_map(greth->dev, frag, 0, skb_frag_size(frag), DMA_TO_DEVICE); if (unlikely(dma_mapping_error(greth->dev, dma_addr))) goto frag_map_error; greth_write_bd(&bdp->addr, dma_addr); curr_tx = NEXT_TX(curr_tx); } wmb(); /* Enable the descriptor chain by enabling the first descriptor */ bdp = greth->tx_bd_base + greth->tx_next; greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN); spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/ greth->tx_next = curr_tx; greth_enable_tx_and_irq(greth); spin_unlock_irqrestore(&greth->devlock, flags); return NETDEV_TX_OK; frag_map_error: /* Unmap SKB mappings that succeeded and disable descriptor */ for (i = 0; greth->tx_next + i != curr_tx; i++) { bdp = greth->tx_bd_base + greth->tx_next + i; dma_unmap_single(greth->dev, greth_read_bd(&bdp->addr), greth_read_bd(&bdp->stat) & GRETH_BD_LEN, DMA_TO_DEVICE); greth_write_bd(&bdp->stat, 0); } map_error: if (net_ratelimit()) dev_warn(greth->dev, "Could not create TX DMA mapping\n"); dev_kfree_skb(skb); out: return err; }
static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) { struct cp_private *cp = netdev_priv(dev); unsigned entry; u32 eor; #if CP_VLAN_TAG_USED u32 vlan_tag = 0; #endif spin_lock_irq(&cp->lock); /* This is a hard error, log it. */ if (TX_BUFFS_AVAIL(cp) <= (skb_shinfo(skb)->nr_frags + 1)) { netif_stop_queue(dev); spin_unlock_irq(&cp->lock); printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", dev->name); return 1; } #if CP_VLAN_TAG_USED if (cp->vlgrp && vlan_tx_tag_present(skb)) vlan_tag = TxVlanTag | cpu_to_be16(vlan_tx_tag_get(skb)); #endif entry = cp->tx_head; eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; if (skb_shinfo(skb)->nr_frags == 0) { struct cp_desc *txd = &cp->tx_ring[entry]; u32 len; dma_addr_t mapping; len = skb->len; mapping = pci_map_single(cp->pdev, skb->data, len, PCI_DMA_TODEVICE); CP_VLAN_TX_TAG(txd, vlan_tag); txd->addr = cpu_to_le64(mapping); wmb(); if (skb->ip_summed == CHECKSUM_HW) { const struct iphdr *ip = skb->nh.iph; if (ip->protocol == IPPROTO_TCP) txd->opts1 = cpu_to_le32(eor | len | DescOwn | FirstFrag | LastFrag | IPCS | TCPCS); else if (ip->protocol == IPPROTO_UDP) txd->opts1 = cpu_to_le32(eor | len | DescOwn | FirstFrag | LastFrag | IPCS | UDPCS); else BUG(); } else txd->opts1 = cpu_to_le32(eor | len | DescOwn | FirstFrag | LastFrag); wmb(); cp->tx_skb[entry].skb = skb; cp->tx_skb[entry].mapping = mapping; cp->tx_skb[entry].frag = 0; entry = NEXT_TX(entry); } else { struct cp_desc *txd; u32 first_len, first_eor; dma_addr_t first_mapping; int frag, first_entry = entry; const struct iphdr *ip = skb->nh.iph; /* We must give this initial chunk to the device last. * Otherwise we could race with the device. */ first_eor = eor; first_len = skb_headlen(skb); first_mapping = pci_map_single(cp->pdev, skb->data, first_len, PCI_DMA_TODEVICE); cp->tx_skb[entry].skb = skb; cp->tx_skb[entry].mapping = first_mapping; cp->tx_skb[entry].frag = 1; entry = NEXT_TX(entry); for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag]; u32 len; u32 ctrl; dma_addr_t mapping; len = this_frag->size; mapping = pci_map_single(cp->pdev, ((void *) page_address(this_frag->page) + this_frag->page_offset), len, PCI_DMA_TODEVICE); eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; if (skb->ip_summed == CHECKSUM_HW) { ctrl = eor | len | DescOwn | IPCS; if (ip->protocol == IPPROTO_TCP) ctrl |= TCPCS; else if (ip->protocol == IPPROTO_UDP) ctrl |= UDPCS; else BUG(); } else ctrl = eor | len | DescOwn; if (frag == skb_shinfo(skb)->nr_frags - 1) ctrl |= LastFrag; txd = &cp->tx_ring[entry]; CP_VLAN_TX_TAG(txd, vlan_tag); txd->addr = cpu_to_le64(mapping); wmb(); txd->opts1 = cpu_to_le32(ctrl); wmb(); cp->tx_skb[entry].skb = skb; cp->tx_skb[entry].mapping = mapping; cp->tx_skb[entry].frag = frag + 2; entry = NEXT_TX(entry); } txd = &cp->tx_ring[first_entry]; CP_VLAN_TX_TAG(txd, vlan_tag); txd->addr = cpu_to_le64(first_mapping); wmb(); if (skb->ip_summed == CHECKSUM_HW) { if (ip->protocol == IPPROTO_TCP) txd->opts1 = cpu_to_le32(first_eor | first_len | FirstFrag | DescOwn | IPCS | TCPCS); else if (ip->protocol == IPPROTO_UDP) txd->opts1 = cpu_to_le32(first_eor | first_len | FirstFrag | DescOwn | IPCS | UDPCS); else BUG(); } else txd->opts1 = cpu_to_le32(first_eor | first_len | FirstFrag | DescOwn); wmb(); } cp->tx_head = entry; if (netif_msg_tx_queued(cp)) printk(KERN_DEBUG "%s: tx queued, slot %d, skblen %d\n", dev->name, entry, skb->len); if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1)) netif_stop_queue(dev); spin_unlock_irq(&cp->lock); cpw8(TxPoll, NormalTxPoll); dev->trans_start = jiffies; return 0; }
static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct sgiseeq_private *sp = netdev_priv(dev); struct hpc3_ethregs *hregs = sp->hregs; unsigned long flags; struct sgiseeq_tx_desc *td; int len, entry; spin_lock_irqsave(&sp->tx_lock, flags); /* Setup... */ len = skb->len; if (len < ETH_ZLEN) { if (skb_padto(skb, ETH_ZLEN)) { spin_unlock_irqrestore(&sp->tx_lock, flags); return NETDEV_TX_OK; } len = ETH_ZLEN; } dev->stats.tx_bytes += len; entry = sp->tx_new; td = &sp->tx_desc[entry]; dma_sync_desc_cpu(dev, td); /* Create entry. There are so many races with adding a new * descriptor to the chain: * 1) Assume that the HPC is off processing a DMA chain while * we are changing all of the following. * 2) Do no allow the HPC to look at a new descriptor until * we have completely set up it's state. This means, do * not clear HPCDMA_EOX in the current last descritptor * until the one we are adding looks consistent and could * be processes right now. * 3) The tx interrupt code must notice when we've added a new * entry and the HPC got to the end of the chain before we * added this new entry and restarted it. */ td->skb = skb; td->tdma.pbuf = dma_map_single(dev->dev.parent, skb->data, len, DMA_TO_DEVICE); td->tdma.cntinfo = (len & HPCDMA_BCNT) | HPCDMA_XIU | HPCDMA_EOXP | HPCDMA_XIE | HPCDMA_EOX; dma_sync_desc_dev(dev, td); if (sp->tx_old != sp->tx_new) { struct sgiseeq_tx_desc *backend; backend = &sp->tx_desc[PREV_TX(sp->tx_new)]; dma_sync_desc_cpu(dev, backend); backend->tdma.cntinfo &= ~HPCDMA_EOX; dma_sync_desc_dev(dev, backend); } sp->tx_new = NEXT_TX(sp->tx_new); /* Advance. */ /* Maybe kick the HPC back into motion. */ if (!(hregs->tx_ctrl & HPC3_ETXCTRL_ACTIVE)) kick_tx(dev, sp, hregs); dev->trans_start = jiffies; if (!TX_BUFFS_AVAIL(sp)) netif_stop_queue(dev); spin_unlock_irqrestore(&sp->tx_lock, flags); return NETDEV_TX_OK; }
static netdev_tx_t greth_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct greth_private *greth = netdev_priv(dev); struct greth_bd *bdp; int err = NETDEV_TX_OK; u32 status, dma_addr; bdp = greth->tx_bd_base + greth->tx_next; if (unlikely(greth->tx_free <= 0)) { netif_stop_queue(dev); return NETDEV_TX_BUSY; } if (netif_msg_pktdata(greth)) greth_print_tx_packet(skb); if (unlikely(skb->len > MAX_FRAME_SIZE)) { dev->stats.tx_errors++; goto out; } dma_addr = greth_read_bd(&bdp->addr); memcpy((unsigned char *) phys_to_virt(dma_addr), skb->data, skb->len); dma_sync_single_for_device(greth->dev, dma_addr, skb->len, DMA_TO_DEVICE); status = GRETH_BD_EN | (skb->len & GRETH_BD_LEN); /* Wrap around descriptor ring */ if (greth->tx_next == GRETH_TXBD_NUM_MASK) { status |= GRETH_BD_WR; } greth->tx_next = NEXT_TX(greth->tx_next); greth->tx_free--; /* No more descriptors */ if (unlikely(greth->tx_free == 0)) { /* Free transmitted descriptors */ greth_clean_tx(dev); /* If nothing was cleaned, stop queue & wait for irq */ if (unlikely(greth->tx_free == 0)) { status |= GRETH_BD_IE; netif_stop_queue(dev); } } /* Write descriptor control word and enable transmission */ greth_write_bd(&bdp->stat, status); greth_enable_tx(greth); out: dev_kfree_skb(skb); return err; }
static netdev_tx_t greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) { struct greth_private *greth = netdev_priv(dev); struct greth_bd *bdp; u32 status = 0, dma_addr; int curr_tx, nr_frags, i, err = NETDEV_TX_OK; nr_frags = skb_shinfo(skb)->nr_frags; if (greth->tx_free < nr_frags + 1) { netif_stop_queue(dev); err = NETDEV_TX_BUSY; goto out; } if (netif_msg_pktdata(greth)) greth_print_tx_packet(skb); if (unlikely(skb->len > MAX_FRAME_SIZE)) { dev->stats.tx_errors++; goto out; } /* Save skb pointer. */ greth->tx_skbuff[greth->tx_next] = skb; /* Linear buf */ if (nr_frags != 0) status = GRETH_TXBD_MORE; status |= GRETH_TXBD_CSALL; status |= skb_headlen(skb) & GRETH_BD_LEN; if (greth->tx_next == GRETH_TXBD_NUM_MASK) status |= GRETH_BD_WR; bdp = greth->tx_bd_base + greth->tx_next; greth_write_bd(&bdp->stat, status); dma_addr = dma_map_single(greth->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); if (unlikely(dma_mapping_error(greth->dev, dma_addr))) goto map_error; greth_write_bd(&bdp->addr, dma_addr); curr_tx = NEXT_TX(greth->tx_next); /* Frags */ for (i = 0; i < nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; greth->tx_skbuff[curr_tx] = NULL; bdp = greth->tx_bd_base + curr_tx; status = GRETH_TXBD_CSALL; status |= frag->size & GRETH_BD_LEN; /* Wrap around descriptor ring */ if (curr_tx == GRETH_TXBD_NUM_MASK) status |= GRETH_BD_WR; /* More fragments left */ if (i < nr_frags - 1) status |= GRETH_TXBD_MORE; /* ... last fragment, check if out of descriptors */ else if (greth->tx_free - nr_frags - 1 < (MAX_SKB_FRAGS + 1)) { /* Enable interrupts and stop queue */ status |= GRETH_BD_IE; netif_stop_queue(dev); } greth_write_bd(&bdp->stat, status); dma_addr = dma_map_page(greth->dev, frag->page, frag->page_offset, frag->size, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(greth->dev, dma_addr))) goto frag_map_error; greth_write_bd(&bdp->addr, dma_addr); curr_tx = NEXT_TX(curr_tx); } wmb(); /* Enable the descriptors that we configured ... */ for (i = 0; i < nr_frags + 1; i++) { bdp = greth->tx_bd_base + greth->tx_next; greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN); greth->tx_next = NEXT_TX(greth->tx_next); greth->tx_free--; } greth_enable_tx(greth); return NETDEV_TX_OK; frag_map_error: /* Unmap SKB mappings that succeeded */ for (i = 0; greth->tx_next + i != curr_tx; i++) { bdp = greth->tx_bd_base + greth->tx_next + i; dma_unmap_single(greth->dev, greth_read_bd(&bdp->addr), greth_read_bd(&bdp->stat) & GRETH_BD_LEN, DMA_TO_DEVICE); } map_error: if (net_ratelimit()) dev_warn(greth->dev, "Could not create TX DMA mapping\n"); dev_kfree_skb(skb); out: return err; }
static netdev_tx_t greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) { struct greth_private *greth = netdev_priv(dev); struct greth_bd *bdp; u32 status = 0, dma_addr, ctrl; int curr_tx, nr_frags, i, err = NETDEV_TX_OK; unsigned long flags; nr_frags = skb_shinfo(skb)->nr_frags; /* Clean TX Ring */ greth_clean_tx_gbit(dev); if (greth->tx_free < nr_frags + 1) { spin_lock_irqsave(&greth->devlock, flags);/*save from poll/irq*/ ctrl = GRETH_REGLOAD(greth->regs->control); /* Enable TX IRQ only if not already in poll() routine */ if (ctrl & GRETH_RXI) GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI); netif_stop_queue(dev); spin_unlock_irqrestore(&greth->devlock, flags); err = NETDEV_TX_BUSY; goto out; } if (netif_msg_pktdata(greth)) greth_print_tx_packet(skb); if (unlikely(skb->len > MAX_FRAME_SIZE)) { dev->stats.tx_errors++; goto out; } /* Save skb pointer. */ greth->tx_skbuff[greth->tx_next] = skb; /* Linear buf */ if (nr_frags != 0) status = GRETH_TXBD_MORE; status |= GRETH_TXBD_CSALL; status |= skb_headlen(skb) & GRETH_BD_LEN; if (greth->tx_next == GRETH_TXBD_NUM_MASK) status |= GRETH_BD_WR; bdp = greth->tx_bd_base + greth->tx_next; greth_write_bd(&bdp->stat, status); dma_addr = dma_map_single(greth->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); if (unlikely(dma_mapping_error(greth->dev, dma_addr))) goto map_error; greth_write_bd(&bdp->addr, dma_addr); curr_tx = NEXT_TX(greth->tx_next); /* Frags */ for (i = 0; i < nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; greth->tx_skbuff[curr_tx] = NULL; bdp = greth->tx_bd_base + curr_tx; status = GRETH_TXBD_CSALL | GRETH_BD_EN; status |= frag->size & GRETH_BD_LEN; /* Wrap around descriptor ring */ if (curr_tx == GRETH_TXBD_NUM_MASK) status |= GRETH_BD_WR; /* More fragments left */ if (i < nr_frags - 1) status |= GRETH_TXBD_MORE; else status |= GRETH_BD_IE; /* enable IRQ on last fragment */ greth_write_bd(&bdp->stat, status); dma_addr = dma_map_page(greth->dev, frag->page, frag->page_offset, frag->size, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(greth->dev, dma_addr))) goto frag_map_error; greth_write_bd(&bdp->addr, dma_addr); curr_tx = NEXT_TX(curr_tx); } wmb(); /* Enable the descriptor chain by enabling the first descriptor */ bdp = greth->tx_bd_base + greth->tx_next; greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN); greth->tx_next = curr_tx; greth->tx_free -= nr_frags + 1; wmb(); spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/ greth_enable_tx(greth); spin_unlock_irqrestore(&greth->devlock, flags); return NETDEV_TX_OK; frag_map_error: /* Unmap SKB mappings that succeeded and disable descriptor */ for (i = 0; greth->tx_next + i != curr_tx; i++) { bdp = greth->tx_bd_base + greth->tx_next + i; dma_unmap_single(greth->dev, greth_read_bd(&bdp->addr), greth_read_bd(&bdp->stat) & GRETH_BD_LEN, DMA_TO_DEVICE); greth_write_bd(&bdp->stat, 0); } map_error: if (net_ratelimit()) dev_warn(greth->dev, "Could not create TX DMA mapping\n"); dev_kfree_skb(skb); out: return err; }