- priv->regs->rx_ack[channel] = virt_to_phys(pkt);
- dma_cache_inv((u32)pkt, 16);
- if (!pkt->datalen) {
- if (printk_ratelimit())
- printk(KERN_NOTICE "%s: rx: spurious interrupt\n",
- dev->name);
- priv->stats.rx_errors++;
- return;
- }
- skb = dev_alloc_skb(1536);
- if (!skb) {
- if (printk_ratelimit())
- printk(KERN_NOTICE "%s: rx: low on mem - packet dropped\n",
- dev->name);
- priv->stats.rx_dropped++;
- } else {
- data = (char *)phys_to_virt(pkt->hw_data);
- dma_cache_inv((u32)data, pkt->datalen);
- skb_put(pkt->skb, pkt->datalen);
- pkt->skb->protocol = eth_type_trans(pkt->skb, dev);
- pkt->skb->ip_summed = CHECKSUM_NONE;
- priv->stats.rx_packets++;
- priv->stats.rx_bytes += pkt->datalen;
- netif_rx(pkt->skb);
- skb_reserve(skb, 2);
- skb->dev = dev;
- pkt->skb = skb;
- pkt->hw_data = virt_to_phys(skb->data);
+ desc = priv->rx_head;
+ dma_cache_inv((u32)desc, 16);
+
+ while((desc->dataflags & CPMAC_OWN) == 0) {
+ priv->regs->rx_ack[0] = virt_to_phys(desc);
+ if (unlikely(!desc->datalen)) {
+ if (printk_ratelimit())
+ printk(KERN_NOTICE "%s: rx: spurious interrupt\n",
+ dev->name);
+ priv->stats.rx_errors++;
+ goto out;
+ }
+
+ skb = cpmac_get_skb(dev);
+ if (likely(skb)) {
+ data = (char *)phys_to_virt(desc->hw_data);
+ dma_cache_inv((u32)data, desc->datalen);
+ skb_put(desc->skb, desc->datalen);
+ desc->skb->protocol = eth_type_trans(desc->skb, dev);
+ desc->skb->ip_summed = CHECKSUM_NONE;
+ priv->stats.rx_packets++;
+ priv->stats.rx_bytes += desc->datalen;
+ netif_rx(desc->skb);
+ desc->skb = skb;
+ } else {
+ if (printk_ratelimit())
+ printk(KERN_NOTICE "%s: rx: no free skbs, dropping packet\n",
+ dev->name);
+ priv->stats.rx_dropped++;
+ }
+ desc->hw_data = virt_to_phys(desc->skb->data);
+ desc->buflen = CPMAC_SKB_SIZE;
+ desc->dataflags = CPMAC_OWN;
+ dma_cache_wback((u32)desc, 16);
+ desc = desc->next;
+ dma_cache_inv((u32)desc, 16);