1 /* ib-hw-nes-create-qp-null.c - make nes driver return NULL
3 * Copyright (c) 2014 OPTEYA SAS
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenIB.org BSD license below:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 * Author: Yann Droneaud <ydroneaud@opteya.com>
54 #include <infiniband/kern-abi.h>
55 #include <infiniband/verbs.h>
57 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
59 /* from libibverbs, file src/ibverbs.h */
60 #define IBV_INIT_CMD(cmd, size, opcode) \
62 (cmd)->command = IB_USER_VERBS_CMD_##opcode; \
63 (cmd)->in_words = (size) / 4; \
64 (cmd)->out_words = 0; \
67 #define IBV_INIT_CMD_RESP(cmd, size, opcode, out, outsize) \
69 (cmd)->command = IB_USER_VERBS_CMD_##opcode; \
70 (cmd)->in_words = (size) / 4; \
71 (cmd)->out_words = (outsize) / 4; \
72 (cmd)->response = (uintptr_t) (out); \
75 /* Need 5 pages [M M M] */
79 /* define UNMAPPED_RESPONSE to make it impossible to uverbs
80 * to return the result (if any) of qp creation:
81 * in this case, it will make uverbs_create_qp() call
82 * ib_destroy_qp() on NULL, but only if a page were mapped
85 #define UNMAPPED_RESPONSE 1
91 struct ibv_context *context;
92 struct ibv_device **dev_list;
95 struct ibv_create_qp create_qp_cmd;
96 struct ibv_create_qp *create_qp_cmd_ptr;
97 struct ibv_create_qp_resp create_qp_resp;
98 struct ibv_create_qp_resp *create_qp_resp_ptr;
100 struct ibv_destroy_qp destroy_qp_cmd;
101 struct ibv_destroy_qp_resp destroy_qp_resp;
106 uint8_t *pages_mmap[PAGES_COUNT];
117 size = sysconf(_SC_PAGESIZE);
120 fprintf(stderr, "Failed to get page size: %d (%s)\n", err, strerror(errno));
124 page_size = (size_t) size;
126 assert(page_size >= sizeof(struct ibv_create_qp));
127 assert(page_size >= sizeof(struct ibv_create_qp_resp));
130 dev_list = ibv_get_device_list(&dev_count);
131 if (dev_list == NULL) {
132 fprintf(stderr, "No infiniband/RDMA support ?\n");
136 if (dev_count <= 0) {
137 fprintf(stderr, "No infiniband/RDMA adapter\n");
141 printf("Opening %s\n", ibv_get_device_name(dev_list[0]));
143 context = ibv_open_device(dev_list[0]);
144 if (context == NULL) {
145 fprintf(stderr, "Failed to open first infiniband/RDMA adapter\n");
149 pd = ibv_alloc_pd(context);
151 fprintf(stderr, "Can't allocate protection domain\n");
155 cq = ibv_create_cq(context, 1, NULL, NULL, 0);
157 fprintf(stderr, "Can't create completion queue\n");
161 /* allocate some pages [MMMMM] */
162 pages_mmap[0] = mmap(NULL,
163 ARRAY_SIZE(pages_mmap) * page_size,
164 PROT_READ | PROT_WRITE,
165 MAP_PRIVATE | MAP_ANONYMOUS,
167 if (pages_mmap[0] == MAP_FAILED) {
169 fprintf(stderr, "mmap() failed: %d (%s)\n", err, strerror(err));
173 assert(pages_mmap[0] != NULL); /* having pages @ 0x0 will make thing worse */
175 printf("Memory mapped @ %p [page 0]\n", pages_mmap[0]);
177 for(i = 1; i < ARRAY_SIZE(pages_mmap); i++) {
178 pages_mmap[i] = pages_mmap[i - 1] + page_size;
179 printf(" @ %p [page %u]\n", pages_mmap[i], i);
182 /* create holes [M M M] */
183 for(i = 1; i < ARRAY_SIZE(pages_mmap); i += 2) {
185 printf(" Unmapping @ %p [page %u]\n", pages_mmap[i], i);
187 ret = mprotect(pages_mmap[i], page_size, PROT_NONE);
190 fprintf(stderr, "mprotect() failed: %d (%s)\n", err, strerror(err));
194 ret = munmap(pages_mmap[i], page_size);
197 fprintf(stderr, "munmap() failed: %d (%s)\n", err, strerror(err));
203 #if defined(UNMAPPED_RESPONSE)
204 /* response buffer, in hole */
205 create_qp_resp_ptr = (struct ibv_create_qp_resp *)pages_mmap[3];
206 printf("Using unmmaped page @ %p [page %u] for response\n", pages_mmap[3], 3);
207 printf(" Response @ %p [page %u]\n", create_qp_resp_ptr, 3);
209 /* response buffer on hole boundary */
210 create_qp_resp_ptr = (struct ibv_create_qp_resp *)(pages_mmap[3] - sizeof(struct ibv_create_qp_resp));
211 printf("Using unmmaped page @ %p [page %u] for response\n", pages_mmap[3], 3);
212 printf(" Response @ %p [page %u]\n", create_qp_resp_ptr, 2);
215 /* set up command: no provider (eg. hw) specific command fields included */
216 IBV_INIT_CMD_RESP(&create_qp_cmd, sizeof(struct ibv_create_qp),
218 create_qp_resp_ptr, sizeof(struct ibv_create_qp_resp));
220 create_qp_cmd.user_handle = getpid(); /* not used kernel side ? */
222 create_qp_cmd.pd_handle = pd->handle;
224 create_qp_cmd.send_cq_handle = cq->handle;
225 create_qp_cmd.recv_cq_handle = cq->handle;
227 create_qp_cmd.srq_handle = 0;
229 create_qp_cmd.max_send_wr = 1;
230 create_qp_cmd.max_recv_wr = 1;
231 create_qp_cmd.max_send_sge = 1;
232 create_qp_cmd.max_recv_sge = 1;
233 create_qp_cmd.max_inline_data = 0;
235 create_qp_cmd.sq_sig_all = 0;
236 create_qp_cmd.qp_type = IBV_QPT_RC;
237 create_qp_cmd.is_srq = 0;
238 create_qp_cmd.reserved = 0;
240 /* command buffer, at hole boundary */
241 create_qp_cmd_ptr = (struct ibv_create_qp *)(pages_mmap[1] - sizeof(struct ibv_create_qp));
242 printf("Using unmmaped page @ %p [page %u] for command\n", pages_mmap[1], 1);
243 printf(" Command @ %p [page %u]\n", create_qp_cmd_ptr, 0);
245 /* copy command at end of page */
246 memcpy(create_qp_cmd_ptr, &create_qp_cmd, sizeof(struct ibv_create_qp));
248 printf("CREATE_QP : ");
251 sret = write(context->cmd_fd, create_qp_cmd_ptr, sizeof(struct ibv_create_qp));
254 printf(" sret = %zi errno = %d : ", sret, err);
255 if (sret == sizeof(struct ibv_create_qp)) {
256 printf(" SUCCESS\n");
258 printf(" FAILURE\n");
262 #if !defined(UNMAPPED_RESPONSE)
263 /* copy response from end of page */
264 memcpy(&create_qp_resp, create_qp_resp_ptr, sizeof(struct ibv_create_qp_resp));
266 /* destroy the QP which could have been created */
267 IBV_INIT_CMD_RESP(&destroy_qp_cmd, sizeof(struct ibv_destroy_qp),
269 &destroy_qp_resp, sizeof(struct ibv_destroy_qp_resp));
271 destroy_qp_cmd.qp_handle = create_qp_resp.qp_handle;
272 destroy_qp_cmd.reserved = 0;
274 printf("DESTROY_QP : ");
277 sret = write(context->cmd_fd, &destroy_qp_cmd, sizeof(struct ibv_destroy_qp));
280 printf(" sret = %zi, errno = %d : ", sret, err);
281 if (sret == sizeof(struct ibv_destroy_qp)) {
282 printf(" SUCCESS\n");
284 printf(" FAILURE\n");
286 #endif /* !defined(UNMAPPED_RESPONSE) */
289 munmap(pages_mmap[0], ARRAY_SIZE(pages_mmap) * page_size);
298 ibv_close_device(context);
301 ibv_free_device_list(dev_list);