18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2012-2016 VMware, Inc. All rights reserved. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or 58c2ecf20Sopenharmony_ci * modify it under the terms of EITHER the GNU General Public License 68c2ecf20Sopenharmony_ci * version 2 as published by the Free Software Foundation or the BSD 78c2ecf20Sopenharmony_ci * 2-Clause License. This program is distributed in the hope that it 88c2ecf20Sopenharmony_ci * will be useful, but WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED 98c2ecf20Sopenharmony_ci * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 108c2ecf20Sopenharmony_ci * See the GNU General Public License version 2 for more details at 118c2ecf20Sopenharmony_ci * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License 148c2ecf20Sopenharmony_ci * along with this program available in the file COPYING in the main 158c2ecf20Sopenharmony_ci * directory of this source tree. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * The BSD 2-Clause License 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 208c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 218c2ecf20Sopenharmony_ci * conditions are met: 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 248c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 258c2ecf20Sopenharmony_ci * disclaimer. 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 288c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 298c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 308c2ecf20Sopenharmony_ci * provided with the distribution. 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 338c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 348c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 358c2ecf20Sopenharmony_ci * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 368c2ecf20Sopenharmony_ci * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 378c2ecf20Sopenharmony_ci * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 388c2ecf20Sopenharmony_ci * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 398c2ecf20Sopenharmony_ci * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 408c2ecf20Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 418c2ecf20Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 428c2ecf20Sopenharmony_ci * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 438c2ecf20Sopenharmony_ci * OF THE POSSIBILITY OF SUCH DAMAGE. 448c2ecf20Sopenharmony_ci */ 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#include <linux/list.h> 478c2ecf20Sopenharmony_ci#include <linux/slab.h> 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#include "pvrdma.h" 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/** 528c2ecf20Sopenharmony_ci * pvrdma_get_dma_mr - get a DMA memory region 538c2ecf20Sopenharmony_ci * @pd: protection domain 548c2ecf20Sopenharmony_ci * @acc: access flags 558c2ecf20Sopenharmony_ci * 568c2ecf20Sopenharmony_ci * @return: ib_mr pointer on success, otherwise returns an errno. 578c2ecf20Sopenharmony_ci */ 588c2ecf20Sopenharmony_cistruct ib_mr *pvrdma_get_dma_mr(struct ib_pd *pd, int acc) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci struct pvrdma_dev *dev = to_vdev(pd->device); 618c2ecf20Sopenharmony_ci struct pvrdma_user_mr *mr; 628c2ecf20Sopenharmony_ci union pvrdma_cmd_req req; 638c2ecf20Sopenharmony_ci union pvrdma_cmd_resp rsp; 648c2ecf20Sopenharmony_ci struct pvrdma_cmd_create_mr *cmd = &req.create_mr; 658c2ecf20Sopenharmony_ci struct pvrdma_cmd_create_mr_resp *resp = &rsp.create_mr_resp; 668c2ecf20Sopenharmony_ci int ret; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci /* Support only LOCAL_WRITE flag for DMA MRs */ 698c2ecf20Sopenharmony_ci if (acc & ~IB_ACCESS_LOCAL_WRITE) { 708c2ecf20Sopenharmony_ci dev_warn(&dev->pdev->dev, 718c2ecf20Sopenharmony_ci "unsupported dma mr access flags %#x\n", acc); 728c2ecf20Sopenharmony_ci return ERR_PTR(-EOPNOTSUPP); 738c2ecf20Sopenharmony_ci } 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci mr = kzalloc(sizeof(*mr), GFP_KERNEL); 768c2ecf20Sopenharmony_ci if (!mr) 778c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci memset(cmd, 0, sizeof(*cmd)); 808c2ecf20Sopenharmony_ci cmd->hdr.cmd = PVRDMA_CMD_CREATE_MR; 818c2ecf20Sopenharmony_ci cmd->pd_handle = to_vpd(pd)->pd_handle; 828c2ecf20Sopenharmony_ci cmd->access_flags = acc; 838c2ecf20Sopenharmony_ci cmd->flags = PVRDMA_MR_FLAG_DMA; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci ret = pvrdma_cmd_post(dev, &req, &rsp, PVRDMA_CMD_CREATE_MR_RESP); 868c2ecf20Sopenharmony_ci if (ret < 0) { 878c2ecf20Sopenharmony_ci dev_warn(&dev->pdev->dev, 888c2ecf20Sopenharmony_ci "could not get DMA mem region, error: %d\n", ret); 898c2ecf20Sopenharmony_ci kfree(mr); 908c2ecf20Sopenharmony_ci return ERR_PTR(ret); 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci mr->mmr.mr_handle = resp->mr_handle; 948c2ecf20Sopenharmony_ci mr->ibmr.lkey = resp->lkey; 958c2ecf20Sopenharmony_ci mr->ibmr.rkey = resp->rkey; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci return &mr->ibmr; 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/** 1018c2ecf20Sopenharmony_ci * pvrdma_reg_user_mr - register a userspace memory region 1028c2ecf20Sopenharmony_ci * @pd: protection domain 1038c2ecf20Sopenharmony_ci * @start: starting address 1048c2ecf20Sopenharmony_ci * @length: length of region 1058c2ecf20Sopenharmony_ci * @virt_addr: I/O virtual address 1068c2ecf20Sopenharmony_ci * @access_flags: access flags for memory region 1078c2ecf20Sopenharmony_ci * @udata: user data 1088c2ecf20Sopenharmony_ci * 1098c2ecf20Sopenharmony_ci * @return: ib_mr pointer on success, otherwise returns an errno. 1108c2ecf20Sopenharmony_ci */ 1118c2ecf20Sopenharmony_cistruct ib_mr *pvrdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, 1128c2ecf20Sopenharmony_ci u64 virt_addr, int access_flags, 1138c2ecf20Sopenharmony_ci struct ib_udata *udata) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci struct pvrdma_dev *dev = to_vdev(pd->device); 1168c2ecf20Sopenharmony_ci struct pvrdma_user_mr *mr = NULL; 1178c2ecf20Sopenharmony_ci struct ib_umem *umem; 1188c2ecf20Sopenharmony_ci union pvrdma_cmd_req req; 1198c2ecf20Sopenharmony_ci union pvrdma_cmd_resp rsp; 1208c2ecf20Sopenharmony_ci struct pvrdma_cmd_create_mr *cmd = &req.create_mr; 1218c2ecf20Sopenharmony_ci struct pvrdma_cmd_create_mr_resp *resp = &rsp.create_mr_resp; 1228c2ecf20Sopenharmony_ci int ret, npages; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (length == 0 || length > dev->dsr->caps.max_mr_size) { 1258c2ecf20Sopenharmony_ci dev_warn(&dev->pdev->dev, "invalid mem region length\n"); 1268c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci umem = ib_umem_get(pd->device, start, length, access_flags); 1308c2ecf20Sopenharmony_ci if (IS_ERR(umem)) { 1318c2ecf20Sopenharmony_ci dev_warn(&dev->pdev->dev, 1328c2ecf20Sopenharmony_ci "could not get umem for mem region\n"); 1338c2ecf20Sopenharmony_ci return ERR_CAST(umem); 1348c2ecf20Sopenharmony_ci } 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci npages = ib_umem_num_dma_blocks(umem, PAGE_SIZE); 1378c2ecf20Sopenharmony_ci if (npages < 0 || npages > PVRDMA_PAGE_DIR_MAX_PAGES) { 1388c2ecf20Sopenharmony_ci dev_warn(&dev->pdev->dev, "overflow %d pages in mem region\n", 1398c2ecf20Sopenharmony_ci npages); 1408c2ecf20Sopenharmony_ci ret = -EINVAL; 1418c2ecf20Sopenharmony_ci goto err_umem; 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci mr = kzalloc(sizeof(*mr), GFP_KERNEL); 1458c2ecf20Sopenharmony_ci if (!mr) { 1468c2ecf20Sopenharmony_ci ret = -ENOMEM; 1478c2ecf20Sopenharmony_ci goto err_umem; 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci mr->mmr.iova = virt_addr; 1518c2ecf20Sopenharmony_ci mr->mmr.size = length; 1528c2ecf20Sopenharmony_ci mr->umem = umem; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci ret = pvrdma_page_dir_init(dev, &mr->pdir, npages, false); 1558c2ecf20Sopenharmony_ci if (ret) { 1568c2ecf20Sopenharmony_ci dev_warn(&dev->pdev->dev, 1578c2ecf20Sopenharmony_ci "could not allocate page directory\n"); 1588c2ecf20Sopenharmony_ci goto err_umem; 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci ret = pvrdma_page_dir_insert_umem(&mr->pdir, mr->umem, 0); 1628c2ecf20Sopenharmony_ci if (ret) 1638c2ecf20Sopenharmony_ci goto err_pdir; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci memset(cmd, 0, sizeof(*cmd)); 1668c2ecf20Sopenharmony_ci cmd->hdr.cmd = PVRDMA_CMD_CREATE_MR; 1678c2ecf20Sopenharmony_ci cmd->start = start; 1688c2ecf20Sopenharmony_ci cmd->length = length; 1698c2ecf20Sopenharmony_ci cmd->pd_handle = to_vpd(pd)->pd_handle; 1708c2ecf20Sopenharmony_ci cmd->access_flags = access_flags; 1718c2ecf20Sopenharmony_ci cmd->nchunks = npages; 1728c2ecf20Sopenharmony_ci cmd->pdir_dma = mr->pdir.dir_dma; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci ret = pvrdma_cmd_post(dev, &req, &rsp, PVRDMA_CMD_CREATE_MR_RESP); 1758c2ecf20Sopenharmony_ci if (ret < 0) { 1768c2ecf20Sopenharmony_ci dev_warn(&dev->pdev->dev, 1778c2ecf20Sopenharmony_ci "could not register mem region, error: %d\n", ret); 1788c2ecf20Sopenharmony_ci goto err_pdir; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci mr->mmr.mr_handle = resp->mr_handle; 1828c2ecf20Sopenharmony_ci mr->ibmr.lkey = resp->lkey; 1838c2ecf20Sopenharmony_ci mr->ibmr.rkey = resp->rkey; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci return &mr->ibmr; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cierr_pdir: 1888c2ecf20Sopenharmony_ci pvrdma_page_dir_cleanup(dev, &mr->pdir); 1898c2ecf20Sopenharmony_cierr_umem: 1908c2ecf20Sopenharmony_ci ib_umem_release(umem); 1918c2ecf20Sopenharmony_ci kfree(mr); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci return ERR_PTR(ret); 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci/** 1978c2ecf20Sopenharmony_ci * pvrdma_alloc_mr - allocate a memory region 1988c2ecf20Sopenharmony_ci * @pd: protection domain 1998c2ecf20Sopenharmony_ci * @mr_type: type of memory region 2008c2ecf20Sopenharmony_ci * @max_num_sg: maximum number of pages 2018c2ecf20Sopenharmony_ci * 2028c2ecf20Sopenharmony_ci * @return: ib_mr pointer on success, otherwise returns an errno. 2038c2ecf20Sopenharmony_ci */ 2048c2ecf20Sopenharmony_cistruct ib_mr *pvrdma_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, 2058c2ecf20Sopenharmony_ci u32 max_num_sg) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci struct pvrdma_dev *dev = to_vdev(pd->device); 2088c2ecf20Sopenharmony_ci struct pvrdma_user_mr *mr; 2098c2ecf20Sopenharmony_ci union pvrdma_cmd_req req; 2108c2ecf20Sopenharmony_ci union pvrdma_cmd_resp rsp; 2118c2ecf20Sopenharmony_ci struct pvrdma_cmd_create_mr *cmd = &req.create_mr; 2128c2ecf20Sopenharmony_ci struct pvrdma_cmd_create_mr_resp *resp = &rsp.create_mr_resp; 2138c2ecf20Sopenharmony_ci int size = max_num_sg * sizeof(u64); 2148c2ecf20Sopenharmony_ci int ret; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci if (mr_type != IB_MR_TYPE_MEM_REG || 2178c2ecf20Sopenharmony_ci max_num_sg > PVRDMA_MAX_FAST_REG_PAGES) 2188c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci mr = kzalloc(sizeof(*mr), GFP_KERNEL); 2218c2ecf20Sopenharmony_ci if (!mr) 2228c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci mr->pages = kzalloc(size, GFP_KERNEL); 2258c2ecf20Sopenharmony_ci if (!mr->pages) { 2268c2ecf20Sopenharmony_ci ret = -ENOMEM; 2278c2ecf20Sopenharmony_ci goto freemr; 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci ret = pvrdma_page_dir_init(dev, &mr->pdir, max_num_sg, false); 2318c2ecf20Sopenharmony_ci if (ret) { 2328c2ecf20Sopenharmony_ci dev_warn(&dev->pdev->dev, 2338c2ecf20Sopenharmony_ci "failed to allocate page dir for mr\n"); 2348c2ecf20Sopenharmony_ci ret = -ENOMEM; 2358c2ecf20Sopenharmony_ci goto freepages; 2368c2ecf20Sopenharmony_ci } 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci memset(cmd, 0, sizeof(*cmd)); 2398c2ecf20Sopenharmony_ci cmd->hdr.cmd = PVRDMA_CMD_CREATE_MR; 2408c2ecf20Sopenharmony_ci cmd->pd_handle = to_vpd(pd)->pd_handle; 2418c2ecf20Sopenharmony_ci cmd->access_flags = 0; 2428c2ecf20Sopenharmony_ci cmd->flags = PVRDMA_MR_FLAG_FRMR; 2438c2ecf20Sopenharmony_ci cmd->nchunks = max_num_sg; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci ret = pvrdma_cmd_post(dev, &req, &rsp, PVRDMA_CMD_CREATE_MR_RESP); 2468c2ecf20Sopenharmony_ci if (ret < 0) { 2478c2ecf20Sopenharmony_ci dev_warn(&dev->pdev->dev, 2488c2ecf20Sopenharmony_ci "could not create FR mem region, error: %d\n", ret); 2498c2ecf20Sopenharmony_ci goto freepdir; 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci mr->max_pages = max_num_sg; 2538c2ecf20Sopenharmony_ci mr->mmr.mr_handle = resp->mr_handle; 2548c2ecf20Sopenharmony_ci mr->ibmr.lkey = resp->lkey; 2558c2ecf20Sopenharmony_ci mr->ibmr.rkey = resp->rkey; 2568c2ecf20Sopenharmony_ci mr->page_shift = PAGE_SHIFT; 2578c2ecf20Sopenharmony_ci mr->umem = NULL; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci return &mr->ibmr; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cifreepdir: 2628c2ecf20Sopenharmony_ci pvrdma_page_dir_cleanup(dev, &mr->pdir); 2638c2ecf20Sopenharmony_cifreepages: 2648c2ecf20Sopenharmony_ci kfree(mr->pages); 2658c2ecf20Sopenharmony_cifreemr: 2668c2ecf20Sopenharmony_ci kfree(mr); 2678c2ecf20Sopenharmony_ci return ERR_PTR(ret); 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci/** 2718c2ecf20Sopenharmony_ci * pvrdma_dereg_mr - deregister a memory region 2728c2ecf20Sopenharmony_ci * @ibmr: memory region 2738c2ecf20Sopenharmony_ci * @udata: pointer to user data 2748c2ecf20Sopenharmony_ci * 2758c2ecf20Sopenharmony_ci * @return: 0 on success. 2768c2ecf20Sopenharmony_ci */ 2778c2ecf20Sopenharmony_ciint pvrdma_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata) 2788c2ecf20Sopenharmony_ci{ 2798c2ecf20Sopenharmony_ci struct pvrdma_user_mr *mr = to_vmr(ibmr); 2808c2ecf20Sopenharmony_ci struct pvrdma_dev *dev = to_vdev(ibmr->device); 2818c2ecf20Sopenharmony_ci union pvrdma_cmd_req req; 2828c2ecf20Sopenharmony_ci struct pvrdma_cmd_destroy_mr *cmd = &req.destroy_mr; 2838c2ecf20Sopenharmony_ci int ret; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci memset(cmd, 0, sizeof(*cmd)); 2868c2ecf20Sopenharmony_ci cmd->hdr.cmd = PVRDMA_CMD_DESTROY_MR; 2878c2ecf20Sopenharmony_ci cmd->mr_handle = mr->mmr.mr_handle; 2888c2ecf20Sopenharmony_ci ret = pvrdma_cmd_post(dev, &req, NULL, 0); 2898c2ecf20Sopenharmony_ci if (ret < 0) 2908c2ecf20Sopenharmony_ci dev_warn(&dev->pdev->dev, 2918c2ecf20Sopenharmony_ci "could not deregister mem region, error: %d\n", ret); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci pvrdma_page_dir_cleanup(dev, &mr->pdir); 2948c2ecf20Sopenharmony_ci ib_umem_release(mr->umem); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci kfree(mr->pages); 2978c2ecf20Sopenharmony_ci kfree(mr); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci return 0; 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic int pvrdma_set_page(struct ib_mr *ibmr, u64 addr) 3038c2ecf20Sopenharmony_ci{ 3048c2ecf20Sopenharmony_ci struct pvrdma_user_mr *mr = to_vmr(ibmr); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci if (mr->npages == mr->max_pages) 3078c2ecf20Sopenharmony_ci return -ENOMEM; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci mr->pages[mr->npages++] = addr; 3108c2ecf20Sopenharmony_ci return 0; 3118c2ecf20Sopenharmony_ci} 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ciint pvrdma_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents, 3148c2ecf20Sopenharmony_ci unsigned int *sg_offset) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci struct pvrdma_user_mr *mr = to_vmr(ibmr); 3178c2ecf20Sopenharmony_ci struct pvrdma_dev *dev = to_vdev(ibmr->device); 3188c2ecf20Sopenharmony_ci int ret; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci mr->npages = 0; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci ret = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, pvrdma_set_page); 3238c2ecf20Sopenharmony_ci if (ret < 0) 3248c2ecf20Sopenharmony_ci dev_warn(&dev->pdev->dev, "could not map sg to pages\n"); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci return ret; 3278c2ecf20Sopenharmony_ci} 328