sky2: Create buffer alloc and free helpers

Refactor similar two sections of code that free buffers into one.
Only call tx_init if all buffer allocations succeed.

Signed-off-by: Mike McCormack <mikem@ring3k.org>
Acked-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Mike McCormack 2009-09-01 03:21:35 +00:00 committed by David S. Miller
parent 10547ae2c0
commit 90bbebb4a8

View File

@ -1405,6 +1405,61 @@ nomem:
return -ENOMEM;
}
static int sky2_alloc_buffers(struct sky2_port *sky2)
{
struct sky2_hw *hw = sky2->hw;
/* must be power of 2 */
sky2->tx_le = pci_alloc_consistent(hw->pdev,
sky2->tx_ring_size *
sizeof(struct sky2_tx_le),
&sky2->tx_le_map);
if (!sky2->tx_le)
goto nomem;
sky2->tx_ring = kcalloc(sky2->tx_ring_size, sizeof(struct tx_ring_info),
GFP_KERNEL);
if (!sky2->tx_ring)
goto nomem;
sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES,
&sky2->rx_le_map);
if (!sky2->rx_le)
goto nomem;
memset(sky2->rx_le, 0, RX_LE_BYTES);
sky2->rx_ring = kcalloc(sky2->rx_pending, sizeof(struct rx_ring_info),
GFP_KERNEL);
if (!sky2->rx_ring)
goto nomem;
return 0;
nomem:
return -ENOMEM;
}
static void sky2_free_buffers(struct sky2_port *sky2)
{
struct sky2_hw *hw = sky2->hw;
if (sky2->rx_le) {
pci_free_consistent(hw->pdev, RX_LE_BYTES,
sky2->rx_le, sky2->rx_le_map);
sky2->rx_le = NULL;
}
if (sky2->tx_le) {
pci_free_consistent(hw->pdev,
sky2->tx_ring_size * sizeof(struct sky2_tx_le),
sky2->tx_le, sky2->tx_le_map);
sky2->tx_le = NULL;
}
kfree(sky2->tx_ring);
kfree(sky2->rx_ring);
sky2->tx_ring = NULL;
sky2->rx_ring = NULL;
}
/* Bring up network interface. */
static int sky2_up(struct net_device *dev)
{
@ -1412,7 +1467,7 @@ static int sky2_up(struct net_device *dev)
struct sky2_hw *hw = sky2->hw;
unsigned port = sky2->port;
u32 imask, ramsize;
int cap, err = -ENOMEM;
int cap, err;
struct net_device *otherdev = hw->dev[sky2->port^1];
/*
@ -1431,32 +1486,12 @@ static int sky2_up(struct net_device *dev)
netif_carrier_off(dev);
/* must be power of 2 */
sky2->tx_le = pci_alloc_consistent(hw->pdev,
sky2->tx_ring_size *
sizeof(struct sky2_tx_le),
&sky2->tx_le_map);
if (!sky2->tx_le)
goto err_out;
sky2->tx_ring = kcalloc(sky2->tx_ring_size, sizeof(struct tx_ring_info),
GFP_KERNEL);
if (!sky2->tx_ring)
err = sky2_alloc_buffers(sky2);
if (err)
goto err_out;
tx_init(sky2);
sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES,
&sky2->rx_le_map);
if (!sky2->rx_le)
goto err_out;
memset(sky2->rx_le, 0, RX_LE_BYTES);
sky2->rx_ring = kcalloc(sky2->rx_pending, sizeof(struct rx_ring_info),
GFP_KERNEL);
if (!sky2->rx_ring)
goto err_out;
sky2_mac_init(hw, port);
/* Register is number of 4K blocks on internal RAM buffer. */
@ -1513,22 +1548,7 @@ static int sky2_up(struct net_device *dev)
return 0;
err_out:
if (sky2->rx_le) {
pci_free_consistent(hw->pdev, RX_LE_BYTES,
sky2->rx_le, sky2->rx_le_map);
sky2->rx_le = NULL;
}
if (sky2->tx_le) {
pci_free_consistent(hw->pdev,
sky2->tx_ring_size * sizeof(struct sky2_tx_le),
sky2->tx_le, sky2->tx_le_map);
sky2->tx_le = NULL;
}
kfree(sky2->tx_ring);
kfree(sky2->rx_ring);
sky2->tx_ring = NULL;
sky2->rx_ring = NULL;
sky2_free_buffers(sky2);
return err;
}
@ -1880,20 +1900,7 @@ static int sky2_down(struct net_device *dev)
sky2_rx_clean(sky2);
pci_free_consistent(hw->pdev, RX_LE_BYTES,
sky2->rx_le, sky2->rx_le_map);
kfree(sky2->rx_ring);
pci_free_consistent(hw->pdev,
sky2->tx_ring_size * sizeof(struct sky2_tx_le),
sky2->tx_le, sky2->tx_le_map);
kfree(sky2->tx_ring);
sky2->tx_le = NULL;
sky2->rx_le = NULL;
sky2->rx_ring = NULL;
sky2->tx_ring = NULL;
sky2_free_buffers(sky2);
return 0;
}