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

Commit d18ca7df authored by Intiyaz Basha's avatar Intiyaz Basha Committed by David S. Miller
Browse files

liquidio: added support for ethtool --set-ring feature



added support for ethtool --set-ring feature

Signed-off-by: default avatarIntiyaz Basha <intiyaz.basha@cavium.com>
Signed-off-by: default avatarFelix Manlunas <felix.manlunas@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8974de1b
Loading
Loading
Loading
Loading
+131 −0
Original line number Diff line number Diff line
@@ -637,6 +637,9 @@ lio_ethtool_get_ringparam(struct net_device *netdev,
	u32 tx_max_pending = 0, rx_max_pending = 0, tx_pending = 0,
	    rx_pending = 0;

	if (ifstate_check(lio, LIO_IFSTATE_RESETTING))
		return;

	if (OCTEON_CN6XXX(oct)) {
		struct octeon_config *conf6x = CHIP_CONF(oct, cn6xxx);

@@ -661,6 +664,126 @@ lio_ethtool_get_ringparam(struct net_device *netdev,
	ering->rx_jumbo_max_pending = 0;
}

static int lio_reset_queues(struct net_device *netdev)
{
	struct lio *lio = GET_LIO(netdev);
	struct octeon_device *oct = lio->oct_dev;
	struct napi_struct *napi, *n;
	int i;

	dev_dbg(&oct->pci_dev->dev, "%s:%d ifidx %d\n",
		__func__, __LINE__, lio->ifidx);

	if (wait_for_pending_requests(oct))
		dev_err(&oct->pci_dev->dev, "There were pending requests\n");

	if (lio_wait_for_instr_fetch(oct))
		dev_err(&oct->pci_dev->dev, "IQ had pending instructions\n");

	if (octeon_set_io_queues_off(oct)) {
		dev_err(&oct->pci_dev->dev, "setting io queues off failed\n");
		return -1;
	}

	/* Disable the input and output queues now. No more packets will
	 * arrive from Octeon.
	 */
	oct->fn_list.disable_io_queues(oct);
	/* Delete NAPI */
	list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
		netif_napi_del(napi);

	for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
		if (!(oct->io_qmask.oq & BIT_ULL(i)))
			continue;
		octeon_delete_droq(oct, i);
	}

	for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
		if (!(oct->io_qmask.iq & BIT_ULL(i)))
			continue;
		octeon_delete_instr_queue(oct, i);
	}

	if (oct->fn_list.setup_device_regs(oct)) {
		dev_err(&oct->pci_dev->dev, "Failed to configure device registers\n");
		return -1;
	}

	if (liquidio_setup_io_queues(oct, 0)) {
		dev_err(&oct->pci_dev->dev, "IO queues initialization failed\n");
		return -1;
	}

	/* Enable the input and output queues for this Octeon device */
	if (oct->fn_list.enable_io_queues(oct)) {
		dev_err(&oct->pci_dev->dev, "Failed to enable input/output queues");
		return -1;
	}

	return 0;
}

static int lio_ethtool_set_ringparam(struct net_device *netdev,
				     struct ethtool_ringparam *ering)
{
	u32 rx_count, tx_count, rx_count_old, tx_count_old;
	struct lio *lio = GET_LIO(netdev);
	struct octeon_device *oct = lio->oct_dev;
	int stopped = 0;

	if (!OCTEON_CN23XX_PF(oct) && !OCTEON_CN23XX_VF(oct))
		return -EINVAL;

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

	rx_count = clamp_t(u32, ering->rx_pending, CN23XX_MIN_OQ_DESCRIPTORS,
			   CN23XX_MAX_OQ_DESCRIPTORS);
	tx_count = clamp_t(u32, ering->tx_pending, CN23XX_MIN_IQ_DESCRIPTORS,
			   CN23XX_MAX_IQ_DESCRIPTORS);

	rx_count_old = oct->droq[0]->max_count;
	tx_count_old = oct->instr_queue[0]->max_count;

	if (rx_count == rx_count_old && tx_count == tx_count_old)
		return 0;

	ifstate_set(lio, LIO_IFSTATE_RESETTING);

	if (netif_running(netdev)) {
		netdev->netdev_ops->ndo_stop(netdev);
		stopped = 1;
	}

	/* Change RX/TX DESCS  count */
	if (tx_count != tx_count_old)
		CFG_SET_NUM_TX_DESCS_NIC_IF(octeon_get_conf(oct), lio->ifidx,
					    tx_count);
	if (rx_count != rx_count_old)
		CFG_SET_NUM_RX_DESCS_NIC_IF(octeon_get_conf(oct), lio->ifidx,
					    rx_count);

	if (lio_reset_queues(netdev))
		goto err_lio_reset_queues;

	if (stopped)
		netdev->netdev_ops->ndo_open(netdev);

