summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/r6040.c53
1 files changed, 44 insertions, 9 deletions
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 0972152e5d2..4f2ebb2e71b 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -312,7 +312,7 @@ static void r6040_rx_buf_alloc(struct r6040_private *lp, struct net_device *dev)
lp->rx_insert_ptr = descptr;
}
-static void r6040_alloc_txbufs(struct net_device *dev)
+static void r6040_init_txbufs(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
@@ -322,16 +322,39 @@ static void r6040_alloc_txbufs(struct net_device *dev)
r6040_init_ring_desc(lp->tx_ring, lp->tx_ring_dma, TX_DCNT);
}
-static void r6040_alloc_rxbufs(struct net_device *dev)
+static int r6040_alloc_rxbufs(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
-
- lp->rx_free_desc = 0;
+ struct r6040_descriptor *desc;
+ struct sk_buff *skb;
+ int rc;
lp->rx_remove_ptr = lp->rx_insert_ptr = lp->rx_ring;
r6040_init_ring_desc(lp->rx_ring, lp->rx_ring_dma, RX_DCNT);
- r6040_rx_buf_alloc(lp, dev);
+ /* Allocate skbs for the rx descriptors */
+ desc = lp->rx_ring;
+ do {
+ skb = netdev_alloc_skb(dev, MAX_BUF_SIZE);
+ if (!skb) {
+ printk(KERN_ERR "%s: failed to alloc skb for rx\n", dev->name);
+ rc = -ENOMEM;
+ goto err_exit;
+ }
+ desc->skb_ptr = skb;
+ desc->buf = cpu_to_le32(pci_map_single(lp->pdev,
+ desc->skb_ptr->data,
+ MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
+ desc->status = 0x8000;
+ desc = desc->vndescp;
+ } while (desc != lp->rx_ring);
+
+ return 0;
+
+err_exit:
+ /* Deallocate all previously allocated skbs */
+ r6040_free_rxbufs(dev);
+ return rc;
}
static void r6040_init_mac_regs(struct net_device *dev)
@@ -697,14 +720,17 @@ static void r6040_poll_controller(struct net_device *dev)
#endif
/* Init RDC MAC */
-static void r6040_up(struct net_device *dev)
+static int r6040_up(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
+ int ret;
/* Initialise and alloc RX/TX buffers */
- r6040_alloc_txbufs(dev);
- r6040_alloc_rxbufs(dev);
+ r6040_init_txbufs(dev);
+ ret = r6040_alloc_rxbufs(dev);
+ if (ret)
+ return ret;
/* Read the PHY ID */
lp->switch_sig = r6040_phy_read(ioaddr, 0, 2);
@@ -734,6 +760,8 @@ static void r6040_up(struct net_device *dev)
/* Initialize all MAC registers */
r6040_init_mac_regs(dev);
+
+ return 0;
}
/*
@@ -812,7 +840,14 @@ static int r6040_open(struct net_device *dev)
return -ENOMEM;
}
- r6040_up(dev);
+ ret = r6040_up(dev);
+ if (ret) {
+ pci_free_consistent(lp->pdev, TX_DESC_SIZE, lp->tx_ring,
+ lp->tx_ring_dma);
+ pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring,
+ lp->rx_ring_dma);
+ return ret;
+ }
napi_enable(&lp->napi);
netif_start_queue(dev);