162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2022, Microsoft Corporation. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include "mana_ib.h" 762306a36Sopenharmony_ci 862306a36Sopenharmony_civoid mana_ib_uncfg_vport(struct mana_ib_dev *dev, struct mana_ib_pd *pd, 962306a36Sopenharmony_ci u32 port) 1062306a36Sopenharmony_ci{ 1162306a36Sopenharmony_ci struct gdma_dev *gd = dev->gdma_dev; 1262306a36Sopenharmony_ci struct mana_port_context *mpc; 1362306a36Sopenharmony_ci struct net_device *ndev; 1462306a36Sopenharmony_ci struct mana_context *mc; 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci mc = gd->driver_data; 1762306a36Sopenharmony_ci ndev = mc->ports[port]; 1862306a36Sopenharmony_ci mpc = netdev_priv(ndev); 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci mutex_lock(&pd->vport_mutex); 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci pd->vport_use_count--; 2362306a36Sopenharmony_ci WARN_ON(pd->vport_use_count < 0); 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci if (!pd->vport_use_count) 2662306a36Sopenharmony_ci mana_uncfg_vport(mpc); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci mutex_unlock(&pd->vport_mutex); 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ciint mana_ib_cfg_vport(struct mana_ib_dev *dev, u32 port, struct mana_ib_pd *pd, 3262306a36Sopenharmony_ci u32 doorbell_id) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci struct gdma_dev *mdev = dev->gdma_dev; 3562306a36Sopenharmony_ci struct mana_port_context *mpc; 3662306a36Sopenharmony_ci struct mana_context *mc; 3762306a36Sopenharmony_ci struct net_device *ndev; 3862306a36Sopenharmony_ci int err; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci mc = mdev->driver_data; 4162306a36Sopenharmony_ci ndev = mc->ports[port]; 4262306a36Sopenharmony_ci mpc = netdev_priv(ndev); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci mutex_lock(&pd->vport_mutex); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci pd->vport_use_count++; 4762306a36Sopenharmony_ci if (pd->vport_use_count > 1) { 4862306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, 4962306a36Sopenharmony_ci "Skip as this PD is already configured vport\n"); 5062306a36Sopenharmony_ci mutex_unlock(&pd->vport_mutex); 5162306a36Sopenharmony_ci return 0; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci err = mana_cfg_vport(mpc, pd->pdn, doorbell_id); 5562306a36Sopenharmony_ci if (err) { 5662306a36Sopenharmony_ci pd->vport_use_count--; 5762306a36Sopenharmony_ci mutex_unlock(&pd->vport_mutex); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, "Failed to configure vPort %d\n", err); 6062306a36Sopenharmony_ci return err; 6162306a36Sopenharmony_ci } 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci mutex_unlock(&pd->vport_mutex); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci pd->tx_shortform_allowed = mpc->tx_shortform_allowed; 6662306a36Sopenharmony_ci pd->tx_vp_offset = mpc->tx_vp_offset; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, "vport handle %llx pdid %x doorbell_id %x\n", 6962306a36Sopenharmony_ci mpc->port_handle, pd->pdn, doorbell_id); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci return 0; 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ciint mana_ib_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci struct mana_ib_pd *pd = container_of(ibpd, struct mana_ib_pd, ibpd); 7762306a36Sopenharmony_ci struct ib_device *ibdev = ibpd->device; 7862306a36Sopenharmony_ci struct gdma_create_pd_resp resp = {}; 7962306a36Sopenharmony_ci struct gdma_create_pd_req req = {}; 8062306a36Sopenharmony_ci enum gdma_pd_flags flags = 0; 8162306a36Sopenharmony_ci struct mana_ib_dev *dev; 8262306a36Sopenharmony_ci struct gdma_dev *mdev; 8362306a36Sopenharmony_ci int err; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci dev = container_of(ibdev, struct mana_ib_dev, ib_dev); 8662306a36Sopenharmony_ci mdev = dev->gdma_dev; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci mana_gd_init_req_hdr(&req.hdr, GDMA_CREATE_PD, sizeof(req), 8962306a36Sopenharmony_ci sizeof(resp)); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci req.flags = flags; 9262306a36Sopenharmony_ci err = mana_gd_send_request(mdev->gdma_context, sizeof(req), &req, 9362306a36Sopenharmony_ci sizeof(resp), &resp); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci if (err || resp.hdr.status) { 9662306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, 9762306a36Sopenharmony_ci "Failed to get pd_id err %d status %u\n", err, 9862306a36Sopenharmony_ci resp.hdr.status); 9962306a36Sopenharmony_ci if (!err) 10062306a36Sopenharmony_ci err = -EPROTO; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci return err; 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci pd->pd_handle = resp.pd_handle; 10662306a36Sopenharmony_ci pd->pdn = resp.pd_id; 10762306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, "pd_handle 0x%llx pd_id %d\n", 10862306a36Sopenharmony_ci pd->pd_handle, pd->pdn); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci mutex_init(&pd->vport_mutex); 11162306a36Sopenharmony_ci pd->vport_use_count = 0; 11262306a36Sopenharmony_ci return 0; 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciint mana_ib_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci struct mana_ib_pd *pd = container_of(ibpd, struct mana_ib_pd, ibpd); 11862306a36Sopenharmony_ci struct ib_device *ibdev = ibpd->device; 11962306a36Sopenharmony_ci struct gdma_destory_pd_resp resp = {}; 12062306a36Sopenharmony_ci struct gdma_destroy_pd_req req = {}; 12162306a36Sopenharmony_ci struct mana_ib_dev *dev; 12262306a36Sopenharmony_ci struct gdma_dev *mdev; 12362306a36Sopenharmony_ci int err; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci dev = container_of(ibdev, struct mana_ib_dev, ib_dev); 12662306a36Sopenharmony_ci mdev = dev->gdma_dev; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci mana_gd_init_req_hdr(&req.hdr, GDMA_DESTROY_PD, sizeof(req), 12962306a36Sopenharmony_ci sizeof(resp)); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci req.pd_handle = pd->pd_handle; 13262306a36Sopenharmony_ci err = mana_gd_send_request(mdev->gdma_context, sizeof(req), &req, 13362306a36Sopenharmony_ci sizeof(resp), &resp); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci if (err || resp.hdr.status) { 13662306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, 13762306a36Sopenharmony_ci "Failed to destroy pd_handle 0x%llx err %d status %u", 13862306a36Sopenharmony_ci pd->pd_handle, err, resp.hdr.status); 13962306a36Sopenharmony_ci if (!err) 14062306a36Sopenharmony_ci err = -EPROTO; 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci return err; 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic int mana_gd_destroy_doorbell_page(struct gdma_context *gc, 14762306a36Sopenharmony_ci int doorbell_page) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci struct gdma_destroy_resource_range_req req = {}; 15062306a36Sopenharmony_ci struct gdma_resp_hdr resp = {}; 15162306a36Sopenharmony_ci int err; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci mana_gd_init_req_hdr(&req.hdr, GDMA_DESTROY_RESOURCE_RANGE, 15462306a36Sopenharmony_ci sizeof(req), sizeof(resp)); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci req.resource_type = GDMA_RESOURCE_DOORBELL_PAGE; 15762306a36Sopenharmony_ci req.num_resources = 1; 15862306a36Sopenharmony_ci req.allocated_resources = doorbell_page; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci err = mana_gd_send_request(gc, sizeof(req), &req, sizeof(resp), &resp); 16162306a36Sopenharmony_ci if (err || resp.status) { 16262306a36Sopenharmony_ci dev_err(gc->dev, 16362306a36Sopenharmony_ci "Failed to destroy doorbell page: ret %d, 0x%x\n", 16462306a36Sopenharmony_ci err, resp.status); 16562306a36Sopenharmony_ci return err ?: -EPROTO; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci return 0; 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cistatic int mana_gd_allocate_doorbell_page(struct gdma_context *gc, 17262306a36Sopenharmony_ci int *doorbell_page) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci struct gdma_allocate_resource_range_req req = {}; 17562306a36Sopenharmony_ci struct gdma_allocate_resource_range_resp resp = {}; 17662306a36Sopenharmony_ci int err; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci mana_gd_init_req_hdr(&req.hdr, GDMA_ALLOCATE_RESOURCE_RANGE, 17962306a36Sopenharmony_ci sizeof(req), sizeof(resp)); 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci req.resource_type = GDMA_RESOURCE_DOORBELL_PAGE; 18262306a36Sopenharmony_ci req.num_resources = 1; 18362306a36Sopenharmony_ci req.alignment = 1; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci /* Have GDMA start searching from 0 */ 18662306a36Sopenharmony_ci req.allocated_resources = 0; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci err = mana_gd_send_request(gc, sizeof(req), &req, sizeof(resp), &resp); 18962306a36Sopenharmony_ci if (err || resp.hdr.status) { 19062306a36Sopenharmony_ci dev_err(gc->dev, 19162306a36Sopenharmony_ci "Failed to allocate doorbell page: ret %d, 0x%x\n", 19262306a36Sopenharmony_ci err, resp.hdr.status); 19362306a36Sopenharmony_ci return err ?: -EPROTO; 19462306a36Sopenharmony_ci } 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci *doorbell_page = resp.allocated_resources; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci return 0; 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ciint mana_ib_alloc_ucontext(struct ib_ucontext *ibcontext, 20262306a36Sopenharmony_ci struct ib_udata *udata) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci struct mana_ib_ucontext *ucontext = 20562306a36Sopenharmony_ci container_of(ibcontext, struct mana_ib_ucontext, ibucontext); 20662306a36Sopenharmony_ci struct ib_device *ibdev = ibcontext->device; 20762306a36Sopenharmony_ci struct mana_ib_dev *mdev; 20862306a36Sopenharmony_ci struct gdma_context *gc; 20962306a36Sopenharmony_ci struct gdma_dev *dev; 21062306a36Sopenharmony_ci int doorbell_page; 21162306a36Sopenharmony_ci int ret; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci mdev = container_of(ibdev, struct mana_ib_dev, ib_dev); 21462306a36Sopenharmony_ci dev = mdev->gdma_dev; 21562306a36Sopenharmony_ci gc = dev->gdma_context; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* Allocate a doorbell page index */ 21862306a36Sopenharmony_ci ret = mana_gd_allocate_doorbell_page(gc, &doorbell_page); 21962306a36Sopenharmony_ci if (ret) { 22062306a36Sopenharmony_ci ibdev_dbg(ibdev, "Failed to allocate doorbell page %d\n", ret); 22162306a36Sopenharmony_ci return ret; 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci ibdev_dbg(ibdev, "Doorbell page allocated %d\n", doorbell_page); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci ucontext->doorbell = doorbell_page; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci return 0; 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_civoid mana_ib_dealloc_ucontext(struct ib_ucontext *ibcontext) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci struct mana_ib_ucontext *mana_ucontext = 23462306a36Sopenharmony_ci container_of(ibcontext, struct mana_ib_ucontext, ibucontext); 23562306a36Sopenharmony_ci struct ib_device *ibdev = ibcontext->device; 23662306a36Sopenharmony_ci struct mana_ib_dev *mdev; 23762306a36Sopenharmony_ci struct gdma_context *gc; 23862306a36Sopenharmony_ci int ret; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci mdev = container_of(ibdev, struct mana_ib_dev, ib_dev); 24162306a36Sopenharmony_ci gc = mdev->gdma_dev->gdma_context; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci ret = mana_gd_destroy_doorbell_page(gc, mana_ucontext->doorbell); 24462306a36Sopenharmony_ci if (ret) 24562306a36Sopenharmony_ci ibdev_dbg(ibdev, "Failed to destroy doorbell page %d\n", ret); 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic int 24962306a36Sopenharmony_cimana_ib_gd_first_dma_region(struct mana_ib_dev *dev, 25062306a36Sopenharmony_ci struct gdma_context *gc, 25162306a36Sopenharmony_ci struct gdma_create_dma_region_req *create_req, 25262306a36Sopenharmony_ci size_t num_pages, mana_handle_t *gdma_region, 25362306a36Sopenharmony_ci u32 expected_status) 25462306a36Sopenharmony_ci{ 25562306a36Sopenharmony_ci struct gdma_create_dma_region_resp create_resp = {}; 25662306a36Sopenharmony_ci unsigned int create_req_msg_size; 25762306a36Sopenharmony_ci int err; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci create_req_msg_size = 26062306a36Sopenharmony_ci struct_size(create_req, page_addr_list, num_pages); 26162306a36Sopenharmony_ci create_req->page_addr_list_len = num_pages; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci err = mana_gd_send_request(gc, create_req_msg_size, create_req, 26462306a36Sopenharmony_ci sizeof(create_resp), &create_resp); 26562306a36Sopenharmony_ci if (err || create_resp.hdr.status != expected_status) { 26662306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, 26762306a36Sopenharmony_ci "Failed to create DMA region: %d, 0x%x\n", 26862306a36Sopenharmony_ci err, create_resp.hdr.status); 26962306a36Sopenharmony_ci if (!err) 27062306a36Sopenharmony_ci err = -EPROTO; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci return err; 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci *gdma_region = create_resp.dma_region_handle; 27662306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, "Created DMA region handle 0x%llx\n", 27762306a36Sopenharmony_ci *gdma_region); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci return 0; 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistatic int 28362306a36Sopenharmony_cimana_ib_gd_add_dma_region(struct mana_ib_dev *dev, struct gdma_context *gc, 28462306a36Sopenharmony_ci struct gdma_dma_region_add_pages_req *add_req, 28562306a36Sopenharmony_ci unsigned int num_pages, u32 expected_status) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci unsigned int add_req_msg_size = 28862306a36Sopenharmony_ci struct_size(add_req, page_addr_list, num_pages); 28962306a36Sopenharmony_ci struct gdma_general_resp add_resp = {}; 29062306a36Sopenharmony_ci int err; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci mana_gd_init_req_hdr(&add_req->hdr, GDMA_DMA_REGION_ADD_PAGES, 29362306a36Sopenharmony_ci add_req_msg_size, sizeof(add_resp)); 29462306a36Sopenharmony_ci add_req->page_addr_list_len = num_pages; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci err = mana_gd_send_request(gc, add_req_msg_size, add_req, 29762306a36Sopenharmony_ci sizeof(add_resp), &add_resp); 29862306a36Sopenharmony_ci if (err || add_resp.hdr.status != expected_status) { 29962306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, 30062306a36Sopenharmony_ci "Failed to create DMA region: %d, 0x%x\n", 30162306a36Sopenharmony_ci err, add_resp.hdr.status); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci if (!err) 30462306a36Sopenharmony_ci err = -EPROTO; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci return err; 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci return 0; 31062306a36Sopenharmony_ci} 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ciint mana_ib_gd_create_dma_region(struct mana_ib_dev *dev, struct ib_umem *umem, 31362306a36Sopenharmony_ci mana_handle_t *gdma_region) 31462306a36Sopenharmony_ci{ 31562306a36Sopenharmony_ci struct gdma_dma_region_add_pages_req *add_req = NULL; 31662306a36Sopenharmony_ci size_t num_pages_processed = 0, num_pages_to_handle; 31762306a36Sopenharmony_ci struct gdma_create_dma_region_req *create_req; 31862306a36Sopenharmony_ci unsigned int create_req_msg_size; 31962306a36Sopenharmony_ci struct hw_channel_context *hwc; 32062306a36Sopenharmony_ci struct ib_block_iter biter; 32162306a36Sopenharmony_ci size_t max_pgs_add_cmd = 0; 32262306a36Sopenharmony_ci size_t max_pgs_create_cmd; 32362306a36Sopenharmony_ci struct gdma_context *gc; 32462306a36Sopenharmony_ci size_t num_pages_total; 32562306a36Sopenharmony_ci struct gdma_dev *mdev; 32662306a36Sopenharmony_ci unsigned long page_sz; 32762306a36Sopenharmony_ci unsigned int tail = 0; 32862306a36Sopenharmony_ci u64 *page_addr_list; 32962306a36Sopenharmony_ci void *request_buf; 33062306a36Sopenharmony_ci int err; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci mdev = dev->gdma_dev; 33362306a36Sopenharmony_ci gc = mdev->gdma_context; 33462306a36Sopenharmony_ci hwc = gc->hwc.driver_data; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci /* Hardware requires dma region to align to chosen page size */ 33762306a36Sopenharmony_ci page_sz = ib_umem_find_best_pgsz(umem, PAGE_SZ_BM, 0); 33862306a36Sopenharmony_ci if (!page_sz) { 33962306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, "failed to find page size.\n"); 34062306a36Sopenharmony_ci return -ENOMEM; 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci num_pages_total = ib_umem_num_dma_blocks(umem, page_sz); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci max_pgs_create_cmd = 34562306a36Sopenharmony_ci (hwc->max_req_msg_size - sizeof(*create_req)) / sizeof(u64); 34662306a36Sopenharmony_ci num_pages_to_handle = 34762306a36Sopenharmony_ci min_t(size_t, num_pages_total, max_pgs_create_cmd); 34862306a36Sopenharmony_ci create_req_msg_size = 34962306a36Sopenharmony_ci struct_size(create_req, page_addr_list, num_pages_to_handle); 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci request_buf = kzalloc(hwc->max_req_msg_size, GFP_KERNEL); 35262306a36Sopenharmony_ci if (!request_buf) 35362306a36Sopenharmony_ci return -ENOMEM; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci create_req = request_buf; 35662306a36Sopenharmony_ci mana_gd_init_req_hdr(&create_req->hdr, GDMA_CREATE_DMA_REGION, 35762306a36Sopenharmony_ci create_req_msg_size, 35862306a36Sopenharmony_ci sizeof(struct gdma_create_dma_region_resp)); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci create_req->length = umem->length; 36162306a36Sopenharmony_ci create_req->offset_in_page = ib_umem_dma_offset(umem, page_sz); 36262306a36Sopenharmony_ci create_req->gdma_page_type = order_base_2(page_sz) - PAGE_SHIFT; 36362306a36Sopenharmony_ci create_req->page_count = num_pages_total; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, "size_dma_region %lu num_pages_total %lu\n", 36662306a36Sopenharmony_ci umem->length, num_pages_total); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, "page_sz %lu offset_in_page %u\n", 36962306a36Sopenharmony_ci page_sz, create_req->offset_in_page); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, "num_pages_to_handle %lu, gdma_page_type %u", 37262306a36Sopenharmony_ci num_pages_to_handle, create_req->gdma_page_type); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci page_addr_list = create_req->page_addr_list; 37562306a36Sopenharmony_ci rdma_umem_for_each_dma_block(umem, &biter, page_sz) { 37662306a36Sopenharmony_ci u32 expected_status = 0; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci page_addr_list[tail++] = rdma_block_iter_dma_address(&biter); 37962306a36Sopenharmony_ci if (tail < num_pages_to_handle) 38062306a36Sopenharmony_ci continue; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci if (num_pages_processed + num_pages_to_handle < 38362306a36Sopenharmony_ci num_pages_total) 38462306a36Sopenharmony_ci expected_status = GDMA_STATUS_MORE_ENTRIES; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci if (!num_pages_processed) { 38762306a36Sopenharmony_ci /* First create message */ 38862306a36Sopenharmony_ci err = mana_ib_gd_first_dma_region(dev, gc, create_req, 38962306a36Sopenharmony_ci tail, gdma_region, 39062306a36Sopenharmony_ci expected_status); 39162306a36Sopenharmony_ci if (err) 39262306a36Sopenharmony_ci goto out; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci max_pgs_add_cmd = (hwc->max_req_msg_size - 39562306a36Sopenharmony_ci sizeof(*add_req)) / sizeof(u64); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci add_req = request_buf; 39862306a36Sopenharmony_ci add_req->dma_region_handle = *gdma_region; 39962306a36Sopenharmony_ci add_req->reserved3 = 0; 40062306a36Sopenharmony_ci page_addr_list = add_req->page_addr_list; 40162306a36Sopenharmony_ci } else { 40262306a36Sopenharmony_ci /* Subsequent create messages */ 40362306a36Sopenharmony_ci err = mana_ib_gd_add_dma_region(dev, gc, add_req, tail, 40462306a36Sopenharmony_ci expected_status); 40562306a36Sopenharmony_ci if (err) 40662306a36Sopenharmony_ci break; 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci num_pages_processed += tail; 41062306a36Sopenharmony_ci tail = 0; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci /* The remaining pages to create */ 41362306a36Sopenharmony_ci num_pages_to_handle = 41462306a36Sopenharmony_ci min_t(size_t, 41562306a36Sopenharmony_ci num_pages_total - num_pages_processed, 41662306a36Sopenharmony_ci max_pgs_add_cmd); 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci if (err) 42062306a36Sopenharmony_ci mana_ib_gd_destroy_dma_region(dev, *gdma_region); 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ciout: 42362306a36Sopenharmony_ci kfree(request_buf); 42462306a36Sopenharmony_ci return err; 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ciint mana_ib_gd_destroy_dma_region(struct mana_ib_dev *dev, u64 gdma_region) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci struct gdma_dev *mdev = dev->gdma_dev; 43062306a36Sopenharmony_ci struct gdma_context *gc; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci gc = mdev->gdma_context; 43362306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, "destroy dma region 0x%llx\n", gdma_region); 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci return mana_gd_destroy_dma_region(gc, gdma_region); 43662306a36Sopenharmony_ci} 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ciint mana_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vma) 43962306a36Sopenharmony_ci{ 44062306a36Sopenharmony_ci struct mana_ib_ucontext *mana_ucontext = 44162306a36Sopenharmony_ci container_of(ibcontext, struct mana_ib_ucontext, ibucontext); 44262306a36Sopenharmony_ci struct ib_device *ibdev = ibcontext->device; 44362306a36Sopenharmony_ci struct mana_ib_dev *mdev; 44462306a36Sopenharmony_ci struct gdma_context *gc; 44562306a36Sopenharmony_ci phys_addr_t pfn; 44662306a36Sopenharmony_ci pgprot_t prot; 44762306a36Sopenharmony_ci int ret; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci mdev = container_of(ibdev, struct mana_ib_dev, ib_dev); 45062306a36Sopenharmony_ci gc = mdev->gdma_dev->gdma_context; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci if (vma->vm_pgoff != 0) { 45362306a36Sopenharmony_ci ibdev_dbg(ibdev, "Unexpected vm_pgoff %lu\n", vma->vm_pgoff); 45462306a36Sopenharmony_ci return -EINVAL; 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci /* Map to the page indexed by ucontext->doorbell */ 45862306a36Sopenharmony_ci pfn = (gc->phys_db_page_base + 45962306a36Sopenharmony_ci gc->db_page_size * mana_ucontext->doorbell) >> 46062306a36Sopenharmony_ci PAGE_SHIFT; 46162306a36Sopenharmony_ci prot = pgprot_writecombine(vma->vm_page_prot); 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci ret = rdma_user_mmap_io(ibcontext, vma, pfn, gc->db_page_size, prot, 46462306a36Sopenharmony_ci NULL); 46562306a36Sopenharmony_ci if (ret) 46662306a36Sopenharmony_ci ibdev_dbg(ibdev, "can't rdma_user_mmap_io ret %d\n", ret); 46762306a36Sopenharmony_ci else 46862306a36Sopenharmony_ci ibdev_dbg(ibdev, "mapped I/O pfn 0x%llx page_size %u, ret %d\n", 46962306a36Sopenharmony_ci pfn, gc->db_page_size, ret); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci return ret; 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ciint mana_ib_get_port_immutable(struct ib_device *ibdev, u32 port_num, 47562306a36Sopenharmony_ci struct ib_port_immutable *immutable) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci /* 47862306a36Sopenharmony_ci * This version only support RAW_PACKET 47962306a36Sopenharmony_ci * other values need to be filled for other types 48062306a36Sopenharmony_ci */ 48162306a36Sopenharmony_ci immutable->core_cap_flags = RDMA_CORE_PORT_RAW_PACKET; 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci return 0; 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ciint mana_ib_query_device(struct ib_device *ibdev, struct ib_device_attr *props, 48762306a36Sopenharmony_ci struct ib_udata *uhw) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci props->max_qp = MANA_MAX_NUM_QUEUES; 49062306a36Sopenharmony_ci props->max_qp_wr = MAX_SEND_BUFFERS_PER_QUEUE; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci /* 49362306a36Sopenharmony_ci * max_cqe could be potentially much bigger. 49462306a36Sopenharmony_ci * As this version of driver only support RAW QP, set it to the same 49562306a36Sopenharmony_ci * value as max_qp_wr 49662306a36Sopenharmony_ci */ 49762306a36Sopenharmony_ci props->max_cqe = MAX_SEND_BUFFERS_PER_QUEUE; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci props->max_mr_size = MANA_IB_MAX_MR_SIZE; 50062306a36Sopenharmony_ci props->max_mr = MANA_IB_MAX_MR; 50162306a36Sopenharmony_ci props->max_send_sge = MAX_TX_WQE_SGL_ENTRIES; 50262306a36Sopenharmony_ci props->max_recv_sge = MAX_RX_WQE_SGL_ENTRIES; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci return 0; 50562306a36Sopenharmony_ci} 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ciint mana_ib_query_port(struct ib_device *ibdev, u32 port, 50862306a36Sopenharmony_ci struct ib_port_attr *props) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci /* This version doesn't return port properties */ 51162306a36Sopenharmony_ci return 0; 51262306a36Sopenharmony_ci} 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ciint mana_ib_query_gid(struct ib_device *ibdev, u32 port, int index, 51562306a36Sopenharmony_ci union ib_gid *gid) 51662306a36Sopenharmony_ci{ 51762306a36Sopenharmony_ci /* This version doesn't return GID properties */ 51862306a36Sopenharmony_ci return 0; 51962306a36Sopenharmony_ci} 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_civoid mana_ib_disassociate_ucontext(struct ib_ucontext *ibcontext) 52262306a36Sopenharmony_ci{ 52362306a36Sopenharmony_ci} 524