diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 96dc6a6dc737..71e663c3b421 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -4716,7 +4716,6 @@ int mlx5e_change_mtu(struct net_device *netdev, int new_mtu, struct mlx5e_priv *priv = netdev_priv(netdev); struct mlx5e_params new_params; struct mlx5e_params *params; - bool reset = true; int err = 0; mutex_lock(&priv->state_lock); @@ -4742,28 +4741,8 @@ int mlx5e_change_mtu(struct net_device *netdev, int new_mtu, goto out; } - if (params->packet_merge.type == MLX5E_PACKET_MERGE_LRO) - reset = false; - - if (params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ && - params->packet_merge.type != MLX5E_PACKET_MERGE_SHAMPO) { - bool is_linear_old = mlx5e_rx_mpwqe_is_linear_skb(priv->mdev, params, NULL); - bool is_linear_new = mlx5e_rx_mpwqe_is_linear_skb(priv->mdev, - &new_params, NULL); - u8 sz_old = mlx5e_mpwqe_get_log_rq_size(priv->mdev, params, NULL); - u8 sz_new = mlx5e_mpwqe_get_log_rq_size(priv->mdev, &new_params, NULL); - - /* Always reset in linear mode - hw_mtu is used in data path. - * Check that the mode was non-linear and didn't change. - * If XSK is active, XSK RQs are linear. - * Reset if the RQ size changed, even if it's non-linear. - */ - if (!is_linear_old && !is_linear_new && !priv->xsk.refcnt && - sz_old == sz_new) - reset = false; - } - - err = mlx5e_safe_switch_params(priv, &new_params, preactivate, NULL, reset); + err = mlx5e_safe_switch_params(priv, &new_params, preactivate, NULL, + true); out: WRITE_ONCE(netdev->mtu, params->sw_mtu); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 1fc3720d2201..849e1f16482a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -1087,11 +1087,24 @@ int mlx5e_poll_ico_cq(struct mlx5e_cq *cq) return i; } +static void mlx5e_reclaim_mpwqe_pages(struct mlx5e_rq *rq, int head, + int reclaim) +{ + struct mlx5_wq_ll *wq = &rq->mpwqe.wq; + + for (int i = 0; i < reclaim; i++) { + head = mlx5_wq_ll_get_wqe_next_ix(wq, head); + + mlx5e_dealloc_rx_mpwqe(rq, head); + } +} + INDIRECT_CALLABLE_SCOPE bool mlx5e_post_rx_mpwqes(struct mlx5e_rq *rq) { struct mlx5_wq_ll *wq = &rq->mpwqe.wq; u8 umr_completed = rq->mpwqe.umr_completed; struct mlx5e_icosq *sq = rq->icosq; + bool reclaimed = false; int alloc_err = 0; u8 missing, i; u16 head; @@ -1126,11 +1139,20 @@ INDIRECT_CALLABLE_SCOPE bool mlx5e_post_rx_mpwqes(struct mlx5e_rq *rq) /* Deferred free for better page pool cache usage. */ mlx5e_free_rx_mpwqe(rq, wi); +retry: alloc_err = rq->xsk_pool ? mlx5e_xsk_alloc_rx_mpwqe(rq, head) : mlx5e_alloc_rx_mpwqe(rq, head); + if (unlikely(alloc_err)) { + int reclaim = i - 1; - if (unlikely(alloc_err)) - break; + if (reclaimed || !reclaim) + break; + + mlx5e_reclaim_mpwqe_pages(rq, head, reclaim); + reclaimed = true; + + goto retry; + } head = mlx5_wq_ll_get_wqe_next_ix(wq, head); } while (--i); @@ -1574,7 +1596,7 @@ static inline bool mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe, struct mlx5e_rq *rq, struct sk_buff *skb) { - u8 lro_num_seg = be32_to_cpu(cqe->srqn) >> 24; + u8 lro_num_seg = get_cqe_lro_num_seg(cqe); struct mlx5e_rq_stats *stats = rq->stats; struct net_device *netdev = rq->netdev; @@ -2058,6 +2080,15 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w u16 linear_hr; void *va; + if (unlikely(cqe_bcnt > rq->hw_mtu)) { + u8 lro_num_seg = get_cqe_lro_num_seg(cqe); + + if (lro_num_seg <= 1) { + rq->stats->oversize_pkts_sw_drop++; + return NULL; + } + } + prog = rcu_dereference(rq->xdp_prog); if (prog) { diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index d7f46a8fbfa1..b37fe39cef27 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h @@ -962,6 +962,11 @@ static inline u16 get_cqe_flow_tag(struct mlx5_cqe64 *cqe) return be32_to_cpu(cqe->sop_drop_qpn) & 0xFFF; } +static inline u8 get_cqe_lro_num_seg(struct mlx5_cqe64 *cqe) +{ + return be32_to_cpu(cqe->srqn) >> 24; +} + #define MLX5_MPWQE_LOG_NUM_STRIDES_EXT_BASE 3 #define MLX5_MPWQE_LOG_NUM_STRIDES_BASE 9 #define MLX5_MPWQE_LOG_NUM_STRIDES_MAX 16