1*40909f66SGal Pressman // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2*40909f66SGal Pressman /* 3*40909f66SGal Pressman * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All rights reserved. 4*40909f66SGal Pressman */ 5*40909f66SGal Pressman 6*40909f66SGal Pressman #include <linux/vmalloc.h> 7*40909f66SGal Pressman 8*40909f66SGal Pressman #include <rdma/ib_addr.h> 9*40909f66SGal Pressman #include <rdma/ib_umem.h> 10*40909f66SGal Pressman #include <rdma/ib_user_verbs.h> 11*40909f66SGal Pressman #include <rdma/ib_verbs.h> 12*40909f66SGal Pressman #include <rdma/uverbs_ioctl.h> 13*40909f66SGal Pressman 14*40909f66SGal Pressman #include "efa.h" 15*40909f66SGal Pressman 16*40909f66SGal Pressman #define EFA_MMAP_FLAG_SHIFT 56 17*40909f66SGal Pressman #define EFA_MMAP_PAGE_MASK GENMASK(EFA_MMAP_FLAG_SHIFT - 1, 0) 18*40909f66SGal Pressman #define EFA_MMAP_INVALID U64_MAX 19*40909f66SGal Pressman 20*40909f66SGal Pressman enum { 21*40909f66SGal Pressman EFA_MMAP_DMA_PAGE = 0, 22*40909f66SGal Pressman EFA_MMAP_IO_WC, 23*40909f66SGal Pressman EFA_MMAP_IO_NC, 24*40909f66SGal Pressman }; 25*40909f66SGal Pressman 26*40909f66SGal Pressman #define EFA_AENQ_ENABLED_GROUPS \ 27*40909f66SGal Pressman (BIT(EFA_ADMIN_FATAL_ERROR) | BIT(EFA_ADMIN_WARNING) | \ 28*40909f66SGal Pressman BIT(EFA_ADMIN_NOTIFICATION) | BIT(EFA_ADMIN_KEEP_ALIVE)) 29*40909f66SGal Pressman 30*40909f66SGal Pressman struct efa_mmap_entry { 31*40909f66SGal Pressman void *obj; 32*40909f66SGal Pressman u64 address; 33*40909f66SGal Pressman u64 length; 34*40909f66SGal Pressman u32 mmap_page; 35*40909f66SGal Pressman u8 mmap_flag; 36*40909f66SGal Pressman }; 37*40909f66SGal Pressman 38*40909f66SGal Pressman static inline u64 get_mmap_key(const struct efa_mmap_entry *efa) 39*40909f66SGal Pressman { 40*40909f66SGal Pressman return ((u64)efa->mmap_flag << EFA_MMAP_FLAG_SHIFT) | 41*40909f66SGal Pressman ((u64)efa->mmap_page << PAGE_SHIFT); 42*40909f66SGal Pressman } 43*40909f66SGal Pressman 44*40909f66SGal Pressman #define EFA_CHUNK_PAYLOAD_SHIFT 12 45*40909f66SGal Pressman #define EFA_CHUNK_PAYLOAD_SIZE BIT(EFA_CHUNK_PAYLOAD_SHIFT) 46*40909f66SGal Pressman #define EFA_CHUNK_PAYLOAD_PTR_SIZE 8 47*40909f66SGal Pressman 48*40909f66SGal Pressman #define EFA_CHUNK_SHIFT 12 49*40909f66SGal Pressman #define EFA_CHUNK_SIZE BIT(EFA_CHUNK_SHIFT) 50*40909f66SGal Pressman #define EFA_CHUNK_PTR_SIZE sizeof(struct efa_com_ctrl_buff_info) 51*40909f66SGal Pressman 52*40909f66SGal Pressman #define EFA_PTRS_PER_CHUNK \ 53*40909f66SGal Pressman ((EFA_CHUNK_SIZE - EFA_CHUNK_PTR_SIZE) / EFA_CHUNK_PAYLOAD_PTR_SIZE) 54*40909f66SGal Pressman 55*40909f66SGal Pressman #define EFA_CHUNK_USED_SIZE \ 56*40909f66SGal Pressman ((EFA_PTRS_PER_CHUNK * EFA_CHUNK_PAYLOAD_PTR_SIZE) + EFA_CHUNK_PTR_SIZE) 57*40909f66SGal Pressman 58*40909f66SGal Pressman #define EFA_SUPPORTED_ACCESS_FLAGS IB_ACCESS_LOCAL_WRITE 59*40909f66SGal Pressman 60*40909f66SGal Pressman struct pbl_chunk { 61*40909f66SGal Pressman dma_addr_t dma_addr; 62*40909f66SGal Pressman u64 *buf; 63*40909f66SGal Pressman u32 length; 64*40909f66SGal Pressman }; 65*40909f66SGal Pressman 66*40909f66SGal Pressman struct pbl_chunk_list { 67*40909f66SGal Pressman struct pbl_chunk *chunks; 68*40909f66SGal Pressman unsigned int size; 69*40909f66SGal Pressman }; 70*40909f66SGal Pressman 71*40909f66SGal Pressman struct pbl_context { 72*40909f66SGal Pressman union { 73*40909f66SGal Pressman struct { 74*40909f66SGal Pressman dma_addr_t dma_addr; 75*40909f66SGal Pressman } continuous; 76*40909f66SGal Pressman struct { 77*40909f66SGal Pressman u32 pbl_buf_size_in_pages; 78*40909f66SGal Pressman struct scatterlist *sgl; 79*40909f66SGal Pressman int sg_dma_cnt; 80*40909f66SGal Pressman struct pbl_chunk_list chunk_list; 81*40909f66SGal Pressman } indirect; 82*40909f66SGal Pressman } phys; 83*40909f66SGal Pressman u64 *pbl_buf; 84*40909f66SGal Pressman u32 pbl_buf_size_in_bytes; 85*40909f66SGal Pressman u8 physically_continuous; 86*40909f66SGal Pressman }; 87*40909f66SGal Pressman 88*40909f66SGal Pressman static inline struct efa_dev *to_edev(struct ib_device *ibdev) 89*40909f66SGal Pressman { 90*40909f66SGal Pressman return container_of(ibdev, struct efa_dev, ibdev); 91*40909f66SGal Pressman } 92*40909f66SGal Pressman 93*40909f66SGal Pressman static inline struct efa_ucontext *to_eucontext(struct ib_ucontext *ibucontext) 94*40909f66SGal Pressman { 95*40909f66SGal Pressman return container_of(ibucontext, struct efa_ucontext, ibucontext); 96*40909f66SGal Pressman } 97*40909f66SGal Pressman 98*40909f66SGal Pressman static inline struct efa_pd *to_epd(struct ib_pd *ibpd) 99*40909f66SGal Pressman { 100*40909f66SGal Pressman return container_of(ibpd, struct efa_pd, ibpd); 101*40909f66SGal Pressman } 102*40909f66SGal Pressman 103*40909f66SGal Pressman static inline struct efa_mr *to_emr(struct ib_mr *ibmr) 104*40909f66SGal Pressman { 105*40909f66SGal Pressman return container_of(ibmr, struct efa_mr, ibmr); 106*40909f66SGal Pressman } 107*40909f66SGal Pressman 108*40909f66SGal Pressman static inline struct efa_qp *to_eqp(struct ib_qp *ibqp) 109*40909f66SGal Pressman { 110*40909f66SGal Pressman return container_of(ibqp, struct efa_qp, ibqp); 111*40909f66SGal Pressman } 112*40909f66SGal Pressman 113*40909f66SGal Pressman static inline struct efa_cq *to_ecq(struct ib_cq *ibcq) 114*40909f66SGal Pressman { 115*40909f66SGal Pressman return container_of(ibcq, struct efa_cq, ibcq); 116*40909f66SGal Pressman } 117*40909f66SGal Pressman 118*40909f66SGal Pressman static inline struct efa_ah *to_eah(struct ib_ah *ibah) 119*40909f66SGal Pressman { 120*40909f66SGal Pressman return container_of(ibah, struct efa_ah, ibah); 121*40909f66SGal Pressman } 122*40909f66SGal Pressman 123*40909f66SGal Pressman #define field_avail(x, fld, sz) (offsetof(typeof(x), fld) + \ 124*40909f66SGal Pressman sizeof(((typeof(x) *)0)->fld) <= (sz)) 125*40909f66SGal Pressman 126*40909f66SGal Pressman #define is_reserved_cleared(reserved) \ 127*40909f66SGal Pressman !memchr_inv(reserved, 0, sizeof(reserved)) 128*40909f66SGal Pressman 129*40909f66SGal Pressman static void *efa_zalloc_mapped(struct efa_dev *dev, dma_addr_t *dma_addr, 130*40909f66SGal Pressman size_t size, enum dma_data_direction dir) 131*40909f66SGal Pressman { 132*40909f66SGal Pressman void *addr; 133*40909f66SGal Pressman 134*40909f66SGal Pressman addr = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO); 135*40909f66SGal Pressman if (!addr) 136*40909f66SGal Pressman return NULL; 137*40909f66SGal Pressman 138*40909f66SGal Pressman *dma_addr = dma_map_single(&dev->pdev->dev, addr, size, dir); 139*40909f66SGal Pressman if (dma_mapping_error(&dev->pdev->dev, *dma_addr)) { 140*40909f66SGal Pressman ibdev_err(&dev->ibdev, "Failed to map DMA address\n"); 141*40909f66SGal Pressman free_pages_exact(addr, size); 142*40909f66SGal Pressman return NULL; 143*40909f66SGal Pressman } 144*40909f66SGal Pressman 145*40909f66SGal Pressman return addr; 146*40909f66SGal Pressman } 147*40909f66SGal Pressman 148*40909f66SGal Pressman /* 149*40909f66SGal Pressman * This is only called when the ucontext is destroyed and there can be no 150*40909f66SGal Pressman * concurrent query via mmap or allocate on the xarray, thus we can be sure no 151*40909f66SGal Pressman * other thread is using the entry pointer. We also know that all the BAR 152*40909f66SGal Pressman * pages have either been zap'd or munmaped at this point. Normal pages are 153*40909f66SGal Pressman * refcounted and will be freed at the proper time. 154*40909f66SGal Pressman */ 155*40909f66SGal Pressman static void mmap_entries_remove_free(struct efa_dev *dev, 156*40909f66SGal Pressman struct efa_ucontext *ucontext) 157*40909f66SGal Pressman { 158*40909f66SGal Pressman struct efa_mmap_entry *entry; 159*40909f66SGal Pressman unsigned long mmap_page; 160*40909f66SGal Pressman 161*40909f66SGal Pressman xa_for_each(&ucontext->mmap_xa, mmap_page, entry) { 162*40909f66SGal Pressman xa_erase(&ucontext->mmap_xa, mmap_page); 163*40909f66SGal Pressman 164*40909f66SGal Pressman ibdev_dbg( 165*40909f66SGal Pressman &dev->ibdev, 166*40909f66SGal Pressman "mmap: obj[0x%p] key[%#llx] addr[%#llx] len[%#llx] removed\n", 167*40909f66SGal Pressman entry->obj, get_mmap_key(entry), entry->address, 168*40909f66SGal Pressman entry->length); 169*40909f66SGal Pressman if (entry->mmap_flag == EFA_MMAP_DMA_PAGE) 170*40909f66SGal Pressman /* DMA mapping is already gone, now free the pages */ 171*40909f66SGal Pressman free_pages_exact(phys_to_virt(entry->address), 172*40909f66SGal Pressman entry->length); 173*40909f66SGal Pressman kfree(entry); 174*40909f66SGal Pressman } 175*40909f66SGal Pressman } 176*40909f66SGal Pressman 177*40909f66SGal Pressman static struct efa_mmap_entry *mmap_entry_get(struct efa_dev *dev, 178*40909f66SGal Pressman struct efa_ucontext *ucontext, 179*40909f66SGal Pressman u64 key, u64 len) 180*40909f66SGal Pressman { 181*40909f66SGal Pressman struct efa_mmap_entry *entry; 182*40909f66SGal Pressman u64 mmap_page; 183*40909f66SGal Pressman 184*40909f66SGal Pressman mmap_page = (key & EFA_MMAP_PAGE_MASK) >> PAGE_SHIFT; 185*40909f66SGal Pressman if (mmap_page > U32_MAX) 186*40909f66SGal Pressman return NULL; 187*40909f66SGal Pressman 188*40909f66SGal Pressman entry = xa_load(&ucontext->mmap_xa, mmap_page); 189*40909f66SGal Pressman if (!entry || get_mmap_key(entry) != key || entry->length != len) 190*40909f66SGal Pressman return NULL; 191*40909f66SGal Pressman 192*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 193*40909f66SGal Pressman "mmap: obj[0x%p] key[%#llx] addr[%#llx] len[%#llx] removed\n", 194*40909f66SGal Pressman entry->obj, key, entry->address, entry->length); 195*40909f66SGal Pressman 196*40909f66SGal Pressman return entry; 197*40909f66SGal Pressman } 198*40909f66SGal Pressman 199*40909f66SGal Pressman /* 200*40909f66SGal Pressman * Note this locking scheme cannot support removal of entries, except during 201*40909f66SGal Pressman * ucontext destruction when the core code guarentees no concurrency. 202*40909f66SGal Pressman */ 203*40909f66SGal Pressman static u64 mmap_entry_insert(struct efa_dev *dev, struct efa_ucontext *ucontext, 204*40909f66SGal Pressman void *obj, u64 address, u64 length, u8 mmap_flag) 205*40909f66SGal Pressman { 206*40909f66SGal Pressman struct efa_mmap_entry *entry; 207*40909f66SGal Pressman int err; 208*40909f66SGal Pressman 209*40909f66SGal Pressman entry = kmalloc(sizeof(*entry), GFP_KERNEL); 210*40909f66SGal Pressman if (!entry) 211*40909f66SGal Pressman return EFA_MMAP_INVALID; 212*40909f66SGal Pressman 213*40909f66SGal Pressman entry->obj = obj; 214*40909f66SGal Pressman entry->address = address; 215*40909f66SGal Pressman entry->length = length; 216*40909f66SGal Pressman entry->mmap_flag = mmap_flag; 217*40909f66SGal Pressman 218*40909f66SGal Pressman xa_lock(&ucontext->mmap_xa); 219*40909f66SGal Pressman entry->mmap_page = ucontext->mmap_xa_page; 220*40909f66SGal Pressman ucontext->mmap_xa_page += DIV_ROUND_UP(length, PAGE_SIZE); 221*40909f66SGal Pressman err = __xa_insert(&ucontext->mmap_xa, entry->mmap_page, entry, 222*40909f66SGal Pressman GFP_KERNEL); 223*40909f66SGal Pressman xa_unlock(&ucontext->mmap_xa); 224*40909f66SGal Pressman if (err){ 225*40909f66SGal Pressman kfree(entry); 226*40909f66SGal Pressman return EFA_MMAP_INVALID; 227*40909f66SGal Pressman } 228*40909f66SGal Pressman 229*40909f66SGal Pressman ibdev_dbg( 230*40909f66SGal Pressman &dev->ibdev, 231*40909f66SGal Pressman "mmap: obj[0x%p] addr[%#llx], len[%#llx], key[%#llx] inserted\n", 232*40909f66SGal Pressman entry->obj, entry->address, entry->length, get_mmap_key(entry)); 233*40909f66SGal Pressman 234*40909f66SGal Pressman return get_mmap_key(entry); 235*40909f66SGal Pressman } 236*40909f66SGal Pressman 237*40909f66SGal Pressman int efa_query_device(struct ib_device *ibdev, 238*40909f66SGal Pressman struct ib_device_attr *props, 239*40909f66SGal Pressman struct ib_udata *udata) 240*40909f66SGal Pressman { 241*40909f66SGal Pressman struct efa_com_get_device_attr_result *dev_attr; 242*40909f66SGal Pressman struct efa_ibv_ex_query_device_resp resp = {}; 243*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibdev); 244*40909f66SGal Pressman int err; 245*40909f66SGal Pressman 246*40909f66SGal Pressman if (udata && udata->inlen && 247*40909f66SGal Pressman !ib_is_udata_cleared(udata, 0, udata->inlen)) { 248*40909f66SGal Pressman ibdev_dbg(ibdev, 249*40909f66SGal Pressman "Incompatible ABI params, udata not cleared\n"); 250*40909f66SGal Pressman return -EINVAL; 251*40909f66SGal Pressman } 252*40909f66SGal Pressman 253*40909f66SGal Pressman dev_attr = &dev->dev_attr; 254*40909f66SGal Pressman 255*40909f66SGal Pressman memset(props, 0, sizeof(*props)); 256*40909f66SGal Pressman props->max_mr_size = dev_attr->max_mr_pages * PAGE_SIZE; 257*40909f66SGal Pressman props->page_size_cap = dev_attr->page_size_cap; 258*40909f66SGal Pressman props->vendor_id = dev->pdev->vendor; 259*40909f66SGal Pressman props->vendor_part_id = dev->pdev->device; 260*40909f66SGal Pressman props->hw_ver = dev->pdev->subsystem_device; 261*40909f66SGal Pressman props->max_qp = dev_attr->max_qp; 262*40909f66SGal Pressman props->max_cq = dev_attr->max_cq; 263*40909f66SGal Pressman props->max_pd = dev_attr->max_pd; 264*40909f66SGal Pressman props->max_mr = dev_attr->max_mr; 265*40909f66SGal Pressman props->max_ah = dev_attr->max_ah; 266*40909f66SGal Pressman props->max_cqe = dev_attr->max_cq_depth; 267*40909f66SGal Pressman props->max_qp_wr = min_t(u32, dev_attr->max_sq_depth, 268*40909f66SGal Pressman dev_attr->max_rq_depth); 269*40909f66SGal Pressman props->max_send_sge = dev_attr->max_sq_sge; 270*40909f66SGal Pressman props->max_recv_sge = dev_attr->max_rq_sge; 271*40909f66SGal Pressman 272*40909f66SGal Pressman if (udata && udata->outlen) { 273*40909f66SGal Pressman resp.max_sq_sge = dev_attr->max_sq_sge; 274*40909f66SGal Pressman resp.max_rq_sge = dev_attr->max_rq_sge; 275*40909f66SGal Pressman resp.max_sq_wr = dev_attr->max_sq_depth; 276*40909f66SGal Pressman resp.max_rq_wr = dev_attr->max_rq_depth; 277*40909f66SGal Pressman 278*40909f66SGal Pressman err = ib_copy_to_udata(udata, &resp, 279*40909f66SGal Pressman min(sizeof(resp), udata->outlen)); 280*40909f66SGal Pressman if (err) { 281*40909f66SGal Pressman ibdev_dbg(ibdev, 282*40909f66SGal Pressman "Failed to copy udata for query_device\n"); 283*40909f66SGal Pressman return err; 284*40909f66SGal Pressman } 285*40909f66SGal Pressman } 286*40909f66SGal Pressman 287*40909f66SGal Pressman return 0; 288*40909f66SGal Pressman } 289*40909f66SGal Pressman 290*40909f66SGal Pressman int efa_query_port(struct ib_device *ibdev, u8 port, 291*40909f66SGal Pressman struct ib_port_attr *props) 292*40909f66SGal Pressman { 293*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibdev); 294*40909f66SGal Pressman 295*40909f66SGal Pressman props->lmc = 1; 296*40909f66SGal Pressman 297*40909f66SGal Pressman props->state = IB_PORT_ACTIVE; 298*40909f66SGal Pressman props->phys_state = 5; 299*40909f66SGal Pressman props->gid_tbl_len = 1; 300*40909f66SGal Pressman props->pkey_tbl_len = 1; 301*40909f66SGal Pressman props->active_speed = IB_SPEED_EDR; 302*40909f66SGal Pressman props->active_width = IB_WIDTH_4X; 303*40909f66SGal Pressman props->max_mtu = ib_mtu_int_to_enum(dev->mtu); 304*40909f66SGal Pressman props->active_mtu = ib_mtu_int_to_enum(dev->mtu); 305*40909f66SGal Pressman props->max_msg_sz = dev->mtu; 306*40909f66SGal Pressman props->max_vl_num = 1; 307*40909f66SGal Pressman 308*40909f66SGal Pressman return 0; 309*40909f66SGal Pressman } 310*40909f66SGal Pressman 311*40909f66SGal Pressman int efa_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, 312*40909f66SGal Pressman int qp_attr_mask, 313*40909f66SGal Pressman struct ib_qp_init_attr *qp_init_attr) 314*40909f66SGal Pressman { 315*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibqp->device); 316*40909f66SGal Pressman struct efa_com_query_qp_params params = {}; 317*40909f66SGal Pressman struct efa_com_query_qp_result result; 318*40909f66SGal Pressman struct efa_qp *qp = to_eqp(ibqp); 319*40909f66SGal Pressman int err; 320*40909f66SGal Pressman 321*40909f66SGal Pressman #define EFA_QUERY_QP_SUPP_MASK \ 322*40909f66SGal Pressman (IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT | \ 323*40909f66SGal Pressman IB_QP_QKEY | IB_QP_SQ_PSN | IB_QP_CAP) 324*40909f66SGal Pressman 325*40909f66SGal Pressman if (qp_attr_mask & ~EFA_QUERY_QP_SUPP_MASK) { 326*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 327*40909f66SGal Pressman "Unsupported qp_attr_mask[%#x] supported[%#x]\n", 328*40909f66SGal Pressman qp_attr_mask, EFA_QUERY_QP_SUPP_MASK); 329*40909f66SGal Pressman return -EOPNOTSUPP; 330*40909f66SGal Pressman } 331*40909f66SGal Pressman 332*40909f66SGal Pressman memset(qp_attr, 0, sizeof(*qp_attr)); 333*40909f66SGal Pressman memset(qp_init_attr, 0, sizeof(*qp_init_attr)); 334*40909f66SGal Pressman 335*40909f66SGal Pressman params.qp_handle = qp->qp_handle; 336*40909f66SGal Pressman err = efa_com_query_qp(&dev->edev, ¶ms, &result); 337*40909f66SGal Pressman if (err) 338*40909f66SGal Pressman return err; 339*40909f66SGal Pressman 340*40909f66SGal Pressman qp_attr->qp_state = result.qp_state; 341*40909f66SGal Pressman qp_attr->qkey = result.qkey; 342*40909f66SGal Pressman qp_attr->sq_psn = result.sq_psn; 343*40909f66SGal Pressman qp_attr->sq_draining = result.sq_draining; 344*40909f66SGal Pressman qp_attr->port_num = 1; 345*40909f66SGal Pressman 346*40909f66SGal Pressman qp_attr->cap.max_send_wr = qp->max_send_wr; 347*40909f66SGal Pressman qp_attr->cap.max_recv_wr = qp->max_recv_wr; 348*40909f66SGal Pressman qp_attr->cap.max_send_sge = qp->max_send_sge; 349*40909f66SGal Pressman qp_attr->cap.max_recv_sge = qp->max_recv_sge; 350*40909f66SGal Pressman qp_attr->cap.max_inline_data = qp->max_inline_data; 351*40909f66SGal Pressman 352*40909f66SGal Pressman qp_init_attr->qp_type = ibqp->qp_type; 353*40909f66SGal Pressman qp_init_attr->recv_cq = ibqp->recv_cq; 354*40909f66SGal Pressman qp_init_attr->send_cq = ibqp->send_cq; 355*40909f66SGal Pressman qp_init_attr->qp_context = ibqp->qp_context; 356*40909f66SGal Pressman qp_init_attr->cap = qp_attr->cap; 357*40909f66SGal Pressman 358*40909f66SGal Pressman return 0; 359*40909f66SGal Pressman } 360*40909f66SGal Pressman 361*40909f66SGal Pressman int efa_query_gid(struct ib_device *ibdev, u8 port, int index, 362*40909f66SGal Pressman union ib_gid *gid) 363*40909f66SGal Pressman { 364*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibdev); 365*40909f66SGal Pressman 366*40909f66SGal Pressman memcpy(gid->raw, dev->addr, sizeof(dev->addr)); 367*40909f66SGal Pressman 368*40909f66SGal Pressman return 0; 369*40909f66SGal Pressman } 370*40909f66SGal Pressman 371*40909f66SGal Pressman int efa_query_pkey(struct ib_device *ibdev, u8 port, u16 index, 372*40909f66SGal Pressman u16 *pkey) 373*40909f66SGal Pressman { 374*40909f66SGal Pressman if (index > 0) 375*40909f66SGal Pressman return -EINVAL; 376*40909f66SGal Pressman 377*40909f66SGal Pressman *pkey = 0xffff; 378*40909f66SGal Pressman return 0; 379*40909f66SGal Pressman } 380*40909f66SGal Pressman 381*40909f66SGal Pressman static int efa_pd_dealloc(struct efa_dev *dev, u16 pdn) 382*40909f66SGal Pressman { 383*40909f66SGal Pressman struct efa_com_dealloc_pd_params params = { 384*40909f66SGal Pressman .pdn = pdn, 385*40909f66SGal Pressman }; 386*40909f66SGal Pressman 387*40909f66SGal Pressman return efa_com_dealloc_pd(&dev->edev, ¶ms); 388*40909f66SGal Pressman } 389*40909f66SGal Pressman 390*40909f66SGal Pressman int efa_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata) 391*40909f66SGal Pressman { 392*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibpd->device); 393*40909f66SGal Pressman struct efa_ibv_alloc_pd_resp resp = {}; 394*40909f66SGal Pressman struct efa_com_alloc_pd_result result; 395*40909f66SGal Pressman struct efa_pd *pd = to_epd(ibpd); 396*40909f66SGal Pressman int err; 397*40909f66SGal Pressman 398*40909f66SGal Pressman if (udata->inlen && 399*40909f66SGal Pressman !ib_is_udata_cleared(udata, 0, udata->inlen)) { 400*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 401*40909f66SGal Pressman "Incompatible ABI params, udata not cleared\n"); 402*40909f66SGal Pressman err = -EINVAL; 403*40909f66SGal Pressman goto err_out; 404*40909f66SGal Pressman } 405*40909f66SGal Pressman 406*40909f66SGal Pressman err = efa_com_alloc_pd(&dev->edev, &result); 407*40909f66SGal Pressman if (err) 408*40909f66SGal Pressman goto err_out; 409*40909f66SGal Pressman 410*40909f66SGal Pressman pd->pdn = result.pdn; 411*40909f66SGal Pressman resp.pdn = result.pdn; 412*40909f66SGal Pressman 413*40909f66SGal Pressman if (udata->outlen) { 414*40909f66SGal Pressman err = ib_copy_to_udata(udata, &resp, 415*40909f66SGal Pressman min(sizeof(resp), udata->outlen)); 416*40909f66SGal Pressman if (err) { 417*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 418*40909f66SGal Pressman "Failed to copy udata for alloc_pd\n"); 419*40909f66SGal Pressman goto err_dealloc_pd; 420*40909f66SGal Pressman } 421*40909f66SGal Pressman } 422*40909f66SGal Pressman 423*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Allocated pd[%d]\n", pd->pdn); 424*40909f66SGal Pressman 425*40909f66SGal Pressman return 0; 426*40909f66SGal Pressman 427*40909f66SGal Pressman err_dealloc_pd: 428*40909f66SGal Pressman efa_pd_dealloc(dev, result.pdn); 429*40909f66SGal Pressman err_out: 430*40909f66SGal Pressman atomic64_inc(&dev->stats.sw_stats.alloc_pd_err); 431*40909f66SGal Pressman return err; 432*40909f66SGal Pressman } 433*40909f66SGal Pressman 434*40909f66SGal Pressman void efa_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata) 435*40909f66SGal Pressman { 436*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibpd->device); 437*40909f66SGal Pressman struct efa_pd *pd = to_epd(ibpd); 438*40909f66SGal Pressman 439*40909f66SGal Pressman if (udata->inlen && 440*40909f66SGal Pressman !ib_is_udata_cleared(udata, 0, udata->inlen)) { 441*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Incompatible ABI params\n"); 442*40909f66SGal Pressman return; 443*40909f66SGal Pressman } 444*40909f66SGal Pressman 445*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Dealloc pd[%d]\n", pd->pdn); 446*40909f66SGal Pressman efa_pd_dealloc(dev, pd->pdn); 447*40909f66SGal Pressman } 448*40909f66SGal Pressman 449*40909f66SGal Pressman static int efa_destroy_qp_handle(struct efa_dev *dev, u32 qp_handle) 450*40909f66SGal Pressman { 451*40909f66SGal Pressman struct efa_com_destroy_qp_params params = { .qp_handle = qp_handle }; 452*40909f66SGal Pressman 453*40909f66SGal Pressman return efa_com_destroy_qp(&dev->edev, ¶ms); 454*40909f66SGal Pressman } 455*40909f66SGal Pressman 456*40909f66SGal Pressman int efa_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata) 457*40909f66SGal Pressman { 458*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibqp->pd->device); 459*40909f66SGal Pressman struct efa_qp *qp = to_eqp(ibqp); 460*40909f66SGal Pressman int err; 461*40909f66SGal Pressman 462*40909f66SGal Pressman if (udata->inlen && 463*40909f66SGal Pressman !ib_is_udata_cleared(udata, 0, udata->inlen)) { 464*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Incompatible ABI params\n"); 465*40909f66SGal Pressman return -EINVAL; 466*40909f66SGal Pressman } 467*40909f66SGal Pressman 468*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Destroy qp[%u]\n", ibqp->qp_num); 469*40909f66SGal Pressman err = efa_destroy_qp_handle(dev, qp->qp_handle); 470*40909f66SGal Pressman if (err) 471*40909f66SGal Pressman return err; 472*40909f66SGal Pressman 473*40909f66SGal Pressman if (qp->rq_cpu_addr) { 474*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 475*40909f66SGal Pressman "qp->cpu_addr[0x%p] freed: size[%lu], dma[%pad]\n", 476*40909f66SGal Pressman qp->rq_cpu_addr, qp->rq_size, 477*40909f66SGal Pressman &qp->rq_dma_addr); 478*40909f66SGal Pressman dma_unmap_single(&dev->pdev->dev, qp->rq_dma_addr, qp->rq_size, 479*40909f66SGal Pressman DMA_TO_DEVICE); 480*40909f66SGal Pressman } 481*40909f66SGal Pressman 482*40909f66SGal Pressman kfree(qp); 483*40909f66SGal Pressman return 0; 484*40909f66SGal Pressman } 485*40909f66SGal Pressman 486*40909f66SGal Pressman static int qp_mmap_entries_setup(struct efa_qp *qp, 487*40909f66SGal Pressman struct efa_dev *dev, 488*40909f66SGal Pressman struct efa_ucontext *ucontext, 489*40909f66SGal Pressman struct efa_com_create_qp_params *params, 490*40909f66SGal Pressman struct efa_ibv_create_qp_resp *resp) 491*40909f66SGal Pressman { 492*40909f66SGal Pressman /* 493*40909f66SGal Pressman * Once an entry is inserted it might be mmapped, hence cannot be 494*40909f66SGal Pressman * cleaned up until dealloc_ucontext. 495*40909f66SGal Pressman */ 496*40909f66SGal Pressman resp->sq_db_mmap_key = 497*40909f66SGal Pressman mmap_entry_insert(dev, ucontext, qp, 498*40909f66SGal Pressman dev->db_bar_addr + resp->sq_db_offset, 499*40909f66SGal Pressman PAGE_SIZE, EFA_MMAP_IO_NC); 500*40909f66SGal Pressman if (resp->sq_db_mmap_key == EFA_MMAP_INVALID) 501*40909f66SGal Pressman return -ENOMEM; 502*40909f66SGal Pressman 503*40909f66SGal Pressman resp->sq_db_offset &= ~PAGE_MASK; 504*40909f66SGal Pressman 505*40909f66SGal Pressman resp->llq_desc_mmap_key = 506*40909f66SGal Pressman mmap_entry_insert(dev, ucontext, qp, 507*40909f66SGal Pressman dev->mem_bar_addr + resp->llq_desc_offset, 508*40909f66SGal Pressman PAGE_ALIGN(params->sq_ring_size_in_bytes + 509*40909f66SGal Pressman (resp->llq_desc_offset & ~PAGE_MASK)), 510*40909f66SGal Pressman EFA_MMAP_IO_WC); 511*40909f66SGal Pressman if (resp->llq_desc_mmap_key == EFA_MMAP_INVALID) 512*40909f66SGal Pressman return -ENOMEM; 513*40909f66SGal Pressman 514*40909f66SGal Pressman resp->llq_desc_offset &= ~PAGE_MASK; 515*40909f66SGal Pressman 516*40909f66SGal Pressman if (qp->rq_size) { 517*40909f66SGal Pressman resp->rq_db_mmap_key = 518*40909f66SGal Pressman mmap_entry_insert(dev, ucontext, qp, 519*40909f66SGal Pressman dev->db_bar_addr + resp->rq_db_offset, 520*40909f66SGal Pressman PAGE_SIZE, EFA_MMAP_IO_NC); 521*40909f66SGal Pressman if (resp->rq_db_mmap_key == EFA_MMAP_INVALID) 522*40909f66SGal Pressman return -ENOMEM; 523*40909f66SGal Pressman 524*40909f66SGal Pressman resp->rq_db_offset &= ~PAGE_MASK; 525*40909f66SGal Pressman 526*40909f66SGal Pressman resp->rq_mmap_key = 527*40909f66SGal Pressman mmap_entry_insert(dev, ucontext, qp, 528*40909f66SGal Pressman virt_to_phys(qp->rq_cpu_addr), 529*40909f66SGal Pressman qp->rq_size, EFA_MMAP_DMA_PAGE); 530*40909f66SGal Pressman if (resp->rq_mmap_key == EFA_MMAP_INVALID) 531*40909f66SGal Pressman return -ENOMEM; 532*40909f66SGal Pressman 533*40909f66SGal Pressman resp->rq_mmap_size = qp->rq_size; 534*40909f66SGal Pressman } 535*40909f66SGal Pressman 536*40909f66SGal Pressman return 0; 537*40909f66SGal Pressman } 538*40909f66SGal Pressman 539*40909f66SGal Pressman static int efa_qp_validate_cap(struct efa_dev *dev, 540*40909f66SGal Pressman struct ib_qp_init_attr *init_attr) 541*40909f66SGal Pressman { 542*40909f66SGal Pressman if (init_attr->cap.max_send_wr > dev->dev_attr.max_sq_depth) { 543*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 544*40909f66SGal Pressman "qp: requested send wr[%u] exceeds the max[%u]\n", 545*40909f66SGal Pressman init_attr->cap.max_send_wr, 546*40909f66SGal Pressman dev->dev_attr.max_sq_depth); 547*40909f66SGal Pressman return -EINVAL; 548*40909f66SGal Pressman } 549*40909f66SGal Pressman if (init_attr->cap.max_recv_wr > dev->dev_attr.max_rq_depth) { 550*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 551*40909f66SGal Pressman "qp: requested receive wr[%u] exceeds the max[%u]\n", 552*40909f66SGal Pressman init_attr->cap.max_recv_wr, 553*40909f66SGal Pressman dev->dev_attr.max_rq_depth); 554*40909f66SGal Pressman return -EINVAL; 555*40909f66SGal Pressman } 556*40909f66SGal Pressman if (init_attr->cap.max_send_sge > dev->dev_attr.max_sq_sge) { 557*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 558*40909f66SGal Pressman "qp: requested sge send[%u] exceeds the max[%u]\n", 559*40909f66SGal Pressman init_attr->cap.max_send_sge, dev->dev_attr.max_sq_sge); 560*40909f66SGal Pressman return -EINVAL; 561*40909f66SGal Pressman } 562*40909f66SGal Pressman if (init_attr->cap.max_recv_sge > dev->dev_attr.max_rq_sge) { 563*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 564*40909f66SGal Pressman "qp: requested sge recv[%u] exceeds the max[%u]\n", 565*40909f66SGal Pressman init_attr->cap.max_recv_sge, dev->dev_attr.max_rq_sge); 566*40909f66SGal Pressman return -EINVAL; 567*40909f66SGal Pressman } 568*40909f66SGal Pressman if (init_attr->cap.max_inline_data > dev->dev_attr.inline_buf_size) { 569*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 570*40909f66SGal Pressman "qp: requested inline data[%u] exceeds the max[%u]\n", 571*40909f66SGal Pressman init_attr->cap.max_inline_data, 572*40909f66SGal Pressman dev->dev_attr.inline_buf_size); 573*40909f66SGal Pressman return -EINVAL; 574*40909f66SGal Pressman } 575*40909f66SGal Pressman 576*40909f66SGal Pressman return 0; 577*40909f66SGal Pressman } 578*40909f66SGal Pressman 579*40909f66SGal Pressman static int efa_qp_validate_attr(struct efa_dev *dev, 580*40909f66SGal Pressman struct ib_qp_init_attr *init_attr) 581*40909f66SGal Pressman { 582*40909f66SGal Pressman if (init_attr->qp_type != IB_QPT_DRIVER && 583*40909f66SGal Pressman init_attr->qp_type != IB_QPT_UD) { 584*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 585*40909f66SGal Pressman "Unsupported qp type %d\n", init_attr->qp_type); 586*40909f66SGal Pressman return -EOPNOTSUPP; 587*40909f66SGal Pressman } 588*40909f66SGal Pressman 589*40909f66SGal Pressman if (init_attr->srq) { 590*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "SRQ is not supported\n"); 591*40909f66SGal Pressman return -EOPNOTSUPP; 592*40909f66SGal Pressman } 593*40909f66SGal Pressman 594*40909f66SGal Pressman if (init_attr->create_flags) { 595*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Unsupported create flags\n"); 596*40909f66SGal Pressman return -EOPNOTSUPP; 597*40909f66SGal Pressman } 598*40909f66SGal Pressman 599*40909f66SGal Pressman return 0; 600*40909f66SGal Pressman } 601*40909f66SGal Pressman 602*40909f66SGal Pressman struct ib_qp *efa_create_qp(struct ib_pd *ibpd, 603*40909f66SGal Pressman struct ib_qp_init_attr *init_attr, 604*40909f66SGal Pressman struct ib_udata *udata) 605*40909f66SGal Pressman { 606*40909f66SGal Pressman struct efa_com_create_qp_params create_qp_params = {}; 607*40909f66SGal Pressman struct efa_com_create_qp_result create_qp_resp; 608*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibpd->device); 609*40909f66SGal Pressman struct efa_ibv_create_qp_resp resp = {}; 610*40909f66SGal Pressman struct efa_ibv_create_qp cmd = {}; 611*40909f66SGal Pressman bool rq_entry_inserted = false; 612*40909f66SGal Pressman struct efa_ucontext *ucontext; 613*40909f66SGal Pressman struct efa_qp *qp; 614*40909f66SGal Pressman int err; 615*40909f66SGal Pressman 616*40909f66SGal Pressman ucontext = rdma_udata_to_drv_context(udata, struct efa_ucontext, 617*40909f66SGal Pressman ibucontext); 618*40909f66SGal Pressman 619*40909f66SGal Pressman err = efa_qp_validate_cap(dev, init_attr); 620*40909f66SGal Pressman if (err) 621*40909f66SGal Pressman goto err_out; 622*40909f66SGal Pressman 623*40909f66SGal Pressman err = efa_qp_validate_attr(dev, init_attr); 624*40909f66SGal Pressman if (err) 625*40909f66SGal Pressman goto err_out; 626*40909f66SGal Pressman 627*40909f66SGal Pressman if (!field_avail(cmd, driver_qp_type, udata->inlen)) { 628*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 629*40909f66SGal Pressman "Incompatible ABI params, no input udata\n"); 630*40909f66SGal Pressman err = -EINVAL; 631*40909f66SGal Pressman goto err_out; 632*40909f66SGal Pressman } 633*40909f66SGal Pressman 634*40909f66SGal Pressman if (udata->inlen > sizeof(cmd) && 635*40909f66SGal Pressman !ib_is_udata_cleared(udata, sizeof(cmd), 636*40909f66SGal Pressman udata->inlen - sizeof(cmd))) { 637*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 638*40909f66SGal Pressman "Incompatible ABI params, unknown fields in udata\n"); 639*40909f66SGal Pressman err = -EINVAL; 640*40909f66SGal Pressman goto err_out; 641*40909f66SGal Pressman } 642*40909f66SGal Pressman 643*40909f66SGal Pressman err = ib_copy_from_udata(&cmd, udata, 644*40909f66SGal Pressman min(sizeof(cmd), udata->inlen)); 645*40909f66SGal Pressman if (err) { 646*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 647*40909f66SGal Pressman "Cannot copy udata for create_qp\n"); 648*40909f66SGal Pressman goto err_out; 649*40909f66SGal Pressman } 650*40909f66SGal Pressman 651*40909f66SGal Pressman if (cmd.comp_mask) { 652*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 653*40909f66SGal Pressman "Incompatible ABI params, unknown fields in udata\n"); 654*40909f66SGal Pressman err = -EINVAL; 655*40909f66SGal Pressman goto err_out; 656*40909f66SGal Pressman } 657*40909f66SGal Pressman 658*40909f66SGal Pressman qp = kzalloc(sizeof(*qp), GFP_KERNEL); 659*40909f66SGal Pressman if (!qp) { 660*40909f66SGal Pressman err = -ENOMEM; 661*40909f66SGal Pressman goto err_out; 662*40909f66SGal Pressman } 663*40909f66SGal Pressman 664*40909f66SGal Pressman create_qp_params.uarn = ucontext->uarn; 665*40909f66SGal Pressman create_qp_params.pd = to_epd(ibpd)->pdn; 666*40909f66SGal Pressman 667*40909f66SGal Pressman if (init_attr->qp_type == IB_QPT_UD) { 668*40909f66SGal Pressman create_qp_params.qp_type = EFA_ADMIN_QP_TYPE_UD; 669*40909f66SGal Pressman } else if (cmd.driver_qp_type == EFA_QP_DRIVER_TYPE_SRD) { 670*40909f66SGal Pressman create_qp_params.qp_type = EFA_ADMIN_QP_TYPE_SRD; 671*40909f66SGal Pressman } else { 672*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 673*40909f66SGal Pressman "Unsupported qp type %d driver qp type %d\n", 674*40909f66SGal Pressman init_attr->qp_type, cmd.driver_qp_type); 675*40909f66SGal Pressman err = -EOPNOTSUPP; 676*40909f66SGal Pressman goto err_free_qp; 677*40909f66SGal Pressman } 678*40909f66SGal Pressman 679*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Create QP: qp type %d driver qp type %#x\n", 680*40909f66SGal Pressman init_attr->qp_type, cmd.driver_qp_type); 681*40909f66SGal Pressman create_qp_params.send_cq_idx = to_ecq(init_attr->send_cq)->cq_idx; 682*40909f66SGal Pressman create_qp_params.recv_cq_idx = to_ecq(init_attr->recv_cq)->cq_idx; 683*40909f66SGal Pressman create_qp_params.sq_depth = init_attr->cap.max_send_wr; 684*40909f66SGal Pressman create_qp_params.sq_ring_size_in_bytes = cmd.sq_ring_size; 685*40909f66SGal Pressman 686*40909f66SGal Pressman create_qp_params.rq_depth = init_attr->cap.max_recv_wr; 687*40909f66SGal Pressman create_qp_params.rq_ring_size_in_bytes = cmd.rq_ring_size; 688*40909f66SGal Pressman qp->rq_size = PAGE_ALIGN(create_qp_params.rq_ring_size_in_bytes); 689*40909f66SGal Pressman if (qp->rq_size) { 690*40909f66SGal Pressman qp->rq_cpu_addr = efa_zalloc_mapped(dev, &qp->rq_dma_addr, 691*40909f66SGal Pressman qp->rq_size, DMA_TO_DEVICE); 692*40909f66SGal Pressman if (!qp->rq_cpu_addr) { 693*40909f66SGal Pressman err = -ENOMEM; 694*40909f66SGal Pressman goto err_free_qp; 695*40909f66SGal Pressman } 696*40909f66SGal Pressman 697*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 698*40909f66SGal Pressman "qp->cpu_addr[0x%p] allocated: size[%lu], dma[%pad]\n", 699*40909f66SGal Pressman qp->rq_cpu_addr, qp->rq_size, &qp->rq_dma_addr); 700*40909f66SGal Pressman create_qp_params.rq_base_addr = qp->rq_dma_addr; 701*40909f66SGal Pressman } 702*40909f66SGal Pressman 703*40909f66SGal Pressman err = efa_com_create_qp(&dev->edev, &create_qp_params, 704*40909f66SGal Pressman &create_qp_resp); 705*40909f66SGal Pressman if (err) 706*40909f66SGal Pressman goto err_free_mapped; 707*40909f66SGal Pressman 708*40909f66SGal Pressman resp.sq_db_offset = create_qp_resp.sq_db_offset; 709*40909f66SGal Pressman resp.rq_db_offset = create_qp_resp.rq_db_offset; 710*40909f66SGal Pressman resp.llq_desc_offset = create_qp_resp.llq_descriptors_offset; 711*40909f66SGal Pressman resp.send_sub_cq_idx = create_qp_resp.send_sub_cq_idx; 712*40909f66SGal Pressman resp.recv_sub_cq_idx = create_qp_resp.recv_sub_cq_idx; 713*40909f66SGal Pressman 714*40909f66SGal Pressman err = qp_mmap_entries_setup(qp, dev, ucontext, &create_qp_params, 715*40909f66SGal Pressman &resp); 716*40909f66SGal Pressman if (err) 717*40909f66SGal Pressman goto err_destroy_qp; 718*40909f66SGal Pressman 719*40909f66SGal Pressman rq_entry_inserted = true; 720*40909f66SGal Pressman qp->qp_handle = create_qp_resp.qp_handle; 721*40909f66SGal Pressman qp->ibqp.qp_num = create_qp_resp.qp_num; 722*40909f66SGal Pressman qp->ibqp.qp_type = init_attr->qp_type; 723*40909f66SGal Pressman qp->max_send_wr = init_attr->cap.max_send_wr; 724*40909f66SGal Pressman qp->max_recv_wr = init_attr->cap.max_recv_wr; 725*40909f66SGal Pressman qp->max_send_sge = init_attr->cap.max_send_sge; 726*40909f66SGal Pressman qp->max_recv_sge = init_attr->cap.max_recv_sge; 727*40909f66SGal Pressman qp->max_inline_data = init_attr->cap.max_inline_data; 728*40909f66SGal Pressman 729*40909f66SGal Pressman if (udata->outlen) { 730*40909f66SGal Pressman err = ib_copy_to_udata(udata, &resp, 731*40909f66SGal Pressman min(sizeof(resp), udata->outlen)); 732*40909f66SGal Pressman if (err) { 733*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 734*40909f66SGal Pressman "Failed to copy udata for qp[%u]\n", 735*40909f66SGal Pressman create_qp_resp.qp_num); 736*40909f66SGal Pressman goto err_destroy_qp; 737*40909f66SGal Pressman } 738*40909f66SGal Pressman } 739*40909f66SGal Pressman 740*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Created qp[%d]\n", qp->ibqp.qp_num); 741*40909f66SGal Pressman 742*40909f66SGal Pressman return &qp->ibqp; 743*40909f66SGal Pressman 744*40909f66SGal Pressman err_destroy_qp: 745*40909f66SGal Pressman efa_destroy_qp_handle(dev, create_qp_resp.qp_handle); 746*40909f66SGal Pressman err_free_mapped: 747*40909f66SGal Pressman if (qp->rq_size) { 748*40909f66SGal Pressman dma_unmap_single(&dev->pdev->dev, qp->rq_dma_addr, qp->rq_size, 749*40909f66SGal Pressman DMA_TO_DEVICE); 750*40909f66SGal Pressman if (!rq_entry_inserted) 751*40909f66SGal Pressman free_pages_exact(qp->rq_cpu_addr, qp->rq_size); 752*40909f66SGal Pressman } 753*40909f66SGal Pressman err_free_qp: 754*40909f66SGal Pressman kfree(qp); 755*40909f66SGal Pressman err_out: 756*40909f66SGal Pressman atomic64_inc(&dev->stats.sw_stats.create_qp_err); 757*40909f66SGal Pressman return ERR_PTR(err); 758*40909f66SGal Pressman } 759*40909f66SGal Pressman 760*40909f66SGal Pressman static int efa_modify_qp_validate(struct efa_dev *dev, struct efa_qp *qp, 761*40909f66SGal Pressman struct ib_qp_attr *qp_attr, int qp_attr_mask, 762*40909f66SGal Pressman enum ib_qp_state cur_state, 763*40909f66SGal Pressman enum ib_qp_state new_state) 764*40909f66SGal Pressman { 765*40909f66SGal Pressman #define EFA_MODIFY_QP_SUPP_MASK \ 766*40909f66SGal Pressman (IB_QP_STATE | IB_QP_CUR_STATE | IB_QP_EN_SQD_ASYNC_NOTIFY | \ 767*40909f66SGal Pressman IB_QP_PKEY_INDEX | IB_QP_PORT | IB_QP_QKEY | IB_QP_SQ_PSN) 768*40909f66SGal Pressman 769*40909f66SGal Pressman if (qp_attr_mask & ~EFA_MODIFY_QP_SUPP_MASK) { 770*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 771*40909f66SGal Pressman "Unsupported qp_attr_mask[%#x] supported[%#x]\n", 772*40909f66SGal Pressman qp_attr_mask, EFA_MODIFY_QP_SUPP_MASK); 773*40909f66SGal Pressman return -EOPNOTSUPP; 774*40909f66SGal Pressman } 775*40909f66SGal Pressman 776*40909f66SGal Pressman if (!ib_modify_qp_is_ok(cur_state, new_state, IB_QPT_UD, 777*40909f66SGal Pressman qp_attr_mask)) { 778*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Invalid modify QP parameters\n"); 779*40909f66SGal Pressman return -EINVAL; 780*40909f66SGal Pressman } 781*40909f66SGal Pressman 782*40909f66SGal Pressman if ((qp_attr_mask & IB_QP_PORT) && qp_attr->port_num != 1) { 783*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Can't change port num\n"); 784*40909f66SGal Pressman return -EOPNOTSUPP; 785*40909f66SGal Pressman } 786*40909f66SGal Pressman 787*40909f66SGal Pressman if ((qp_attr_mask & IB_QP_PKEY_INDEX) && qp_attr->pkey_index) { 788*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Can't change pkey index\n"); 789*40909f66SGal Pressman return -EOPNOTSUPP; 790*40909f66SGal Pressman } 791*40909f66SGal Pressman 792*40909f66SGal Pressman return 0; 793*40909f66SGal Pressman } 794*40909f66SGal Pressman 795*40909f66SGal Pressman int efa_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, 796*40909f66SGal Pressman int qp_attr_mask, struct ib_udata *udata) 797*40909f66SGal Pressman { 798*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibqp->device); 799*40909f66SGal Pressman struct efa_com_modify_qp_params params = {}; 800*40909f66SGal Pressman struct efa_qp *qp = to_eqp(ibqp); 801*40909f66SGal Pressman enum ib_qp_state cur_state; 802*40909f66SGal Pressman enum ib_qp_state new_state; 803*40909f66SGal Pressman int err; 804*40909f66SGal Pressman 805*40909f66SGal Pressman if (udata->inlen && 806*40909f66SGal Pressman !ib_is_udata_cleared(udata, 0, udata->inlen)) { 807*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 808*40909f66SGal Pressman "Incompatible ABI params, udata not cleared\n"); 809*40909f66SGal Pressman return -EINVAL; 810*40909f66SGal Pressman } 811*40909f66SGal Pressman 812*40909f66SGal Pressman cur_state = qp_attr_mask & IB_QP_CUR_STATE ? qp_attr->cur_qp_state : 813*40909f66SGal Pressman qp->state; 814*40909f66SGal Pressman new_state = qp_attr_mask & IB_QP_STATE ? qp_attr->qp_state : cur_state; 815*40909f66SGal Pressman 816*40909f66SGal Pressman err = efa_modify_qp_validate(dev, qp, qp_attr, qp_attr_mask, cur_state, 817*40909f66SGal Pressman new_state); 818*40909f66SGal Pressman if (err) 819*40909f66SGal Pressman return err; 820*40909f66SGal Pressman 821*40909f66SGal Pressman params.qp_handle = qp->qp_handle; 822*40909f66SGal Pressman 823*40909f66SGal Pressman if (qp_attr_mask & IB_QP_STATE) { 824*40909f66SGal Pressman params.modify_mask |= BIT(EFA_ADMIN_QP_STATE_BIT) | 825*40909f66SGal Pressman BIT(EFA_ADMIN_CUR_QP_STATE_BIT); 826*40909f66SGal Pressman params.cur_qp_state = qp_attr->cur_qp_state; 827*40909f66SGal Pressman params.qp_state = qp_attr->qp_state; 828*40909f66SGal Pressman } 829*40909f66SGal Pressman 830*40909f66SGal Pressman if (qp_attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY) { 831*40909f66SGal Pressman params.modify_mask |= 832*40909f66SGal Pressman BIT(EFA_ADMIN_SQ_DRAINED_ASYNC_NOTIFY_BIT); 833*40909f66SGal Pressman params.sq_drained_async_notify = qp_attr->en_sqd_async_notify; 834*40909f66SGal Pressman } 835*40909f66SGal Pressman 836*40909f66SGal Pressman if (qp_attr_mask & IB_QP_QKEY) { 837*40909f66SGal Pressman params.modify_mask |= BIT(EFA_ADMIN_QKEY_BIT); 838*40909f66SGal Pressman params.qkey = qp_attr->qkey; 839*40909f66SGal Pressman } 840*40909f66SGal Pressman 841*40909f66SGal Pressman if (qp_attr_mask & IB_QP_SQ_PSN) { 842*40909f66SGal Pressman params.modify_mask |= BIT(EFA_ADMIN_SQ_PSN_BIT); 843*40909f66SGal Pressman params.sq_psn = qp_attr->sq_psn; 844*40909f66SGal Pressman } 845*40909f66SGal Pressman 846*40909f66SGal Pressman err = efa_com_modify_qp(&dev->edev, ¶ms); 847*40909f66SGal Pressman if (err) 848*40909f66SGal Pressman return err; 849*40909f66SGal Pressman 850*40909f66SGal Pressman qp->state = new_state; 851*40909f66SGal Pressman 852*40909f66SGal Pressman return 0; 853*40909f66SGal Pressman } 854*40909f66SGal Pressman 855*40909f66SGal Pressman static int efa_destroy_cq_idx(struct efa_dev *dev, int cq_idx) 856*40909f66SGal Pressman { 857*40909f66SGal Pressman struct efa_com_destroy_cq_params params = { .cq_idx = cq_idx }; 858*40909f66SGal Pressman 859*40909f66SGal Pressman return efa_com_destroy_cq(&dev->edev, ¶ms); 860*40909f66SGal Pressman } 861*40909f66SGal Pressman 862*40909f66SGal Pressman int efa_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata) 863*40909f66SGal Pressman { 864*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibcq->device); 865*40909f66SGal Pressman struct efa_cq *cq = to_ecq(ibcq); 866*40909f66SGal Pressman int err; 867*40909f66SGal Pressman 868*40909f66SGal Pressman if (udata->inlen && 869*40909f66SGal Pressman !ib_is_udata_cleared(udata, 0, udata->inlen)) { 870*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Incompatible ABI params\n"); 871*40909f66SGal Pressman return -EINVAL; 872*40909f66SGal Pressman } 873*40909f66SGal Pressman 874*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 875*40909f66SGal Pressman "Destroy cq[%d] virt[0x%p] freed: size[%lu], dma[%pad]\n", 876*40909f66SGal Pressman cq->cq_idx, cq->cpu_addr, cq->size, &cq->dma_addr); 877*40909f66SGal Pressman 878*40909f66SGal Pressman err = efa_destroy_cq_idx(dev, cq->cq_idx); 879*40909f66SGal Pressman if (err) 880*40909f66SGal Pressman return err; 881*40909f66SGal Pressman 882*40909f66SGal Pressman dma_unmap_single(&dev->pdev->dev, cq->dma_addr, cq->size, 883*40909f66SGal Pressman DMA_FROM_DEVICE); 884*40909f66SGal Pressman 885*40909f66SGal Pressman kfree(cq); 886*40909f66SGal Pressman return 0; 887*40909f66SGal Pressman } 888*40909f66SGal Pressman 889*40909f66SGal Pressman static int cq_mmap_entries_setup(struct efa_dev *dev, struct efa_cq *cq, 890*40909f66SGal Pressman struct efa_ibv_create_cq_resp *resp) 891*40909f66SGal Pressman { 892*40909f66SGal Pressman resp->q_mmap_size = cq->size; 893*40909f66SGal Pressman resp->q_mmap_key = mmap_entry_insert(dev, cq->ucontext, cq, 894*40909f66SGal Pressman virt_to_phys(cq->cpu_addr), 895*40909f66SGal Pressman cq->size, EFA_MMAP_DMA_PAGE); 896*40909f66SGal Pressman if (resp->q_mmap_key == EFA_MMAP_INVALID) 897*40909f66SGal Pressman return -ENOMEM; 898*40909f66SGal Pressman 899*40909f66SGal Pressman return 0; 900*40909f66SGal Pressman } 901*40909f66SGal Pressman 902*40909f66SGal Pressman static struct ib_cq *do_create_cq(struct ib_device *ibdev, int entries, 903*40909f66SGal Pressman int vector, struct ib_ucontext *ibucontext, 904*40909f66SGal Pressman struct ib_udata *udata) 905*40909f66SGal Pressman { 906*40909f66SGal Pressman struct efa_ibv_create_cq_resp resp = {}; 907*40909f66SGal Pressman struct efa_com_create_cq_params params; 908*40909f66SGal Pressman struct efa_com_create_cq_result result; 909*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibdev); 910*40909f66SGal Pressman struct efa_ibv_create_cq cmd = {}; 911*40909f66SGal Pressman bool cq_entry_inserted = false; 912*40909f66SGal Pressman struct efa_cq *cq; 913*40909f66SGal Pressman int err; 914*40909f66SGal Pressman 915*40909f66SGal Pressman ibdev_dbg(ibdev, "create_cq entries %d\n", entries); 916*40909f66SGal Pressman 917*40909f66SGal Pressman if (entries < 1 || entries > dev->dev_attr.max_cq_depth) { 918*40909f66SGal Pressman ibdev_dbg(ibdev, 919*40909f66SGal Pressman "cq: requested entries[%u] non-positive or greater than max[%u]\n", 920*40909f66SGal Pressman entries, dev->dev_attr.max_cq_depth); 921*40909f66SGal Pressman err = -EINVAL; 922*40909f66SGal Pressman goto err_out; 923*40909f66SGal Pressman } 924*40909f66SGal Pressman 925*40909f66SGal Pressman if (!field_avail(cmd, num_sub_cqs, udata->inlen)) { 926*40909f66SGal Pressman ibdev_dbg(ibdev, 927*40909f66SGal Pressman "Incompatible ABI params, no input udata\n"); 928*40909f66SGal Pressman err = -EINVAL; 929*40909f66SGal Pressman goto err_out; 930*40909f66SGal Pressman } 931*40909f66SGal Pressman 932*40909f66SGal Pressman if (udata->inlen > sizeof(cmd) && 933*40909f66SGal Pressman !ib_is_udata_cleared(udata, sizeof(cmd), 934*40909f66SGal Pressman udata->inlen - sizeof(cmd))) { 935*40909f66SGal Pressman ibdev_dbg(ibdev, 936*40909f66SGal Pressman "Incompatible ABI params, unknown fields in udata\n"); 937*40909f66SGal Pressman err = -EINVAL; 938*40909f66SGal Pressman goto err_out; 939*40909f66SGal Pressman } 940*40909f66SGal Pressman 941*40909f66SGal Pressman err = ib_copy_from_udata(&cmd, udata, 942*40909f66SGal Pressman min(sizeof(cmd), udata->inlen)); 943*40909f66SGal Pressman if (err) { 944*40909f66SGal Pressman ibdev_dbg(ibdev, "Cannot copy udata for create_cq\n"); 945*40909f66SGal Pressman goto err_out; 946*40909f66SGal Pressman } 947*40909f66SGal Pressman 948*40909f66SGal Pressman if (cmd.comp_mask || !is_reserved_cleared(cmd.reserved_50)) { 949*40909f66SGal Pressman ibdev_dbg(ibdev, 950*40909f66SGal Pressman "Incompatible ABI params, unknown fields in udata\n"); 951*40909f66SGal Pressman err = -EINVAL; 952*40909f66SGal Pressman goto err_out; 953*40909f66SGal Pressman } 954*40909f66SGal Pressman 955*40909f66SGal Pressman if (!cmd.cq_entry_size) { 956*40909f66SGal Pressman ibdev_dbg(ibdev, 957*40909f66SGal Pressman "Invalid entry size [%u]\n", cmd.cq_entry_size); 958*40909f66SGal Pressman err = -EINVAL; 959*40909f66SGal Pressman goto err_out; 960*40909f66SGal Pressman } 961*40909f66SGal Pressman 962*40909f66SGal Pressman if (cmd.num_sub_cqs != dev->dev_attr.sub_cqs_per_cq) { 963*40909f66SGal Pressman ibdev_dbg(ibdev, 964*40909f66SGal Pressman "Invalid number of sub cqs[%u] expected[%u]\n", 965*40909f66SGal Pressman cmd.num_sub_cqs, dev->dev_attr.sub_cqs_per_cq); 966*40909f66SGal Pressman err = -EINVAL; 967*40909f66SGal Pressman goto err_out; 968*40909f66SGal Pressman } 969*40909f66SGal Pressman 970*40909f66SGal Pressman cq = kzalloc(sizeof(*cq), GFP_KERNEL); 971*40909f66SGal Pressman if (!cq) { 972*40909f66SGal Pressman err = -ENOMEM; 973*40909f66SGal Pressman goto err_out; 974*40909f66SGal Pressman } 975*40909f66SGal Pressman 976*40909f66SGal Pressman cq->ucontext = to_eucontext(ibucontext); 977*40909f66SGal Pressman cq->size = PAGE_ALIGN(cmd.cq_entry_size * entries * cmd.num_sub_cqs); 978*40909f66SGal Pressman cq->cpu_addr = efa_zalloc_mapped(dev, &cq->dma_addr, cq->size, 979*40909f66SGal Pressman DMA_FROM_DEVICE); 980*40909f66SGal Pressman if (!cq->cpu_addr) { 981*40909f66SGal Pressman err = -ENOMEM; 982*40909f66SGal Pressman goto err_free_cq; 983*40909f66SGal Pressman } 984*40909f66SGal Pressman 985*40909f66SGal Pressman params.uarn = cq->ucontext->uarn; 986*40909f66SGal Pressman params.cq_depth = entries; 987*40909f66SGal Pressman params.dma_addr = cq->dma_addr; 988*40909f66SGal Pressman params.entry_size_in_bytes = cmd.cq_entry_size; 989*40909f66SGal Pressman params.num_sub_cqs = cmd.num_sub_cqs; 990*40909f66SGal Pressman err = efa_com_create_cq(&dev->edev, ¶ms, &result); 991*40909f66SGal Pressman if (err) 992*40909f66SGal Pressman goto err_free_mapped; 993*40909f66SGal Pressman 994*40909f66SGal Pressman resp.cq_idx = result.cq_idx; 995*40909f66SGal Pressman cq->cq_idx = result.cq_idx; 996*40909f66SGal Pressman cq->ibcq.cqe = result.actual_depth; 997*40909f66SGal Pressman WARN_ON_ONCE(entries != result.actual_depth); 998*40909f66SGal Pressman 999*40909f66SGal Pressman err = cq_mmap_entries_setup(dev, cq, &resp); 1000*40909f66SGal Pressman if (err) { 1001*40909f66SGal Pressman ibdev_dbg(ibdev, 1002*40909f66SGal Pressman "Could not setup cq[%u] mmap entries\n", cq->cq_idx); 1003*40909f66SGal Pressman goto err_destroy_cq; 1004*40909f66SGal Pressman } 1005*40909f66SGal Pressman 1006*40909f66SGal Pressman cq_entry_inserted = true; 1007*40909f66SGal Pressman 1008*40909f66SGal Pressman if (udata->outlen) { 1009*40909f66SGal Pressman err = ib_copy_to_udata(udata, &resp, 1010*40909f66SGal Pressman min(sizeof(resp), udata->outlen)); 1011*40909f66SGal Pressman if (err) { 1012*40909f66SGal Pressman ibdev_dbg(ibdev, 1013*40909f66SGal Pressman "Failed to copy udata for create_cq\n"); 1014*40909f66SGal Pressman goto err_destroy_cq; 1015*40909f66SGal Pressman } 1016*40909f66SGal Pressman } 1017*40909f66SGal Pressman 1018*40909f66SGal Pressman ibdev_dbg(ibdev, 1019*40909f66SGal Pressman "Created cq[%d], cq depth[%u]. dma[%pad] virt[0x%p]\n", 1020*40909f66SGal Pressman cq->cq_idx, result.actual_depth, &cq->dma_addr, cq->cpu_addr); 1021*40909f66SGal Pressman 1022*40909f66SGal Pressman return &cq->ibcq; 1023*40909f66SGal Pressman 1024*40909f66SGal Pressman err_destroy_cq: 1025*40909f66SGal Pressman efa_destroy_cq_idx(dev, cq->cq_idx); 1026*40909f66SGal Pressman err_free_mapped: 1027*40909f66SGal Pressman dma_unmap_single(&dev->pdev->dev, cq->dma_addr, cq->size, 1028*40909f66SGal Pressman DMA_FROM_DEVICE); 1029*40909f66SGal Pressman if (!cq_entry_inserted) 1030*40909f66SGal Pressman free_pages_exact(cq->cpu_addr, cq->size); 1031*40909f66SGal Pressman err_free_cq: 1032*40909f66SGal Pressman kfree(cq); 1033*40909f66SGal Pressman err_out: 1034*40909f66SGal Pressman atomic64_inc(&dev->stats.sw_stats.create_cq_err); 1035*40909f66SGal Pressman return ERR_PTR(err); 1036*40909f66SGal Pressman } 1037*40909f66SGal Pressman 1038*40909f66SGal Pressman struct ib_cq *efa_create_cq(struct ib_device *ibdev, 1039*40909f66SGal Pressman const struct ib_cq_init_attr *attr, 1040*40909f66SGal Pressman struct ib_udata *udata) 1041*40909f66SGal Pressman { 1042*40909f66SGal Pressman struct efa_ucontext *ucontext = rdma_udata_to_drv_context(udata, 1043*40909f66SGal Pressman struct efa_ucontext, 1044*40909f66SGal Pressman ibucontext); 1045*40909f66SGal Pressman 1046*40909f66SGal Pressman return do_create_cq(ibdev, attr->cqe, attr->comp_vector, 1047*40909f66SGal Pressman &ucontext->ibucontext, udata); 1048*40909f66SGal Pressman } 1049*40909f66SGal Pressman 1050*40909f66SGal Pressman static int umem_to_page_list(struct efa_dev *dev, 1051*40909f66SGal Pressman struct ib_umem *umem, 1052*40909f66SGal Pressman u64 *page_list, 1053*40909f66SGal Pressman u32 hp_cnt, 1054*40909f66SGal Pressman u8 hp_shift) 1055*40909f66SGal Pressman { 1056*40909f66SGal Pressman u32 pages_in_hp = BIT(hp_shift - PAGE_SHIFT); 1057*40909f66SGal Pressman struct sg_dma_page_iter sg_iter; 1058*40909f66SGal Pressman unsigned int page_idx = 0; 1059*40909f66SGal Pressman unsigned int hp_idx = 0; 1060*40909f66SGal Pressman 1061*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "hp_cnt[%u], pages_in_hp[%u]\n", 1062*40909f66SGal Pressman hp_cnt, pages_in_hp); 1063*40909f66SGal Pressman 1064*40909f66SGal Pressman for_each_sg_dma_page(umem->sg_head.sgl, &sg_iter, umem->nmap, 0) { 1065*40909f66SGal Pressman if (page_idx % pages_in_hp == 0) { 1066*40909f66SGal Pressman page_list[hp_idx] = sg_page_iter_dma_address(&sg_iter); 1067*40909f66SGal Pressman hp_idx++; 1068*40909f66SGal Pressman } 1069*40909f66SGal Pressman 1070*40909f66SGal Pressman page_idx++; 1071*40909f66SGal Pressman } 1072*40909f66SGal Pressman 1073*40909f66SGal Pressman return 0; 1074*40909f66SGal Pressman } 1075*40909f66SGal Pressman 1076*40909f66SGal Pressman static struct scatterlist *efa_vmalloc_buf_to_sg(u64 *buf, int page_cnt) 1077*40909f66SGal Pressman { 1078*40909f66SGal Pressman struct scatterlist *sglist; 1079*40909f66SGal Pressman struct page *pg; 1080*40909f66SGal Pressman int i; 1081*40909f66SGal Pressman 1082*40909f66SGal Pressman sglist = kcalloc(page_cnt, sizeof(*sglist), GFP_KERNEL); 1083*40909f66SGal Pressman if (!sglist) 1084*40909f66SGal Pressman return NULL; 1085*40909f66SGal Pressman sg_init_table(sglist, page_cnt); 1086*40909f66SGal Pressman for (i = 0; i < page_cnt; i++) { 1087*40909f66SGal Pressman pg = vmalloc_to_page(buf); 1088*40909f66SGal Pressman if (!pg) 1089*40909f66SGal Pressman goto err; 1090*40909f66SGal Pressman sg_set_page(&sglist[i], pg, PAGE_SIZE, 0); 1091*40909f66SGal Pressman buf += PAGE_SIZE / sizeof(*buf); 1092*40909f66SGal Pressman } 1093*40909f66SGal Pressman return sglist; 1094*40909f66SGal Pressman 1095*40909f66SGal Pressman err: 1096*40909f66SGal Pressman kfree(sglist); 1097*40909f66SGal Pressman return NULL; 1098*40909f66SGal Pressman } 1099*40909f66SGal Pressman 1100*40909f66SGal Pressman /* 1101*40909f66SGal Pressman * create a chunk list of physical pages dma addresses from the supplied 1102*40909f66SGal Pressman * scatter gather list 1103*40909f66SGal Pressman */ 1104*40909f66SGal Pressman static int pbl_chunk_list_create(struct efa_dev *dev, struct pbl_context *pbl) 1105*40909f66SGal Pressman { 1106*40909f66SGal Pressman unsigned int entry, payloads_in_sg, chunk_list_size, chunk_idx, payload_idx; 1107*40909f66SGal Pressman struct pbl_chunk_list *chunk_list = &pbl->phys.indirect.chunk_list; 1108*40909f66SGal Pressman int page_cnt = pbl->phys.indirect.pbl_buf_size_in_pages; 1109*40909f66SGal Pressman struct scatterlist *pages_sgl = pbl->phys.indirect.sgl; 1110*40909f66SGal Pressman int sg_dma_cnt = pbl->phys.indirect.sg_dma_cnt; 1111*40909f66SGal Pressman struct efa_com_ctrl_buff_info *ctrl_buf; 1112*40909f66SGal Pressman u64 *cur_chunk_buf, *prev_chunk_buf; 1113*40909f66SGal Pressman struct scatterlist *sg; 1114*40909f66SGal Pressman dma_addr_t dma_addr; 1115*40909f66SGal Pressman int i; 1116*40909f66SGal Pressman 1117*40909f66SGal Pressman /* allocate a chunk list that consists of 4KB chunks */ 1118*40909f66SGal Pressman chunk_list_size = DIV_ROUND_UP(page_cnt, EFA_PTRS_PER_CHUNK); 1119*40909f66SGal Pressman 1120*40909f66SGal Pressman chunk_list->size = chunk_list_size; 1121*40909f66SGal Pressman chunk_list->chunks = kcalloc(chunk_list_size, 1122*40909f66SGal Pressman sizeof(*chunk_list->chunks), 1123*40909f66SGal Pressman GFP_KERNEL); 1124*40909f66SGal Pressman if (!chunk_list->chunks) 1125*40909f66SGal Pressman return -ENOMEM; 1126*40909f66SGal Pressman 1127*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1128*40909f66SGal Pressman "chunk_list_size[%u] - pages[%u]\n", chunk_list_size, 1129*40909f66SGal Pressman page_cnt); 1130*40909f66SGal Pressman 1131*40909f66SGal Pressman /* allocate chunk buffers: */ 1132*40909f66SGal Pressman for (i = 0; i < chunk_list_size; i++) { 1133*40909f66SGal Pressman chunk_list->chunks[i].buf = kzalloc(EFA_CHUNK_SIZE, GFP_KERNEL); 1134*40909f66SGal Pressman if (!chunk_list->chunks[i].buf) 1135*40909f66SGal Pressman goto chunk_list_dealloc; 1136*40909f66SGal Pressman 1137*40909f66SGal Pressman chunk_list->chunks[i].length = EFA_CHUNK_USED_SIZE; 1138*40909f66SGal Pressman } 1139*40909f66SGal Pressman chunk_list->chunks[chunk_list_size - 1].length = 1140*40909f66SGal Pressman ((page_cnt % EFA_PTRS_PER_CHUNK) * EFA_CHUNK_PAYLOAD_PTR_SIZE) + 1141*40909f66SGal Pressman EFA_CHUNK_PTR_SIZE; 1142*40909f66SGal Pressman 1143*40909f66SGal Pressman /* fill the dma addresses of sg list pages to chunks: */ 1144*40909f66SGal Pressman chunk_idx = 0; 1145*40909f66SGal Pressman payload_idx = 0; 1146*40909f66SGal Pressman cur_chunk_buf = chunk_list->chunks[0].buf; 1147*40909f66SGal Pressman for_each_sg(pages_sgl, sg, sg_dma_cnt, entry) { 1148*40909f66SGal Pressman payloads_in_sg = sg_dma_len(sg) >> EFA_CHUNK_PAYLOAD_SHIFT; 1149*40909f66SGal Pressman for (i = 0; i < payloads_in_sg; i++) { 1150*40909f66SGal Pressman cur_chunk_buf[payload_idx++] = 1151*40909f66SGal Pressman (sg_dma_address(sg) & ~(EFA_CHUNK_PAYLOAD_SIZE - 1)) + 1152*40909f66SGal Pressman (EFA_CHUNK_PAYLOAD_SIZE * i); 1153*40909f66SGal Pressman 1154*40909f66SGal Pressman if (payload_idx == EFA_PTRS_PER_CHUNK) { 1155*40909f66SGal Pressman chunk_idx++; 1156*40909f66SGal Pressman cur_chunk_buf = chunk_list->chunks[chunk_idx].buf; 1157*40909f66SGal Pressman payload_idx = 0; 1158*40909f66SGal Pressman } 1159*40909f66SGal Pressman } 1160*40909f66SGal Pressman } 1161*40909f66SGal Pressman 1162*40909f66SGal Pressman /* map chunks to dma and fill chunks next ptrs */ 1163*40909f66SGal Pressman for (i = chunk_list_size - 1; i >= 0; i--) { 1164*40909f66SGal Pressman dma_addr = dma_map_single(&dev->pdev->dev, 1165*40909f66SGal Pressman chunk_list->chunks[i].buf, 1166*40909f66SGal Pressman chunk_list->chunks[i].length, 1167*40909f66SGal Pressman DMA_TO_DEVICE); 1168*40909f66SGal Pressman if (dma_mapping_error(&dev->pdev->dev, dma_addr)) { 1169*40909f66SGal Pressman ibdev_err(&dev->ibdev, 1170*40909f66SGal Pressman "chunk[%u] dma_map_failed\n", i); 1171*40909f66SGal Pressman goto chunk_list_unmap; 1172*40909f66SGal Pressman } 1173*40909f66SGal Pressman 1174*40909f66SGal Pressman chunk_list->chunks[i].dma_addr = dma_addr; 1175*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1176*40909f66SGal Pressman "chunk[%u] mapped at [%pad]\n", i, &dma_addr); 1177*40909f66SGal Pressman 1178*40909f66SGal Pressman if (!i) 1179*40909f66SGal Pressman break; 1180*40909f66SGal Pressman 1181*40909f66SGal Pressman prev_chunk_buf = chunk_list->chunks[i - 1].buf; 1182*40909f66SGal Pressman 1183*40909f66SGal Pressman ctrl_buf = (struct efa_com_ctrl_buff_info *) 1184*40909f66SGal Pressman &prev_chunk_buf[EFA_PTRS_PER_CHUNK]; 1185*40909f66SGal Pressman ctrl_buf->length = chunk_list->chunks[i].length; 1186*40909f66SGal Pressman 1187*40909f66SGal Pressman efa_com_set_dma_addr(dma_addr, 1188*40909f66SGal Pressman &ctrl_buf->address.mem_addr_high, 1189*40909f66SGal Pressman &ctrl_buf->address.mem_addr_low); 1190*40909f66SGal Pressman } 1191*40909f66SGal Pressman 1192*40909f66SGal Pressman return 0; 1193*40909f66SGal Pressman 1194*40909f66SGal Pressman chunk_list_unmap: 1195*40909f66SGal Pressman for (; i < chunk_list_size; i++) { 1196*40909f66SGal Pressman dma_unmap_single(&dev->pdev->dev, chunk_list->chunks[i].dma_addr, 1197*40909f66SGal Pressman chunk_list->chunks[i].length, DMA_TO_DEVICE); 1198*40909f66SGal Pressman } 1199*40909f66SGal Pressman chunk_list_dealloc: 1200*40909f66SGal Pressman for (i = 0; i < chunk_list_size; i++) 1201*40909f66SGal Pressman kfree(chunk_list->chunks[i].buf); 1202*40909f66SGal Pressman 1203*40909f66SGal Pressman kfree(chunk_list->chunks); 1204*40909f66SGal Pressman return -ENOMEM; 1205*40909f66SGal Pressman } 1206*40909f66SGal Pressman 1207*40909f66SGal Pressman static void pbl_chunk_list_destroy(struct efa_dev *dev, struct pbl_context *pbl) 1208*40909f66SGal Pressman { 1209*40909f66SGal Pressman struct pbl_chunk_list *chunk_list = &pbl->phys.indirect.chunk_list; 1210*40909f66SGal Pressman int i; 1211*40909f66SGal Pressman 1212*40909f66SGal Pressman for (i = 0; i < chunk_list->size; i++) { 1213*40909f66SGal Pressman dma_unmap_single(&dev->pdev->dev, chunk_list->chunks[i].dma_addr, 1214*40909f66SGal Pressman chunk_list->chunks[i].length, DMA_TO_DEVICE); 1215*40909f66SGal Pressman kfree(chunk_list->chunks[i].buf); 1216*40909f66SGal Pressman } 1217*40909f66SGal Pressman 1218*40909f66SGal Pressman kfree(chunk_list->chunks); 1219*40909f66SGal Pressman } 1220*40909f66SGal Pressman 1221*40909f66SGal Pressman /* initialize pbl continuous mode: map pbl buffer to a dma address. */ 1222*40909f66SGal Pressman static int pbl_continuous_initialize(struct efa_dev *dev, 1223*40909f66SGal Pressman struct pbl_context *pbl) 1224*40909f66SGal Pressman { 1225*40909f66SGal Pressman dma_addr_t dma_addr; 1226*40909f66SGal Pressman 1227*40909f66SGal Pressman dma_addr = dma_map_single(&dev->pdev->dev, pbl->pbl_buf, 1228*40909f66SGal Pressman pbl->pbl_buf_size_in_bytes, DMA_TO_DEVICE); 1229*40909f66SGal Pressman if (dma_mapping_error(&dev->pdev->dev, dma_addr)) { 1230*40909f66SGal Pressman ibdev_err(&dev->ibdev, "Unable to map pbl to DMA address\n"); 1231*40909f66SGal Pressman return -ENOMEM; 1232*40909f66SGal Pressman } 1233*40909f66SGal Pressman 1234*40909f66SGal Pressman pbl->phys.continuous.dma_addr = dma_addr; 1235*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1236*40909f66SGal Pressman "pbl continuous - dma_addr = %pad, size[%u]\n", 1237*40909f66SGal Pressman &dma_addr, pbl->pbl_buf_size_in_bytes); 1238*40909f66SGal Pressman 1239*40909f66SGal Pressman return 0; 1240*40909f66SGal Pressman } 1241*40909f66SGal Pressman 1242*40909f66SGal Pressman /* 1243*40909f66SGal Pressman * initialize pbl indirect mode: 1244*40909f66SGal Pressman * create a chunk list out of the dma addresses of the physical pages of 1245*40909f66SGal Pressman * pbl buffer. 1246*40909f66SGal Pressman */ 1247*40909f66SGal Pressman static int pbl_indirect_initialize(struct efa_dev *dev, struct pbl_context *pbl) 1248*40909f66SGal Pressman { 1249*40909f66SGal Pressman u32 size_in_pages = DIV_ROUND_UP(pbl->pbl_buf_size_in_bytes, PAGE_SIZE); 1250*40909f66SGal Pressman struct scatterlist *sgl; 1251*40909f66SGal Pressman int sg_dma_cnt, err; 1252*40909f66SGal Pressman 1253*40909f66SGal Pressman BUILD_BUG_ON(EFA_CHUNK_PAYLOAD_SIZE > PAGE_SIZE); 1254*40909f66SGal Pressman sgl = efa_vmalloc_buf_to_sg(pbl->pbl_buf, size_in_pages); 1255*40909f66SGal Pressman if (!sgl) 1256*40909f66SGal Pressman return -ENOMEM; 1257*40909f66SGal Pressman 1258*40909f66SGal Pressman sg_dma_cnt = dma_map_sg(&dev->pdev->dev, sgl, size_in_pages, DMA_TO_DEVICE); 1259*40909f66SGal Pressman if (!sg_dma_cnt) { 1260*40909f66SGal Pressman err = -EINVAL; 1261*40909f66SGal Pressman goto err_map; 1262*40909f66SGal Pressman } 1263*40909f66SGal Pressman 1264*40909f66SGal Pressman pbl->phys.indirect.pbl_buf_size_in_pages = size_in_pages; 1265*40909f66SGal Pressman pbl->phys.indirect.sgl = sgl; 1266*40909f66SGal Pressman pbl->phys.indirect.sg_dma_cnt = sg_dma_cnt; 1267*40909f66SGal Pressman err = pbl_chunk_list_create(dev, pbl); 1268*40909f66SGal Pressman if (err) { 1269*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1270*40909f66SGal Pressman "chunk_list creation failed[%d]\n", err); 1271*40909f66SGal Pressman goto err_chunk; 1272*40909f66SGal Pressman } 1273*40909f66SGal Pressman 1274*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1275*40909f66SGal Pressman "pbl indirect - size[%u], chunks[%u]\n", 1276*40909f66SGal Pressman pbl->pbl_buf_size_in_bytes, 1277*40909f66SGal Pressman pbl->phys.indirect.chunk_list.size); 1278*40909f66SGal Pressman 1279*40909f66SGal Pressman return 0; 1280*40909f66SGal Pressman 1281*40909f66SGal Pressman err_chunk: 1282*40909f66SGal Pressman dma_unmap_sg(&dev->pdev->dev, sgl, size_in_pages, DMA_TO_DEVICE); 1283*40909f66SGal Pressman err_map: 1284*40909f66SGal Pressman kfree(sgl); 1285*40909f66SGal Pressman return err; 1286*40909f66SGal Pressman } 1287*40909f66SGal Pressman 1288*40909f66SGal Pressman static void pbl_indirect_terminate(struct efa_dev *dev, struct pbl_context *pbl) 1289*40909f66SGal Pressman { 1290*40909f66SGal Pressman pbl_chunk_list_destroy(dev, pbl); 1291*40909f66SGal Pressman dma_unmap_sg(&dev->pdev->dev, pbl->phys.indirect.sgl, 1292*40909f66SGal Pressman pbl->phys.indirect.pbl_buf_size_in_pages, DMA_TO_DEVICE); 1293*40909f66SGal Pressman kfree(pbl->phys.indirect.sgl); 1294*40909f66SGal Pressman } 1295*40909f66SGal Pressman 1296*40909f66SGal Pressman /* create a page buffer list from a mapped user memory region */ 1297*40909f66SGal Pressman static int pbl_create(struct efa_dev *dev, 1298*40909f66SGal Pressman struct pbl_context *pbl, 1299*40909f66SGal Pressman struct ib_umem *umem, 1300*40909f66SGal Pressman int hp_cnt, 1301*40909f66SGal Pressman u8 hp_shift) 1302*40909f66SGal Pressman { 1303*40909f66SGal Pressman int err; 1304*40909f66SGal Pressman 1305*40909f66SGal Pressman pbl->pbl_buf_size_in_bytes = hp_cnt * EFA_CHUNK_PAYLOAD_PTR_SIZE; 1306*40909f66SGal Pressman pbl->pbl_buf = kzalloc(pbl->pbl_buf_size_in_bytes, 1307*40909f66SGal Pressman GFP_KERNEL | __GFP_NOWARN); 1308*40909f66SGal Pressman if (pbl->pbl_buf) { 1309*40909f66SGal Pressman pbl->physically_continuous = 1; 1310*40909f66SGal Pressman err = umem_to_page_list(dev, umem, pbl->pbl_buf, hp_cnt, 1311*40909f66SGal Pressman hp_shift); 1312*40909f66SGal Pressman if (err) 1313*40909f66SGal Pressman goto err_continuous; 1314*40909f66SGal Pressman err = pbl_continuous_initialize(dev, pbl); 1315*40909f66SGal Pressman if (err) 1316*40909f66SGal Pressman goto err_continuous; 1317*40909f66SGal Pressman } else { 1318*40909f66SGal Pressman pbl->physically_continuous = 0; 1319*40909f66SGal Pressman pbl->pbl_buf = vzalloc(pbl->pbl_buf_size_in_bytes); 1320*40909f66SGal Pressman if (!pbl->pbl_buf) 1321*40909f66SGal Pressman return -ENOMEM; 1322*40909f66SGal Pressman 1323*40909f66SGal Pressman err = umem_to_page_list(dev, umem, pbl->pbl_buf, hp_cnt, 1324*40909f66SGal Pressman hp_shift); 1325*40909f66SGal Pressman if (err) 1326*40909f66SGal Pressman goto err_indirect; 1327*40909f66SGal Pressman err = pbl_indirect_initialize(dev, pbl); 1328*40909f66SGal Pressman if (err) 1329*40909f66SGal Pressman goto err_indirect; 1330*40909f66SGal Pressman } 1331*40909f66SGal Pressman 1332*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1333*40909f66SGal Pressman "user_pbl_created: user_pages[%u], continuous[%u]\n", 1334*40909f66SGal Pressman hp_cnt, pbl->physically_continuous); 1335*40909f66SGal Pressman 1336*40909f66SGal Pressman return 0; 1337*40909f66SGal Pressman 1338*40909f66SGal Pressman err_continuous: 1339*40909f66SGal Pressman kfree(pbl->pbl_buf); 1340*40909f66SGal Pressman return err; 1341*40909f66SGal Pressman err_indirect: 1342*40909f66SGal Pressman vfree(pbl->pbl_buf); 1343*40909f66SGal Pressman return err; 1344*40909f66SGal Pressman } 1345*40909f66SGal Pressman 1346*40909f66SGal Pressman static void pbl_destroy(struct efa_dev *dev, struct pbl_context *pbl) 1347*40909f66SGal Pressman { 1348*40909f66SGal Pressman if (pbl->physically_continuous) { 1349*40909f66SGal Pressman dma_unmap_single(&dev->pdev->dev, pbl->phys.continuous.dma_addr, 1350*40909f66SGal Pressman pbl->pbl_buf_size_in_bytes, DMA_TO_DEVICE); 1351*40909f66SGal Pressman kfree(pbl->pbl_buf); 1352*40909f66SGal Pressman } else { 1353*40909f66SGal Pressman pbl_indirect_terminate(dev, pbl); 1354*40909f66SGal Pressman vfree(pbl->pbl_buf); 1355*40909f66SGal Pressman } 1356*40909f66SGal Pressman } 1357*40909f66SGal Pressman 1358*40909f66SGal Pressman static int efa_create_inline_pbl(struct efa_dev *dev, struct efa_mr *mr, 1359*40909f66SGal Pressman struct efa_com_reg_mr_params *params) 1360*40909f66SGal Pressman { 1361*40909f66SGal Pressman int err; 1362*40909f66SGal Pressman 1363*40909f66SGal Pressman params->inline_pbl = 1; 1364*40909f66SGal Pressman err = umem_to_page_list(dev, mr->umem, params->pbl.inline_pbl_array, 1365*40909f66SGal Pressman params->page_num, params->page_shift); 1366*40909f66SGal Pressman if (err) 1367*40909f66SGal Pressman return err; 1368*40909f66SGal Pressman 1369*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1370*40909f66SGal Pressman "inline_pbl_array - pages[%u]\n", params->page_num); 1371*40909f66SGal Pressman 1372*40909f66SGal Pressman return 0; 1373*40909f66SGal Pressman } 1374*40909f66SGal Pressman 1375*40909f66SGal Pressman static int efa_create_pbl(struct efa_dev *dev, 1376*40909f66SGal Pressman struct pbl_context *pbl, 1377*40909f66SGal Pressman struct efa_mr *mr, 1378*40909f66SGal Pressman struct efa_com_reg_mr_params *params) 1379*40909f66SGal Pressman { 1380*40909f66SGal Pressman int err; 1381*40909f66SGal Pressman 1382*40909f66SGal Pressman err = pbl_create(dev, pbl, mr->umem, params->page_num, 1383*40909f66SGal Pressman params->page_shift); 1384*40909f66SGal Pressman if (err) { 1385*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Failed to create pbl[%d]\n", err); 1386*40909f66SGal Pressman return err; 1387*40909f66SGal Pressman } 1388*40909f66SGal Pressman 1389*40909f66SGal Pressman params->inline_pbl = 0; 1390*40909f66SGal Pressman params->indirect = !pbl->physically_continuous; 1391*40909f66SGal Pressman if (pbl->physically_continuous) { 1392*40909f66SGal Pressman params->pbl.pbl.length = pbl->pbl_buf_size_in_bytes; 1393*40909f66SGal Pressman 1394*40909f66SGal Pressman efa_com_set_dma_addr(pbl->phys.continuous.dma_addr, 1395*40909f66SGal Pressman ¶ms->pbl.pbl.address.mem_addr_high, 1396*40909f66SGal Pressman ¶ms->pbl.pbl.address.mem_addr_low); 1397*40909f66SGal Pressman } else { 1398*40909f66SGal Pressman params->pbl.pbl.length = 1399*40909f66SGal Pressman pbl->phys.indirect.chunk_list.chunks[0].length; 1400*40909f66SGal Pressman 1401*40909f66SGal Pressman efa_com_set_dma_addr(pbl->phys.indirect.chunk_list.chunks[0].dma_addr, 1402*40909f66SGal Pressman ¶ms->pbl.pbl.address.mem_addr_high, 1403*40909f66SGal Pressman ¶ms->pbl.pbl.address.mem_addr_low); 1404*40909f66SGal Pressman } 1405*40909f66SGal Pressman 1406*40909f66SGal Pressman return 0; 1407*40909f66SGal Pressman } 1408*40909f66SGal Pressman 1409*40909f66SGal Pressman static void efa_cont_pages(struct ib_umem *umem, u64 addr, 1410*40909f66SGal Pressman unsigned long max_page_shift, 1411*40909f66SGal Pressman int *count, u8 *shift, u32 *ncont) 1412*40909f66SGal Pressman { 1413*40909f66SGal Pressman struct scatterlist *sg; 1414*40909f66SGal Pressman u64 base = ~0, p = 0; 1415*40909f66SGal Pressman unsigned long tmp; 1416*40909f66SGal Pressman unsigned long m; 1417*40909f66SGal Pressman u64 len, pfn; 1418*40909f66SGal Pressman int i = 0; 1419*40909f66SGal Pressman int entry; 1420*40909f66SGal Pressman 1421*40909f66SGal Pressman addr = addr >> PAGE_SHIFT; 1422*40909f66SGal Pressman tmp = (unsigned long)addr; 1423*40909f66SGal Pressman m = find_first_bit(&tmp, BITS_PER_LONG); 1424*40909f66SGal Pressman if (max_page_shift) 1425*40909f66SGal Pressman m = min_t(unsigned long, max_page_shift - PAGE_SHIFT, m); 1426*40909f66SGal Pressman 1427*40909f66SGal Pressman for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) { 1428*40909f66SGal Pressman len = DIV_ROUND_UP(sg_dma_len(sg), PAGE_SIZE); 1429*40909f66SGal Pressman pfn = sg_dma_address(sg) >> PAGE_SHIFT; 1430*40909f66SGal Pressman if (base + p != pfn) { 1431*40909f66SGal Pressman /* 1432*40909f66SGal Pressman * If either the offset or the new 1433*40909f66SGal Pressman * base are unaligned update m 1434*40909f66SGal Pressman */ 1435*40909f66SGal Pressman tmp = (unsigned long)(pfn | p); 1436*40909f66SGal Pressman if (!IS_ALIGNED(tmp, 1 << m)) 1437*40909f66SGal Pressman m = find_first_bit(&tmp, BITS_PER_LONG); 1438*40909f66SGal Pressman 1439*40909f66SGal Pressman base = pfn; 1440*40909f66SGal Pressman p = 0; 1441*40909f66SGal Pressman } 1442*40909f66SGal Pressman 1443*40909f66SGal Pressman p += len; 1444*40909f66SGal Pressman i += len; 1445*40909f66SGal Pressman } 1446*40909f66SGal Pressman 1447*40909f66SGal Pressman if (i) { 1448*40909f66SGal Pressman m = min_t(unsigned long, ilog2(roundup_pow_of_two(i)), m); 1449*40909f66SGal Pressman *ncont = DIV_ROUND_UP(i, (1 << m)); 1450*40909f66SGal Pressman } else { 1451*40909f66SGal Pressman m = 0; 1452*40909f66SGal Pressman *ncont = 0; 1453*40909f66SGal Pressman } 1454*40909f66SGal Pressman 1455*40909f66SGal Pressman *shift = PAGE_SHIFT + m; 1456*40909f66SGal Pressman *count = i; 1457*40909f66SGal Pressman } 1458*40909f66SGal Pressman 1459*40909f66SGal Pressman struct ib_mr *efa_reg_mr(struct ib_pd *ibpd, u64 start, u64 length, 1460*40909f66SGal Pressman u64 virt_addr, int access_flags, 1461*40909f66SGal Pressman struct ib_udata *udata) 1462*40909f66SGal Pressman { 1463*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibpd->device); 1464*40909f66SGal Pressman struct efa_com_reg_mr_params params = {}; 1465*40909f66SGal Pressman struct efa_com_reg_mr_result result = {}; 1466*40909f66SGal Pressman unsigned long max_page_shift; 1467*40909f66SGal Pressman struct pbl_context pbl; 1468*40909f66SGal Pressman struct efa_mr *mr; 1469*40909f66SGal Pressman int inline_size; 1470*40909f66SGal Pressman int npages; 1471*40909f66SGal Pressman int err; 1472*40909f66SGal Pressman 1473*40909f66SGal Pressman if (udata->inlen && 1474*40909f66SGal Pressman !ib_is_udata_cleared(udata, 0, sizeof(udata->inlen))) { 1475*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1476*40909f66SGal Pressman "Incompatible ABI params, udata not cleared\n"); 1477*40909f66SGal Pressman err = -EINVAL; 1478*40909f66SGal Pressman goto err_out; 1479*40909f66SGal Pressman } 1480*40909f66SGal Pressman 1481*40909f66SGal Pressman if (access_flags & ~EFA_SUPPORTED_ACCESS_FLAGS) { 1482*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1483*40909f66SGal Pressman "Unsupported access flags[%#x], supported[%#x]\n", 1484*40909f66SGal Pressman access_flags, EFA_SUPPORTED_ACCESS_FLAGS); 1485*40909f66SGal Pressman err = -EOPNOTSUPP; 1486*40909f66SGal Pressman goto err_out; 1487*40909f66SGal Pressman } 1488*40909f66SGal Pressman 1489*40909f66SGal Pressman mr = kzalloc(sizeof(*mr), GFP_KERNEL); 1490*40909f66SGal Pressman if (!mr) { 1491*40909f66SGal Pressman err = -ENOMEM; 1492*40909f66SGal Pressman goto err_out; 1493*40909f66SGal Pressman } 1494*40909f66SGal Pressman 1495*40909f66SGal Pressman mr->umem = ib_umem_get(udata, start, length, access_flags, 0); 1496*40909f66SGal Pressman if (IS_ERR(mr->umem)) { 1497*40909f66SGal Pressman err = PTR_ERR(mr->umem); 1498*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1499*40909f66SGal Pressman "Failed to pin and map user space memory[%d]\n", err); 1500*40909f66SGal Pressman goto err_free; 1501*40909f66SGal Pressman } 1502*40909f66SGal Pressman 1503*40909f66SGal Pressman params.pd = to_epd(ibpd)->pdn; 1504*40909f66SGal Pressman params.iova = virt_addr; 1505*40909f66SGal Pressman params.mr_length_in_bytes = length; 1506*40909f66SGal Pressman params.permissions = access_flags & 0x1; 1507*40909f66SGal Pressman max_page_shift = fls64(dev->dev_attr.page_size_cap); 1508*40909f66SGal Pressman 1509*40909f66SGal Pressman efa_cont_pages(mr->umem, start, max_page_shift, &npages, 1510*40909f66SGal Pressman ¶ms.page_shift, ¶ms.page_num); 1511*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1512*40909f66SGal Pressman "start %#llx length %#llx npages %d params.page_shift %u params.page_num %u\n", 1513*40909f66SGal Pressman start, length, npages, params.page_shift, params.page_num); 1514*40909f66SGal Pressman 1515*40909f66SGal Pressman inline_size = ARRAY_SIZE(params.pbl.inline_pbl_array); 1516*40909f66SGal Pressman if (params.page_num <= inline_size) { 1517*40909f66SGal Pressman err = efa_create_inline_pbl(dev, mr, ¶ms); 1518*40909f66SGal Pressman if (err) 1519*40909f66SGal Pressman goto err_unmap; 1520*40909f66SGal Pressman 1521*40909f66SGal Pressman err = efa_com_register_mr(&dev->edev, ¶ms, &result); 1522*40909f66SGal Pressman if (err) 1523*40909f66SGal Pressman goto err_unmap; 1524*40909f66SGal Pressman } else { 1525*40909f66SGal Pressman err = efa_create_pbl(dev, &pbl, mr, ¶ms); 1526*40909f66SGal Pressman if (err) 1527*40909f66SGal Pressman goto err_unmap; 1528*40909f66SGal Pressman 1529*40909f66SGal Pressman err = efa_com_register_mr(&dev->edev, ¶ms, &result); 1530*40909f66SGal Pressman pbl_destroy(dev, &pbl); 1531*40909f66SGal Pressman 1532*40909f66SGal Pressman if (err) 1533*40909f66SGal Pressman goto err_unmap; 1534*40909f66SGal Pressman } 1535*40909f66SGal Pressman 1536*40909f66SGal Pressman mr->ibmr.lkey = result.l_key; 1537*40909f66SGal Pressman mr->ibmr.rkey = result.r_key; 1538*40909f66SGal Pressman mr->ibmr.length = length; 1539*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Registered mr[%d]\n", mr->ibmr.lkey); 1540*40909f66SGal Pressman 1541*40909f66SGal Pressman return &mr->ibmr; 1542*40909f66SGal Pressman 1543*40909f66SGal Pressman err_unmap: 1544*40909f66SGal Pressman ib_umem_release(mr->umem); 1545*40909f66SGal Pressman err_free: 1546*40909f66SGal Pressman kfree(mr); 1547*40909f66SGal Pressman err_out: 1548*40909f66SGal Pressman atomic64_inc(&dev->stats.sw_stats.reg_mr_err); 1549*40909f66SGal Pressman return ERR_PTR(err); 1550*40909f66SGal Pressman } 1551*40909f66SGal Pressman 1552*40909f66SGal Pressman int efa_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata) 1553*40909f66SGal Pressman { 1554*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibmr->device); 1555*40909f66SGal Pressman struct efa_com_dereg_mr_params params; 1556*40909f66SGal Pressman struct efa_mr *mr = to_emr(ibmr); 1557*40909f66SGal Pressman int err; 1558*40909f66SGal Pressman 1559*40909f66SGal Pressman if (udata->inlen && 1560*40909f66SGal Pressman !ib_is_udata_cleared(udata, 0, udata->inlen)) { 1561*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Incompatible ABI params\n"); 1562*40909f66SGal Pressman return -EINVAL; 1563*40909f66SGal Pressman } 1564*40909f66SGal Pressman 1565*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Deregister mr[%d]\n", ibmr->lkey); 1566*40909f66SGal Pressman 1567*40909f66SGal Pressman if (mr->umem) { 1568*40909f66SGal Pressman params.l_key = mr->ibmr.lkey; 1569*40909f66SGal Pressman err = efa_com_dereg_mr(&dev->edev, ¶ms); 1570*40909f66SGal Pressman if (err) 1571*40909f66SGal Pressman return err; 1572*40909f66SGal Pressman ib_umem_release(mr->umem); 1573*40909f66SGal Pressman } 1574*40909f66SGal Pressman 1575*40909f66SGal Pressman kfree(mr); 1576*40909f66SGal Pressman 1577*40909f66SGal Pressman return 0; 1578*40909f66SGal Pressman } 1579*40909f66SGal Pressman 1580*40909f66SGal Pressman int efa_get_port_immutable(struct ib_device *ibdev, u8 port_num, 1581*40909f66SGal Pressman struct ib_port_immutable *immutable) 1582*40909f66SGal Pressman { 1583*40909f66SGal Pressman struct ib_port_attr attr; 1584*40909f66SGal Pressman int err; 1585*40909f66SGal Pressman 1586*40909f66SGal Pressman err = ib_query_port(ibdev, port_num, &attr); 1587*40909f66SGal Pressman if (err) { 1588*40909f66SGal Pressman ibdev_dbg(ibdev, "Couldn't query port err[%d]\n", err); 1589*40909f66SGal Pressman return err; 1590*40909f66SGal Pressman } 1591*40909f66SGal Pressman 1592*40909f66SGal Pressman immutable->pkey_tbl_len = attr.pkey_tbl_len; 1593*40909f66SGal Pressman immutable->gid_tbl_len = attr.gid_tbl_len; 1594*40909f66SGal Pressman 1595*40909f66SGal Pressman return 0; 1596*40909f66SGal Pressman } 1597*40909f66SGal Pressman 1598*40909f66SGal Pressman static int efa_dealloc_uar(struct efa_dev *dev, u16 uarn) 1599*40909f66SGal Pressman { 1600*40909f66SGal Pressman struct efa_com_dealloc_uar_params params = { 1601*40909f66SGal Pressman .uarn = uarn, 1602*40909f66SGal Pressman }; 1603*40909f66SGal Pressman 1604*40909f66SGal Pressman return efa_com_dealloc_uar(&dev->edev, ¶ms); 1605*40909f66SGal Pressman } 1606*40909f66SGal Pressman 1607*40909f66SGal Pressman int efa_alloc_ucontext(struct ib_ucontext *ibucontext, struct ib_udata *udata) 1608*40909f66SGal Pressman { 1609*40909f66SGal Pressman struct efa_ucontext *ucontext = to_eucontext(ibucontext); 1610*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibucontext->device); 1611*40909f66SGal Pressman struct efa_ibv_alloc_ucontext_resp resp = {}; 1612*40909f66SGal Pressman struct efa_com_alloc_uar_result result; 1613*40909f66SGal Pressman int err; 1614*40909f66SGal Pressman 1615*40909f66SGal Pressman /* 1616*40909f66SGal Pressman * it's fine if the driver does not know all request fields, 1617*40909f66SGal Pressman * we will ack input fields in our response. 1618*40909f66SGal Pressman */ 1619*40909f66SGal Pressman 1620*40909f66SGal Pressman err = efa_com_alloc_uar(&dev->edev, &result); 1621*40909f66SGal Pressman if (err) 1622*40909f66SGal Pressman goto err_out; 1623*40909f66SGal Pressman 1624*40909f66SGal Pressman ucontext->uarn = result.uarn; 1625*40909f66SGal Pressman xa_init(&ucontext->mmap_xa); 1626*40909f66SGal Pressman 1627*40909f66SGal Pressman resp.cmds_supp_udata_mask |= EFA_USER_CMDS_SUPP_UDATA_QUERY_DEVICE; 1628*40909f66SGal Pressman resp.cmds_supp_udata_mask |= EFA_USER_CMDS_SUPP_UDATA_CREATE_AH; 1629*40909f66SGal Pressman resp.sub_cqs_per_cq = dev->dev_attr.sub_cqs_per_cq; 1630*40909f66SGal Pressman resp.inline_buf_size = dev->dev_attr.inline_buf_size; 1631*40909f66SGal Pressman resp.max_llq_size = dev->dev_attr.max_llq_size; 1632*40909f66SGal Pressman 1633*40909f66SGal Pressman if (udata && udata->outlen) { 1634*40909f66SGal Pressman err = ib_copy_to_udata(udata, &resp, 1635*40909f66SGal Pressman min(sizeof(resp), udata->outlen)); 1636*40909f66SGal Pressman if (err) 1637*40909f66SGal Pressman goto err_dealloc_uar; 1638*40909f66SGal Pressman } 1639*40909f66SGal Pressman 1640*40909f66SGal Pressman return 0; 1641*40909f66SGal Pressman 1642*40909f66SGal Pressman err_dealloc_uar: 1643*40909f66SGal Pressman efa_dealloc_uar(dev, result.uarn); 1644*40909f66SGal Pressman err_out: 1645*40909f66SGal Pressman atomic64_inc(&dev->stats.sw_stats.alloc_ucontext_err); 1646*40909f66SGal Pressman return err; 1647*40909f66SGal Pressman } 1648*40909f66SGal Pressman 1649*40909f66SGal Pressman void efa_dealloc_ucontext(struct ib_ucontext *ibucontext) 1650*40909f66SGal Pressman { 1651*40909f66SGal Pressman struct efa_ucontext *ucontext = to_eucontext(ibucontext); 1652*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibucontext->device); 1653*40909f66SGal Pressman 1654*40909f66SGal Pressman mmap_entries_remove_free(dev, ucontext); 1655*40909f66SGal Pressman efa_dealloc_uar(dev, ucontext->uarn); 1656*40909f66SGal Pressman } 1657*40909f66SGal Pressman 1658*40909f66SGal Pressman static int __efa_mmap(struct efa_dev *dev, struct efa_ucontext *ucontext, 1659*40909f66SGal Pressman struct vm_area_struct *vma, u64 key, u64 length) 1660*40909f66SGal Pressman { 1661*40909f66SGal Pressman struct efa_mmap_entry *entry; 1662*40909f66SGal Pressman unsigned long va; 1663*40909f66SGal Pressman u64 pfn; 1664*40909f66SGal Pressman int err; 1665*40909f66SGal Pressman 1666*40909f66SGal Pressman entry = mmap_entry_get(dev, ucontext, key, length); 1667*40909f66SGal Pressman if (!entry) { 1668*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "key[%#llx] does not have valid entry\n", 1669*40909f66SGal Pressman key); 1670*40909f66SGal Pressman return -EINVAL; 1671*40909f66SGal Pressman } 1672*40909f66SGal Pressman 1673*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1674*40909f66SGal Pressman "Mapping address[%#llx], length[%#llx], mmap_flag[%d]\n", 1675*40909f66SGal Pressman entry->address, length, entry->mmap_flag); 1676*40909f66SGal Pressman 1677*40909f66SGal Pressman pfn = entry->address >> PAGE_SHIFT; 1678*40909f66SGal Pressman switch (entry->mmap_flag) { 1679*40909f66SGal Pressman case EFA_MMAP_IO_NC: 1680*40909f66SGal Pressman err = rdma_user_mmap_io(&ucontext->ibucontext, vma, pfn, length, 1681*40909f66SGal Pressman pgprot_noncached(vma->vm_page_prot)); 1682*40909f66SGal Pressman break; 1683*40909f66SGal Pressman case EFA_MMAP_IO_WC: 1684*40909f66SGal Pressman err = rdma_user_mmap_io(&ucontext->ibucontext, vma, pfn, length, 1685*40909f66SGal Pressman pgprot_writecombine(vma->vm_page_prot)); 1686*40909f66SGal Pressman break; 1687*40909f66SGal Pressman case EFA_MMAP_DMA_PAGE: 1688*40909f66SGal Pressman for (va = vma->vm_start; va < vma->vm_end; 1689*40909f66SGal Pressman va += PAGE_SIZE, pfn++) { 1690*40909f66SGal Pressman err = vm_insert_page(vma, va, pfn_to_page(pfn)); 1691*40909f66SGal Pressman if (err) 1692*40909f66SGal Pressman break; 1693*40909f66SGal Pressman } 1694*40909f66SGal Pressman break; 1695*40909f66SGal Pressman default: 1696*40909f66SGal Pressman err = -EINVAL; 1697*40909f66SGal Pressman } 1698*40909f66SGal Pressman 1699*40909f66SGal Pressman if (err) 1700*40909f66SGal Pressman ibdev_dbg( 1701*40909f66SGal Pressman &dev->ibdev, 1702*40909f66SGal Pressman "Couldn't mmap address[%#llx] length[%#llx] mmap_flag[%d] err[%d]\n", 1703*40909f66SGal Pressman entry->address, length, entry->mmap_flag, err); 1704*40909f66SGal Pressman 1705*40909f66SGal Pressman return err; 1706*40909f66SGal Pressman } 1707*40909f66SGal Pressman 1708*40909f66SGal Pressman int efa_mmap(struct ib_ucontext *ibucontext, 1709*40909f66SGal Pressman struct vm_area_struct *vma) 1710*40909f66SGal Pressman { 1711*40909f66SGal Pressman struct efa_ucontext *ucontext = to_eucontext(ibucontext); 1712*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibucontext->device); 1713*40909f66SGal Pressman u64 length = vma->vm_end - vma->vm_start; 1714*40909f66SGal Pressman u64 key = vma->vm_pgoff << PAGE_SHIFT; 1715*40909f66SGal Pressman 1716*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1717*40909f66SGal Pressman "start %#lx, end %#lx, length = %#llx, key = %#llx\n", 1718*40909f66SGal Pressman vma->vm_start, vma->vm_end, length, key); 1719*40909f66SGal Pressman 1720*40909f66SGal Pressman if (length % PAGE_SIZE != 0 || !(vma->vm_flags & VM_SHARED)) { 1721*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1722*40909f66SGal Pressman "length[%#llx] is not page size aligned[%#lx] or VM_SHARED is not set [%#lx]\n", 1723*40909f66SGal Pressman length, PAGE_SIZE, vma->vm_flags); 1724*40909f66SGal Pressman return -EINVAL; 1725*40909f66SGal Pressman } 1726*40909f66SGal Pressman 1727*40909f66SGal Pressman if (vma->vm_flags & VM_EXEC) { 1728*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Mapping executable pages is not permitted\n"); 1729*40909f66SGal Pressman return -EPERM; 1730*40909f66SGal Pressman } 1731*40909f66SGal Pressman vma->vm_flags &= ~VM_MAYEXEC; 1732*40909f66SGal Pressman 1733*40909f66SGal Pressman return __efa_mmap(dev, ucontext, vma, key, length); 1734*40909f66SGal Pressman } 1735*40909f66SGal Pressman 1736*40909f66SGal Pressman static int efa_ah_destroy(struct efa_dev *dev, struct efa_ah *ah) 1737*40909f66SGal Pressman { 1738*40909f66SGal Pressman struct efa_com_destroy_ah_params params = { 1739*40909f66SGal Pressman .ah = ah->ah, 1740*40909f66SGal Pressman .pdn = to_epd(ah->ibah.pd)->pdn, 1741*40909f66SGal Pressman }; 1742*40909f66SGal Pressman 1743*40909f66SGal Pressman return efa_com_destroy_ah(&dev->edev, ¶ms); 1744*40909f66SGal Pressman } 1745*40909f66SGal Pressman 1746*40909f66SGal Pressman int efa_create_ah(struct ib_ah *ibah, 1747*40909f66SGal Pressman struct rdma_ah_attr *ah_attr, 1748*40909f66SGal Pressman u32 flags, 1749*40909f66SGal Pressman struct ib_udata *udata) 1750*40909f66SGal Pressman { 1751*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibah->device); 1752*40909f66SGal Pressman struct efa_com_create_ah_params params = {}; 1753*40909f66SGal Pressman struct efa_ibv_create_ah_resp resp = {}; 1754*40909f66SGal Pressman struct efa_com_create_ah_result result; 1755*40909f66SGal Pressman struct efa_ah *ah = to_eah(ibah); 1756*40909f66SGal Pressman int err; 1757*40909f66SGal Pressman 1758*40909f66SGal Pressman if (!(flags & RDMA_CREATE_AH_SLEEPABLE)) { 1759*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1760*40909f66SGal Pressman "Create address handle is not supported in atomic context\n"); 1761*40909f66SGal Pressman err = -EOPNOTSUPP; 1762*40909f66SGal Pressman goto err_out; 1763*40909f66SGal Pressman } 1764*40909f66SGal Pressman 1765*40909f66SGal Pressman if (udata->inlen && 1766*40909f66SGal Pressman !ib_is_udata_cleared(udata, 0, udata->inlen)) { 1767*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Incompatible ABI params\n"); 1768*40909f66SGal Pressman err = -EINVAL; 1769*40909f66SGal Pressman goto err_out; 1770*40909f66SGal Pressman } 1771*40909f66SGal Pressman 1772*40909f66SGal Pressman memcpy(params.dest_addr, ah_attr->grh.dgid.raw, 1773*40909f66SGal Pressman sizeof(params.dest_addr)); 1774*40909f66SGal Pressman params.pdn = to_epd(ibah->pd)->pdn; 1775*40909f66SGal Pressman err = efa_com_create_ah(&dev->edev, ¶ms, &result); 1776*40909f66SGal Pressman if (err) 1777*40909f66SGal Pressman goto err_out; 1778*40909f66SGal Pressman 1779*40909f66SGal Pressman memcpy(ah->id, ah_attr->grh.dgid.raw, sizeof(ah->id)); 1780*40909f66SGal Pressman ah->ah = result.ah; 1781*40909f66SGal Pressman 1782*40909f66SGal Pressman resp.efa_address_handle = result.ah; 1783*40909f66SGal Pressman 1784*40909f66SGal Pressman if (udata->outlen) { 1785*40909f66SGal Pressman err = ib_copy_to_udata(udata, &resp, 1786*40909f66SGal Pressman min(sizeof(resp), udata->outlen)); 1787*40909f66SGal Pressman if (err) { 1788*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1789*40909f66SGal Pressman "Failed to copy udata for create_ah response\n"); 1790*40909f66SGal Pressman goto err_destroy_ah; 1791*40909f66SGal Pressman } 1792*40909f66SGal Pressman } 1793*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Created ah[%d]\n", ah->ah); 1794*40909f66SGal Pressman 1795*40909f66SGal Pressman return 0; 1796*40909f66SGal Pressman 1797*40909f66SGal Pressman err_destroy_ah: 1798*40909f66SGal Pressman efa_ah_destroy(dev, ah); 1799*40909f66SGal Pressman err_out: 1800*40909f66SGal Pressman atomic64_inc(&dev->stats.sw_stats.create_ah_err); 1801*40909f66SGal Pressman return err; 1802*40909f66SGal Pressman } 1803*40909f66SGal Pressman 1804*40909f66SGal Pressman void efa_destroy_ah(struct ib_ah *ibah, u32 flags) 1805*40909f66SGal Pressman { 1806*40909f66SGal Pressman struct efa_dev *dev = to_edev(ibah->pd->device); 1807*40909f66SGal Pressman struct efa_ah *ah = to_eah(ibah); 1808*40909f66SGal Pressman 1809*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, "Destroy ah[%d]\n", ah->ah); 1810*40909f66SGal Pressman 1811*40909f66SGal Pressman if (!(flags & RDMA_DESTROY_AH_SLEEPABLE)) { 1812*40909f66SGal Pressman ibdev_dbg(&dev->ibdev, 1813*40909f66SGal Pressman "Destroy address handle is not supported in atomic context\n"); 1814*40909f66SGal Pressman return; 1815*40909f66SGal Pressman } 1816*40909f66SGal Pressman 1817*40909f66SGal Pressman efa_ah_destroy(dev, ah); 1818*40909f66SGal Pressman } 1819*40909f66SGal Pressman 1820*40909f66SGal Pressman enum rdma_link_layer efa_port_link_layer(struct ib_device *ibdev, 1821*40909f66SGal Pressman u8 port_num) 1822*40909f66SGal Pressman { 1823*40909f66SGal Pressman return IB_LINK_LAYER_UNSPECIFIED; 1824*40909f66SGal Pressman } 1825*40909f66SGal Pressman 1826