	ifstate_reset(lio, LIO_IFSTATE_RESETTING);

	return 0;

err_lio_reset_queues:
	if (tx_count != tx_count_old)
		CFG_SET_NUM_TX_DESCS_NIC_IF(octeon_get_conf(oct), lio->ifidx,
					    tx_count_old);
	if (rx_count != rx_count_old)
		CFG_SET_NUM_RX_DESCS_NIC_IF(octeon_get_conf(oct), lio->ifidx,
					    rx_count_old);
	return -EINVAL;
}

static u32 lio_get_msglevel(struct net_device *netdev)
{
	struct lio *lio = GET_LIO(netdev);
@@ -779,6 +902,9 @@ lio_get_ethtool_stats(struct net_device *netdev,
	struct net_device_stats *netstats = &netdev->stats;
	int i = 0, j;

	if (ifstate_check(lio, LIO_IFSTATE_RESETTING))
		return;

	netdev->netdev_ops->ndo_get_stats(netdev);
	octnet_get_link_stats(netdev);

@@ -1043,6 +1169,9 @@ static void lio_vf_get_ethtool_stats(struct net_device *netdev,
	struct octeon_device *oct_dev = lio->oct_dev;
	int i = 0, j, vj;

	if (ifstate_check(lio, LIO_IFSTATE_RESETTING))
		return;

	netdev->netdev_ops->ndo_get_stats(netdev);
	/* sum of oct->droq[oq_no]->stats->rx_pkts_received */
	data[i++] = CVM_CAST64(netstats->rx_packets);
@@ -2574,6 +2703,7 @@ static const struct ethtool_ops lio_ethtool_ops = {
	.get_link		= ethtool_op_get_link,
	.get_drvinfo		= lio_get_drvinfo,
	.get_ringparam		= lio_ethtool_get_ringparam,
	.set_ringparam		= lio_ethtool_set_ringparam,
	.get_channels		= lio_ethtool_get_channels,
	.set_phys_id		= lio_set_phys_id,
	.get_eeprom_len		= lio_get_eeprom_len,
@@ -2599,6 +2729,7 @@ static const struct ethtool_ops lio_vf_ethtool_ops = {
	.get_link		= ethtool_op_get_link,
	.get_drvinfo		= lio_get_vf_drvinfo,
	.get_ringparam		= lio_ethtool_get_ringparam,
	.set_ringparam          = lio_ethtool_set_ringparam,
	.get_channels		= lio_ethtool_get_channels,
	.get_strings		= lio_vf_get_strings,
	.get_ethtool_stats	= lio_vf_get_ethtool_stats,
+5 −1
Original line number Diff line number Diff line
@@ -817,7 +817,8 @@ static void print_link_info(struct net_device *netdev)
{
	struct lio *lio = GET_LIO(netdev);

	if (atomic_read(&lio->ifstate) & LIO_IFSTATE_REGISTERED) {
	if (!ifstate_check(lio, LIO_IFSTATE_RESETTING) &&
	    ifstate_check(lio, LIO_IFSTATE_REGISTERED)) {
		struct oct_link_info *linfo = &lio->linfo;

		if (linfo->link.s.link_up) {
@@ -2520,6 +2521,9 @@ static struct net_device_stats *liquidio_get_stats(struct net_device *netdev)

	oct = lio->oct_dev;

	if (ifstate_check(lio, LIO_IFSTATE_RESETTING))
		return stats;

	for (i = 0; i < lio->linfo.num_txpciq; i++) {
		iq_no = lio->linfo.txpciq[i].s.q_no;
		iq_stats = &oct->instr_queue[iq_no]->stats;
+5 −1
Original line number Diff line number Diff line
@@ -548,7 +548,8 @@ static void print_link_info(struct net_device *netdev)
{
	struct lio *lio = GET_LIO(netdev);

	if (atomic_read(&lio->ifstate) & LIO_IFSTATE_REGISTERED) {
	if (!ifstate_check(lio, LIO_IFSTATE_RESETTING) &&
	    ifstate_check(lio, LIO_IFSTATE_REGISTERED)) {
		struct oct_link_info *linfo = &lio->linfo;

		if (linfo->link.s.link_up) {
@@ -1633,6 +1634,9 @@ static struct net_device_stats *liquidio_get_stats(struct net_device *netdev)

	oct = lio->oct_dev;

	if (ifstate_check(lio, LIO_IFSTATE_RESETTING))
		return stats;

	for (i = 0; i < lio->linfo.num_txpciq; i++) {
		iq_no = lio->linfo.txpciq[i].s.q_no;
		iq_stats = &oct->instr_queue[iq_no]->stats;
+11 −2
Original line number Diff line number Diff line
@@ -71,13 +71,17 @@
#define   CN23XX_MAX_RINGS_PER_VF          8

#define   CN23XX_MAX_INPUT_QUEUES	CN23XX_MAX_RINGS_PER_PF
#define   CN23XX_MAX_IQ_DESCRIPTORS	512
#define   CN23XX_MAX_IQ_DESCRIPTORS	2048
#define   CN23XX_DEFAULT_IQ_DESCRIPTORS	512
#define   CN23XX_MIN_IQ_DESCRIPTORS	128
#define   CN23XX_DB_MIN                 1
#define   CN23XX_DB_MAX                 8
#define   CN23XX_DB_TIMEOUT             1

#define   CN23XX_MAX_OUTPUT_QUEUES	CN23XX_MAX_RINGS_PER_PF
#define   CN23XX_MAX_OQ_DESCRIPTORS	512
#define   CN23XX_MAX_OQ_DESCRIPTORS	2048
#define   CN23XX_DEFAULT_OQ_DESCRIPTORS	512
#define   CN23XX_MIN_OQ_DESCRIPTORS	128
#define   CN23XX_OQ_BUF_SIZE		1664
#define   CN23XX_OQ_PKTSPER_INTR	128
/*#define CAVIUM_ONLY_CN23XX_RX_PERF*/
@@ -163,6 +167,11 @@
				((cfg)->misc.oct_link_query_interval)
#define CFG_GET_IS_SLI_BP_ON(cfg)                ((cfg)->misc.enable_sli_oq_bp)

#define CFG_SET_NUM_RX_DESCS_NIC_IF(cfg, idx, value) \
				((cfg)->nic_if_cfg[idx].num_rx_descs = value)
#define CFG_SET_NUM_TX_DESCS_NIC_IF(cfg, idx, value) \
				((cfg)->nic_if_cfg[idx].num_tx_descs = value)

/* Max IOQs per OCTEON Link */
#define MAX_IOQS_PER_NICIF              64

+7 −7
Original line number Diff line number Diff line
@@ -418,7 +418,7 @@ static struct octeon_config default_cn23xx_conf = {
	/** IQ attributes */
	.iq = {
		.max_iqs		= CN23XX_CFG_IO_QUEUES,
		.pending_list_size	= (CN23XX_MAX_IQ_DESCRIPTORS *
		.pending_list_size	= (CN23XX_DEFAULT_IQ_DESCRIPTORS *
					   CN23XX_CFG_IO_QUEUES),
		.instr_type		= OCTEON_64BYTE_INSTR,
		.db_min			= CN23XX_DB_MIN,
@@ -436,8 +436,8 @@ static struct octeon_config default_cn23xx_conf = {
	},

	.num_nic_ports				= DEFAULT_NUM_NIC_PORTS_23XX,
	.num_def_rx_descs			= CN23XX_MAX_OQ_DESCRIPTORS,
	.num_def_tx_descs			= CN23XX_MAX_IQ_DESCRIPTORS,
	.num_def_rx_descs			= CN23XX_DEFAULT_OQ_DESCRIPTORS,
	.num_def_tx_descs			= CN23XX_DEFAULT_IQ_DESCRIPTORS,
	.def_rx_buf_size			= CN23XX_OQ_BUF_SIZE,

	/* For ethernet interface 0:  Port cfg Attributes */
@@ -455,10 +455,10 @@ static struct octeon_config default_cn23xx_conf = {
		.num_rxqs			= DEF_RXQS_PER_INTF,

		/* Num of desc for rx rings */
		.num_rx_descs			= CN23XX_MAX_OQ_DESCRIPTORS,
		.num_rx_descs			= CN23XX_DEFAULT_OQ_DESCRIPTORS,

		/* Num of desc for tx rings */
		.num_tx_descs			= CN23XX_MAX_IQ_DESCRIPTORS,
		.num_tx_descs			= CN23XX_DEFAULT_IQ_DESCRIPTORS,

		/* SKB size, We need not change buf size even for Jumbo frames.
		 * Octeon can send jumbo frames in 4 consecutive descriptors,
@@ -484,10 +484,10 @@ static struct octeon_config default_cn23xx_conf = {
		.num_rxqs			= DEF_RXQS_PER_INTF,

		/* Num of desc for rx rings */
		.num_rx_descs			= CN23XX_MAX_OQ_DESCRIPTORS,
		.num_rx_descs			= CN23XX_DEFAULT_OQ_DESCRIPTORS,

		/* Num of desc for tx rings */
		.num_tx_descs			= CN23XX_MAX_IQ_DESCRIPTORS,
		.num_tx_descs			= CN23XX_DEFAULT_IQ_DESCRIPTORS,

		/* SKB size, We need not change buf size even for Jumbo frames.
		 * Octeon can send jumbo frames in 4 consecutive descriptors,
Loading