diff options
Diffstat (limited to 'drivers/net/ethoc.c')
| -rw-r--r-- | drivers/net/ethoc.c | 160 | 
1 files changed, 71 insertions, 89 deletions
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index 6ed2df14ec8..6d653c459c1 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -180,9 +180,9 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");   * @dty_tx:	last buffer actually sent   * @num_rx:	number of receive buffers   * @cur_rx:	current receive buffer + * @vma:        pointer to array of virtual memory addresses for buffers   * @netdev:	pointer to network device structure   * @napi:	NAPI structure - * @stats:	network device statistics   * @msg_enable:	device state flags   * @rx_lock:	receive lock   * @lock:	device lock @@ -203,9 +203,10 @@ struct ethoc {  	unsigned int num_rx;  	unsigned int cur_rx; +	void** vma; +  	struct net_device *netdev;  	struct napi_struct napi; -	struct net_device_stats stats;  	u32 msg_enable;  	spinlock_t rx_lock; @@ -285,18 +286,22 @@ static inline void ethoc_disable_rx_and_tx(struct ethoc *dev)  	ethoc_write(dev, MODER, mode);  } -static int ethoc_init_ring(struct ethoc *dev) +static int ethoc_init_ring(struct ethoc *dev, unsigned long mem_start)  {  	struct ethoc_bd bd;  	int i; +	void* vma;  	dev->cur_tx = 0;  	dev->dty_tx = 0;  	dev->cur_rx = 0; +	ethoc_write(dev, TX_BD_NUM, dev->num_tx); +  	/* setup transmission buffers */ -	bd.addr = virt_to_phys(dev->membase); +	bd.addr = mem_start;  	bd.stat = TX_BD_IRQ | TX_BD_CRC; +	vma = dev->membase;  	for (i = 0; i < dev->num_tx; i++) {  		if (i == dev->num_tx - 1) @@ -304,6 +309,9 @@ static int ethoc_init_ring(struct ethoc *dev)  		ethoc_write_bd(dev, i, &bd);  		bd.addr += ETHOC_BUFSIZ; + +		dev->vma[i] = vma; +		vma += ETHOC_BUFSIZ;  	}  	bd.stat = RX_BD_EMPTY | RX_BD_IRQ; @@ -314,6 +322,9 @@ static int ethoc_init_ring(struct ethoc *dev)  		ethoc_write_bd(dev, dev->num_tx + i, &bd);  		bd.addr += ETHOC_BUFSIZ; + +		dev->vma[dev->num_tx + i] = vma; +		vma += ETHOC_BUFSIZ;  	}  	return 0; @@ -354,39 +365,39 @@ static unsigned int ethoc_update_rx_stats(struct ethoc *dev,  	if (bd->stat & RX_BD_TL) {  		dev_err(&netdev->dev, "RX: frame too long\n"); -		dev->stats.rx_length_errors++; +		netdev->stats.rx_length_errors++;  		ret++;  	}  	if (bd->stat & RX_BD_SF) {  		dev_err(&netdev->dev, "RX: frame too short\n"); -		dev->stats.rx_length_errors++; +		netdev->stats.rx_length_errors++;  		ret++;  	}  	if (bd->stat & RX_BD_DN) {  		dev_err(&netdev->dev, "RX: dribble nibble\n"); -		dev->stats.rx_frame_errors++; +		netdev->stats.rx_frame_errors++;  	}  	if (bd->stat & RX_BD_CRC) {  		dev_err(&netdev->dev, "RX: wrong CRC\n"); -		dev->stats.rx_crc_errors++; +		netdev->stats.rx_crc_errors++;  		ret++;  	}  	if (bd->stat & RX_BD_OR) {  		dev_err(&netdev->dev, "RX: overrun\n"); -		dev->stats.rx_over_errors++; +		netdev->stats.rx_over_errors++;  		ret++;  	}  	if (bd->stat & RX_BD_MISS) -		dev->stats.rx_missed_errors++; +		netdev->stats.rx_missed_errors++;  	if (bd->stat & RX_BD_LC) {  		dev_err(&netdev->dev, "RX: late collision\n"); -		dev->stats.collisions++; +		netdev->stats.collisions++;  		ret++;  	} @@ -415,18 +426,18 @@ static int ethoc_rx(struct net_device *dev, int limit)  			skb = netdev_alloc_skb_ip_align(dev, size);  			if (likely(skb)) { -				void *src = phys_to_virt(bd.addr); +				void *src = priv->vma[entry];  				memcpy_fromio(skb_put(skb, size), src, size);  				skb->protocol = eth_type_trans(skb, dev); -				priv->stats.rx_packets++; -				priv->stats.rx_bytes += size; +				dev->stats.rx_packets++; +				dev->stats.rx_bytes += size;  				netif_receive_skb(skb);  			} else {  				if (net_ratelimit())  					dev_warn(&dev->dev, "low on memory - "  							"packet dropped\n"); -				priv->stats.rx_dropped++; +				dev->stats.rx_dropped++;  				break;  			}  		} @@ -447,30 +458,30 @@ static int ethoc_update_tx_stats(struct ethoc *dev, struct ethoc_bd *bd)  	if (bd->stat & TX_BD_LC) {  		dev_err(&netdev->dev, "TX: late collision\n"); -		dev->stats.tx_window_errors++; +		netdev->stats.tx_window_errors++;  	}  	if (bd->stat & TX_BD_RL) {  		dev_err(&netdev->dev, "TX: retransmit limit\n"); -		dev->stats.tx_aborted_errors++; +		netdev->stats.tx_aborted_errors++;  	}  	if (bd->stat & TX_BD_UR) {  		dev_err(&netdev->dev, "TX: underrun\n"); -		dev->stats.tx_fifo_errors++; +		netdev->stats.tx_fifo_errors++;  	}  	if (bd->stat & TX_BD_CS) {  		dev_err(&netdev->dev, "TX: carrier sense lost\n"); -		dev->stats.tx_carrier_errors++; +		netdev->stats.tx_carrier_errors++;  	}  	if (bd->stat & TX_BD_STATS) -		dev->stats.tx_errors++; +		netdev->stats.tx_errors++; -	dev->stats.collisions += (bd->stat >> 4) & 0xf; -	dev->stats.tx_bytes += bd->stat >> 16; -	dev->stats.tx_packets++; +	netdev->stats.collisions += (bd->stat >> 4) & 0xf; +	netdev->stats.tx_bytes += bd->stat >> 16; +	netdev->stats.tx_packets++;  	return 0;  } @@ -501,7 +512,7 @@ static void ethoc_tx(struct net_device *dev)  static irqreturn_t ethoc_interrupt(int irq, void *dev_id)  { -	struct net_device *dev = (struct net_device *)dev_id; +	struct net_device *dev = dev_id;  	struct ethoc *priv = netdev_priv(dev);  	u32 pending; @@ -516,7 +527,7 @@ static irqreturn_t ethoc_interrupt(int irq, void *dev_id)  	if (pending & INT_MASK_BUSY) {  		dev_err(&dev->dev, "packet dropped\n"); -		priv->stats.rx_dropped++; +		dev->stats.rx_dropped++;  	}  	if (pending & INT_MASK_RX) { @@ -600,8 +611,11 @@ static int ethoc_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)  	while (time_before(jiffies, timeout)) {  		u32 stat = ethoc_read(priv, MIISTATUS); -		if (!(stat & MIISTATUS_BUSY)) +		if (!(stat & MIISTATUS_BUSY)) { +			/* reset MII command register */ +			ethoc_write(priv, MIICOMMAND, 0);  			return 0; +		}  		schedule();  	} @@ -618,25 +632,16 @@ static void ethoc_mdio_poll(struct net_device *dev)  {  } -static int ethoc_mdio_probe(struct net_device *dev) +static int __devinit ethoc_mdio_probe(struct net_device *dev)  {  	struct ethoc *priv = netdev_priv(dev);  	struct phy_device *phy; -	int i; +	int err; -	for (i = 0; i < PHY_MAX_ADDR; i++) { -		phy = priv->mdio->phy_map[i]; -		if (phy) { -			if (priv->phy_id != -1) { -				/* attach to specified PHY */ -				if (priv->phy_id == phy->addr) -					break; -			} else { -				/* autoselect PHY if none was specified */ -				if (phy->addr != 0) -					break; -			} -		} +	if (priv->phy_id != -1) { +		phy = priv->mdio->phy_map[priv->phy_id]; +	} else { +		phy = phy_find_first(priv->mdio);  	}  	if (!phy) { @@ -644,11 +649,11 @@ static int ethoc_mdio_probe(struct net_device *dev)  		return -ENXIO;  	} -	phy = phy_connect(dev, dev_name(&phy->dev), ethoc_mdio_poll, 0, +	err = phy_connect_direct(dev, phy, ethoc_mdio_poll, 0,  			PHY_INTERFACE_MODE_GMII); -	if (IS_ERR(phy)) { +	if (err) {  		dev_err(&dev->dev, "could not attach to PHY\n"); -		return PTR_ERR(phy); +		return err;  	}  	priv->phy = phy; @@ -658,8 +663,6 @@ static int ethoc_mdio_probe(struct net_device *dev)  static int ethoc_open(struct net_device *dev)  {  	struct ethoc *priv = netdev_priv(dev); -	unsigned int min_tx = 2; -	unsigned int num_bd;  	int ret;  	ret = request_irq(dev->irq, ethoc_interrupt, IRQF_SHARED, @@ -667,14 +670,7 @@ static int ethoc_open(struct net_device *dev)  	if (ret)  		return ret; -	/* calculate the number of TX/RX buffers, maximum 128 supported */ -	num_bd = min_t(unsigned int, -		128, (dev->mem_end - dev->mem_start + 1) / ETHOC_BUFSIZ); -	priv->num_tx = max(min_tx, num_bd / 4); -	priv->num_rx = num_bd - priv->num_tx; -	ethoc_write(priv, TX_BD_NUM, priv->num_tx); - -	ethoc_init_ring(priv); +	ethoc_init_ring(priv, dev->mem_start);  	ethoc_reset(priv);  	if (netif_queue_stopped(dev)) { @@ -734,7 +730,7 @@ static int ethoc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)  		phy = priv->phy;  	} -	return phy_mii_ioctl(phy, mdio, cmd); +	return phy_mii_ioctl(phy, ifr, cmd);  }  static int ethoc_config(struct net_device *dev, struct ifmap *map) @@ -812,8 +808,7 @@ static void ethoc_tx_timeout(struct net_device *dev)  static struct net_device_stats *ethoc_stats(struct net_device *dev)  { -	struct ethoc *priv = netdev_priv(dev); -	return &priv->stats; +	return &dev->stats;  }  static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev) @@ -824,7 +819,7 @@ static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev)  	void *dest;  	if (unlikely(skb->len > ETHOC_BUFSIZ)) { -		priv->stats.tx_errors++; +		dev->stats.tx_errors++;  		goto out;  	} @@ -838,7 +833,7 @@ static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev)  	else  		bd.stat &= ~TX_BD_PAD; -	dest = phys_to_virt(bd.addr); +	dest = priv->vma[entry];  	memcpy_toio(dest, skb->data, skb->len);  	bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK); @@ -876,7 +871,7 @@ static const struct net_device_ops ethoc_netdev_ops = {   * ethoc_probe() - initialize OpenCores ethernet MAC   * pdev:	platform device   */ -static int ethoc_probe(struct platform_device *pdev) +static int __devinit ethoc_probe(struct platform_device *pdev)  {  	struct net_device *netdev = NULL;  	struct resource *res = NULL; @@ -884,6 +879,7 @@ static int ethoc_probe(struct platform_device *pdev)  	struct resource *mem = NULL;  	struct ethoc *priv = NULL;  	unsigned int phy; +	int num_bd;  	int ret = 0;  	/* allocate networking device */ @@ -965,7 +961,7 @@ static int ethoc_probe(struct platform_device *pdev)  		}  	} else {  		/* Allocate buffer memory */ -		priv->membase = dma_alloc_coherent(NULL, +		priv->membase = dmam_alloc_coherent(&pdev->dev,  			buffer_size, (void *)&netdev->mem_start,  			GFP_KERNEL);  		if (!priv->membase) { @@ -978,6 +974,18 @@ static int ethoc_probe(struct platform_device *pdev)  		priv->dma_alloc = buffer_size;  	} +	/* calculate the number of TX/RX buffers, maximum 128 supported */ +	num_bd = min_t(unsigned int, +		128, (netdev->mem_end - netdev->mem_start + 1) / ETHOC_BUFSIZ); +	priv->num_tx = max(2, num_bd / 4); +	priv->num_rx = num_bd - priv->num_tx; + +	priv->vma = devm_kzalloc(&pdev->dev, num_bd*sizeof(void*), GFP_KERNEL); +	if (!priv->vma) { +		ret = -ENOMEM; +		goto error; +	} +  	/* Allow the platform setup code to pass in a MAC address. */  	if (pdev->dev.platform_data) {  		struct ethoc_platform_data *pdata = @@ -1063,21 +1071,6 @@ free_mdio:  	kfree(priv->mdio->irq);  	mdiobus_free(priv->mdio);  free: -	if (priv) { -		if (priv->dma_alloc) -			dma_free_coherent(NULL, priv->dma_alloc, priv->membase, -					  netdev->mem_start); -		else if (priv->membase) -			devm_iounmap(&pdev->dev, priv->membase); -		if (priv->iobase) -			devm_iounmap(&pdev->dev, priv->iobase); -	} -	if (mem) -		devm_release_mem_region(&pdev->dev, mem->start, -					mem->end - mem->start + 1); -	if (mmio) -		devm_release_mem_region(&pdev->dev, mmio->start, -					mmio->end - mmio->start + 1);  	free_netdev(netdev);  out:  	return ret; @@ -1087,7 +1080,7 @@ out:   * ethoc_remove() - shutdown OpenCores ethernet MAC   * @pdev:	platform device   */ -static int ethoc_remove(struct platform_device *pdev) +static int __devexit ethoc_remove(struct platform_device *pdev)  {  	struct net_device *netdev = platform_get_drvdata(pdev);  	struct ethoc *priv = netdev_priv(netdev); @@ -1104,17 +1097,6 @@ static int ethoc_remove(struct platform_device *pdev)  			kfree(priv->mdio->irq);  			mdiobus_free(priv->mdio);  		} -		if (priv->dma_alloc) -			dma_free_coherent(NULL, priv->dma_alloc, priv->membase, -				netdev->mem_start); -		else { -			devm_iounmap(&pdev->dev, priv->membase); -			devm_release_mem_region(&pdev->dev, netdev->mem_start, -				netdev->mem_end - netdev->mem_start + 1); -		} -		devm_iounmap(&pdev->dev, priv->iobase); -		devm_release_mem_region(&pdev->dev, netdev->base_addr, -			priv->io_region_size);  		unregister_netdev(netdev);  		free_netdev(netdev);  	} @@ -1139,7 +1121,7 @@ static int ethoc_resume(struct platform_device *pdev)  static struct platform_driver ethoc_driver = {  	.probe   = ethoc_probe, -	.remove  = ethoc_remove, +	.remove  = __devexit_p(ethoc_remove),  	.suspend = ethoc_suspend,  	.resume  = ethoc_resume,  	.driver  = {  |