Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aa4a1f7d authored by Himanshu Madhani's avatar Himanshu Madhani Committed by David S. Miller
Browse files

qlcnic: Enable Tx queue changes using ethtool for 82xx Series adapter.



o using ethtool {set|get}_channel option, user can change number
  of Tx queues for 82xx Series adapter.
o updated ethtool -S <ethX> option to display stats from each Tx queue.

Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 012ec812
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -1531,8 +1531,9 @@ int qlcnic_reset_context(struct qlcnic_adapter *);
void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings);
int qlcnic_diag_alloc_res(struct net_device *netdev, int test);
netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
int qlcnic_set_max_rss(struct qlcnic_adapter *, u8, size_t);
int qlcnic_set_max_rss(struct qlcnic_adapter *, u8, int);
int qlcnic_validate_max_rss(struct qlcnic_adapter *, __u32);
int qlcnic_validate_max_tx_rings(struct qlcnic_adapter *, int);
void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *);
int qlcnic_enable_msix(struct qlcnic_adapter *, u32);
@@ -1679,7 +1680,7 @@ struct qlcnic_hardware_ops {
	int (*write_reg) (struct qlcnic_adapter *, ulong, u32);
	void (*get_ocm_win) (struct qlcnic_hardware_context *);
	int (*get_mac_address) (struct qlcnic_adapter *, u8 *);
	int (*setup_intr) (struct qlcnic_adapter *, u8);
	int (*setup_intr) (struct qlcnic_adapter *, u8, int);
	int (*alloc_mbx_args)(struct qlcnic_cmd_args *,
			      struct qlcnic_adapter *, u32);
	int (*mbx_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
@@ -1745,9 +1746,10 @@ static inline int qlcnic_get_mac_address(struct qlcnic_adapter *adapter,
	return adapter->ahw->hw_ops->get_mac_address(adapter, mac);
}

static inline int qlcnic_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
static inline int qlcnic_setup_intr(struct qlcnic_adapter *adapter,
				    u8 num_intr, int txq)
{
	return adapter->ahw->hw_ops->setup_intr(adapter, num_intr);
	return adapter->ahw->hw_ops->setup_intr(adapter, num_intr, txq);
}

static inline int qlcnic_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
+1 −1
Original line number Diff line number Diff line
@@ -261,7 +261,7 @@ int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *adapter, ulong addr,
	}
}

