/* * poll func, called by network core */ static int bcm_enet_poll(struct napi_struct *napi, int budget) { struct bcm_enet_priv *priv; struct net_device *dev; int tx_work_done, rx_work_done; priv = container_of(napi, struct bcm_enet_priv, napi); dev = priv->net_dev; /* ack interrupts */ enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, ENETDMA_IR_REG(priv->rx_chan)); enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, ENETDMA_IR_REG(priv->tx_chan)); /* reclaim sent skb */ tx_work_done = bcm_enet_tx_reclaim(dev, 0); spin_lock(&priv->rx_lock); rx_work_done = bcm_enet_receive_queue(dev, budget); spin_unlock(&priv->rx_lock); if (rx_work_done >= budget || tx_work_done > 0) { /* rx/tx queue is not yet empty/clean */ return rx_work_done; } /* no more packet in rx/tx queue, remove device from poll * queue */ __netif_rx_complete(dev, napi); /* restore rx/tx interrupt */ enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, ENETDMA_IRMASK_REG(priv->rx_chan)); enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, ENETDMA_IRMASK_REG(priv->tx_chan)); return rx_work_done; }
static int cp_rx_poll (struct net_device *dev, int *budget) { struct cp_private *cp = netdev_priv(dev); unsigned rx_tail = cp->rx_tail; unsigned rx_work = dev->quota; unsigned rx; rx_status_loop: rx = 0; cpw16(IntrStatus, cp_rx_intr_mask); while (1) { u32 status, len; dma_addr_t mapping; struct sk_buff *skb, *new_skb; struct cp_desc *desc; unsigned buflen; skb = cp->rx_skb[rx_tail].skb; if (!skb) BUG(); desc = &cp->rx_ring[rx_tail]; status = le32_to_cpu(desc->opts1); if (status & DescOwn) break; len = (status & 0x1fff) - 4; mapping = cp->rx_skb[rx_tail].mapping; if ((status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag)) { /* we don't support incoming fragmented frames. * instead, we attempt to ensure that the * pre-allocated RX skbs are properly sized such * that RX fragments are never encountered */ cp_rx_err_acct(cp, rx_tail, status, len); cp->net_stats.rx_dropped++; cp->cp_stats.rx_frags++; goto rx_next; } if (status & (RxError | RxErrFIFO)) { cp_rx_err_acct(cp, rx_tail, status, len); goto rx_next; } if (netif_msg_rx_status(cp)) printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d\n", cp->dev->name, rx_tail, status, len); buflen = cp->rx_buf_sz + RX_OFFSET; new_skb = dev_alloc_skb (buflen); if (!new_skb) { cp->net_stats.rx_dropped++; goto rx_next; } skb_reserve(new_skb, RX_OFFSET); new_skb->dev = cp->dev; pci_unmap_single(cp->pdev, mapping, buflen, PCI_DMA_FROMDEVICE); /* Handle checksum offloading for incoming packets. */ if (cp_rx_csum_ok(status)) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb->ip_summed = CHECKSUM_NONE; skb_put(skb, len); mapping = cp->rx_skb[rx_tail].mapping = pci_map_single(cp->pdev, new_skb->tail, buflen, PCI_DMA_FROMDEVICE); cp->rx_skb[rx_tail].skb = new_skb; cp_rx_skb(cp, skb, desc); rx++; rx_next: cp->rx_ring[rx_tail].opts2 = 0; cp->rx_ring[rx_tail].addr = cpu_to_le64(mapping); if (rx_tail == (CP_RX_RING_SIZE - 1)) desc->opts1 = cpu_to_le32(DescOwn | RingEnd | cp->rx_buf_sz); else desc->opts1 = cpu_to_le32(DescOwn | cp->rx_buf_sz); rx_tail = NEXT_RX(rx_tail); if (!rx_work--) break; } cp->rx_tail = rx_tail; dev->quota -= rx; *budget -= rx; /* if we did not reach work limit, then we're done with * this round of polling */ if (rx_work) { if (cpr16(IntrStatus) & cp_rx_intr_mask) goto rx_status_loop; local_irq_disable(); cpw16_f(IntrMask, cp_intr_mask); __netif_rx_complete(dev); local_irq_enable(); return 0; /* done */ } return 1; /* not done */ }