diff options
Diffstat (limited to 'target/linux/ramips')
| -rw-r--r-- | target/linux/ramips/files/drivers/net/ramips.c | 134 | 
1 files changed, 90 insertions, 44 deletions
| diff --git a/target/linux/ramips/files/drivers/net/ramips.c b/target/linux/ramips/files/drivers/net/ramips.c index 7f0f8c469..b9979fce5 100644 --- a/target/linux/ramips/files/drivers/net/ramips.c +++ b/target/linux/ramips/files/drivers/net/ramips.c @@ -102,6 +102,64 @@ ramips_alloc_skb(struct raeth_priv *re)  	return skb;  } +static void +ramips_ring_setup(struct raeth_priv *re) +{ +	int len; +	int i; + +	len = NUM_TX_DESC * sizeof(struct ramips_tx_dma); +	memset(re->tx, 0, len); + +	for (i = 0; i < NUM_TX_DESC; i++) { +		struct ramips_tx_dma *txd; + +		txd = &re->tx[i]; +		txd->txd4 = TX_DMA_QN(3) | TX_DMA_PN(1); +		txd->txd2 = TX_DMA_LSO | TX_DMA_DONE; + +		if (re->tx_skb[i] != NULL) { +			netdev_warn(re->netdev, +				    "dirty skb for TX desc %d\n", i); +			re->tx_skb[i] = NULL; +		} +	} + +	len = NUM_RX_DESC * sizeof(struct ramips_rx_dma); +	memset(re->rx, 0, len); + +	for (i = 0; i < NUM_RX_DESC; i++) { +		dma_addr_t dma_addr; + +		BUG_ON(re->rx_skb[i] == NULL); +		dma_addr = dma_map_single(&re->netdev->dev, re->rx_skb[i]->data, +					  MAX_RX_LENGTH, DMA_FROM_DEVICE); +		re->rx_dma[i] = dma_addr; +		re->rx[i].rxd1 = (unsigned int) dma_addr; +		re->rx[i].rxd2 = RX_DMA_LSO; +	} + +	/* flush descriptors */ +	wmb(); +} + +static void +ramips_ring_cleanup(struct raeth_priv *re) +{ +	int i; + +	for (i = 0; i < NUM_RX_DESC; i++) +		if (re->rx_skb[i]) +			dma_unmap_single(&re->netdev->dev, re->rx_dma[i], +					 MAX_RX_LENGTH, DMA_FROM_DEVICE); + +	for (i = 0; i < NUM_TX_DESC; i++) +		if (re->tx_skb[i]) { +			dev_kfree_skb_any(re->tx_skb[i]); +			re->tx_skb[i] = NULL; +		} +} +  #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT3883)  #define RAMIPS_MDIO_RETRY	1000 @@ -481,77 +539,63 @@ ramips_phy_stop(struct raeth_priv *re)  #endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT3883 */  static void -ramips_cleanup_dma(struct raeth_priv *re) +ramips_ring_free(struct raeth_priv *re)  { +	int len;  	int i;  	for (i = 0; i < NUM_RX_DESC; i++) -		if (re->rx_skb[i]) { -			dma_unmap_single(&re->netdev->dev, re->rx_dma[i], -					 MAX_RX_LENGTH, DMA_FROM_DEVICE); +		if (re->rx_skb[i])  			dev_kfree_skb_any(re->rx_skb[i]); -		} -	if (re->rx) -		dma_free_coherent(&re->netdev->dev, -				  NUM_RX_DESC * sizeof(struct ramips_rx_dma), -				  re->rx, re->rx_desc_dma); +	if (re->rx) { +		len = NUM_RX_DESC * sizeof(struct ramips_rx_dma); +		dma_free_coherent(&re->netdev->dev, len, re->rx, +				  re->rx_desc_dma); +	} -	if (re->tx) -		dma_free_coherent(&re->netdev->dev, -				  NUM_TX_DESC * sizeof(struct ramips_tx_dma), -				  re->tx, re->tx_desc_dma); +	if (re->tx) { +		len = NUM_TX_DESC * sizeof(struct ramips_tx_dma); +		dma_free_coherent(&re->netdev->dev, len, re->tx, +				  re->tx_desc_dma); +	}  }  static int -ramips_alloc_dma(struct raeth_priv *re) +ramips_ring_alloc(struct raeth_priv *re)  { +	int len;  	int err = -ENOMEM;  	int i; -	re->skb_free_idx = 0; - -	/* setup tx ring */ -	re->tx = dma_alloc_coherent(&re->netdev->dev, -				    NUM_TX_DESC * sizeof(struct ramips_tx_dma), -				    &re->tx_desc_dma, GFP_ATOMIC); +	/* allocate tx ring */ +	len = NUM_TX_DESC * sizeof(struct ramips_tx_dma); +	re->tx = dma_alloc_coherent(&re->netdev->dev, len, +					  &re->tx_desc_dma, GFP_ATOMIC);  	if (!re->tx)  		goto err_cleanup; -	memset(re->tx, 0, NUM_TX_DESC * sizeof(struct ramips_tx_dma)); -	for (i = 0; i < NUM_TX_DESC; i++) { -		re->tx[i].txd2 = TX_DMA_LSO | TX_DMA_DONE; -		re->tx[i].txd4 = TX_DMA_QN(3) | TX_DMA_PN(1); -	} - -	/* setup rx ring */ -	re->rx = dma_alloc_coherent(&re->netdev->dev, -				    NUM_RX_DESC * sizeof(struct ramips_rx_dma), +	/* allocate rx ring */ +	len = NUM_RX_DESC * sizeof(struct ramips_rx_dma); +	re->rx = dma_alloc_coherent(&re->netdev->dev, len,  				    &re->rx_desc_dma, GFP_ATOMIC);  	if (!re->rx)  		goto err_cleanup; -	memset(re->rx, 0, sizeof(struct ramips_rx_dma) * NUM_RX_DESC);  	for (i = 0; i < NUM_RX_DESC; i++) { -		dma_addr_t dma_addr; -		struct sk_buff *new_skb; +		struct sk_buff *skb; -		new_skb = ramips_alloc_skb(re); -		if (!new_skb) +		skb = ramips_alloc_skb(re); +		if (!skb)  			goto err_cleanup; -		dma_addr = dma_map_single(&re->netdev->dev, new_skb->data, -					  MAX_RX_LENGTH, DMA_FROM_DEVICE); -		re->rx_dma[i] = dma_addr; -		re->rx[i].rxd1 = (unsigned int) re->rx_dma[i]; -		re->rx[i].rxd2 |= RX_DMA_LSO; -		re->rx_skb[i] = new_skb; +		re->rx_skb[i] = skb;  	}  	return 0; - err_cleanup: -	ramips_cleanup_dma(re); +err_cleanup: +	ramips_ring_free(re);  	return err;  } @@ -739,10 +783,11 @@ ramips_eth_open(struct net_device *dev)  	if (err)  		return err; -	err = ramips_alloc_dma(re); +	err = ramips_ring_alloc(re);  	if (err)  		goto err_free_irq; +	ramips_ring_setup(re);  	ramips_hw_set_macaddr(dev->dev_addr);  	ramips_setup_dma(re); @@ -798,7 +843,8 @@ ramips_eth_stop(struct net_device *dev)  	netif_stop_queue(dev);  	tasklet_kill(&re->tx_housekeeping_tasklet);  	tasklet_kill(&re->rx_tasklet); -	ramips_cleanup_dma(re); +	ramips_ring_cleanup(re); +	ramips_ring_free(re);  	RADEBUG("ramips_eth: stopped\n");  	return 0;  } | 
