--- linux-2.6.27.5/drivers/net/korina.c 2008-11-07 18:55:34.000000000 +0100 +++ ../build_dir/linux-rb532/linux-2.6.27.5/drivers/net/korina.c 2008-11-16 00:38:19.000000000 +0100 @@ -327,12 +327,11 @@ dmas = readl(&lp->rx_dma_regs->dmas); if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) { - netif_rx_schedule_prep(dev, &lp->napi); - dmasm = readl(&lp->rx_dma_regs->dmasm); writel(dmasm | (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR), &lp->rx_dma_regs->dmasm); + netif_rx_schedule(dev, &lp->napi); if (dmas & DMA_STAT_ERR) printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name); @@ -350,14 +349,24 @@ struct dma_desc *rd = &lp->rd_ring[lp->rx_next_done]; struct sk_buff *skb, *skb_new; u8 *pkt_buf; - u32 devcs, pkt_len, dmas, rx_free_desc; + u32 devcs, pkt_len, dmas, pktuncrc_len; int count; dma_cache_inv((u32)rd, sizeof(*rd)); for (count = 0; count < limit; count++) { - + skb_new = NULL; devcs = rd->devcs; + pkt_len = RCVPKT_LENGTH(devcs); + skb = lp->rx_skb[lp->rx_next_done]; + + if ((devcs & ETH_RX_LD) != ETH_RX_LD) { + /* check that this is a whole packet + * WARNING: DMA_FD bit incorrectly set + * in Rc32434 (errata ref #077) */ + dev->stats.rx_errors++; + dev->stats.rx_dropped++; + } /* Update statistics counters */ if (devcs & ETH_RX_CRC) @@ -375,75 +384,79 @@ if (devcs & ETH_RX_MP) dev->stats.multicast++; - if ((devcs & ETH_RX_LD) != ETH_RX_LD) { - /* check that this is a whole packet - * WARNING: DMA_FD bit incorrectly set - * in Rc32434 (errata ref #077) */ - dev->stats.rx_errors++; - dev->stats.rx_dropped++; - } - - while ((rx_free_desc = KORINA_RBSIZE - (u32)DMA_COUNT(rd->control)) != 0) { - /* init the var. used for the later - * operations within the while loop */ - skb_new = NULL; - pkt_len = RCVPKT_LENGTH(devcs); - skb = lp->rx_skb[lp->rx_next_done]; - - if ((devcs & ETH_RX_ROK)) { - /* must be the (first and) last - * descriptor then */ - pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data; + else if ((devcs & ETH_RX_ROK)) { + /* must be the (first and) last + * descriptor then */ + pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data; + pktuncrc_len = pkt_len - 4; - /* invalidate the cache */ - dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4); + /* invalidate the cache */ + dma_cache_inv((unsigned long)pkt_buf, pktuncrc_len); - /* Malloc up new buffer. */ - skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2); + /* Malloc up new buffer. */ + skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2); - if (!skb_new) - break; + if (skb_new) { /* Do not count the CRC */ - skb_put(skb, pkt_len - 4); + skb_put(skb, pktuncrc_len); skb->protocol = eth_type_trans(skb, dev); /* Pass the packet to upper layers */ netif_receive_skb(skb); + dev->last_rx = jiffies; dev->stats.rx_packets++; - dev->stats.rx_bytes += pkt_len; - - /* Update the mcast stats */ - if (devcs & ETH_RX_MP) - dev->stats.multicast++; - + dev->stats.rx_bytes += pktuncrc_len; + lp->rx_skb[lp->rx_next_done] = skb_new; + } else { + dev->stats.rx_errors++; + dev->stats.rx_dropped++; } + } else { + dev->stats.rx_errors++; + dev->stats.rx_dropped++; + + /* Update statistics counters */ + if (devcs & ETH_RX_CRC) + dev->stats.rx_crc_errors++; + else if (devcs & ETH_RX_LOR) + dev->stats.rx_length_errors++; + else if (devcs & ETH_RX_LE) + dev->stats.rx_length_errors++; + else if (devcs & ETH_RX_OVR) + dev->stats.rx_over_errors++; + else if (devcs & ETH_RX_CV) + dev->stats.rx_frame_errors++; + else if (devcs & ETH_RX_CES) + dev->stats.rx_length_errors++; + else if (devcs & ETH_RX_MP) + dev->stats.multicast++; + } - rd->devcs = 0; + rd->devcs = 0; - /* Restore descriptor's curr_addr */ - if (skb_new) - rd->ca = CPHYSADDR(skb_new->data); - else - rd->ca = CPHYSADDR(skb->data); + /* Restore descriptor's curr_addr */ + if (skb_new) + rd->ca = CPHYSADDR(skb_new->data); + else + rd->ca = CPHYSADDR(skb->data); - rd->control = DMA_COUNT(KORINA_RBSIZE) | + rd->control = DMA_COUNT(KORINA_RBSIZE) | DMA_DESC_COD | DMA_DESC_IOD; - lp->rd_ring[(lp->rx_next_done - 1) & - KORINA_RDS_MASK].control &= - ~DMA_DESC_COD; - - lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK; - dma_cache_wback((u32)rd, sizeof(*rd)); - rd = &lp->rd_ring[lp->rx_next_done]; - writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas); - } + lp->rd_ring[(lp->rx_next_done - 1) & + KORINA_RDS_MASK].control &= ~DMA_DESC_COD; + + lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK; + dma_cache_wback((u32)rd, sizeof(*rd)); + rd = &lp->rd_ring[lp->rx_next_done]; + writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas); } dmas = readl(&lp->rx_dma_regs->dmas); if (dmas & DMA_STAT_HALT) { + /* Mask off halt and errors bits */ writel(~(DMA_STAT_HALT | DMA_STAT_ERR), &lp->rx_dma_regs->dmas); @@ -469,8 +482,9 @@ if (work_done < budget) { netif_rx_complete(dev, napi); + /* Mask off interrupts */ writel(readl(&lp->rx_dma_regs->dmasm) & - ~(DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR), + (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR), &lp->rx_dma_regs->dmasm); } return work_done; @@ -534,10 +548,11 @@ { struct korina_private *lp = netdev_priv(dev); struct dma_desc *td = &lp->td_ring[lp->tx_next_done]; + unsigned long flags; u32 devcs; u32 dmas; - spin_lock(&lp->lock); + spin_lock_irqsave(&lp->lock, flags); /* Process all desc that are done */ while (IS_DMA_FINISHED(td->control)) { @@ -610,7 +625,7 @@ ~(DMA_STAT_FINI | DMA_STAT_ERR), &lp->tx_dma_regs->dmasm); - spin_unlock(&lp->lock); + spin_unlock_irqrestore(&lp->lock, flags); } static irqreturn_t @@ -624,11 +639,10 @@ dmas = readl(&lp->tx_dma_regs->dmas); if (dmas & (DMA_STAT_FINI | DMA_STAT_ERR)) { - korina_tx(dev); - dmasm = readl(&lp->tx_dma_regs->dmasm); writel(dmasm | (DMA_STAT_FINI | DMA_STAT_ERR), &lp->tx_dma_regs->dmasm); + korina_tx(dev); if (lp->tx_chain_status == desc_filled && (readl(&(lp->tx_dma_regs->dmandptr)) == 0)) { @@ -1078,11 +1092,18 @@ static int korina_probe(struct platform_device *pdev) { - struct korina_device *bif = platform_get_drvdata(pdev); + struct korina_device *bif; struct korina_private *lp; struct net_device *dev; struct resource *r; int rc; + DECLARE_MAC_BUF(mac); + + bif = (struct korina_device *)pdev->dev.platform_data; + if (!bif) { + printk(KERN_ERR DRV_NAME ": missing platform_data\n"); + return -ENODEV; + } dev = alloc_etherdev(sizeof(struct korina_private)); if (!dev) { @@ -1172,6 +1193,7 @@ ": cannot register net device %d\n", rc); goto probe_err_register; } + printk(KERN_INFO DRV_NAME ": registered %s, IRQ %d MAC %s\n", dev->name, dev->irq, print_mac(mac, dev->dev_addr)); out: return rc;