--- /dev/null
+Bottom: 3c374149dc43dd63cbfda16b151381c36d912259
+Top: 9ae3b5be84001aad21beaa018d680978a03434ee
+Author: Doug Ledford <dledford@redhat.com>
+Date: 2014-06-18 10:45:23 -0700
+
+rdma_server: handle IBV_SEND_INLINE correctly
+
+Not all RDMA devices support IBV_SEND_INLINE. At least some of those
+that don't will ignore the flag passed to rdma_post_send and attempt to
+send the command by using an sge entry instead. Because we don't
+register the send memory, this fails. The proper way to deal with the
+fact that IBV_SEND_INLINE is not guaranteed is to check the returned
+value in our cap struct to see if we have support for inline data, and
+if not, fall back to non-inline sends and to register the send memory
+region.
+
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+
+
+---
+
+diff --git a/examples/rdma_server.c b/examples/rdma_server.c
+index 54922fc..129cf42 100644
+--- a/examples/rdma_server.c
++++ b/examples/rdma_server.c
+@@ -39,14 +39,16 @@
+ static char *port = "7471";
+
+ struct rdma_cm_id *listen_id, *id;
+-struct ibv_mr *mr;
++struct ibv_mr *mr, *send_mr;
++int send_flags;
+ uint8_t send_msg[16];
+ uint8_t recv_msg[16];
+
+ static int run(void)
+ {
+ struct rdma_addrinfo hints, *res;
+- struct ibv_qp_init_attr attr;
++ struct ibv_qp_init_attr init_attr;
++ struct ibv_qp_attr qp_attr;
+ struct ibv_wc wc;
+ int ret;
+
+@@ -59,12 +61,12 @@ static int run(void)
+ return ret;
+ }
+
+- memset(&attr, 0, sizeof attr);
+- attr.cap.max_send_wr = attr.cap.max_recv_wr = 1;
+- attr.cap.max_send_sge = attr.cap.max_recv_sge = 1;
+- attr.cap.max_inline_data = 16;
+- attr.sq_sig_all = 1;
+- ret = rdma_create_ep(&listen_id, res, NULL, &attr);
++ memset(&init_attr, 0, sizeof init_attr);
++ init_attr.cap.max_send_wr = init_attr.cap.max_recv_wr = 1;
++ init_attr.cap.max_send_sge = init_attr.cap.max_recv_sge = 1;
++ init_attr.cap.max_inline_data = 16;
++ init_attr.sq_sig_all = 1;
++ ret = rdma_create_ep(&listen_id, res, NULL, &init_attr);
+ if (ret) {
+ perror("rdma_create_ep");
+ goto out_free_addrinfo;
+@@ -82,23 +84,45 @@ static int run(void)
+ goto out_destroy_listen_ep;
+ }
+
++ memset(&qp_attr, 0, sizeof qp_attr);
++ memset(&init_attr, 0, sizeof init_attr);
++ ret = ibv_query_qp(id->qp, &qp_attr, IBV_QP_CAP,
++ &init_attr);
++ if (ret) {
++ perror("ibv_query_qp");
++ goto out_destroy_accept_ep;
++ }
++ if (init_attr.cap.max_inline_data >= 16)
++ send_flags = IBV_SEND_INLINE;
++ else
++ printf("rdma_server: device doesn't support IBV_SEND_INLINE, "
++ "using sge sends\n");
++
+ mr = rdma_reg_msgs(id, recv_msg, 16);
+ if (!mr) {
+ ret = -1;
+- perror("rdma_reg_msgs");
++ perror("rdma_reg_msgs for recv_msg");
+ goto out_destroy_accept_ep;
+ }
++ if ((send_flags & IBV_SEND_INLINE) == 0) {
++ send_mr = rdma_reg_msgs(id, send_msg, 16);
++ if (!send_mr) {
++ ret = -1;
++ perror("rdma_reg_msgs for send_msg");
++ goto out_dereg_recv;
++ }
++ }
+
+ ret = rdma_post_recv(id, NULL, recv_msg, 16, mr);
+ if (ret) {
+ perror("rdma_post_recv");
+- goto out_dereg;
++ goto out_dereg_send;
+ }
+
+ ret = rdma_accept(id, NULL);
+ if (ret) {
+ perror("rdma_accept");
+- goto out_dereg;
++ goto out_dereg_send;
+ }
+
+ while ((ret = rdma_get_recv_comp(id, &wc)) == 0);
+@@ -107,7 +131,7 @@ static int run(void)
+ goto out_disconnect;
+ }
+
+- ret = rdma_post_send(id, NULL, send_msg, 16, NULL, IBV_SEND_INLINE);
++ ret = rdma_post_send(id, NULL, send_msg, 16, send_mr, send_flags);
+ if (ret) {
+ perror("rdma_post_send");
+ goto out_disconnect;
+@@ -121,7 +145,10 @@ static int run(void)
+
+ out_disconnect:
+ rdma_disconnect(id);
+-out_dereg:
++out_dereg_send:
++ if ((send_flags & IBV_SEND_INLINE) == 0)
++ rdma_dereg_mr(send_mr);
++out_dereg_recv:
+ rdma_dereg_mr(mr);
+ out_destroy_accept_ep:
+ rdma_destroy_ep(id);