/** * e1000e_open - Called when a network interface is made active * * @v netdev network interface device structure * @ret rc Return status code, 0 on success, negative value on failure * **/ static int e1000e_open ( struct net_device *netdev ) { struct e1000_adapter *adapter = netdev_priv(netdev); int err; DBGP ( "e1000e_open\n" ); /* allocate transmit descriptors */ err = e1000e_setup_tx_resources ( adapter ); if ( err ) { DBG ( "Error setting up TX resources!\n" ); goto err_setup_tx; } /* allocate receive descriptors */ err = e1000e_setup_rx_resources ( adapter ); if ( err ) { DBG ( "Error setting up RX resources!\n" ); goto err_setup_rx; } e1000e_configure_tx ( adapter ); e1000e_configure_rx ( adapter ); DBG ( "E1000_RXDCTL(0): %#08x\n", E1000_READ_REG ( &adapter->hw, E1000_RXDCTL(0) ) ); return 0; err_setup_rx: DBG ( "err_setup_rx\n" ); e1000e_free_tx_resources ( adapter ); err_setup_tx: DBG ( "err_setup_tx\n" ); e1000e_reset ( adapter ); return err; }
static int e1000_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { struct e1000_adapter *adapter = netdev_priv(netdev); 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; 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); 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); if ((new_tx_count == adapter->tx_ring_count) && (new_rx_count == adapter->rx_ring_count)) /* nothing to do */ return 0; while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) usleep_range(1000, 2000); 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; } set_tx = (new_tx_count != adapter->tx_ring_count); set_rx = (new_rx_count != adapter->rx_ring_count); /* 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; } } e1000e_down(adapter); /* * 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; } 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_rx; } /* ...then free the old resources and copy back any new ring data */ if (set_tx) { e1000e_free_tx_resources(adapter->tx_ring); 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; } err_setup_rx: 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; }
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; if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) return -EINVAL; while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) msleep(1); if (netif_running(adapter->netdev)) e1000e_down(adapter); tx_old = adapter->tx_ring; rx_old = adapter->rx_ring; err = -ENOMEM; tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); if (!tx_ring) goto err_alloc_tx; /* * use a memcpy to save any previously configured * items like napi structs from having to be * reinitialized */ memcpy(tx_ring, tx_old, sizeof(struct e1000_ring)); rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); if (!rx_ring) goto err_alloc_rx; memcpy(rx_ring, rx_old, sizeof(struct e1000_ring)); adapter->tx_ring = tx_ring; adapter->rx_ring = rx_ring; 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); 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); if (netif_running(adapter->netdev)) { /* Try to get new resources before deleting old */ err = e1000e_setup_rx_resources(adapter); if (err) goto err_setup_rx; err = e1000e_setup_tx_resources(adapter); if (err) goto err_setup_tx; /* * 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); e1000e_free_tx_resources(adapter); 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; } clear_bit(__E1000_RESETTING, &adapter->state); return 0; err_setup_tx: e1000e_free_rx_resources(adapter); 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); err_setup: clear_bit(__E1000_RESETTING, &adapter->state); return err; }