mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
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: Roger Quadros <rogerq@kernel.org> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
52fa3b6532
commit
da70d184a8
@@ -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,34 +912,54 @@ 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_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
|
||||
struct kernel_ethtool_coalesce *kernel_coal,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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_QUEUES)
|
||||
return -EINVAL;
|
||||
|
||||
tx_chn = &common->tx_chns[queue];
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -948,43 +967,7 @@ static int am65_cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coales
|
||||
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;
|
||||
}
|
||||
|
||||
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_tx_chn *tx_chn;
|
||||
|
||||
if (queue >= AM65_CPSW_MAX_TX_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;
|
||||
}
|
||||
|
||||
tx_chn->tx_pace_timeout = coal->tx_coalesce_usecs * 1000;
|
||||
|
||||
return 0;
|
||||
return am65_cpsw_set_per_queue_coalesce(ndev, 0, coal);
|
||||
}
|
||||
|
||||
const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,9 +21,7 @@ struct am65_cpts;
|
||||
|
||||
#define HOST_PORT_NUM 0
|
||||
|
||||
#define AM65_CPSW_MAX_TX_QUEUES 8
|
||||
#define AM65_CPSW_MAX_RX_QUEUES 1
|
||||
#define AM65_CPSW_MAX_RX_FLOWS 1
|
||||
#define AM65_CPSW_MAX_QUEUES 8 /* both TX & RX */
|
||||
|
||||
#define AM65_CPSW_PORT_VLAN_REG_OFFSET 0x014
|
||||
|
||||
@@ -58,7 +56,7 @@ struct am65_cpsw_port {
|
||||
struct am65_cpsw_qos qos;
|
||||
struct devlink_port devlink_port;
|
||||
struct bpf_prog *xdp_prog;
|
||||
struct xdp_rxq_info xdp_rxq;
|
||||
struct xdp_rxq_info xdp_rxq[AM65_CPSW_MAX_QUEUES];
|
||||
/* Only for suspend resume context */
|
||||
u32 vid_context;
|
||||
};
|
||||
@@ -94,16 +92,27 @@ struct am65_cpsw_tx_chn {
|
||||
u32 rate_mbps;
|
||||
};
|
||||
|
||||
struct am65_cpsw_rx_flow {
|
||||
u32 id;
|
||||
struct napi_struct napi_rx;
|
||||
struct am65_cpsw_common *common;
|
||||
int irq;
|
||||
bool irq_disabled;
|
||||
struct hrtimer rx_hrtimer;
|
||||
unsigned long rx_pace_timeout;
|
||||
struct page_pool *page_pool;
|
||||
struct page **pages;
|
||||
char name[32];
|
||||
};
|
||||
|
||||
struct am65_cpsw_rx_chn {
|
||||
struct device *dev;
|
||||
struct device *dma_dev;
|
||||
struct k3_cppi_desc_pool *desc_pool;
|
||||
struct k3_udma_glue_rx_channel *rx_chn;
|
||||
struct page_pool *page_pool;
|
||||
struct page **pages;
|
||||
u32 descs_num;
|
||||
unsigned char dsize_log2;
|
||||
int irq;
|
||||
struct am65_cpsw_rx_flow flows[AM65_CPSW_MAX_QUEUES];
|
||||
};
|
||||
|
||||
#define AM65_CPSW_QUIRK_I2027_NO_TX_CSUM BIT(0)
|
||||
@@ -145,16 +154,12 @@ struct am65_cpsw_common {
|
||||
u32 tx_ch_rate_msk;
|
||||
u32 rx_flow_id_base;
|
||||
|
||||
struct am65_cpsw_tx_chn tx_chns[AM65_CPSW_MAX_TX_QUEUES];
|
||||
struct am65_cpsw_tx_chn tx_chns[AM65_CPSW_MAX_QUEUES];
|
||||
struct completion tdown_complete;
|
||||
atomic_t tdown_cnt;
|
||||
|
||||
int rx_ch_num_flows;
|
||||
struct am65_cpsw_rx_chn rx_chns;
|
||||
struct napi_struct napi_rx;
|
||||
|
||||
bool rx_irq_disabled;
|
||||
struct hrtimer rx_hrtimer;
|
||||
unsigned long rx_pace_timeout;
|
||||
|
||||
u32 nuss_ver;
|
||||
u32 cpsw_ver;
|
||||
@@ -203,8 +208,8 @@ struct am65_cpsw_ndev_priv {
|
||||
#define am65_common_get_host(common) (&(common)->host)
|
||||
#define am65_common_get_port(common, id) (&(common)->ports[(id) - 1])
|
||||
|
||||
#define am65_cpsw_napi_to_common(pnapi) \
|
||||
container_of(pnapi, struct am65_cpsw_common, napi_rx)
|
||||
#define am65_cpsw_napi_to_rx_flow(pnapi) \
|
||||
container_of(pnapi, struct am65_cpsw_rx_flow, napi_rx)
|
||||
#define am65_cpsw_napi_to_tx_chn(pnapi) \
|
||||
container_of(pnapi, struct am65_cpsw_tx_chn, napi_tx)
|
||||
|
||||
@@ -215,8 +220,8 @@ struct am65_cpsw_ndev_priv {
|
||||
extern const struct ethtool_ops am65_cpsw_ethtool_ops_slave;
|
||||
|
||||
void am65_cpsw_nuss_set_p0_ptype(struct am65_cpsw_common *common);
|
||||
void am65_cpsw_nuss_remove_tx_chns(struct am65_cpsw_common *common);
|
||||
int am65_cpsw_nuss_update_tx_chns(struct am65_cpsw_common *common, int num_tx);
|
||||
int am65_cpsw_nuss_update_tx_rx_chns(struct am65_cpsw_common *common,
|
||||
int num_tx, int num_rx);
|
||||
|
||||
bool am65_cpsw_port_dev_check(const struct net_device *dev);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user