Example #1
0
/**
 * fm10k_setup_all_tx_resources - allocate all queues Tx resources
 * @interface: board private structure
 *
 * If this function returns with an error, then it's possible one or
 * more of the rings is populated (while the rest are not).  It is the
 * callers duty to clean those orphaned rings.
 *
 * Return 0 on success, negative on failure
 **/
static int fm10k_setup_all_tx_resources(struct fm10k_intfc *interface)
{
	int i, err = 0;

	for (i = 0; i < interface->num_tx_queues; i++) {
		err = fm10k_setup_tx_resources(interface->tx_ring[i]);
		if (!err)
			continue;

		netif_err(interface, probe, interface->netdev,
			  "Allocation for Tx Queue %u failed\n", i);
		goto err_setup_tx;
	}

	return 0;
err_setup_tx:
	/* rewind the index freeing the rings as we go */
	while (i--)
		fm10k_free_tx_resources(interface->tx_ring[i]);
	return err;
}
Example #2
0
static int fm10k_set_ringparam(struct net_device *netdev,
			       struct ethtool_ringparam *ring)
{
	struct fm10k_intfc *interface = netdev_priv(netdev);
	struct fm10k_ring *temp_ring;
	int i, err = 0;
	u32 new_rx_count, new_tx_count;

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

	new_tx_count = clamp_t(u32, ring->tx_pending,
			       FM10K_MIN_TXD, FM10K_MAX_TXD);
	new_tx_count = ALIGN(new_tx_count, FM10K_REQ_TX_DESCRIPTOR_MULTIPLE);

	new_rx_count = clamp_t(u32, ring->rx_pending,
			       FM10K_MIN_RXD, FM10K_MAX_RXD);
	new_rx_count = ALIGN(new_rx_count, FM10K_REQ_RX_DESCRIPTOR_MULTIPLE);

	if ((new_tx_count == interface->tx_ring_count) &&
	    (new_rx_count == interface->rx_ring_count)) {
		/* nothing to do */
		return 0;
	}

	while (test_and_set_bit(__FM10K_RESETTING, &interface->state))
		usleep_range(1000, 2000);

	if (!netif_running(interface->netdev)) {
		for (i = 0; i < interface->num_tx_queues; i++)
			interface->tx_ring[i]->count = new_tx_count;
		for (i = 0; i < interface->num_rx_queues; i++)
			interface->rx_ring[i]->count = new_rx_count;
		interface->tx_ring_count = new_tx_count;
		interface->rx_ring_count = new_rx_count;
		goto clear_reset;
	}

	/* allocate temporary buffer to store rings in */
	i = max_t(int, interface->num_tx_queues, interface->num_rx_queues);
	temp_ring = vmalloc(i * sizeof(struct fm10k_ring));

	if (!temp_ring) {
		err = -ENOMEM;
		goto clear_reset;
	}

	fm10k_down(interface);

	/* Setup new Tx resources and free the old Tx resources in that order.
	 * We can then assign the new resources to the rings via a memcpy.
	 * The advantage to this approach is that we are guaranteed to still
	 * have resources even in the case of an allocation failure.
	 */
	if (new_tx_count != interface->tx_ring_count) {
		for (i = 0; i < interface->num_tx_queues; i++) {
			memcpy(&temp_ring[i], interface->tx_ring[i],
			       sizeof(struct fm10k_ring));

			temp_ring[i].count = new_tx_count;
			err = fm10k_setup_tx_resources(&temp_ring[i]);
			if (err) {
				while (i) {
					i--;
					fm10k_free_tx_resources(&temp_ring[i]);
				}
				goto err_setup;
			}
		}

		for (i = 0; i < interface->num_tx_queues; i++) {
			fm10k_free_tx_resources(interface->tx_ring[i]);

			memcpy(interface->tx_ring[i], &temp_ring[i],
			       sizeof(struct fm10k_ring));
		}

		interface->tx_ring_count = new_tx_count;
	}

	/* Repeat the process for the Rx rings if needed */
	if (new_rx_count != interface->rx_ring_count) {
		for (i = 0; i < interface->num_rx_queues; i++) {
			memcpy(&temp_ring[i], interface->rx_ring[i],
			       sizeof(struct fm10k_ring));

			temp_ring[i].count = new_rx_count;
			err = fm10k_setup_rx_resources(&temp_ring[i]);
			if (err) {
				while (i) {
					i--;
					fm10k_free_rx_resources(&temp_ring[i]);
				}
				goto err_setup;
			}
		}

		for (i = 0; i < interface->num_rx_queues; i++) {
			fm10k_free_rx_resources(interface->rx_ring[i]);

			memcpy(interface->rx_ring[i], &temp_ring[i],
			       sizeof(struct fm10k_ring));
		}

		interface->rx_ring_count = new_rx_count;
	}

err_setup:
	fm10k_up(interface);
	vfree(temp_ring);
clear_reset:
	clear_bit(__FM10K_RESETTING, &interface->state);
	return err;
}