int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr, int txq)
{
	int err, i, num_msix;
	struct qlcnic_hardware_context *ahw = adapter->ahw;
+1 −1
Original line number Diff line number Diff line
@@ -523,7 +523,7 @@ enum qlc_83xx_ext_regs {
/* 83xx funcitons */
int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *);
int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *, struct qlcnic_cmd_args *);
int qlcnic_83xx_setup_intr(struct qlcnic_adapter *, u8);
int qlcnic_83xx_setup_intr(struct qlcnic_adapter *, u8, int);
void qlcnic_83xx_get_func_no(struct qlcnic_adapter *);
int qlcnic_83xx_cam_lock(struct qlcnic_adapter *);
void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *);
+1 −1
Original line number Diff line number Diff line
@@ -2201,7 +2201,7 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
	if (err)
		goto detach_mbx;

	err = qlcnic_setup_intr(adapter, 0);
	err = qlcnic_setup_intr(adapter, 0, 0);
	if (err) {
		dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");
		goto disable_intr;
+51 −12
Original line number Diff line number Diff line
@@ -125,6 +125,14 @@ static const char qlcnic_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = {
};

#define QLCNIC_STATS_LEN	ARRAY_SIZE(qlcnic_gstrings_stats)

static const char qlcnic_tx_ring_stats_strings[][ETH_GSTRING_LEN] = {
	"xmit_on",
	"xmit_off",
	"xmit_called",
	"xmit_finished",
};

static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = {
	"ctx_rx_bytes",
	"ctx_rx_pkts",
@@ -630,15 +638,15 @@ qlcnic_set_ringparam(struct net_device *dev,
static void qlcnic_get_channels(struct net_device *dev,
		struct ethtool_channels *channel)
{
	int min;
	struct qlcnic_adapter *adapter = netdev_priv(dev);
	int min;

	min = min_t(int, adapter->ahw->max_rx_ques, num_online_cpus());
	channel->max_rx = rounddown_pow_of_two(min);
	channel->max_tx = adapter->ahw->max_tx_ques;
	channel->max_tx = min_t(int, QLCNIC_MAX_TX_RINGS, num_online_cpus());

	channel->rx_count = adapter->max_sds_rings;
	channel->tx_count = adapter->ahw->max_tx_ques;
	channel->tx_count = adapter->max_drv_tx_rings;
}

static int qlcnic_set_channels(struct net_device *dev,
@@ -646,18 +654,27 @@ static int qlcnic_set_channels(struct net_device *dev,
{
	struct qlcnic_adapter *adapter = netdev_priv(dev);
	int err;
	int txq = 0;

	if (channel->other_count || channel->combined_count ||
	    channel->tx_count != channel->max_tx)
	if (channel->other_count || channel->combined_count)
		return -EINVAL;

	if (channel->rx_count) {
		err = qlcnic_validate_max_rss(adapter, channel->rx_count);
		if (err)
			return err;
	}

	err = qlcnic_set_max_rss(adapter, channel->rx_count, 0);
	netdev_info(dev, "allocated 0x%x sds rings\n",
				 adapter->max_sds_rings);
	if (channel->tx_count) {
		err = qlcnic_validate_max_tx_rings(adapter, channel->tx_count);
		if (err)
			return err;
		txq = channel->tx_count;
	}

	err = qlcnic_set_max_rss(adapter, channel->rx_count, txq);
	netdev_info(dev, "allocated 0x%x sds rings and  0x%x tx rings\n",
		    adapter->max_sds_rings, adapter->max_drv_tx_rings);
	return err;
}

@@ -893,6 +910,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
clear_diag_irq:
	adapter->max_sds_rings = max_sds_rings;
	clear_bit(__QLCNIC_RESETTING, &adapter->state);

	return ret;
}

@@ -1077,11 +1095,21 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
		       QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
		break;
	case ETH_SS_STATS:
		num_stats = ARRAY_SIZE(qlcnic_tx_ring_stats_strings);
		for (i = 0; i < adapter->max_drv_tx_rings; i++) {
			for (index = 0; index < num_stats; index++) {
				sprintf(data, "tx_ring_%d %s", i,
					qlcnic_tx_ring_stats_strings[index]);
				data += ETH_GSTRING_LEN;
			}
		}

		for (index = 0; index < QLCNIC_STATS_LEN; index++) {
			memcpy(data + index * ETH_GSTRING_LEN,
			       qlcnic_gstrings_stats[index].stat_string,
			       ETH_GSTRING_LEN);
		}

		if (qlcnic_83xx_check(adapter)) {
			num_stats = ARRAY_SIZE(qlcnic_83xx_tx_stats_strings);
			for (i = 0; i < num_stats; i++, index++)
@@ -1173,11 +1201,22 @@ static void qlcnic_get_ethtool_stats(struct net_device *dev,
				     struct ethtool_stats *stats, u64 *data)
{
	struct qlcnic_adapter *adapter = netdev_priv(dev);
	struct qlcnic_host_tx_ring *tx_ring;
	struct qlcnic_esw_statistics port_stats;
	struct qlcnic_mac_statistics mac_stats;
	int index, ret, length, size;
	int index, ret, length, size, ring;
	char *p;

	memset(data, 0, adapter->max_drv_tx_rings * 4 * sizeof(u64));
	for (ring = 0, index = 0; ring < adapter->max_drv_tx_rings; ring++) {
		if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
			tx_ring = &adapter->tx_ring[ring];
			*data++ = tx_ring->xmit_on;
			*data++ = tx_ring->xmit_off;
			*data++ = tx_ring->xmit_called;
			*data++ = tx_ring->xmit_finished;
		}
	}
	memset(data, 0, stats->n_stats * sizeof(u64));
	length = QLCNIC_STATS_LEN;
	for (index = 0; index < length; index++) {
Loading