diff options
Diffstat (limited to 'drivers/infiniband/hw/mlx4/mr.c')
-rw-r--r-- | drivers/infiniband/hw/mlx4/mr.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c new file mode 100644 index 000000000000..85ae906f1d12 --- /dev/null +++ b/drivers/infiniband/hw/mlx4/mr.c | |||
@@ -0,0 +1,184 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. | ||
3 | * | ||
4 | * This software is available to you under a choice of one of two | ||
5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
6 | * General Public License (GPL) Version 2, available from the file | ||
7 | * COPYING in the main directory of this source tree, or the | ||
8 | * OpenIB.org BSD license below: | ||
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or | ||
11 | * without modification, are permitted provided that the following | ||
12 | * conditions are met: | ||
13 | * | ||
14 | * - Redistributions of source code must retain the above | ||
15 | * copyright notice, this list of conditions and the following | ||
16 | * disclaimer. | ||
17 | * | ||
18 | * - Redistributions in binary form must reproduce the above | ||
19 | * copyright notice, this list of conditions and the following | ||
20 | * disclaimer in the documentation and/or other materials | ||
21 | * provided with the distribution. | ||
22 | * | ||
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
30 | * SOFTWARE. | ||
31 | */ | ||
32 | |||
33 | #include "mlx4_ib.h" | ||
34 | |||
35 | static u32 convert_access(int acc) | ||
36 | { | ||
37 | return (acc & IB_ACCESS_REMOTE_ATOMIC ? MLX4_PERM_ATOMIC : 0) | | ||
38 | (acc & IB_ACCESS_REMOTE_WRITE ? MLX4_PERM_REMOTE_WRITE : 0) | | ||
39 | (acc & IB_ACCESS_REMOTE_READ ? MLX4_PERM_REMOTE_READ : 0) | | ||
40 | (acc & IB_ACCESS_LOCAL_WRITE ? MLX4_PERM_LOCAL_WRITE : 0) | | ||
41 | MLX4_PERM_LOCAL_READ; | ||
42 | } | ||
43 | |||
44 | struct ib_mr *mlx4_ib_get_dma_mr(struct ib_pd *pd, int acc) | ||
45 | { | ||
46 | struct mlx4_ib_mr *mr; | ||
47 | int err; | ||
48 | |||
49 | mr = kmalloc(sizeof *mr, GFP_KERNEL); | ||
50 | if (!mr) | ||
51 | return ERR_PTR(-ENOMEM); | ||
52 | |||
53 | err = mlx4_mr_alloc(to_mdev(pd->device)->dev, to_mpd(pd)->pdn, 0, | ||
54 | ~0ull, convert_access(acc), 0, 0, &mr->mmr); | ||
55 | if (err) | ||
56 | goto err_free; | ||
57 | |||
58 | err = mlx4_mr_enable(to_mdev(pd->device)->dev, &mr->mmr); | ||
59 | if (err) | ||
60 | goto err_mr; | ||
61 | |||
62 | mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; | ||
63 | mr->umem = NULL; | ||
64 | |||
65 | return &mr->ibmr; | ||
66 | |||
67 | err_mr: | ||
68 | mlx4_mr_free(to_mdev(pd->device)->dev, &mr->mmr); | ||
69 | |||
70 | err_free: | ||
71 | kfree(mr); | ||
72 | |||
73 | return ERR_PTR(err); | ||
74 | } | ||
75 | |||
76 | int mlx4_ib_umem_write_mtt(struct mlx4_ib_dev *dev, struct mlx4_mtt *mtt, | ||
77 | struct ib_umem *umem) | ||
78 | { | ||
79 | u64 *pages; | ||
80 | struct ib_umem_chunk *chunk; | ||
81 | int i, j, k; | ||
82 | int n; | ||
83 | int len; | ||
84 | int err = 0; | ||
85 | |||
86 | pages = (u64 *) __get_free_page(GFP_KERNEL); | ||
87 | if (!pages) | ||
88 | return -ENOMEM; | ||
89 | |||
90 | i = n = 0; | ||
91 | |||
92 | list_for_each_entry(chunk, &umem->chunk_list, list) | ||
93 | for (j = 0; j < chunk->nmap; ++j) { | ||
94 | len = sg_dma_len(&chunk->page_list[j]) >> mtt->page_shift; | ||
95 | for (k = 0; k < len; ++k) { | ||
96 | pages[i++] = sg_dma_address(&chunk->page_list[j]) + | ||
97 | umem->page_size * k; | ||
98 | /* | ||
99 | * Be friendly to WRITE_MTT firmware | ||
100 | * command, and pass it chunks of | ||
101 | * appropriate size. | ||
102 | */ | ||
103 | if (i == PAGE_SIZE / sizeof (u64) - 2) { | ||
104 | err = mlx4_write_mtt(dev->dev, mtt, n, | ||
105 | i, pages); | ||
106 | if (err) | ||
107 | goto out; | ||
108 | n += i; | ||
109 | i = 0; | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | |||
114 | if (i) | ||
115 | err = mlx4_write_mtt(dev->dev, mtt, n, i, pages); | ||
116 | |||
117 | out: | ||
118 | free_page((unsigned long) pages); | ||
119 | return err; | ||
120 | } | ||
121 | |||
122 | struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, | ||
123 | u64 virt_addr, int access_flags, | ||
124 | struct ib_udata *udata) | ||
125 | { | ||
126 | struct mlx4_ib_dev *dev = to_mdev(pd->device); | ||
127 | struct mlx4_ib_mr *mr; | ||
128 | int shift; | ||
129 | int err; | ||
130 | int n; | ||
131 | |||
132 | mr = kmalloc(sizeof *mr, GFP_KERNEL); | ||
133 | if (!mr) | ||
134 | return ERR_PTR(-ENOMEM); | ||
135 | |||
136 | mr->umem = ib_umem_get(pd->uobject->context, start, length, access_flags); | ||
137 | if (IS_ERR(mr->umem)) { | ||
138 | err = PTR_ERR(mr->umem); | ||
139 | goto err_free; | ||
140 | } | ||
141 | |||
142 | n = ib_umem_page_count(mr->umem); | ||
143 | shift = ilog2(mr->umem->page_size); | ||
144 | |||
145 | err = mlx4_mr_alloc(dev->dev, to_mpd(pd)->pdn, virt_addr, length, | ||
146 | convert_access(access_flags), n, shift, &mr->mmr); | ||
147 | if (err) | ||
148 | goto err_umem; | ||
149 | |||
150 | err = mlx4_ib_umem_write_mtt(dev, &mr->mmr.mtt, mr->umem); | ||
151 | if (err) | ||
152 | goto err_mr; | ||
153 | |||
154 | err = mlx4_mr_enable(dev->dev, &mr->mmr); | ||
155 | if (err) | ||
156 | goto err_mr; | ||
157 | |||
158 | mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; | ||
159 | |||
160 | return &mr->ibmr; | ||
161 | |||
162 | err_mr: | ||
163 | mlx4_mr_free(to_mdev(pd->device)->dev, &mr->mmr); | ||
164 | |||
165 | err_umem: | ||
166 | ib_umem_release(mr->umem); | ||
167 | |||
168 | err_free: | ||
169 | kfree(mr); | ||
170 | |||
171 | return ERR_PTR(err); | ||
172 | } | ||
173 | |||
174 | int mlx4_ib_dereg_mr(struct ib_mr *ibmr) | ||
175 | { | ||
176 | struct mlx4_ib_mr *mr = to_mmr(ibmr); | ||
177 | |||
178 | mlx4_mr_free(to_mdev(ibmr->device)->dev, &mr->mmr); | ||
179 | if (mr->umem) | ||
180 | ib_umem_release(mr->umem); | ||
181 | kfree(mr); | ||
182 | |||
183 | return 0; | ||
184 | } | ||