/* Packet receive function */ static int sh_eth_rx(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); struct sh_eth_rxdesc *rxdesc; int entry = mdp->cur_rx % RX_RING_SIZE; int boguscnt = (mdp->dirty_rx + RX_RING_SIZE) - mdp->cur_rx; struct sk_buff *skb; u16 pkt_len = 0; u32 desc_status, reserve = 0; rxdesc = &mdp->rx_ring[entry]; while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) { desc_status = edmac_to_cpu(mdp, rxdesc->status); pkt_len = rxdesc->frame_length; if (--boguscnt < 0) break; if (!(desc_status & RDFEND)) mdp->stats.rx_length_errors++; if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 | RD_RFS5 | RD_RFS6 | RD_RFS10)) { mdp->stats.rx_errors++; if (desc_status & RD_RFS1) mdp->stats.rx_crc_errors++; if (desc_status & RD_RFS2) mdp->stats.rx_frame_errors++; if (desc_status & RD_RFS3) mdp->stats.rx_length_errors++; if (desc_status & RD_RFS4) mdp->stats.rx_length_errors++; if (desc_status & RD_RFS6) mdp->stats.rx_missed_errors++; if (desc_status & RD_RFS10) mdp->stats.rx_over_errors++; } else { swaps((char *)(rxdesc->addr & ~0x3), pkt_len + 2); skb = mdp->rx_skbuff[entry]; mdp->rx_skbuff[entry] = NULL; skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, ndev); netif_rx(skb); mdp->stats.rx_packets++; mdp->stats.rx_bytes += pkt_len; } rxdesc->status |= cpu_to_edmac(mdp, RD_RACT); entry = (++mdp->cur_rx) % RX_RING_SIZE; } /* Refill the Rx ring buffers. */ for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) { entry = mdp->dirty_rx % RX_RING_SIZE; rxdesc = &mdp->rx_ring[entry]; /* The size of the buffer is 16 byte boundary. */ rxdesc->buffer_length = (mdp->rx_buf_sz + 16) & ~0x0F; if (mdp->rx_skbuff[entry] == NULL) { skb = dev_alloc_skb(mdp->rx_buf_sz); mdp->rx_skbuff[entry] = skb; if (skb == NULL) break; /* Better luck next round. */ skb->dev = ndev; #if defined(CONFIG_CPU_SUBTYPE_SH7763) reserve = SH7763_SKB_ALIGN - ((uint32_t)skb->data & (SH7763_SKB_ALIGN-1)); if (reserve) skb_reserve(skb, reserve); #else skb_reserve(skb, RX_OFFSET); #endif skb->ip_summed = CHECKSUM_NONE; rxdesc->addr = (u32)skb->data & ~0x3UL; } if (entry >= RX_RING_SIZE - 1) rxdesc->status |= cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDEL); else rxdesc->status |= cpu_to_edmac(mdp, RD_RACT | RD_RFP); } /* Restart Rx engine if stopped. */ /* If we don't need to check status, don't. -KDU */ if (!(ctrl_inl(ndev->base_addr + EDRRR) & EDRRR_R)) ctrl_outl(EDRRR_R, ndev->base_addr + EDRRR); return 0; }
/* Packet receive function */ static int sh_eth_rx(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); struct sh_eth_rxdesc *rxdesc; int entry = mdp->cur_rx % RX_RING_SIZE; int boguscnt = (mdp->dirty_rx + RX_RING_SIZE) - mdp->cur_rx; struct sk_buff *skb; u16 pkt_len = 0; u32 desc_status; rxdesc = &mdp->rx_ring[entry]; while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) { desc_status = edmac_to_cpu(mdp, rxdesc->status); pkt_len = rxdesc->frame_length; if (--boguscnt < 0) break; if (!(desc_status & RDFEND)) mdp->stats.rx_length_errors++; if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 | RD_RFS5 | RD_RFS6 | RD_RFS10)) { mdp->stats.rx_errors++; if (desc_status & RD_RFS1) mdp->stats.rx_crc_errors++; if (desc_status & RD_RFS2) mdp->stats.rx_frame_errors++; if (desc_status & RD_RFS3) mdp->stats.rx_length_errors++; if (desc_status & RD_RFS4) mdp->stats.rx_length_errors++; if (desc_status & RD_RFS6) mdp->stats.rx_missed_errors++; if (desc_status & RD_RFS10) mdp->stats.rx_over_errors++; } else { if (!mdp->cd->hw_swap) sh_eth_soft_swap( phys_to_virt(ALIGN(rxdesc->addr, 4)), pkt_len + 2); skb = mdp->rx_skbuff[entry]; mdp->rx_skbuff[entry] = NULL; if (mdp->cd->rpadir) skb_reserve(skb, NET_IP_ALIGN); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, ndev); netif_rx(skb); mdp->stats.rx_packets++; mdp->stats.rx_bytes += pkt_len; } rxdesc->status |= cpu_to_edmac(mdp, RD_RACT); entry = (++mdp->cur_rx) % RX_RING_SIZE; rxdesc = &mdp->rx_ring[entry]; } /* Refill the Rx ring buffers. */ for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) { entry = mdp->dirty_rx % RX_RING_SIZE; rxdesc = &mdp->rx_ring[entry]; /* The size of the buffer is 16 byte boundary. */ rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16); if (mdp->rx_skbuff[entry] == NULL) { skb = dev_alloc_skb(mdp->rx_buf_sz); mdp->rx_skbuff[entry] = skb; if (skb == NULL) break; /* Better luck next round. */ dma_map_single(&ndev->dev, skb->tail, mdp->rx_buf_sz, DMA_FROM_DEVICE); skb->dev = ndev; sh_eth_set_receive_align(skb); skb_checksum_none_assert(skb); rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4)); } if (entry >= RX_RING_SIZE - 1) rxdesc->status |= cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDEL); else rxdesc->status |= cpu_to_edmac(mdp, RD_RACT | RD_RFP); } /* Restart Rx engine if stopped. */ /* If we don't need to check status, don't. -KDU */ if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R)) sh_eth_write(ndev, EDRRR_R, EDRRR); return 0; }