diff options
| -rw-r--r-- | drivers/infiniband/hw/mlx4/main.c | 2 | ||||
| -rw-r--r-- | drivers/infiniband/hw/mlx4/mlx4_ib.h | 4 | ||||
| -rw-r--r-- | drivers/infiniband/hw/mlx4/mr.c | 88 |
3 files changed, 93 insertions, 1 deletions
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 0f7027e7db13..828a37b24816 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c | |||
| @@ -2007,6 +2007,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) | |||
| 2007 | (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | | 2007 | (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | |
| 2008 | (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | | 2008 | (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | |
| 2009 | (1ull << IB_USER_VERBS_CMD_REG_MR) | | 2009 | (1ull << IB_USER_VERBS_CMD_REG_MR) | |
| 2010 | (1ull << IB_USER_VERBS_CMD_REREG_MR) | | ||
| 2010 | (1ull << IB_USER_VERBS_CMD_DEREG_MR) | | 2011 | (1ull << IB_USER_VERBS_CMD_DEREG_MR) | |
| 2011 | (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | | 2012 | (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | |
| 2012 | (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | | 2013 | (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | |
| @@ -2059,6 +2060,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) | |||
| 2059 | ibdev->ib_dev.req_notify_cq = mlx4_ib_arm_cq; | 2060 | ibdev->ib_dev.req_notify_cq = mlx4_ib_arm_cq; |
| 2060 | ibdev->ib_dev.get_dma_mr = mlx4_ib_get_dma_mr; | 2061 | ibdev->ib_dev.get_dma_mr = mlx4_ib_get_dma_mr; |
| 2061 | ibdev->ib_dev.reg_user_mr = mlx4_ib_reg_user_mr; | 2062 | ibdev->ib_dev.reg_user_mr = mlx4_ib_reg_user_mr; |
| 2063 | ibdev->ib_dev.rereg_user_mr = mlx4_ib_rereg_user_mr; | ||
| 2062 | ibdev->ib_dev.dereg_mr = mlx4_ib_dereg_mr; | 2064 | ibdev->ib_dev.dereg_mr = mlx4_ib_dereg_mr; |
| 2063 | ibdev->ib_dev.alloc_fast_reg_mr = mlx4_ib_alloc_fast_reg_mr; | 2065 | ibdev->ib_dev.alloc_fast_reg_mr = mlx4_ib_alloc_fast_reg_mr; |
| 2064 | ibdev->ib_dev.alloc_fast_reg_page_list = mlx4_ib_alloc_fast_reg_page_list; | 2066 | ibdev->ib_dev.alloc_fast_reg_page_list = mlx4_ib_alloc_fast_reg_page_list; |
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index 369da3ca5d64..e8cad3926bfc 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h | |||
| @@ -788,5 +788,9 @@ int mlx4_ib_steer_qp_alloc(struct mlx4_ib_dev *dev, int count, int *qpn); | |||
| 788 | void mlx4_ib_steer_qp_free(struct mlx4_ib_dev *dev, u32 qpn, int count); | 788 | void mlx4_ib_steer_qp_free(struct mlx4_ib_dev *dev, u32 qpn, int count); |
| 789 | int mlx4_ib_steer_qp_reg(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp, | 789 | int mlx4_ib_steer_qp_reg(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp, |
| 790 | int is_attach); | 790 | int is_attach); |
| 791 | int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, | ||
| 792 | u64 start, u64 length, u64 virt_addr, | ||
| 793 | int mr_access_flags, struct ib_pd *pd, | ||
| 794 | struct ib_udata *udata); | ||
| 791 | 795 | ||
| 792 | #endif /* MLX4_IB_H */ | 796 | #endif /* MLX4_IB_H */ |
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c index cb2a8727f3fb..9b0e80e59b08 100644 --- a/drivers/infiniband/hw/mlx4/mr.c +++ b/drivers/infiniband/hw/mlx4/mr.c | |||
| @@ -144,8 +144,10 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, | |||
| 144 | if (!mr) | 144 | if (!mr) |
| 145 | return ERR_PTR(-ENOMEM); | 145 | return ERR_PTR(-ENOMEM); |
| 146 | 146 | ||
| 147 | /* Force registering the memory as writable. */ | ||
| 148 | /* Used for memory re-registeration. HCA protects the access */ | ||
| 147 | mr->umem = ib_umem_get(pd->uobject->context, start, length, | 149 | mr->umem = ib_umem_get(pd->uobject->context, start, length, |
| 148 | access_flags, 0); | 150 | access_flags | IB_ACCESS_LOCAL_WRITE, 0); |
| 149 | if (IS_ERR(mr->umem)) { | 151 | if (IS_ERR(mr->umem)) { |
| 150 | err = PTR_ERR(mr->umem); | 152 | err = PTR_ERR(mr->umem); |
| 151 | goto err_free; | 153 | goto err_free; |
| @@ -183,6 +185,90 @@ err_free: | |||
| 183 | return ERR_PTR(err); | 185 | return ERR_PTR(err); |
| 184 | } | 186 | } |
| 185 | 187 | ||
| 188 | int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, | ||
| 189 | u64 start, u64 length, u64 virt_addr, | ||
| 190 | int mr_access_flags, struct ib_pd *pd, | ||
| 191 | struct ib_udata *udata) | ||
| 192 | { | ||
| 193 | struct mlx4_ib_dev *dev = to_mdev(mr->device); | ||
| 194 | struct mlx4_ib_mr *mmr = to_mmr(mr); | ||
| 195 | struct mlx4_mpt_entry *mpt_entry; | ||
| 196 | struct mlx4_mpt_entry **pmpt_entry = &mpt_entry; | ||
| 197 | int err; | ||
| 198 | |||
| 199 | /* Since we synchronize this call and mlx4_ib_dereg_mr via uverbs, | ||
| 200 | * we assume that the calls can't run concurrently. Otherwise, a | ||
| 201 | * race exists. | ||
| 202 | */ | ||
| 203 | err = mlx4_mr_hw_get_mpt(dev->dev, &mmr->mmr, &pmpt_entry); | ||
| 204 | |||
| 205 | if (err) | ||
| 206 | return err; | ||
| 207 | |||
| 208 | if (flags & IB_MR_REREG_PD) { | ||
| 209 | err = mlx4_mr_hw_change_pd(dev->dev, *pmpt_entry, | ||
| 210 | to_mpd(pd)->pdn); | ||
| 211 | |||
| 212 | if (err) | ||
| 213 | goto release_mpt_entry; | ||
| 214 | } | ||
| 215 | |||
| 216 | if (flags & IB_MR_REREG_ACCESS) { | ||
| 217 | err = mlx4_mr_hw_change_access(dev->dev, *pmpt_entry, | ||
| 218 | convert_access(mr_access_flags)); | ||
| 219 | |||
| 220 | if (err) | ||
| 221 | goto release_mpt_entry; | ||
| 222 | } | ||
| 223 | |||
| 224 | if (flags & IB_MR_REREG_TRANS) { | ||
| 225 | int shift; | ||
| 226 | int err; | ||
| 227 | int n; | ||
| 228 | |||
| 229 | mlx4_mr_rereg_mem_cleanup(dev->dev, &mmr->mmr); | ||
| 230 | ib_umem_release(mmr->umem); | ||
| 231 | mmr->umem = ib_umem_get(mr->uobject->context, start, length, | ||
| 232 | mr_access_flags | | ||
| 233 | IB_ACCESS_LOCAL_WRITE, | ||
| 234 | 0); | ||
| 235 | if (IS_ERR(mmr->umem)) { | ||
| 236 | err = PTR_ERR(mmr->umem); | ||
| 237 | mmr->umem = NULL; | ||
| 238 | goto release_mpt_entry; | ||
| 239 | } | ||
| 240 | n = ib_umem_page_count(mmr->umem); | ||
| 241 | shift = ilog2(mmr->umem->page_size); | ||
| 242 | |||
| 243 | mmr->mmr.iova = virt_addr; | ||
| 244 | mmr->mmr.size = length; | ||
| 245 | err = mlx4_mr_rereg_mem_write(dev->dev, &mmr->mmr, | ||
| 246 | virt_addr, length, n, shift, | ||
| 247 | *pmpt_entry); | ||
| 248 | if (err) { | ||
| 249 | ib_umem_release(mmr->umem); | ||
| 250 | goto release_mpt_entry; | ||
| 251 | } | ||
| 252 | |||
| 253 | err = mlx4_ib_umem_write_mtt(dev, &mmr->mmr.mtt, mmr->umem); | ||
| 254 | if (err) { | ||
| 255 | mlx4_mr_rereg_mem_cleanup(dev->dev, &mmr->mmr); | ||
| 256 | ib_umem_release(mmr->umem); | ||
| 257 | goto release_mpt_entry; | ||
| 258 | } | ||
| 259 | } | ||
| 260 | |||
| 261 | /* If we couldn't transfer the MR to the HCA, just remember to | ||
| 262 | * return a failure. But dereg_mr will free the resources. | ||
| 263 | */ | ||
| 264 | err = mlx4_mr_hw_write_mpt(dev->dev, &mmr->mmr, pmpt_entry); | ||
| 265 | |||
| 266 | release_mpt_entry: | ||
| 267 | mlx4_mr_hw_put_mpt(dev->dev, pmpt_entry); | ||
| 268 | |||
| 269 | return err; | ||
| 270 | } | ||
| 271 | |||
| 186 | int mlx4_ib_dereg_mr(struct ib_mr *ibmr) | 272 | int mlx4_ib_dereg_mr(struct ib_mr *ibmr) |
| 187 | { | 273 | { |
| 188 | struct mlx4_ib_mr *mr = to_mmr(ibmr); | 274 | struct mlx4_ib_mr *mr = to_mmr(ibmr); |
