Commit da70d184 authored by Roger Quadros's avatar Roger Quadros Committed by David S. Miller
Browse files

net: ethernet: ti: am65-cpsw: Introduce multi queue Rx



am65-cpsw can support up to 8 queues at Rx.
Use a macro AM65_CPSW_MAX_RX_QUEUES to indicate that.
As there is only one DMA channel for RX traffic, the
8 queues come as 8 flows in that channel.

By default, we will start with 1 flow as defined by the
macro AM65_CPSW_DEFAULT_RX_CHN_FLOWS.

User can change the number of flows by ethtool like so
'ethtool -L ethx rx <N>'

All traffic will still come on flow 0. To get traffic on
different flows the Classifiers will need to be set up.

Signed-off-by: default avatarRoger Quadros <rogerq@kernel.org>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 52fa3b65
Loading
Loading
Loading
Loading
+29 −46
Original line number Diff line number Diff line
@@ -427,9 +427,9 @@ static void am65_cpsw_get_channels(struct net_device *ndev,
{
	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);

	ch->max_rx = AM65_CPSW_MAX_RX_QUEUES;
	ch->max_tx = AM65_CPSW_MAX_TX_QUEUES;
	ch->rx_count = AM65_CPSW_MAX_RX_QUEUES;
	ch->max_rx = AM65_CPSW_MAX_QUEUES;
	ch->max_tx = AM65_CPSW_MAX_QUEUES;
	ch->rx_count = common->rx_ch_num_flows;
	ch->tx_count = common->tx_ch_num;
}

@@ -447,9 +447,8 @@ static int am65_cpsw_set_channels(struct net_device *ndev,
	if (common->usage_count)
		return -EBUSY;

	am65_cpsw_nuss_remove_tx_chns(common);

	return am65_cpsw_nuss_update_tx_chns(common, chs->tx_count);
	return am65_cpsw_nuss_update_tx_rx_chns(common, chs->tx_count,
						chs->rx_count);
}

static void
@@ -913,80 +912,64 @@ static void am65_cpsw_get_mm_stats(struct net_device *ndev,
	s->MACMergeHoldCount = readl(base + AM65_CPSW_STATN_IET_TX_HOLD);
}

static int am65_cpsw_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
				  struct kernel_ethtool_coalesce *kernel_coal,
				  struct netlink_ext_ack *extack)
{
	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
	struct am65_cpsw_tx_chn *tx_chn;

	tx_chn = &common->tx_chns[0];

	coal->rx_coalesce_usecs = common->rx_pace_timeout / 1000;
	coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout / 1000;

	return 0;
}

static int am65_cpsw_get_per_queue_coalesce(struct net_device *ndev, u32 queue,
					    struct ethtool_coalesce *coal)
{
	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
	struct am65_cpsw_rx_flow *rx_flow;
	struct am65_cpsw_tx_chn *tx_chn;

	if (queue >= AM65_CPSW_MAX_TX_QUEUES)
	if (queue >= AM65_CPSW_MAX_QUEUES)
		return -EINVAL;

	tx_chn = &common->tx_chns[queue];

	coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout / 1000;

	rx_flow = &common->rx_chns.flows[queue];
	coal->rx_coalesce_usecs = rx_flow->rx_pace_timeout / 1000;

	return 0;
}

static int am65_cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
static int am65_cpsw_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
				  struct kernel_ethtool_coalesce *kernel_coal,
				  struct netlink_ext_ack *extack)
{
	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
	struct am65_cpsw_tx_chn *tx_chn;

	tx_chn = &common->tx_chns[0];

	if (coal->rx_coalesce_usecs && coal->rx_coalesce_usecs < 20)
		return -EINVAL;

	if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < 20)
		return -EINVAL;

	common->rx_pace_timeout = coal->rx_coalesce_usecs * 1000;
	tx_chn->tx_pace_timeout = coal->tx_coalesce_usecs * 1000;

	return 0;
	return am65_cpsw_get_per_queue_coalesce(ndev, 0, coal);
}

static int am65_cpsw_set_per_queue_coalesce(struct net_device *ndev, u32 queue,
					    struct ethtool_coalesce *coal)
{
	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
	struct am65_cpsw_rx_flow *rx_flow;
	struct am65_cpsw_tx_chn *tx_chn;

	if (queue >= AM65_CPSW_MAX_TX_QUEUES)
	if (queue >= AM65_CPSW_MAX_QUEUES)
		return -EINVAL;

	tx_chn = &common->tx_chns[queue];

	if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < 20) {
		dev_info(common->dev, "defaulting to min value of 20us for tx-usecs for tx-%u\n",
			 queue);
		coal->tx_coalesce_usecs = 20;
	}
	if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < 20)
		return -EINVAL;

	tx_chn->tx_pace_timeout = coal->tx_coalesce_usecs * 1000;

	rx_flow = &common->rx_chns.flows[queue];
	if (coal->rx_coalesce_usecs && coal->rx_coalesce_usecs < 20)
		return -EINVAL;

	rx_flow->rx_pace_timeout = coal->rx_coalesce_usecs * 1000;

	return 0;
}

static int am65_cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
				  struct kernel_ethtool_coalesce *kernel_coal,
				  struct netlink_ext_ack *extack)
{
	return am65_cpsw_set_per_queue_coalesce(ndev, 0, coal);
}

const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
	.begin			= am65_cpsw_ethtool_op_begin,
	.complete		= am65_cpsw_ethtool_op_complete,
+218 −167

File changed.

Preview size limit exceeded, changes collapsed.

+22 −17

File changed.

Preview size limit exceeded, changes collapsed.