Commit a8d5dd19 authored by David S. Miller's avatar David S. Miller

Merge tag 'mlx5-updates-2020-12-01' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

mlx5-updates-2020-12-01

mlx5e port TX timestamping support and MISC updates

1) Add support for port TX timestamping, for better PTP accuracy.

Currently in mlx5 HW TX timestamping is done on CQE (TX completion)
generation, which much earlier than when the packet actually goes out to
the wire, in this series Eran implements the option to do timestamping on
the port using a special SQ (Send Queue), such Send Queue will generate 2
CQEs (TX completions), the original one and a new one when the packet
leaves the port, due to the nature of this special handling, such mechanism
is an opt-in only and it is off by default to avoid any performance
degradation on normal traffic flows.

This patchset improves TX Hardware timestamping offset to be less than
40ns at a 100Gbps line rate, compared to 600ns before.

With that, making our HW compliant with G.8273.2 class C, and allow Linux
systems to be deployed in the 5G telco edge, where this standard is a must.

2) Misc updates and trivial improvements.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c22c0d55 2f6b379c
......@@ -25,7 +25,7 @@ mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \
en_tx.o en_rx.o en_dim.o en_txrx.o en/xdp.o en_stats.o \
en_selftest.o en/port.o en/monitor_stats.o en/health.o \
en/reporter_tx.o en/reporter_rx.o en/params.o en/xsk/pool.o \
en/xsk/setup.o en/xsk/rx.o en/xsk/tx.o en/devlink.o
en/xsk/setup.o en/xsk/rx.o en/xsk/tx.o en/devlink.o en/ptp.o
#
# Netdev extra
......
......@@ -227,6 +227,7 @@ enum mlx5e_priv_flag {
MLX5E_PFLAG_RX_NO_CSUM_COMPLETE,
MLX5E_PFLAG_XDP_TX_MPWQE,
MLX5E_PFLAG_SKB_TX_MPWQE,
MLX5E_PFLAG_TX_PORT_TS,
MLX5E_NUM_PFLAGS, /* Keep last */
};
......@@ -282,10 +283,12 @@ struct mlx5e_cq {
u16 event_ctr;
struct napi_struct *napi;
struct mlx5_core_cq mcq;
struct mlx5e_channel *channel;
struct mlx5e_ch_stats *ch_stats;
/* control */
struct net_device *netdev;
struct mlx5_core_dev *mdev;
struct mlx5e_priv *priv;
struct mlx5_wq_ctrl wq_ctrl;
} ____cacheline_aligned_in_smp;
......@@ -329,6 +332,15 @@ struct mlx5e_tx_mpwqe {
u8 inline_on;
};
struct mlx5e_skb_fifo {
struct sk_buff **fifo;
u16 *pc;
u16 *cc;
u16 mask;
};
struct mlx5e_ptpsq;
struct mlx5e_txqsq {
/* data path */
......@@ -349,11 +361,10 @@ struct mlx5e_txqsq {
/* read only */
struct mlx5_wq_cyc wq;
u32 dma_fifo_mask;
u16 skb_fifo_mask;
struct mlx5e_sq_stats *stats;
struct {
struct mlx5e_sq_dma *dma_fifo;
struct sk_buff **skb_fifo;
struct mlx5e_skb_fifo skb_fifo;
struct mlx5e_tx_wqe_info *wqe_info;
} db;
void __iomem *uar_map;
......@@ -367,14 +378,17 @@ struct mlx5e_txqsq {
unsigned int hw_mtu;
struct hwtstamp_config *tstamp;
struct mlx5_clock *clock;
struct net_device *netdev;
struct mlx5_core_dev *mdev;
struct mlx5e_priv *priv;
/* control path */
struct mlx5_wq_ctrl wq_ctrl;
struct mlx5e_channel *channel;
int ch_ix;
int txq_ix;
u32 rate_limit;
struct work_struct recover_work;
struct mlx5e_ptpsq *ptpsq;
} ____cacheline_aligned_in_smp;
struct mlx5e_dma_info {
......@@ -593,7 +607,6 @@ struct mlx5e_rq {
u8 map_dir; /* dma map direction */
} buff;
struct mlx5e_channel *channel;
struct device *pdev;
struct net_device *netdev;
struct mlx5e_rq_stats *stats;
......@@ -602,6 +615,8 @@ struct mlx5e_rq {
struct mlx5e_page_cache page_cache;
struct hwtstamp_config *tstamp;
struct mlx5_clock *clock;
struct mlx5e_icosq *icosq;
struct mlx5e_priv *priv;
mlx5e_fp_handle_rx_cqe handle_rx_cqe;
mlx5e_fp_post_rx_wqes post_wqes;
......@@ -681,8 +696,11 @@ struct mlx5e_channel {
int cpu;
};
struct mlx5e_port_ptp;
struct mlx5e_channels {
struct mlx5e_channel **c;
struct mlx5e_port_ptp *port_ptp;
unsigned int num;
struct mlx5e_params params;
};
......@@ -697,6 +715,12 @@ struct mlx5e_channel_stats {
struct mlx5e_xdpsq_stats xsksq;
} ____cacheline_aligned_in_smp;
struct mlx5e_port_ptp_stats {
struct mlx5e_ch_stats ch;
struct mlx5e_sq_stats sq[MLX5E_MAX_NUM_TC];
struct mlx5e_ptp_cq_stats cq[MLX5E_MAX_NUM_TC];
} ____cacheline_aligned_in_smp;
enum {
MLX5E_STATE_OPENED,
MLX5E_STATE_DESTROYING,
......@@ -766,8 +790,10 @@ struct mlx5e_scratchpad {
struct mlx5e_priv {
/* priv data path fields - start */
struct mlx5e_txqsq *txq2sq[MLX5E_MAX_NUM_CHANNELS * MLX5E_MAX_NUM_TC];
/* +1 for port ptp ts */
struct mlx5e_txqsq *txq2sq[(MLX5E_MAX_NUM_CHANNELS + 1) * MLX5E_MAX_NUM_TC];
int channel_tc2realtxq[MLX5E_MAX_NUM_CHANNELS][MLX5E_MAX_NUM_TC];
int port_ptp_tc2realtxq[MLX5E_MAX_NUM_TC];
#ifdef CONFIG_MLX5_CORE_EN_DCB
struct mlx5e_dcbx_dp dcbx_dp;
#endif
......@@ -802,12 +828,15 @@ struct mlx5e_priv {
struct net_device *netdev;
struct mlx5e_stats stats;
struct mlx5e_channel_stats channel_stats[MLX5E_MAX_NUM_CHANNELS];
struct mlx5e_port_ptp_stats port_ptp_stats;
u16 max_nch;
u8 max_opened_tc;
bool port_ptp_opened;
struct hwtstamp_config tstamp;
u16 q_counter;
u16 drop_rq_q_counter;
struct notifier_block events_nb;
int num_tc_x_num_ch;
struct udp_tunnel_nic_info nic_info;
#ifdef CONFIG_MLX5_CORE_EN_DCB
......@@ -923,9 +952,17 @@ int mlx5e_open_xdpsq(struct mlx5e_channel *c, struct mlx5e_params *params,
struct mlx5e_xdpsq *sq, bool is_redirect);
void mlx5e_close_xdpsq(struct mlx5e_xdpsq *sq);
struct mlx5e_create_cq_param {
struct napi_struct *napi;
struct mlx5e_ch_stats *ch_stats;
int node;
int ix;
};
struct mlx5e_cq_param;
int mlx5e_open_cq(struct mlx5e_channel *c, struct dim_cq_moder moder,
struct mlx5e_cq_param *param, struct mlx5e_cq *cq);
int mlx5e_open_cq(struct mlx5e_priv *priv, struct dim_cq_moder moder,
struct mlx5e_cq_param *param, struct mlx5e_create_cq_param *ccp,
struct mlx5e_cq *cq);
void mlx5e_close_cq(struct mlx5e_cq *cq);
int mlx5e_open_locked(struct net_device *netdev);
......@@ -974,7 +1011,17 @@ void mlx5e_deactivate_icosq(struct mlx5e_icosq *icosq);
int mlx5e_modify_sq(struct mlx5_core_dev *mdev, u32 sqn,
struct mlx5e_modify_sq_param *p);
void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq);
void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq);
void mlx5e_free_txqsq(struct mlx5e_txqsq *sq);
void mlx5e_tx_disable_queue(struct netdev_queue *txq);
int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa);
void mlx5e_free_txqsq_db(struct mlx5e_txqsq *sq);
struct mlx5e_create_sq_param;
int mlx5e_create_sq_rdy(struct mlx5_core_dev *mdev,
struct mlx5e_sq_param *param,
struct mlx5e_create_sq_param *csp,
u32 *sqn);
void mlx5e_tx_err_cqe_work(struct work_struct *recover_work);
static inline bool mlx5_tx_swp_supported(struct mlx5_core_dev *mdev)
{
......
......@@ -287,8 +287,7 @@ void mlx5e_disable_cvlan_filter(struct mlx5e_priv *priv);
int mlx5e_create_flow_steering(struct mlx5e_priv *priv);
void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv);
bool mlx5e_tunnel_proto_supported(struct mlx5_core_dev *mdev, u8 proto_type);
bool mlx5e_any_tunnel_proto_supported(struct mlx5_core_dev *mdev);
u8 mlx5e_get_proto_by_tunnel_type(enum mlx5e_tunnel_types tt);
#endif /* __MLX5E_FLOW_STEER_H__ */
......@@ -37,13 +37,12 @@ int mlx5e_health_fmsg_named_obj_nest_end(struct devlink_fmsg *fmsg)
int mlx5e_health_cq_diag_fmsg(struct mlx5e_cq *cq, struct devlink_fmsg *fmsg)
{
struct mlx5e_priv *priv = cq->channel->priv;
u32 out[MLX5_ST_SZ_DW(query_cq_out)] = {};
u8 hw_status;
void *cqc;
int err;
err = mlx5_core_query_cq(priv->mdev, &cq->mcq, out);
err = mlx5_core_query_cq(cq->mdev, &cq->mcq, out);
if (err)
return err;
......@@ -158,10 +157,8 @@ void mlx5e_health_channels_update(struct mlx5e_priv *priv)
DEVLINK_HEALTH_REPORTER_STATE_HEALTHY);
}
int mlx5e_health_sq_to_ready(struct mlx5e_channel *channel, u32 sqn)
int mlx5e_health_sq_to_ready(struct mlx5_core_dev *mdev, struct net_device *dev, u32 sqn)
{
struct mlx5_core_dev *mdev = channel->mdev;
struct net_device *dev = channel->netdev;
struct mlx5e_modify_sq_param msp = {};
int err;
......@@ -206,21 +203,22 @@ int mlx5e_health_recover_channels(struct mlx5e_priv *priv)
return err;
}
int mlx5e_health_channel_eq_recover(struct mlx5_eq_comp *eq, struct mlx5e_channel *channel)
int mlx5e_health_channel_eq_recover(struct net_device *dev, struct mlx5_eq_comp *eq,
struct mlx5e_ch_stats *stats)
{
u32 eqe_count;
netdev_err(channel->netdev, "EQ 0x%x: Cons = 0x%x, irqn = 0x%x\n",
netdev_err(dev, "EQ 0x%x: Cons = 0x%x, irqn = 0x%x\n",
eq->core.eqn, eq->core.cons_index, eq->core.irqn);
eqe_count = mlx5_eq_poll_irq_disabled(eq);
if (!eqe_count)
return -EIO;
netdev_err(channel->netdev, "Recovered %d eqes on EQ 0x%x\n",
netdev_err(dev, "Recovered %d eqes on EQ 0x%x\n",
eqe_count, eq->core.eqn);
channel->stats->eq_rearm++;
stats->eq_rearm++;
return 0;
}
......
......@@ -7,8 +7,6 @@
#include "en.h"
#include "diag/rsc_dump.h"
#define MLX5E_RX_ERR_CQE(cqe) (get_cqe_opcode(cqe) != MLX5_CQE_RESP_SEND)
static inline bool cqe_syndrome_needs_recover(u8 syndrome)
{
return syndrome == MLX5_CQE_SYNDROME_LOCAL_QP_OP_ERR ||
......@@ -42,8 +40,9 @@ struct mlx5e_err_ctx {
void *ctx;
};
int mlx5e_health_sq_to_ready(struct mlx5e_channel *channel, u32 sqn);
int mlx5e_health_channel_eq_recover(struct mlx5_eq_comp *eq, struct mlx5e_channel *channel);
int mlx5e_health_sq_to_ready(struct mlx5_core_dev *mdev, struct net_device *dev, u32 sqn);
int mlx5e_health_channel_eq_recover(struct net_device *dev, struct mlx5_eq_comp *eq,
struct mlx5e_ch_stats *stats);
int mlx5e_health_recover_channels(struct mlx5e_priv *priv);
int mlx5e_health_report(struct mlx5e_priv *priv,
struct devlink_health_reporter *reporter, char *err_str,
......
......@@ -41,6 +41,15 @@ struct mlx5e_channel_param {
struct mlx5e_sq_param async_icosq;
};
struct mlx5e_create_sq_param {
struct mlx5_wq_ctrl *wq_ctrl;
u32 cqn;
u32 ts_cqe_to_dest_cqn;
u32 tisn;
u8 tis_lst_sz;
u8 min_inline_mode;
};
static inline bool mlx5e_qid_get_ch_if_in_group(struct mlx5e_params *params,
u16 qid,
enum mlx5e_rq_group group,
......@@ -102,6 +111,7 @@ u16 mlx5e_get_rq_headroom(struct mlx5_core_dev *mdev,
/* Build queue parameters */
void mlx5e_build_create_cq_param(struct mlx5e_create_cq_param *ccp, struct mlx5e_channel *c);
void mlx5e_build_rq_param(struct mlx5e_priv *priv,
struct mlx5e_params *params,
struct mlx5e_xsk_param *xsk,
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2020 Mellanox Technologies. */
#ifndef __MLX5_EN_PTP_H__
#define __MLX5_EN_PTP_H__
#include "en.h"
#include "en/params.h"
#include "en_stats.h"
struct mlx5e_ptpsq {
struct mlx5e_txqsq txqsq;
struct mlx5e_cq ts_cq;
u16 skb_fifo_cc;
u16 skb_fifo_pc;
struct mlx5e_skb_fifo skb_fifo;
struct mlx5e_ptp_cq_stats *cq_stats;
};
struct mlx5e_port_ptp {
/* data path */
struct mlx5e_ptpsq ptpsq[MLX5E_MAX_NUM_TC];
struct napi_struct napi;
struct device *pdev;
struct net_device *netdev;
__be32 mkey_be;
u8 num_tc;
u8 lag_port;
/* data path - accessed per napi poll */
struct irq_desc *irq_desc;
struct mlx5e_ch_stats *stats;
/* control */
struct mlx5e_priv *priv;
struct mlx5_core_dev *mdev;
struct hwtstamp_config *tstamp;
DECLARE_BITMAP(state, MLX5E_CHANNEL_NUM_STATES);
int ix;
};
struct mlx5e_ptp_params {
struct mlx5e_params params;
struct mlx5e_sq_param txq_sq_param;
};
int mlx5e_port_ptp_open(struct mlx5e_priv *priv, struct mlx5e_params *params,
u8 lag_port, struct mlx5e_port_ptp **cp);
void mlx5e_port_ptp_close(struct mlx5e_port_ptp *c);
void mlx5e_ptp_activate_channel(struct mlx5e_port_ptp *c);
void mlx5e_ptp_deactivate_channel(struct mlx5e_port_ptp *c);
enum {
MLX5E_SKB_CB_CQE_HWTSTAMP = BIT(0),
MLX5E_SKB_CB_PORT_HWTSTAMP = BIT(1),
};
void mlx5e_skb_cb_hwtstamp_handler(struct sk_buff *skb, int hwtstamp_type,
ktime_t hwtstamp,
struct mlx5e_ptp_cq_stats *cq_stats);
void mlx5e_skb_cb_hwtstamp_init(struct sk_buff *skb);
#endif /* __MLX5_EN_PTP_H__ */
......@@ -87,7 +87,7 @@ static int mlx5e_rx_reporter_err_icosq_cqe_recover(void *ctx)
/* At this point, both the rq and the icosq are disabled */
err = mlx5e_health_sq_to_ready(icosq->channel, icosq->sqn);
err = mlx5e_health_sq_to_ready(mdev, dev, icosq->sqn);
if (err)
goto out;
......@@ -146,17 +146,16 @@ static int mlx5e_rx_reporter_err_rq_cqe_recover(void *ctx)
static int mlx5e_rx_reporter_timeout_recover(void *ctx)
{
struct mlx5e_icosq *icosq;
struct mlx5_eq_comp *eq;
struct mlx5e_rq *rq;
int err;
rq = ctx;
icosq = &rq->channel->icosq;
eq = rq->cq.mcq.eq;
err = mlx5e_health_channel_eq_recover(eq, rq->channel);
if (err)
clear_bit(MLX5E_SQ_STATE_ENABLED, &icosq->state);
err = mlx5e_health_channel_eq_recover(rq->netdev, eq, rq->cq.ch_stats);
if (err && rq->icosq)
clear_bit(MLX5E_SQ_STATE_ENABLED, &rq->icosq->state);
return err;
}
......@@ -233,21 +232,13 @@ static int mlx5e_reporter_icosq_diagnose(struct mlx5e_icosq *icosq, u8 hw_state,
static int mlx5e_rx_reporter_build_diagnose_output(struct mlx5e_rq *rq,
struct devlink_fmsg *fmsg)
{
struct mlx5e_priv *priv = rq->channel->priv;
struct mlx5e_icosq *icosq;
u8 icosq_hw_state;
u16 wqe_counter;
int wqes_sz;
u8 hw_state;
u16 wq_head;
int err;
icosq = &rq->channel->icosq;
err = mlx5e_query_rq_state(priv->mdev, rq->rqn, &hw_state);
if (err)
return err;
err = mlx5_core_query_sq_state(priv->mdev, icosq->sqn, &icosq_hw_state);
err = mlx5e_query_rq_state(rq->mdev, rq->rqn, &hw_state);
if (err)
return err;
......@@ -259,7 +250,7 @@ static int mlx5e_rx_reporter_build_diagnose_output(struct mlx5e_rq *rq,
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "channel ix", rq->channel->ix);
err = devlink_fmsg_u32_pair_put(fmsg, "channel ix", rq->ix);
if (err)
return err;
......@@ -295,9 +286,18 @@ static int mlx5e_rx_reporter_build_diagnose_output(struct mlx5e_rq *rq,
if (err)
return err;
err = mlx5e_reporter_icosq_diagnose(icosq, icosq_hw_state, fmsg);
if (err)
return err;
if (rq->icosq) {
struct mlx5e_icosq *icosq = rq->icosq;
u8 icosq_hw_state;
err = mlx5_core_query_sq_state(rq->mdev, icosq->sqn, &icosq_hw_state);
if (err)
return err;
err = mlx5e_reporter_icosq_diagnose(icosq, icosq_hw_state, fmsg);
if (err)
return err;
}
err = devlink_fmsg_obj_nest_end(fmsg);
if (err)
......@@ -557,25 +557,29 @@ static int mlx5e_rx_reporter_dump(struct devlink_health_reporter *reporter,
void mlx5e_reporter_rx_timeout(struct mlx5e_rq *rq)
{
struct mlx5e_icosq *icosq = &rq->channel->icosq;
struct mlx5e_priv *priv = rq->channel->priv;
char icosq_str[MLX5E_REPORTER_PER_Q_MAX_LEN] = {};
char err_str[MLX5E_REPORTER_PER_Q_MAX_LEN];
struct mlx5e_icosq *icosq = rq->icosq;
struct mlx5e_priv *priv = rq->priv;
struct mlx5e_err_ctx err_ctx = {};
err_ctx.ctx = rq;
err_ctx.recover = mlx5e_rx_reporter_timeout_recover;
err_ctx.dump = mlx5e_rx_reporter_dump_rq;
if (icosq)
snprintf(icosq_str, sizeof(icosq_str), "ICOSQ: 0x%x, ", icosq->sqn);
snprintf(err_str, sizeof(err_str),
"RX timeout on channel: %d, ICOSQ: 0x%x RQ: 0x%x, CQ: 0x%x",
icosq->channel->ix, icosq->sqn, rq->rqn, rq->cq.mcq.cqn);
"RX timeout on channel: %d, %sRQ: 0x%x, CQ: 0x%x",
rq->ix, icosq_str, rq->rqn, rq->cq.mcq.cqn);
mlx5e_health_report(priv, priv->rx_reporter, err_str, &err_ctx);
}
void mlx5e_reporter_rq_cqe_err(struct mlx5e_rq *rq)
{
struct mlx5e_priv *priv = rq->channel->priv;
char err_str[MLX5E_REPORTER_PER_Q_MAX_LEN];
struct mlx5e_priv *priv = rq->priv;
struct mlx5e_err_ctx err_ctx = {};
err_ctx.ctx = rq;
......
......@@ -2,6 +2,7 @@
/* Copyright (c) 2019 Mellanox Technologies. */
#include "health.h"
#include "en/ptp.h"
static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq)
{
......@@ -15,7 +16,7 @@ static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq)
msleep(20);
}
netdev_err(sq->channel->netdev,
netdev_err(sq->netdev,
"Wait for SQ 0x%x flush timeout (sq cc = 0x%x, sq pc = 0x%x)\n",
sq->sqn, sq->cc, sq->pc);
......@@ -41,8 +42,8 @@ static int mlx5e_tx_reporter_err_cqe_recover(void *ctx)
int err;
sq = ctx;
mdev = sq->channel->mdev;
dev = sq->channel->netdev;
mdev = sq->mdev;
dev = sq->netdev;
if (!test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state))
return 0;
......@@ -68,7 +69,7 @@ static int mlx5e_tx_reporter_err_cqe_recover(void *ctx)
* pending WQEs. SQ can safely reset the SQ.
*/
err = mlx5e_health_sq_to_ready(sq->channel, sq->sqn);
err = mlx5e_health_sq_to_ready(mdev, dev, sq->sqn);
if (err)
goto out;
......@@ -99,8 +100,8 @@ static int mlx5e_tx_reporter_timeout_recover(void *ctx)
to_ctx = ctx;
sq = to_ctx->sq;
eq = sq->cq.mcq.eq;
priv = sq->channel->priv;
err = mlx5e_health_channel_eq_recover(eq, sq->channel);
priv = sq->priv;
err = mlx5e_health_channel_eq_recover(sq->netdev, eq, sq->cq.ch_stats);
if (!err) {
to_ctx->status = 0; /* this sq recovered */
return err;
......@@ -141,11 +142,11 @@ static int mlx5e_tx_reporter_recover(struct devlink_health_reporter *reporter,
}
static int
mlx5e_tx_reporter_build_diagnose_output(struct devlink_fmsg *fmsg,
struct mlx5e_txqsq *sq, int tc)
mlx5e_tx_reporter_build_diagnose_output_sq_common(struct devlink_fmsg *fmsg,
struct mlx5e_txqsq *sq, int tc)
{
struct mlx5e_priv *priv = sq->channel->priv;
bool stopped = netif_xmit_stopped(sq->txq);
struct mlx5e_priv *priv = sq->priv;
u8 state;
int err;
......@@ -153,14 +154,6 @@ mlx5e_tx_reporter_build_diagnose_output(struct devlink_fmsg *fmsg,
if (err)
return err;
err = devlink_fmsg_obj_nest_start(fmsg);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "channel ix", sq->ch_ix);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "tc", tc);
if (err)
return err;
......@@ -193,7 +186,24 @@ mlx5e_tx_reporter_build_diagnose_output(struct devlink_fmsg *fmsg,
if (err)
return err;
err = mlx5e_health_eq_diag_fmsg(sq->cq.mcq.eq, fmsg);
return mlx5e_health_eq_diag_fmsg(sq->cq.mcq.eq, fmsg);
}
static int
mlx5e_tx_reporter_build_diagnose_output(struct devlink_fmsg *fmsg,
struct mlx5e_txqsq *sq, int tc)
{
int err;
err = devlink_fmsg_obj_nest_start(fmsg);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "channel ix", sq->ch_ix);
if (err)
return err;
err = mlx5e_tx_reporter_build_diagnose_output_sq_common(fmsg, sq, tc);
if (err)
return err;
......@@ -204,49 +214,147 @@ mlx5e_tx_reporter_build_diagnose_output(struct devlink_fmsg *fmsg,
return 0;
}
static int mlx5e_tx_reporter_diagnose(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg,
struct netlink_ext_ack *extack)
static int
mlx5e_tx_reporter_build_diagnose_output_ptpsq(struct devlink_fmsg *fmsg,
struct mlx5e_ptpsq *ptpsq, int tc)
{
struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
struct mlx5e_txqsq *generic_sq = priv->txq2sq[0];
u32 sq_stride, sq_sz;
int err;
int i, tc, err = 0;
err = devlink_fmsg_obj_nest_start(fmsg);
if (err)
return err;
mutex_lock(&priv->state_lock);
err = devlink_fmsg_string_pair_put(fmsg, "channel", "ptp");
if (err)
return err;
if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
goto unlock;
err = mlx5e_tx_reporter_build_diagnose_output_sq_common(fmsg, &ptpsq->txqsq, tc);
if (err)
return err;
sq_sz = mlx5_wq_cyc_get_size(&generic_sq->wq);
sq_stride = MLX5_SEND_WQE_BB;
err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "Port TS");
if (err)
return err;
err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "Common Config");
err = mlx5e_health_cq_diag_fmsg(&ptpsq->ts_cq, fmsg);
if (err)
goto unlock;
return err;
err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
if (err)
return err;
err = devlink_fmsg_obj_nest_end(fmsg);
if (err)
return err;
return 0;
}
static int
mlx5e_tx_reporter_diagnose_generic_txqsq(struct devlink_fmsg *fmsg,
struct mlx5e_txqsq *txqsq)
{
u32 sq_stride, sq_sz;
int err;
err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "SQ");
if (err)
goto unlock;
return err;
sq_sz = mlx5_wq_cyc_get_size(&txqsq->wq);
sq_stride = MLX5_SEND_WQE_BB;
err = devlink_fmsg_u64_pair_put(fmsg, "stride size", sq_stride);
if (err)
goto unlock;
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "size", sq_sz);
if (err)
goto unlock;
return err;
err = mlx5e_health_cq_common_diag_fmsg(&generic_sq->cq, fmsg);
err = mlx5e_health_cq_common_diag_fmsg(&txqsq->cq, fmsg);
if (err)
goto unlock;
return err;
return mlx5e_health_fmsg_named_obj_nest_end(fmsg);
}
static int
mlx5e_tx_reporter_diagnose_generic_tx_port_ts(struct devlink_fmsg *fmsg,
struct mlx5e_ptpsq *ptpsq)
{
int err;
err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "Port TS");
if (err)
return err;
err = mlx5e_health_cq_common_diag_fmsg(&ptpsq->ts_cq, fmsg);
if (err)
return err;
return mlx5e_health_fmsg_named_obj_nest_end(fmsg);
}
static int
mlx5e_tx_reporter_diagnose_common_config(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg)
{
struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
struct mlx5e_txqsq *generic_sq = priv->txq2sq[0];
struct mlx5e_ptpsq *generic_ptpsq;
int err;
err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "Common Config");
if (err)
return err;
err = mlx5e_tx_reporter_diagnose_generic_txqsq(fmsg, generic_sq);
if (err)
return err;
generic_ptpsq = priv->channels.port_ptp ?
&priv->channels.port_ptp->ptpsq[0] :
NULL;
if (!generic_ptpsq)
goto out;
err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "PTP");
if (err)
return err;
err = mlx5e_tx_reporter_diagnose_generic_txqsq(fmsg, &generic_ptpsq->txqsq);
if (err)
return err;
err = mlx5e_tx_reporter_diagnose_generic_tx_port_ts(fmsg, generic_ptpsq);
if (err)
return err;
err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
if (err)
return err;
out:
return mlx5e_health_fmsg_named_obj_nest_end(fmsg);
}
static int mlx5e_tx_reporter_diagnose(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg,
struct netlink_ext_ack *extack)
{
struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
struct mlx5e_port_ptp *ptp_ch = priv->channels.port_ptp;
int i, tc, err = 0;
mutex_lock(&priv->state_lock);
if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
goto unlock;
err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
err = mlx5e_tx_reporter_diagnose_common_config(reporter, fmsg);
if (err)
goto unlock;
......@@ -265,6 +373,19 @@ static int mlx5e_tx_reporter_diagnose(struct devlink_health_reporter *reporter,
goto unlock;
}
}
if (!ptp_ch)
goto close_sqs_nest;
for (tc = 0; tc < priv->channels.params.num_tc; tc++) {
err = mlx5e_tx_reporter_build_diagnose_output_ptpsq(fmsg,
&ptp_ch->ptpsq[tc],
tc);
if (err)
goto unlock;
}
close_sqs_nest:
err = devlink_fmsg_arr_pair_nest_end(fmsg);
if (err)
goto unlock;
......@@ -338,6 +459,7 @@ static int mlx5e_tx_reporter_dump_sq(struct mlx5e_priv *priv, struct devlink_fms
static int mlx5e_tx_reporter_dump_all_sqs(struct mlx5e_priv *priv,
struct devlink_fmsg *fmsg)
{
struct mlx5e_port_ptp *ptp_ch = priv->channels.port_ptp;
struct mlx5_rsc_key key = {};
int i, tc, err;
......@@ -373,6 +495,17 @@ static int mlx5e_tx_reporter_dump_all_sqs(struct mlx5e_priv *priv,
return err;
}
}
if (ptp_ch) {
for (tc = 0; tc < priv->channels.params.num_tc; tc++) {
struct mlx5e_txqsq *sq = &ptp_ch->ptpsq[tc].txqsq;
err = mlx5e_health_queue_dump(priv, fmsg, sq->sqn, "PTP SQ");
if (err)
return err;
}
}
return devlink_fmsg_arr_pair_nest_end(fmsg);
}
......@@ -396,8 +529,8 @@ static int mlx5e_tx_reporter_dump(struct devlink_health_reporter *reporter,
void mlx5e_reporter_tx_err_cqe(struct mlx5e_txqsq *sq)
{
struct mlx5e_priv *priv = sq->channel->priv;
char err_str[MLX5E_REPORTER_PER_Q_MAX_LEN];
struct mlx5e_priv *priv = sq->priv;
struct mlx5e_err_ctx err_ctx = {};
err_ctx.ctx = sq;
......@@ -410,9 +543,9 @@ void mlx5e_reporter_tx_err_cqe(struct mlx5e_txqsq *sq)
int mlx5e_reporter_tx_timeout(struct mlx5e_txqsq *sq)
{
struct mlx5e_priv *priv = sq->channel->priv;
char err_str[MLX5E_REPORTER_PER_Q_MAX_LEN];
struct mlx5e_tx_timeout_ctx to_ctx = {};
struct mlx5e_priv *priv = sq->priv;
struct mlx5e_err_ctx err_ctx = {};
to_ctx.sq = sq;
......@@ -421,7 +554,7 @@ int mlx5e_reporter_tx_timeout(struct mlx5e_txqsq *sq)
err_ctx.dump = mlx5e_tx_reporter_dump_sq;
snprintf(err_str, sizeof(err_str),
"TX timeout on queue: %d, SQ: 0x%x, CQ: 0x%x, SQ Cons: 0x%x SQ Prod: 0x%x, usecs since last trans: %u",
sq->channel->ix, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc,
sq->ch_ix, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc,
jiffies_to_usecs(jiffies - sq->txq->trans_start));
mlx5e_health_report(priv, priv->tx_reporter, err_str, &err_ctx);
......
......@@ -24,6 +24,8 @@
#define INL_HDR_START_SZ (sizeof(((struct mlx5_wqe_eth_seg *)NULL)->inline_hdr.start))
#define MLX5E_RX_ERR_CQE(cqe) (get_cqe_opcode(cqe) != MLX5_CQE_RESP_SEND)
enum mlx5e_icosq_wqe_type {
MLX5E_ICOSQ_WQE_NOP,
MLX5E_ICOSQ_WQE_UMR_RX,
......@@ -250,21 +252,24 @@ mlx5e_dma_push(struct mlx5e_txqsq *sq, dma_addr_t addr, u32 size,
dma->type = map_type;
}
static inline struct sk_buff **mlx5e_skb_fifo_get(struct mlx5e_txqsq *sq, u16 i)
static inline
struct sk_buff **mlx5e_skb_fifo_get(struct mlx5e_skb_fifo *fifo, u16 i)
{
return &sq->db.skb_fifo[i & sq->skb_fifo_mask];
return &fifo->fifo[i & fifo->mask];
}
static inline void mlx5e_skb_fifo_push(struct mlx5e_txqsq *sq, struct sk_buff *skb)
static inline
void mlx5e_skb_fifo_push(struct mlx5e_skb_fifo *fifo, struct sk_buff *skb)
{
struct sk_buff **skb_item = mlx5e_skb_fifo_get(sq, sq->skb_fifo_pc++);
struct sk_buff **skb_item = mlx5e_skb_fifo_get(fifo, (*fifo->pc)++);
*skb_item = skb;
}
static inline struct sk_buff *mlx5e_skb_fifo_pop(struct mlx5e_txqsq *sq)
static inline
struct sk_buff *mlx5e_skb_fifo_pop(struct mlx5e_skb_fifo *fifo)
{
return *mlx5e_skb_fifo_get(sq, sq->skb_fifo_cc++);
return *mlx5e_skb_fifo_get(fifo, (*fifo->cc)++);
}
static inline void
......@@ -308,7 +313,7 @@ static inline void mlx5e_dump_error_cqe(struct mlx5e_cq *cq, u32 qn,
ci = mlx5_cqwq_ctr2ix(wq, wq->cc - 1);
netdev_err(cq->channel->netdev,
netdev_err(cq->netdev,
"Error cqe on cqn 0x%x, ci 0x%x, qn 0x%x, opcode 0x%x, syndrome 0x%x, vendor syndrome 0x%x\n",
cq->mcq.cqn, ci, qn,
get_cqe_opcode((struct mlx5_cqe64 *)err_cqe),
......
......@@ -49,8 +49,11 @@ int mlx5e_open_xsk(struct mlx5e_priv *priv, struct mlx5e_params *params,
struct mlx5e_channel *c)
{
struct mlx5e_channel_param *cparam;
struct mlx5e_create_cq_param ccp;
int err;
mlx5e_build_create_cq_param(&ccp, c);
if (!mlx5e_validate_xsk_param(params, xsk, priv->mdev))
return -EINVAL;
......@@ -60,7 +63,8 @@ int mlx5e_open_xsk(struct mlx5e_priv *priv, struct mlx5e_params *params,
mlx5e_build_xsk_cparam(priv, params, xsk, cparam);
err = mlx5e_open_cq(c, params->rx_cq_moderation, &cparam->rq.cqp, &c->xskrq.cq);
err = mlx5e_open_cq(c->priv, params->rx_cq_moderation, &cparam->rq.cqp, &ccp,
&c->xskrq.cq);
if (unlikely(err))
goto err_free_cparam;
......@@ -68,7 +72,8 @@ int mlx5e_open_xsk(struct mlx5e_priv *priv, struct mlx5e_params *params,
if (unlikely(err))
goto err_close_rx_cq;
err = mlx5e_open_cq(c, params->tx_cq_moderation, &cparam->xdp_sq.cqp, &c->xsksq.cq);
err = mlx5e_open_cq(c->priv, params->tx_cq_moderation, &cparam->xdp_sq.cqp, &ccp,
&c->xsksq.cq);
if (unlikely(err))
goto err_close_rq;
......
......@@ -276,7 +276,7 @@ bool mlx5e_tls_handle_tx_skb(struct net_device *netdev, struct mlx5e_txqsq *sq,
if (WARN_ON_ONCE(tls_ctx->netdev != netdev))
goto err_out;
if (mlx5_accel_is_ktls_tx(sq->channel->mdev))
if (mlx5_accel_is_ktls_tx(sq->mdev))
return mlx5e_ktls_handle_tx_skb(tls_ctx, sq, skb, datalen, state);
/* FPGA */
......
......@@ -1944,6 +1944,38 @@ static int set_pflag_skb_tx_mpwqe(struct net_device *netdev, bool enable)
return set_pflag_tx_mpwqe_common(netdev, MLX5E_PFLAG_SKB_TX_MPWQE, enable);
}
static int set_pflag_tx_port_ts(struct net_device *netdev, bool enable)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
struct mlx5_core_dev *mdev = priv->mdev;
struct mlx5e_channels new_channels = {};
int err;
if (!MLX5_CAP_GEN(mdev, ts_cqe_to_dest_cqn))
return -EOPNOTSUPP;
new_channels.params = priv->channels.params;
MLX5E_SET_PFLAG(&new_channels.params, MLX5E_PFLAG_TX_PORT_TS, enable);
/* No need to verify SQ stop room as
* ptpsq.txqsq.stop_room <= generic_sq->stop_room, and both
* has the same log_sq_size.
*/
if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
priv->channels.params = new_channels.params;
err = mlx5e_num_channels_changed(priv);
goto out;
}
err = mlx5e_safe_switch_channels(priv, &new_channels,
mlx5e_num_channels_changed_ctx, NULL);
out:
if (!err)
priv->port_ptp_opened = true;
return err;
}
static const struct pflag_desc mlx5e_priv_flags[MLX5E_NUM_PFLAGS] = {
{ "rx_cqe_moder", set_pflag_rx_cqe_based_moder },
{ "tx_cqe_moder", set_pflag_tx_cqe_based_moder },
......@@ -1952,6 +1984,7 @@ static const struct pflag_desc mlx5e_priv_flags[MLX5E_NUM_PFLAGS] = {
{ "rx_no_csum_complete", set_pflag_rx_no_csum_complete },
{ "xdp_tx_mpwqe", set_pflag_xdp_tx_mpwqe },
{ "skb_tx_mpwqe", set_pflag_skb_tx_mpwqe },
{ "tx_port_ts", set_pflag_tx_port_ts },
};
static int mlx5e_handle_pflag(struct net_device *netdev,
......
......@@ -772,25 +772,31 @@ static struct mlx5e_etype_proto ttc_tunnel_rules[] = {
};
bool mlx5e_tunnel_proto_supported(struct mlx5_core_dev *mdev, u8 proto_type)
u8 mlx5e_get_proto_by_tunnel_type(enum mlx5e_tunnel_types tt)
{
return ttc_tunnel_rules[tt].proto;
}
static bool mlx5e_tunnel_proto_supported_rx(struct mlx5_core_dev *mdev, u8 proto_type)
{
switch (proto_type) {
case IPPROTO_GRE:
return MLX5_CAP_ETH(mdev, tunnel_stateless_gre);
case IPPROTO_IPIP:
case IPPROTO_IPV6:
return MLX5_CAP_ETH(mdev, tunnel_stateless_ip_over_ip);
return (MLX5_CAP_ETH(mdev, tunnel_stateless_ip_over_ip) ||
MLX5_CAP_ETH(mdev, tunnel_stateless_ip_over_ip_rx));
default:
return false;
}
}
bool mlx5e_any_tunnel_proto_supported(struct mlx5_core_dev *mdev)
static bool mlx5e_tunnel_any_rx_proto_supported(struct mlx5_core_dev *mdev)
{
int tt;
for (tt = 0; tt < MLX5E_NUM_TUNNEL_TT; tt++) {
if (mlx5e_tunnel_proto_supported(mdev, ttc_tunnel_rules[tt].proto))
if (mlx5e_tunnel_proto_supported_rx(mdev, ttc_tunnel_rules[tt].proto))
return true;
}
return false;
......@@ -798,7 +804,7 @@ bool mlx5e_any_tunnel_proto_supported(struct mlx5_core_dev *mdev)
bool mlx5e_tunnel_inner_ft_supported(struct mlx5_core_dev *mdev)
{
return (mlx5e_any_tunnel_proto_supported(mdev) &&
return (mlx5e_tunnel_any_rx_proto_supported(mdev) &&
MLX5_CAP_FLOWTABLE_NIC_RX(mdev, ft_field_support.inner_ip_version));
}
......@@ -899,8 +905,8 @@ static int mlx5e_generate_ttc_table_rules(struct mlx5e_priv *priv,
dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
dest.ft = params->inner_ttc->ft.t;
for (tt = 0; tt < MLX5E_NUM_TUNNEL_TT; tt++) {
if (!mlx5e_tunnel_proto_supported(priv->mdev,
ttc_tunnel_rules[tt].proto))
if (!mlx5e_tunnel_proto_supported_rx(priv->mdev,
ttc_tunnel_rules[tt].proto))
continue;
trules[tt] = mlx5e_generate_ttc_rule(priv, ft, &dest,
ttc_tunnel_rules[tt].etype,
......
......@@ -52,7 +52,6 @@
#include "en/xsk/rx.h"
#include "en/health.h"
#include "en/params.h"
#include "en/txrx.h"
static struct sk_buff *
mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
......@@ -503,7 +502,7 @@ static int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, u16 ix)
{
struct mlx5e_mpw_info *wi = &rq->mpwqe.info[ix];
struct mlx5e_dma_info *dma_info = &wi->umr.dma_info[0];
struct mlx5e_icosq *sq = &rq->channel->icosq;
struct mlx5e_icosq *sq = rq->icosq;
struct mlx5_wq_cyc *wq = &sq->wq;
struct mlx5e_umr_wqe *umr_wqe;
u16 xlt_offset = ix << (MLX5E_LOG_ALIGNED_MPWQE_PPW - 1);
......@@ -670,13 +669,13 @@ int mlx5e_poll_ico_cq(struct mlx5e_cq *cq)
sqcc += wi->num_wqebbs;
if (last_wqe && unlikely(get_cqe_opcode(cqe) != MLX5_CQE_REQ)) {
netdev_WARN_ONCE(cq->channel->netdev,
netdev_WARN_ONCE(cq->netdev,
"Bad OP in ICOSQ CQE: 0x%x\n",
get_cqe_opcode(cqe));
mlx5e_dump_error_cqe(&sq->cq, sq->sqn,
(struct mlx5_err_cqe *)cqe);
if (!test_and_set_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state))
queue_work(cq->channel->priv->wq, &sq->recover_work);
queue_work(cq->priv->wq, &sq->recover_work);
break;
}
......@@ -697,7 +696,7 @@ int mlx5e_poll_ico_cq(struct mlx5e_cq *cq)
break;
#endif
default:
netdev_WARN_ONCE(cq->channel->netdev,
netdev_WARN_ONCE(cq->netdev,
"Bad WQE type in ICOSQ WQE info: 0x%x\n",
wi->wqe_type);
}
......@@ -713,9 +712,9 @@ int mlx5e_poll_ico_cq(struct mlx5e_cq *cq)
INDIRECT_CALLABLE_SCOPE bool mlx5e_post_rx_mpwqes(struct mlx5e_rq *rq)
{
struct mlx5e_icosq *sq = &rq->channel->icosq;
struct mlx5_wq_ll *wq = &rq->mpwqe.wq;
u8 umr_completed = rq->mpwqe.umr_completed;
struct mlx5e_icosq *sq = rq->icosq;
int alloc_err = 0;
u8 missing, i;
u16 head;
......@@ -1218,11 +1217,12 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
static void trigger_report(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
{
struct mlx5_err_cqe *err_cqe = (struct mlx5_err_cqe *)cqe;
struct mlx5e_priv *priv = rq->priv;
if (cqe_syndrome_needs_recover(err_cqe->syndrome) &&
!test_and_set_bit(MLX5E_RQ_STATE_RECOVERING, &rq->state)) {
mlx5e_dump_error_cqe(&rq->cq, rq->rqn, err_cqe);
queue_work(rq->channel->priv->wq, &rq->recover_work);
queue_work(priv->wq, &rq->recover_work);
}
}
......@@ -1771,8 +1771,9 @@ static void mlx5e_ipsec_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cq
int mlx5e_rq_set_handlers(struct mlx5e_rq *rq, struct mlx5e_params *params, bool xsk)
{
struct net_device *netdev = rq->netdev;
struct mlx5_core_dev *mdev = rq->mdev;
struct mlx5e_channel *c = rq->channel;
struct mlx5e_priv *priv = rq->priv;
switch (rq->wq_type) {
case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
......@@ -1784,15 +1785,15 @@ int mlx5e_rq_set_handlers(struct mlx5e_rq *rq, struct mlx5e_params *params, bool
rq->post_wqes = mlx5e_post_rx_mpwqes;
rq->dealloc_wqe = mlx5e_dealloc_rx_mpwqe;
rq->handle_rx_cqe = c->priv->profile->rx_handlers->handle_rx_cqe_mpwqe;
rq->handle_rx_cqe = priv->profile->rx_handlers->handle_rx_cqe_mpwqe;
#ifdef CONFIG_MLX5_EN_IPSEC
if (MLX5_IPSEC_DEV(mdev)) {
netdev_err(c->netdev, "MPWQE RQ with IPSec offload not supported\n");
netdev_err(netdev, "MPWQE RQ with IPSec offload not supported\n");
return -EINVAL;
}
#endif
if (!rq->handle_rx_cqe) {
netdev_err(c->netdev, "RX handler of MPWQE RQ is not set\n");
netdev_err(netdev, "RX handler of MPWQE RQ is not set\n");
return -EINVAL;
}
break;
......@@ -1807,13 +1808,13 @@ int mlx5e_rq_set_handlers(struct mlx5e_rq *rq, struct mlx5e_params *params, bool
#ifdef CONFIG_MLX5_EN_IPSEC
if ((mlx5_fpga_ipsec_device_caps(mdev) & MLX5_ACCEL_IPSEC_CAP_DEVICE) &&
c->priv->ipsec)
priv->ipsec)
rq->handle_rx_cqe = mlx5e_ipsec_handle_rx_cqe;
else
#endif
rq->handle_rx_cqe = c->priv->profile->rx_handlers->handle_rx_cqe;
rq->handle_rx_cqe = priv->profile->rx_handlers->handle_rx_cqe;
if (!rq->handle_rx_cqe) {
netdev_err(c->netdev, "RX handler of RQ is not set\n");
netdev_err(netdev, "RX handler of RQ is not set\n");
return -EINVAL;
}
}
......
......@@ -51,6 +51,10 @@
#define MLX5E_DECLARE_XSKSQ_STAT(type, fld) "tx%d_xsk_"#fld, offsetof(type, fld)
#define MLX5E_DECLARE_CH_STAT(type, fld) "ch%d_"#fld, offsetof(type, fld)
#define MLX5E_DECLARE_PTP_TX_STAT(type, fld) "ptp_tx%d_"#fld, offsetof(type, fld)
#define MLX5E_DECLARE_PTP_CH_STAT(type, fld) "ptp_ch_"#fld, offsetof(type, fld)
#define MLX5E_DECLARE_PTP_CQ_STAT(type, fld) "ptp_cq%d_"#fld, offsetof(type, fld)
struct counter_desc {
char format[ETH_GSTRING_LEN];
size_t offset; /* Byte offset */
......@@ -398,6 +402,13 @@ struct mlx5e_ch_stats {
u64 eq_rearm;
};
struct mlx5e_ptp_cq_stats {
u64 cqe;
u64 err_cqe;
u64 abort;
u64 abort_abs_diff_ns;
};
struct mlx5e_stats {
struct mlx5e_sw_stats sw;
struct mlx5e_qcounter_stats qcnt;
......
......@@ -32,6 +32,7 @@
#include <linux/tcp.h>
#include <linux/if_vlan.h>
#include <linux/ptp_classify.h>
#include <net/geneve.h>
#include <net/dsfield.h>
#include "en.h"
......@@ -39,6 +40,7 @@
#include "ipoib/ipoib.h"
#include "en_accel/en_accel.h"
#include "lib/clock.h"
#include "en/ptp.h"
static void mlx5e_dma_unmap_wqe_err(struct mlx5e_txqsq *sq, u8 num_dma)
{
......@@ -66,14 +68,73 @@ static inline int mlx5e_get_dscp_up(struct mlx5e_priv *priv, struct sk_buff *skb
}
#endif
static bool mlx5e_use_ptpsq(struct sk_buff *skb)
{
struct flow_keys fk;
if (!skb_flow_dissect_flow_keys(skb, &fk, 0))
return false;
if (fk.basic.n_proto == htons(ETH_P_1588))
return true;
if (fk.basic.n_proto != htons(ETH_P_IP) &&
fk.basic.n_proto != htons(ETH_P_IPV6))
return false;
return (fk.basic.ip_proto == IPPROTO_UDP &&
fk.ports.dst == htons(PTP_EV_PORT));
}
static u16 mlx5e_select_ptpsq(struct net_device *dev, struct sk_buff *skb)
{
struct mlx5e_priv *priv = netdev_priv(dev);
int up = 0;
if (!netdev_get_num_tc(dev))
goto return_txq;
#ifdef CONFIG_MLX5_CORE_EN_DCB
if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_DSCP)
up = mlx5e_get_dscp_up(priv, skb);
else
#endif
if (skb_vlan_tag_present(skb))
up = skb_vlan_tag_get_prio(skb);
return_txq:
return priv->port_ptp_tc2realtxq[up];
}
u16 mlx5e_select_queue(struct net_device *dev, struct sk_buff *skb,
struct net_device *sb_dev)
{
int txq_ix = netdev_pick_tx(dev, skb, NULL);
struct mlx5e_priv *priv = netdev_priv(dev);
int txq_ix;
int up = 0;
int ch_ix;
if (unlikely(priv->channels.port_ptp)) {
int num_tc_x_num_ch;
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
mlx5e_use_ptpsq(skb))
return mlx5e_select_ptpsq(dev, skb);
/* Sync with mlx5e_update_num_tc_x_num_ch - avoid refetching. */
num_tc_x_num_ch = READ_ONCE(priv->num_tc_x_num_ch);
txq_ix = netdev_pick_tx(dev, skb, NULL);
/* Fix netdev_pick_tx() not to choose ptp_channel txqs.
* If they are selected, switch to regular queues.
* Driver to select these queues only at mlx5e_select_ptpsq().
*/
if (unlikely(txq_ix >= num_tc_x_num_ch))
txq_ix %= num_tc_x_num_ch;
} else {
txq_ix = netdev_pick_tx(dev, skb, NULL);
}
if (!netdev_get_num_tc(dev))
return txq_ix;
......@@ -402,6 +463,12 @@ mlx5e_txwqe_complete(struct mlx5e_txqsq *sq, struct sk_buff *skb,
mlx5e_tx_check_stop(sq);
if (unlikely(sq->ptpsq)) {
mlx5e_skb_cb_hwtstamp_init(skb);
mlx5e_skb_fifo_push(&sq->ptpsq->skb_fifo, skb);
skb_get(skb);
}
send_doorbell = __netdev_tx_sent_queue(sq->txq, attr->num_bytes, xmit_more);
if (send_doorbell)
mlx5e_notify_hw(wq, sq->pc, sq->uar_map, cseg);
......@@ -579,7 +646,7 @@ mlx5e_sq_xmit_mpwqe(struct mlx5e_txqsq *sq, struct sk_buff *skb,
goto err_unmap;
mlx5e_dma_push(sq, txd.dma_addr, txd.len, MLX5E_DMA_MAP_SINGLE);
mlx5e_skb_fifo_push(sq, skb);
mlx5e_skb_fifo_push(&sq->db.skb_fifo, skb);
mlx5e_tx_mpwqe_add_dseg(sq, &txd);
......@@ -707,7 +774,11 @@ static void mlx5e_consume_skb(struct mlx5e_txqsq *sq, struct sk_buff *skb,
u64 ts = get_cqe_ts(cqe);
hwts.hwtstamp = mlx5_timecounter_cyc2time(sq->clock, ts);
skb_tstamp_tx(skb, &hwts);
if (sq->ptpsq)
mlx5e_skb_cb_hwtstamp_handler(skb, MLX5E_SKB_CB_CQE_HWTSTAMP,
hwts.hwtstamp, sq->ptpsq->cq_stats);
else
skb_tstamp_tx(skb, &hwts);
}
napi_consume_skb(skb, napi_budget);
......@@ -719,7 +790,7 @@ static void mlx5e_tx_wi_consume_fifo_skbs(struct mlx5e_txqsq *sq, struct mlx5e_t
int i;
for (i = 0; i < wi->num_fifo_pkts; i++) {
struct sk_buff *skb = mlx5e_skb_fifo_pop(sq);
struct sk_buff *skb = mlx5e_skb_fifo_pop(&sq->db.skb_fifo);
mlx5e_consume_skb(sq, skb, cqe, napi_budget);
}
......@@ -805,8 +876,7 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget)
mlx5e_dump_error_cqe(&sq->cq, sq->sqn,
(struct mlx5_err_cqe *)cqe);
mlx5_wq_cyc_wqe_dump(&sq->wq, ci, wi->num_wqebbs);
queue_work(cq->channel->priv->wq,
&sq->recover_work);
queue_work(cq->priv->wq, &sq->recover_work);
}
stats->cqe_err++;
}
......@@ -840,7 +910,7 @@ static void mlx5e_tx_wi_kfree_fifo_skbs(struct mlx5e_txqsq *sq, struct mlx5e_tx_
int i;
for (i = 0; i < wi->num_fifo_pkts; i++)
dev_kfree_skb_any(mlx5e_skb_fifo_pop(sq));
dev_kfree_skb_any(mlx5e_skb_fifo_pop(&sq->db.skb_fifo));
}
void mlx5e_free_txqsq_descs(struct mlx5e_txqsq *sq)
......
......@@ -221,14 +221,13 @@ void mlx5e_completion_event(struct mlx5_core_cq *mcq, struct mlx5_eqe *eqe)
napi_schedule(cq->napi);
cq->event_ctr++;
cq->channel->stats->events++;
cq->ch_stats->events++;
}
void mlx5e_cq_error_event(struct mlx5_core_cq *mcq, enum mlx5_event event)
{
struct mlx5e_cq *cq = container_of(mcq, struct mlx5e_cq, mcq);
struct mlx5e_channel *c = cq->channel;
struct net_device *netdev = c->netdev;
struct net_device *netdev = cq->netdev;
netdev_err(netdev, "%s: cqn=0x%.6x event=0x%.2x\n",
__func__, mcq->cqn, event);
......
......@@ -136,7 +136,7 @@ static int mlx5_eq_comp_int(struct notifier_block *nb,
eqe = next_eqe_sw(eq);
if (!eqe)
goto out;
return 0;
do {
struct mlx5_core_cq *cq;
......@@ -161,8 +161,6 @@ static int mlx5_eq_comp_int(struct notifier_block *nb,
++eq->cons_index;
} while ((++num_eqes < MLX5_EQ_POLLING_BUDGET) && (eqe = next_eqe_sw(eq)));
out:
eq_update_ci(eq, 1);
if (cqn != -1)
......@@ -250,9 +248,9 @@ static int mlx5_eq_async_int(struct notifier_block *nb,
++eq->cons_index;
} while ((++num_eqes < MLX5_EQ_POLLING_BUDGET) && (eqe = next_eqe_sw(eq)));
eq_update_ci(eq, 1);
out:
eq_update_ci(eq, 1);
mlx5_eq_async_int_unlock(eq_async, recovery, &flags);
return unlikely(recovery) ? num_eqes : 0;
......
......@@ -101,7 +101,7 @@ int esw_acl_egress_lgcy_setup(struct mlx5_eswitch *esw,
vport->egress.acl = esw_acl_table_create(esw, vport->vport,
MLX5_FLOW_NAMESPACE_ESW_EGRESS,
table_size);
if (IS_ERR_OR_NULL(vport->egress.acl)) {
if (IS_ERR(vport->egress.acl)) {
err = PTR_ERR(vport->egress.acl);
vport->egress.acl = NULL;
goto out;
......
......@@ -173,7 +173,7 @@ int esw_acl_egress_ofld_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport
table_size++;
vport->egress.acl = esw_acl_table_create(esw, vport->vport,
MLX5_FLOW_NAMESPACE_ESW_EGRESS, table_size);
if (IS_ERR_OR_NULL(vport->egress.acl)) {
if (IS_ERR(vport->egress.acl)) {
err = PTR_ERR(vport->egress.acl);
vport->egress.acl = NULL;
return err;
......
......@@ -180,7 +180,7 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw,
vport->ingress.acl = esw_acl_table_create(esw, vport->vport,
MLX5_FLOW_NAMESPACE_ESW_INGRESS,
table_size);
if (IS_ERR_OR_NULL(vport->ingress.acl)) {
if (IS_ERR(vport->ingress.acl)) {
err = PTR_ERR(vport->ingress.acl);
vport->ingress.acl = NULL;
return err;
......
......@@ -258,7 +258,7 @@ int esw_acl_ingress_ofld_setup(struct mlx5_eswitch *esw,
vport->ingress.acl = esw_acl_table_create(esw, vport->vport,
MLX5_FLOW_NAMESPACE_ESW_INGRESS,
num_ftes);
if (IS_ERR_OR_NULL(vport->ingress.acl)) {
if (IS_ERR(vport->ingress.acl)) {
err = PTR_ERR(vport->ingress.acl);
vport->ingress.acl = NULL;
return err;
......
......@@ -1680,7 +1680,6 @@ static int esw_create_restore_table(struct mlx5_eswitch *esw)
goto out_free;
}
memset(flow_group_in, 0, inlen);
match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in,
match_criteria);
misc = MLX5_ADDR_OF(fte_match_param, match_criteria,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment