mirror of
https://github.com/torvalds/linux.git
synced 2025-11-07 03:59:22 +02:00
Add support for DMABUF MR registrations with Data-direct device. Upon userspace calling to register a DMABUF MR with the data direct bit set, the below algorithm will be followed. 1) Obtain a pinned DMABUF umem from the IB core using the user input parameters (FD, offset, length) and the DMA PF device. The DMA PF device is needed to allow the IOMMU to enable the DMA PF to access the user buffer over PCI. 2) Create a KSM MKEY by setting its entries according to the user buffer VA to IOVA mapping, with the MKEY being the data direct device-crossed MKEY. This KSM MKEY is umrable and will be used as part of the MR cache. The PD for creating it is the internal device 'data direct' kernel one. 3) Create a crossing MKEY that points to the KSM MKEY using the crossing access mode. 4) Manage the KSM MKEY by adding it to a list of 'data direct' MKEYs managed on the mlx5_ib device. 5) Return the crossing MKEY to the user, created with its supplied PD. Upon DMA PF unbind flow, the driver will revoke the KSM entries. The final deregistration will occur under the hood once the application deregisters its MKEY. Notes: - This version supports only the PINNED UMEM mode, so there is no dependency on ODP. - The IOVA supplied by the application must be system page aligned due to HW translations of KSM. - The crossing MKEY will not be umrable or part of the MR cache, as we cannot change its crossed (i.e. KSM) MKEY over UMR. Signed-off-by: Yishai Hadas <yishaih@nvidia.com> Link: https://patch.msgid.link/1f99d8020ed540d9702b9e2252a145a439609ba6.1722512548.git.leon@kernel.org Signed-off-by: Leon Romanovsky <leon@kernel.org>
102 lines
3.1 KiB
C
102 lines
3.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
|
/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */
|
|
|
|
#ifndef _MLX5_IB_UMR_H
|
|
#define _MLX5_IB_UMR_H
|
|
|
|
#include "mlx5_ib.h"
|
|
|
|
|
|
#define MLX5_MAX_UMR_SHIFT 16
|
|
#define MLX5_MAX_UMR_PAGES (1 << MLX5_MAX_UMR_SHIFT)
|
|
|
|
#define MLX5_IB_UMR_OCTOWORD 16
|
|
#define MLX5_IB_UMR_XLT_ALIGNMENT 64
|
|
|
|
int mlx5r_umr_resource_init(struct mlx5_ib_dev *dev);
|
|
void mlx5r_umr_resource_cleanup(struct mlx5_ib_dev *dev);
|
|
|
|
int mlx5r_umr_init(struct mlx5_ib_dev *dev);
|
|
void mlx5r_umr_cleanup(struct mlx5_ib_dev *dev);
|
|
|
|
static inline bool mlx5r_umr_can_load_pas(struct mlx5_ib_dev *dev,
|
|
size_t length)
|
|
{
|
|
/*
|
|
* umr_check_mkey_mask() rejects MLX5_MKEY_MASK_PAGE_SIZE which is
|
|
* always set if MLX5_IB_SEND_UMR_UPDATE_TRANSLATION (aka
|
|
* MLX5_IB_UPD_XLT_ADDR and MLX5_IB_UPD_XLT_ENABLE) is set. Thus, a mkey
|
|
* can never be enabled without this capability. Simplify this weird
|
|
* quirky hardware by just saying it can't use PAS lists with UMR at
|
|
* all.
|
|
*/
|
|
if (MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled))
|
|
return false;
|
|
|
|
/*
|
|
* length is the size of the MR in bytes when mlx5_ib_update_xlt() is
|
|
* used.
|
|
*/
|
|
if (!MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset) &&
|
|
length >= MLX5_MAX_UMR_PAGES * PAGE_SIZE)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* true if an existing MR can be reconfigured to new access_flags using UMR.
|
|
* Older HW cannot use UMR to update certain elements of the MKC. See
|
|
* get_umr_update_access_mask() and umr_check_mkey_mask()
|
|
*/
|
|
static inline bool mlx5r_umr_can_reconfig(struct mlx5_ib_dev *dev,
|
|
unsigned int current_access_flags,
|
|
unsigned int target_access_flags)
|
|
{
|
|
unsigned int diffs = current_access_flags ^ target_access_flags;
|
|
|
|
if ((diffs & IB_ACCESS_REMOTE_ATOMIC) &&
|
|
MLX5_CAP_GEN(dev->mdev, atomic) &&
|
|
MLX5_CAP_GEN(dev->mdev, umr_modify_atomic_disabled))
|
|
return false;
|
|
|
|
if ((diffs & IB_ACCESS_RELAXED_ORDERING) &&
|
|
MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write) &&
|
|
!MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr))
|
|
return false;
|
|
|
|
if ((diffs & IB_ACCESS_RELAXED_ORDERING) &&
|
|
(MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read) ||
|
|
MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_pci_enabled)) &&
|
|
!MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline u64 mlx5r_umr_get_xlt_octo(u64 bytes)
|
|
{
|
|
return ALIGN(bytes, MLX5_IB_UMR_XLT_ALIGNMENT) /
|
|
MLX5_IB_UMR_OCTOWORD;
|
|
}
|
|
|
|
struct mlx5r_umr_context {
|
|
struct ib_cqe cqe;
|
|
enum ib_wc_status status;
|
|
struct completion done;
|
|
};
|
|
|
|
struct mlx5r_umr_wqe {
|
|
struct mlx5_wqe_umr_ctrl_seg ctrl_seg;
|
|
struct mlx5_mkey_seg mkey_seg;
|
|
struct mlx5_wqe_data_seg data_seg;
|
|
};
|
|
|
|
int mlx5r_umr_revoke_mr(struct mlx5_ib_mr *mr);
|
|
int mlx5r_umr_rereg_pd_access(struct mlx5_ib_mr *mr, struct ib_pd *pd,
|
|
int access_flags);
|
|
int mlx5r_umr_update_mr_pas(struct mlx5_ib_mr *mr, unsigned int flags);
|
|
int mlx5r_umr_update_data_direct_ksm_pas(struct mlx5_ib_mr *mr, unsigned int flags);
|
|
int mlx5r_umr_update_xlt(struct mlx5_ib_mr *mr, u64 idx, int npages,
|
|
int page_shift, int flags);
|
|
|
|
#endif /* _MLX5_IB_UMR_H */
|