+ switch (type) {
+ case GNILND_MSG_GET_DONE:
+ case GNILND_MSG_PUT_DONE:
+ post_type = GNI_POST_RDMA_PUT;
+ break;
+ case GNILND_MSG_GET_DONE_REV:
+ case GNILND_MSG_PUT_DONE_REV:
+ post_type = GNI_POST_RDMA_GET;
+ break;
+ default:
+ CERROR("invalid msg type %s (%d)\n",
+ kgnilnd_msgtype2str(type), type);
+ LBUG();
+ }
+ if (post_type == GNI_POST_RDMA_GET) {
+ /* Check for remote buffer / local buffer / length alignment. All must be 4 byte
+ * aligned. If the local buffer is not aligned correctly using the copy buffer
+ * will fix that issue. If length is misaligned copy buffer will also fix the issue, we end
+ * up transferring extra bytes into the buffer but only copy the correct nob into the original
+ * buffer. Remote offset correction is done through a combination of adjusting the offset,
+ * making sure the length and addr are aligned and copying the data into the correct location
+ * once the transfer has completed.
+ */
+ if ((((__u64)((unsigned long)tx->tx_buffer)) & 3) ||
+ (sink->gnrd_addr & 3) ||
+ (nob & 3)) {
+
+ tx->tx_offset = ((__u64)((unsigned long)sink->gnrd_addr)) & 3;
+ if (tx->tx_offset)
+ kgnilnd_admin_addref(kgnilnd_data.kgn_rev_offset);
+
+ if ((nob + tx->tx_offset) & 3) {
+ desc_nob = ((nob + tx->tx_offset) + (4 - ((nob + tx->tx_offset) & 3)));
+ kgnilnd_admin_addref(kgnilnd_data.kgn_rev_length);
+ } else {
+ desc_nob = (nob + tx->tx_offset);
+ }
+
+ if (tx->tx_buffer_copy == NULL) {
+ /* Allocate the largest copy buffer we will need, this will prevent us from overwriting data
+ * and require at most we allocate a few extra bytes. */
+ tx->tx_buffer_copy = vmalloc(desc_nob);
+
+ if (!tx->tx_buffer_copy) {
+ /* allocation of buffer failed nak the rdma */
+ kgnilnd_nak_rdma(tx->tx_conn, tx->tx_msg.gnm_type, -EFAULT, cookie, tx->tx_msg.gnm_srcnid);
+ kgnilnd_tx_done(tx, -EFAULT);
+ return 0;
+ }
+ kgnilnd_admin_addref(kgnilnd_data.kgn_rev_copy_buff);
+ rc = kgnilnd_mem_register(conn->gnc_device->gnd_handle, (__u64)tx->tx_buffer_copy, desc_nob, NULL, GNI_MEM_READWRITE, &tx->tx_buffer_copy_map_key);
+ if (rc != GNI_RC_SUCCESS) {
+ /* Registration Failed nak rdma and kill the tx. */
+ vfree(tx->tx_buffer_copy);
+ tx->tx_buffer_copy = NULL;
+ kgnilnd_nak_rdma(tx->tx_conn, tx->tx_msg.gnm_type, -EFAULT, cookie, tx->tx_msg.gnm_srcnid);
+ kgnilnd_tx_done(tx, -EFAULT);
+ return 0;
+ }
+ }
+ desc_map_key = tx->tx_buffer_copy_map_key;
+ desc_buffer = tx->tx_buffer_copy;
+ }
+ }
+