diff options
author | Saeed Mahameed <saeedm@mellanox.com> | 2016-08-28 18:13:42 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-08-28 23:24:15 -0400 |
commit | fe4c988bdd1cc60402a4e3ca3976a686ea991b5a (patch) | |
tree | d003855813fc889c189d2e44f13db431afbec16b | |
parent | 9dbeea7f08f3784b152d9fb3b86beb34aad77c72 (diff) |
net/mlx5e: Limit UMR length to the device's limitation
ConnectX-4 UMR (User Memory Region) MTT translation table offset in WQE
is limited to U16_MAX, before this patch we ignored that limitation and
requested the maximum possible UMR translation length that the netdev
might need (MAX channels * MAX pages per channel).
In case of a system with #cores > 32 and when linear WQE allocation fails,
falling back to using UMR WQEs will cause the RQ (Receive Queue) to get
stuck.
Here we limit UMR length to min(U16_MAX, max required pages) (while
considering the required alignments) on driver load, by default U16_MAX is
sufficient since the default RX rings value guarantees that we are in
range, dynamically (on set_ringparam/set_channels) we will check if the
new required UMR length (num mtts) is still in range, if not, fail the
request.
Fixes: bc77b240b3c5 ('net/mlx5e: Add fragmented memory support for RX multi packet WQE')
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en.h | 14 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 19 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 11 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 12 |
4 files changed, 40 insertions, 16 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 1b495efa7490..d63a1b8f9c13 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h | |||
@@ -73,8 +73,12 @@ | |||
73 | #define MLX5_MPWRQ_PAGES_PER_WQE BIT(MLX5_MPWRQ_WQE_PAGE_ORDER) | 73 | #define MLX5_MPWRQ_PAGES_PER_WQE BIT(MLX5_MPWRQ_WQE_PAGE_ORDER) |
74 | #define MLX5_MPWRQ_STRIDES_PER_PAGE (MLX5_MPWRQ_NUM_STRIDES >> \ | 74 | #define MLX5_MPWRQ_STRIDES_PER_PAGE (MLX5_MPWRQ_NUM_STRIDES >> \ |
75 | MLX5_MPWRQ_WQE_PAGE_ORDER) | 75 | MLX5_MPWRQ_WQE_PAGE_ORDER) |
76 | #define MLX5_CHANNEL_MAX_NUM_MTTS (ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8) * \ | 76 | |
77 | BIT(MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE_MPW)) | 77 | #define MLX5_MTT_OCTW(npages) (ALIGN(npages, 8) / 2) |
78 | #define MLX5E_REQUIRED_MTTS(rqs, wqes)\ | ||
79 | (rqs * wqes * ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8)) | ||
80 | #define MLX5E_VALID_NUM_MTTS(num_mtts) (MLX5_MTT_OCTW(num_mtts) <= U16_MAX) | ||
81 | |||
78 | #define MLX5_UMR_ALIGN (2048) | 82 | #define MLX5_UMR_ALIGN (2048) |
79 | #define MLX5_MPWRQ_SMALL_PACKET_THRESHOLD (128) | 83 | #define MLX5_MPWRQ_SMALL_PACKET_THRESHOLD (128) |
80 | 84 | ||
@@ -304,6 +308,7 @@ struct mlx5e_rq { | |||
304 | 308 | ||
305 | unsigned long state; | 309 | unsigned long state; |
306 | int ix; | 310 | int ix; |
311 | u32 mpwqe_mtt_offset; | ||
307 | 312 | ||
308 | struct mlx5e_rx_am am; /* Adaptive Moderation */ | 313 | struct mlx5e_rx_am am; /* Adaptive Moderation */ |
309 | 314 | ||
@@ -814,11 +819,6 @@ static inline int mlx5e_get_max_num_channels(struct mlx5_core_dev *mdev) | |||
814 | MLX5E_MAX_NUM_CHANNELS); | 819 | MLX5E_MAX_NUM_CHANNELS); |
815 | } | 820 | } |
816 | 821 | ||
817 | static inline int mlx5e_get_mtt_octw(int npages) | ||
818 | { | ||
819 | return ALIGN(npages, 8) / 2; | ||
820 | } | ||
821 | |||
822 | extern const struct ethtool_ops mlx5e_ethtool_ops; | 822 | extern const struct ethtool_ops mlx5e_ethtool_ops; |
823 | #ifdef CONFIG_MLX5_CORE_EN_DCB | 823 | #ifdef CONFIG_MLX5_CORE_EN_DCB |
824 | extern const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops; | 824 | extern const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops; |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 4a3757e60441..9cfe4088d008 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | |||
@@ -373,6 +373,7 @@ static int mlx5e_set_ringparam(struct net_device *dev, | |||
373 | u16 min_rx_wqes; | 373 | u16 min_rx_wqes; |
374 | u8 log_rq_size; | 374 | u8 log_rq_size; |
375 | u8 log_sq_size; | 375 | u8 log_sq_size; |
376 | u32 num_mtts; | ||
376 | int err = 0; | 377 | int err = 0; |
377 | 378 | ||
378 | if (param->rx_jumbo_pending) { | 379 | if (param->rx_jumbo_pending) { |
@@ -397,6 +398,15 @@ static int mlx5e_set_ringparam(struct net_device *dev, | |||
397 | 1 << mlx5_max_log_rq_size(rq_wq_type)); | 398 | 1 << mlx5_max_log_rq_size(rq_wq_type)); |
398 | return -EINVAL; | 399 | return -EINVAL; |
399 | } | 400 | } |
401 | |||
402 | num_mtts = MLX5E_REQUIRED_MTTS(priv->params.num_channels, param->rx_pending); | ||
403 | if (priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ && | ||
404 | !MLX5E_VALID_NUM_MTTS(num_mtts)) { | ||
405 | netdev_info(dev, "%s: rx_pending (%d) request can't be satisfied, try to reduce.\n", | ||
406 | __func__, param->rx_pending); | ||
407 | return -EINVAL; | ||
408 | } | ||
409 | |||
400 | if (param->tx_pending < (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) { | 410 | if (param->tx_pending < (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) { |
401 | netdev_info(dev, "%s: tx_pending (%d) < min (%d)\n", | 411 | netdev_info(dev, "%s: tx_pending (%d) < min (%d)\n", |
402 | __func__, param->tx_pending, | 412 | __func__, param->tx_pending, |
@@ -454,6 +464,7 @@ static int mlx5e_set_channels(struct net_device *dev, | |||
454 | unsigned int count = ch->combined_count; | 464 | unsigned int count = ch->combined_count; |
455 | bool arfs_enabled; | 465 | bool arfs_enabled; |
456 | bool was_opened; | 466 | bool was_opened; |
467 | u32 num_mtts; | ||
457 | int err = 0; | 468 | int err = 0; |
458 | 469 | ||
459 | if (!count) { | 470 | if (!count) { |
@@ -472,6 +483,14 @@ static int mlx5e_set_channels(struct net_device *dev, | |||
472 | return -EINVAL; | 483 | return -EINVAL; |
473 | } | 484 | } |
474 | 485 | ||
486 | num_mtts = MLX5E_REQUIRED_MTTS(count, BIT(priv->params.log_rq_size)); | ||
487 | if (priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ && | ||
488 | !MLX5E_VALID_NUM_MTTS(num_mtts)) { | ||
489 | netdev_info(dev, "%s: rx count (%d) request can't be satisfied, try to reduce.\n", | ||
490 | __func__, count); | ||
491 | return -EINVAL; | ||
492 | } | ||
493 | |||
475 | if (priv->params.num_channels == count) | 494 | if (priv->params.num_channels == count) |
476 | return 0; | 495 | return 0; |
477 | 496 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 03d944c0077e..65360b1f6ee3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c | |||
@@ -340,6 +340,9 @@ static int mlx5e_create_rq(struct mlx5e_channel *c, | |||
340 | rq->alloc_wqe = mlx5e_alloc_rx_mpwqe; | 340 | rq->alloc_wqe = mlx5e_alloc_rx_mpwqe; |
341 | rq->dealloc_wqe = mlx5e_dealloc_rx_mpwqe; | 341 | rq->dealloc_wqe = mlx5e_dealloc_rx_mpwqe; |
342 | 342 | ||
343 | rq->mpwqe_mtt_offset = c->ix * | ||
344 | MLX5E_REQUIRED_MTTS(1, BIT(priv->params.log_rq_size)); | ||
345 | |||
343 | rq->mpwqe_stride_sz = BIT(priv->params.mpwqe_log_stride_sz); | 346 | rq->mpwqe_stride_sz = BIT(priv->params.mpwqe_log_stride_sz); |
344 | rq->mpwqe_num_strides = BIT(priv->params.mpwqe_log_num_strides); | 347 | rq->mpwqe_num_strides = BIT(priv->params.mpwqe_log_num_strides); |
345 | rq->wqe_sz = rq->mpwqe_stride_sz * rq->mpwqe_num_strides; | 348 | rq->wqe_sz = rq->mpwqe_stride_sz * rq->mpwqe_num_strides; |
@@ -3233,8 +3236,8 @@ static int mlx5e_create_umr_mkey(struct mlx5e_priv *priv) | |||
3233 | struct mlx5_create_mkey_mbox_in *in; | 3236 | struct mlx5_create_mkey_mbox_in *in; |
3234 | struct mlx5_mkey_seg *mkc; | 3237 | struct mlx5_mkey_seg *mkc; |
3235 | int inlen = sizeof(*in); | 3238 | int inlen = sizeof(*in); |
3236 | u64 npages = | 3239 | u64 npages = MLX5E_REQUIRED_MTTS(priv->profile->max_nch(mdev), |
3237 | priv->profile->max_nch(mdev) * MLX5_CHANNEL_MAX_NUM_MTTS; | 3240 | BIT(MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE_MPW)); |
3238 | int err; | 3241 | int err; |
3239 | 3242 | ||
3240 | in = mlx5_vzalloc(inlen); | 3243 | in = mlx5_vzalloc(inlen); |
@@ -3248,10 +3251,12 @@ static int mlx5e_create_umr_mkey(struct mlx5e_priv *priv) | |||
3248 | MLX5_PERM_LOCAL_WRITE | | 3251 | MLX5_PERM_LOCAL_WRITE | |
3249 | MLX5_ACCESS_MODE_MTT; | 3252 | MLX5_ACCESS_MODE_MTT; |
3250 | 3253 | ||
3254 | npages = min_t(u32, ALIGN(U16_MAX, 4) * 2, npages); | ||
3255 | |||
3251 | mkc->qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); | 3256 | mkc->qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); |
3252 | mkc->flags_pd = cpu_to_be32(mdev->mlx5e_res.pdn); | 3257 | mkc->flags_pd = cpu_to_be32(mdev->mlx5e_res.pdn); |
3253 | mkc->len = cpu_to_be64(npages << PAGE_SHIFT); | 3258 | mkc->len = cpu_to_be64(npages << PAGE_SHIFT); |
3254 | mkc->xlt_oct_size = cpu_to_be32(mlx5e_get_mtt_octw(npages)); | 3259 | mkc->xlt_oct_size = cpu_to_be32(MLX5_MTT_OCTW(npages)); |
3255 | mkc->log2_page_size = PAGE_SHIFT; | 3260 | mkc->log2_page_size = PAGE_SHIFT; |
3256 | 3261 | ||
3257 | err = mlx5_core_create_mkey(mdev, &priv->umr_mkey, in, inlen, NULL, | 3262 | err = mlx5_core_create_mkey(mdev, &priv->umr_mkey, in, inlen, NULL, |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 9f2a16a507e0..bdc9e33a06e4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | |||
@@ -324,9 +324,9 @@ mlx5e_copy_skb_header_fragmented_mpwqe(struct device *pdev, | |||
324 | } | 324 | } |
325 | } | 325 | } |
326 | 326 | ||
327 | static u16 mlx5e_get_wqe_mtt_offset(u16 rq_ix, u16 wqe_ix) | 327 | static u32 mlx5e_get_wqe_mtt_offset(struct mlx5e_rq *rq, u16 wqe_ix) |
328 | { | 328 | { |
329 | return rq_ix * MLX5_CHANNEL_MAX_NUM_MTTS + | 329 | return rq->mpwqe_mtt_offset + |
330 | wqe_ix * ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8); | 330 | wqe_ix * ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8); |
331 | } | 331 | } |
332 | 332 | ||
@@ -340,7 +340,7 @@ static void mlx5e_build_umr_wqe(struct mlx5e_rq *rq, | |||
340 | struct mlx5_wqe_data_seg *dseg = &wqe->data; | 340 | struct mlx5_wqe_data_seg *dseg = &wqe->data; |
341 | struct mlx5e_mpw_info *wi = &rq->wqe_info[ix]; | 341 | struct mlx5e_mpw_info *wi = &rq->wqe_info[ix]; |
342 | u8 ds_cnt = DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS); | 342 | u8 ds_cnt = DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS); |
343 | u16 umr_wqe_mtt_offset = mlx5e_get_wqe_mtt_offset(rq->ix, ix); | 343 | u32 umr_wqe_mtt_offset = mlx5e_get_wqe_mtt_offset(rq, ix); |
344 | 344 | ||
345 | memset(wqe, 0, sizeof(*wqe)); | 345 | memset(wqe, 0, sizeof(*wqe)); |
346 | cseg->opmod_idx_opcode = | 346 | cseg->opmod_idx_opcode = |
@@ -353,9 +353,9 @@ static void mlx5e_build_umr_wqe(struct mlx5e_rq *rq, | |||
353 | 353 | ||
354 | ucseg->flags = MLX5_UMR_TRANSLATION_OFFSET_EN; | 354 | ucseg->flags = MLX5_UMR_TRANSLATION_OFFSET_EN; |
355 | ucseg->klm_octowords = | 355 | ucseg->klm_octowords = |
356 | cpu_to_be16(mlx5e_get_mtt_octw(MLX5_MPWRQ_PAGES_PER_WQE)); | 356 | cpu_to_be16(MLX5_MTT_OCTW(MLX5_MPWRQ_PAGES_PER_WQE)); |
357 | ucseg->bsf_octowords = | 357 | ucseg->bsf_octowords = |
358 | cpu_to_be16(mlx5e_get_mtt_octw(umr_wqe_mtt_offset)); | 358 | cpu_to_be16(MLX5_MTT_OCTW(umr_wqe_mtt_offset)); |
359 | ucseg->mkey_mask = cpu_to_be64(MLX5_MKEY_MASK_FREE); | 359 | ucseg->mkey_mask = cpu_to_be64(MLX5_MKEY_MASK_FREE); |
360 | 360 | ||
361 | dseg->lkey = sq->mkey_be; | 361 | dseg->lkey = sq->mkey_be; |
@@ -423,7 +423,7 @@ static int mlx5e_alloc_rx_fragmented_mpwqe(struct mlx5e_rq *rq, | |||
423 | { | 423 | { |
424 | struct mlx5e_mpw_info *wi = &rq->wqe_info[ix]; | 424 | struct mlx5e_mpw_info *wi = &rq->wqe_info[ix]; |
425 | int mtt_sz = mlx5e_get_wqe_mtt_sz(); | 425 | int mtt_sz = mlx5e_get_wqe_mtt_sz(); |
426 | u32 dma_offset = mlx5e_get_wqe_mtt_offset(rq->ix, ix) << PAGE_SHIFT; | 426 | u64 dma_offset = (u64)mlx5e_get_wqe_mtt_offset(rq, ix) << PAGE_SHIFT; |
427 | int i; | 427 | int i; |
428 | 428 | ||
429 | wi->umr.dma_info = kmalloc(sizeof(*wi->umr.dma_info) * | 429 | wi->umr.dma_info = kmalloc(sizeof(*wi->umr.dma_info) * |