Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 289744
b: refs/heads/master
c: 508da42
h: refs/heads/master
v: v3
  • Loading branch information
Bruce Allan authored and Jeff Kirsher committed Jan 26, 2012
1 parent 87db300 commit fbfea7d
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 60 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 55aa69854a93d7aaf123a882b0b1f93c86cf3c7e
refs/heads/master: 508da4264add2eb13bd4d32bb896e79e6f8821fc
136 changes: 77 additions & 59 deletions trunk/drivers/net/ethernet/intel/e1000e/ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,94 +605,112 @@ static void e1000_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_ring *tx_ring = adapter->tx_ring;
struct e1000_ring *rx_ring = adapter->rx_ring;

ring->rx_max_pending = E1000_MAX_RXD;
ring->tx_max_pending = E1000_MAX_TXD;
ring->rx_pending = rx_ring->count;
ring->tx_pending = tx_ring->count;
ring->rx_pending = adapter->rx_ring_count;
ring->tx_pending = adapter->tx_ring_count;
}

static int e1000_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_ring *tx_ring, *tx_old;
struct e1000_ring *rx_ring, *rx_old;
int err;
struct e1000_ring *temp_tx = NULL, *temp_rx = NULL;
int err = 0, size = sizeof(struct e1000_ring);
bool set_tx = false, set_rx = false;
u16 new_rx_count, new_tx_count;

if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;

while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
usleep_range(1000, 2000);
new_rx_count = clamp_t(u32, ring->rx_pending, E1000_MIN_RXD,
E1000_MAX_RXD);
new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE);

if (netif_running(adapter->netdev))
e1000e_down(adapter);
new_tx_count = clamp_t(u32, ring->tx_pending, E1000_MIN_TXD,
E1000_MAX_TXD);
new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);

tx_old = adapter->tx_ring;
rx_old = adapter->rx_ring;
if ((new_tx_count == adapter->tx_ring_count) &&
(new_rx_count == adapter->rx_ring_count))
/* nothing to do */
return 0;

err = -ENOMEM;
tx_ring = kmemdup(tx_old, sizeof(struct e1000_ring), GFP_KERNEL);
if (!tx_ring)
goto err_alloc_tx;
while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
usleep_range(1000, 2000);

rx_ring = kmemdup(rx_old, sizeof(struct e1000_ring), GFP_KERNEL);
if (!rx_ring)
goto err_alloc_rx;
if (!netif_running(adapter->netdev)) {
/* Set counts now and allocate resources during open() */
adapter->tx_ring->count = new_tx_count;
adapter->rx_ring->count = new_rx_count;
adapter->tx_ring_count = new_tx_count;
adapter->rx_ring_count = new_rx_count;
goto clear_reset;
}

adapter->tx_ring = tx_ring;
adapter->rx_ring = rx_ring;
set_tx = (new_tx_count != adapter->tx_ring_count);
set_rx = (new_rx_count != adapter->rx_ring_count);

rx_ring->count = max(ring->rx_pending, (u32)E1000_MIN_RXD);
rx_ring->count = min(rx_ring->count, (u32)(E1000_MAX_RXD));
rx_ring->count = ALIGN(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE);
/* Allocate temporary storage for ring updates */
if (set_tx) {
temp_tx = vmalloc(size);
if (!temp_tx) {
err = -ENOMEM;
goto free_temp;
}
}
if (set_rx) {
temp_rx = vmalloc(size);
if (!temp_rx) {
err = -ENOMEM;
goto free_temp;
}
}

tx_ring->count = max(ring->tx_pending, (u32)E1000_MIN_TXD);
tx_ring->count = min(tx_ring->count, (u32)(E1000_MAX_TXD));
tx_ring->count = ALIGN(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE);
e1000e_down(adapter);

if (netif_running(adapter->netdev)) {
/* Try to get new resources before deleting old */
err = e1000e_setup_rx_resources(rx_ring);
/*
* We can't just free everything and then setup again, because the
* ISRs in MSI-X mode get passed pointers to the Tx and Rx ring
* structs. First, attempt to allocate new resources...
*/
if (set_tx) {
memcpy(temp_tx, adapter->tx_ring, size);
temp_tx->count = new_tx_count;
err = e1000e_setup_tx_resources(temp_tx);
if (err)
goto err_setup_rx;
err = e1000e_setup_tx_resources(tx_ring);
goto err_setup;
}
if (set_rx) {
memcpy(temp_rx, adapter->rx_ring, size);
temp_rx->count = new_rx_count;
err = e1000e_setup_rx_resources(temp_rx);
if (err)
goto err_setup_tx;
goto err_setup_rx;
}

/*
* restore the old in order to free it,
* then add in the new
*/
adapter->rx_ring = rx_old;
adapter->tx_ring = tx_old;
e1000e_free_rx_resources(adapter->rx_ring);
/* ...then free the old resources and copy back any new ring data */
if (set_tx) {
e1000e_free_tx_resources(adapter->tx_ring);
kfree(tx_old);
kfree(rx_old);
adapter->rx_ring = rx_ring;
adapter->tx_ring = tx_ring;
err = e1000e_up(adapter);
if (err)
goto err_setup;
memcpy(adapter->tx_ring, temp_tx, size);
adapter->tx_ring_count = new_tx_count;
}
if (set_rx) {
e1000e_free_rx_resources(adapter->rx_ring);
memcpy(adapter->rx_ring, temp_rx, size);
adapter->rx_ring_count = new_rx_count;
}

clear_bit(__E1000_RESETTING, &adapter->state);
return 0;
err_setup_tx:
e1000e_free_rx_resources(rx_ring);
err_setup_rx:
adapter->rx_ring = rx_old;
adapter->tx_ring = tx_old;
kfree(rx_ring);
err_alloc_rx:
kfree(tx_ring);
err_alloc_tx:
e1000e_up(adapter);
if (err && set_tx)
e1000e_free_tx_resources(temp_tx);
err_setup:
e1000e_up(adapter);
free_temp:
vfree(temp_tx);
vfree(temp_rx);
clear_reset:
clear_bit(__E1000_RESETTING, &adapter->state);
return err;
}
Expand Down

0 comments on commit fbfea7d

Please sign in to comment.