summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/faraday/ftgmac100.c68
1 files changed, 47 insertions, 21 deletions
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 69daf2a50573..a533a7d5a5cc 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -794,6 +794,7 @@ static void ftgmac100_free_buffers(struct ftgmac100 *priv)
{
int i;
+ /* Free all RX buffers */
for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
struct ftgmac100_rxdes *rxdes = &priv->descs->rxdes[i];
struct page *page = ftgmac100_rxdes_get_page(priv, rxdes);
@@ -806,6 +807,7 @@ static void ftgmac100_free_buffers(struct ftgmac100 *priv)
__free_page(page);
}
+ /* Free all TX buffers */
for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
struct ftgmac100_txdes *txdes = &priv->descs->txdes[i];
struct sk_buff *skb = ftgmac100_txdes_get_skb(txdes);
@@ -817,40 +819,54 @@ static void ftgmac100_free_buffers(struct ftgmac100 *priv)
dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
kfree_skb(skb);
}
-
- dma_free_coherent(priv->dev, sizeof(struct ftgmac100_descs),
- priv->descs, priv->descs_dma_addr);
}
-static int ftgmac100_alloc_buffers(struct ftgmac100 *priv)
+static void ftgmac100_free_rings(struct ftgmac100 *priv)
{
- int i;
+ /* Free descriptors */
+ if (priv->descs)
+ dma_free_coherent(priv->dev, sizeof(struct ftgmac100_descs),
+ priv->descs, priv->descs_dma_addr);
+}
+static int ftgmac100_alloc_rings(struct ftgmac100 *priv)
+{
+ /* Allocate descriptors */
priv->descs = dma_zalloc_coherent(priv->dev,
sizeof(struct ftgmac100_descs),
&priv->descs_dma_addr, GFP_KERNEL);
if (!priv->descs)
return -ENOMEM;
- /* initialize RX ring */
- ftgmac100_rxdes_set_end_of_ring(priv,
- &priv->descs->rxdes[RX_QUEUE_ENTRIES - 1]);
+ return 0;
+}
+
+static void ftgmac100_init_rings(struct ftgmac100 *priv)
+{
+ int i;
+
+ /* Initialize RX ring */
+ for (i = 0; i < RX_QUEUE_ENTRIES; i++)
+ priv->descs->rxdes[i].rxdes0 = 0;
+ ftgmac100_rxdes_set_end_of_ring(priv, &priv->descs->rxdes[i - 1]);
+
+ /* Initialize TX ring */
+ for (i = 0; i < TX_QUEUE_ENTRIES; i++)
+ priv->descs->txdes[i].txdes0 = 0;
+ ftgmac100_txdes_set_end_of_ring(priv, &priv->descs->txdes[i -1]);
+}
+
+static int ftgmac100_alloc_rx_buffers(struct ftgmac100 *priv)
+{
+ int i;
for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
struct ftgmac100_rxdes *rxdes = &priv->descs->rxdes[i];
if (ftgmac100_alloc_rx_page(priv, rxdes, GFP_KERNEL))
- goto err;
+ return -ENOMEM;
}
-
- /* initialize TX ring */
- ftgmac100_txdes_set_end_of_ring(priv,
- &priv->descs->txdes[TX_QUEUE_ENTRIES - 1]);
return 0;
-
-err:
- ftgmac100_free_buffers(priv);
- return -ENOMEM;
}
static void ftgmac100_adjust_link(struct net_device *netdev)
@@ -1101,12 +1117,20 @@ static int ftgmac100_open(struct net_device *netdev)
unsigned int status;
int err;
- err = ftgmac100_alloc_buffers(priv);
+ /* Allocate ring buffers */
+ err = ftgmac100_alloc_rings(priv);
if (err) {
- netdev_err(netdev, "failed to allocate buffers\n");
- goto err_alloc;
+ netdev_err(netdev, "Failed to allocate descriptors\n");
+ return err;
}
+ /* Initialize the rings */
+ ftgmac100_init_rings(priv);
+
+ /* Allocate receive buffers */
+ if (ftgmac100_alloc_rx_buffers(priv))
+ goto err_alloc;
+
err = request_irq(netdev->irq, ftgmac100_interrupt, 0, netdev->name, netdev);
if (err) {
netdev_err(netdev, "failed to request irq %d\n", netdev->irq);
@@ -1170,8 +1194,9 @@ err_ncsi:
err_hw:
free_irq(netdev->irq, netdev);
err_irq:
- ftgmac100_free_buffers(priv);
err_alloc:
+ ftgmac100_free_buffers(priv);
+ ftgmac100_free_rings(priv);
return err;
}
@@ -1192,6 +1217,7 @@ static int ftgmac100_stop(struct net_device *netdev)
ftgmac100_stop_hw(priv);
free_irq(netdev->irq, netdev);
ftgmac100_free_buffers(priv);
+ ftgmac100_free_rings(priv);
return 0;
}