diff options
Diffstat (limited to 'target')
-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; } |