diff options
Diffstat (limited to 'drivers/infiniband/hw/mthca/mthca_provider.c')
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_provider.c | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 1c05486c3c68..6bcde1cb9688 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c | |||
@@ -37,6 +37,7 @@ | |||
37 | */ | 37 | */ |
38 | 38 | ||
39 | #include <rdma/ib_smi.h> | 39 | #include <rdma/ib_smi.h> |
40 | #include <rdma/ib_umem.h> | ||
40 | #include <rdma/ib_user_verbs.h> | 41 | #include <rdma/ib_user_verbs.h> |
41 | #include <linux/mm.h> | 42 | #include <linux/mm.h> |
42 | 43 | ||
@@ -908,6 +909,8 @@ static struct ib_mr *mthca_get_dma_mr(struct ib_pd *pd, int acc) | |||
908 | return ERR_PTR(err); | 909 | return ERR_PTR(err); |
909 | } | 910 | } |
910 | 911 | ||
912 | mr->umem = NULL; | ||
913 | |||
911 | return &mr->ibmr; | 914 | return &mr->ibmr; |
912 | } | 915 | } |
913 | 916 | ||
@@ -1003,11 +1006,13 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd *pd, | |||
1003 | } | 1006 | } |
1004 | 1007 | ||
1005 | kfree(page_list); | 1008 | kfree(page_list); |
1009 | mr->umem = NULL; | ||
1010 | |||
1006 | return &mr->ibmr; | 1011 | return &mr->ibmr; |
1007 | } | 1012 | } |
1008 | 1013 | ||
1009 | static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, | 1014 | static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, |
1010 | int acc, struct ib_udata *udata) | 1015 | u64 virt, int acc, struct ib_udata *udata) |
1011 | { | 1016 | { |
1012 | struct mthca_dev *dev = to_mdev(pd->device); | 1017 | struct mthca_dev *dev = to_mdev(pd->device); |
1013 | struct ib_umem_chunk *chunk; | 1018 | struct ib_umem_chunk *chunk; |
@@ -1018,20 +1023,26 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, | |||
1018 | int err = 0; | 1023 | int err = 0; |
1019 | int write_mtt_size; | 1024 | int write_mtt_size; |
1020 | 1025 | ||
1021 | shift = ffs(region->page_size) - 1; | ||
1022 | |||
1023 | mr = kmalloc(sizeof *mr, GFP_KERNEL); | 1026 | mr = kmalloc(sizeof *mr, GFP_KERNEL); |
1024 | if (!mr) | 1027 | if (!mr) |
1025 | return ERR_PTR(-ENOMEM); | 1028 | return ERR_PTR(-ENOMEM); |
1026 | 1029 | ||
1030 | mr->umem = ib_umem_get(pd->uobject->context, start, length, acc); | ||
1031 | if (IS_ERR(mr->umem)) { | ||
1032 | err = PTR_ERR(mr->umem); | ||
1033 | goto err; | ||
1034 | } | ||
1035 | |||
1036 | shift = ffs(mr->umem->page_size) - 1; | ||
1037 | |||
1027 | n = 0; | 1038 | n = 0; |
1028 | list_for_each_entry(chunk, ®ion->chunk_list, list) | 1039 | list_for_each_entry(chunk, &mr->umem->chunk_list, list) |
1029 | n += chunk->nents; | 1040 | n += chunk->nents; |
1030 | 1041 | ||
1031 | mr->mtt = mthca_alloc_mtt(dev, n); | 1042 | mr->mtt = mthca_alloc_mtt(dev, n); |
1032 | if (IS_ERR(mr->mtt)) { | 1043 | if (IS_ERR(mr->mtt)) { |
1033 | err = PTR_ERR(mr->mtt); | 1044 | err = PTR_ERR(mr->mtt); |
1034 | goto err; | 1045 | goto err_umem; |
1035 | } | 1046 | } |
1036 | 1047 | ||
1037 | pages = (u64 *) __get_free_page(GFP_KERNEL); | 1048 | pages = (u64 *) __get_free_page(GFP_KERNEL); |
@@ -1044,12 +1055,12 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, | |||
1044 | 1055 | ||
1045 | write_mtt_size = min(mthca_write_mtt_size(dev), (int) (PAGE_SIZE / sizeof *pages)); | 1056 | write_mtt_size = min(mthca_write_mtt_size(dev), (int) (PAGE_SIZE / sizeof *pages)); |
1046 | 1057 | ||
1047 | list_for_each_entry(chunk, ®ion->chunk_list, list) | 1058 | list_for_each_entry(chunk, &mr->umem->chunk_list, list) |
1048 | for (j = 0; j < chunk->nmap; ++j) { | 1059 | for (j = 0; j < chunk->nmap; ++j) { |
1049 | len = sg_dma_len(&chunk->page_list[j]) >> shift; | 1060 | len = sg_dma_len(&chunk->page_list[j]) >> shift; |
1050 | for (k = 0; k < len; ++k) { | 1061 | for (k = 0; k < len; ++k) { |
1051 | pages[i++] = sg_dma_address(&chunk->page_list[j]) + | 1062 | pages[i++] = sg_dma_address(&chunk->page_list[j]) + |
1052 | region->page_size * k; | 1063 | mr->umem->page_size * k; |
1053 | /* | 1064 | /* |
1054 | * Be friendly to write_mtt and pass it chunks | 1065 | * Be friendly to write_mtt and pass it chunks |
1055 | * of appropriate size. | 1066 | * of appropriate size. |
@@ -1071,8 +1082,8 @@ mtt_done: | |||
1071 | if (err) | 1082 | if (err) |
1072 | goto err_mtt; | 1083 | goto err_mtt; |
1073 | 1084 | ||
1074 | err = mthca_mr_alloc(dev, to_mpd(pd)->pd_num, shift, region->virt_base, | 1085 | err = mthca_mr_alloc(dev, to_mpd(pd)->pd_num, shift, virt, length, |
1075 | region->length, convert_access(acc), mr); | 1086 | convert_access(acc), mr); |
1076 | 1087 | ||
1077 | if (err) | 1088 | if (err) |
1078 | goto err_mtt; | 1089 | goto err_mtt; |
@@ -1082,6 +1093,9 @@ mtt_done: | |||
1082 | err_mtt: | 1093 | err_mtt: |
1083 | mthca_free_mtt(dev, mr->mtt); | 1094 | mthca_free_mtt(dev, mr->mtt); |
1084 | 1095 | ||
1096 | err_umem: | ||
1097 | ib_umem_release(mr->umem); | ||
1098 | |||
1085 | err: | 1099 | err: |
1086 | kfree(mr); | 1100 | kfree(mr); |
1087 | return ERR_PTR(err); | 1101 | return ERR_PTR(err); |
@@ -1090,8 +1104,12 @@ err: | |||
1090 | static int mthca_dereg_mr(struct ib_mr *mr) | 1104 | static int mthca_dereg_mr(struct ib_mr *mr) |
1091 | { | 1105 | { |
1092 | struct mthca_mr *mmr = to_mmr(mr); | 1106 | struct mthca_mr *mmr = to_mmr(mr); |
1107 | |||
1093 | mthca_free_mr(to_mdev(mr->device), mmr); | 1108 | mthca_free_mr(to_mdev(mr->device), mmr); |
1109 | if (mmr->umem) | ||
1110 | ib_umem_release(mmr->umem); | ||
1094 | kfree(mmr); | 1111 | kfree(mmr); |
1112 | |||
1095 | return 0; | 1113 | return 0; |
1096 | } | 1114 | } |
1097 | 1115 | ||