162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2022, Microsoft Corporation. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include "mana_ib.h" 762306a36Sopenharmony_ci 862306a36Sopenharmony_cistatic int mana_ib_cfg_vport_steering(struct mana_ib_dev *dev, 962306a36Sopenharmony_ci struct net_device *ndev, 1062306a36Sopenharmony_ci mana_handle_t default_rxobj, 1162306a36Sopenharmony_ci mana_handle_t ind_table[], 1262306a36Sopenharmony_ci u32 log_ind_tbl_size, u32 rx_hash_key_len, 1362306a36Sopenharmony_ci u8 *rx_hash_key) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci struct mana_port_context *mpc = netdev_priv(ndev); 1662306a36Sopenharmony_ci struct mana_cfg_rx_steer_req_v2 *req; 1762306a36Sopenharmony_ci struct mana_cfg_rx_steer_resp resp = {}; 1862306a36Sopenharmony_ci mana_handle_t *req_indir_tab; 1962306a36Sopenharmony_ci struct gdma_context *gc; 2062306a36Sopenharmony_ci struct gdma_dev *mdev; 2162306a36Sopenharmony_ci u32 req_buf_size; 2262306a36Sopenharmony_ci int i, err; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci mdev = dev->gdma_dev; 2562306a36Sopenharmony_ci gc = mdev->gdma_context; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci req_buf_size = 2862306a36Sopenharmony_ci sizeof(*req) + sizeof(mana_handle_t) * MANA_INDIRECT_TABLE_SIZE; 2962306a36Sopenharmony_ci req = kzalloc(req_buf_size, GFP_KERNEL); 3062306a36Sopenharmony_ci if (!req) 3162306a36Sopenharmony_ci return -ENOMEM; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci mana_gd_init_req_hdr(&req->hdr, MANA_CONFIG_VPORT_RX, req_buf_size, 3462306a36Sopenharmony_ci sizeof(resp)); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci req->hdr.req.msg_version = GDMA_MESSAGE_V2; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci req->vport = mpc->port_handle; 3962306a36Sopenharmony_ci req->rx_enable = 1; 4062306a36Sopenharmony_ci req->update_default_rxobj = 1; 4162306a36Sopenharmony_ci req->default_rxobj = default_rxobj; 4262306a36Sopenharmony_ci req->hdr.dev_id = mdev->dev_id; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci /* If there are more than 1 entries in indirection table, enable RSS */ 4562306a36Sopenharmony_ci if (log_ind_tbl_size) 4662306a36Sopenharmony_ci req->rss_enable = true; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci req->num_indir_entries = MANA_INDIRECT_TABLE_SIZE; 4962306a36Sopenharmony_ci req->indir_tab_offset = sizeof(*req); 5062306a36Sopenharmony_ci req->update_indir_tab = true; 5162306a36Sopenharmony_ci req->cqe_coalescing_enable = 1; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci req_indir_tab = (mana_handle_t *)(req + 1); 5462306a36Sopenharmony_ci /* The ind table passed to the hardware must have 5562306a36Sopenharmony_ci * MANA_INDIRECT_TABLE_SIZE entries. Adjust the verb 5662306a36Sopenharmony_ci * ind_table to MANA_INDIRECT_TABLE_SIZE if required 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, "ind table size %u\n", 1 << log_ind_tbl_size); 5962306a36Sopenharmony_ci for (i = 0; i < MANA_INDIRECT_TABLE_SIZE; i++) { 6062306a36Sopenharmony_ci req_indir_tab[i] = ind_table[i % (1 << log_ind_tbl_size)]; 6162306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, "index %u handle 0x%llx\n", i, 6262306a36Sopenharmony_ci req_indir_tab[i]); 6362306a36Sopenharmony_ci } 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci req->update_hashkey = true; 6662306a36Sopenharmony_ci if (rx_hash_key_len) 6762306a36Sopenharmony_ci memcpy(req->hashkey, rx_hash_key, rx_hash_key_len); 6862306a36Sopenharmony_ci else 6962306a36Sopenharmony_ci netdev_rss_key_fill(req->hashkey, MANA_HASH_KEY_SIZE); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci ibdev_dbg(&dev->ib_dev, "vport handle %llu default_rxobj 0x%llx\n", 7262306a36Sopenharmony_ci req->vport, default_rxobj); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci err = mana_gd_send_request(gc, req_buf_size, req, sizeof(resp), &resp); 7562306a36Sopenharmony_ci if (err) { 7662306a36Sopenharmony_ci netdev_err(ndev, "Failed to configure vPort RX: %d\n", err); 7762306a36Sopenharmony_ci goto out; 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci if (resp.hdr.status) { 8162306a36Sopenharmony_ci netdev_err(ndev, "vPort RX configuration failed: 0x%x\n", 8262306a36Sopenharmony_ci resp.hdr.status); 8362306a36Sopenharmony_ci err = -EPROTO; 8462306a36Sopenharmony_ci goto out; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci netdev_info(ndev, "Configured steering vPort %llu log_entries %u\n", 8862306a36Sopenharmony_ci mpc->port_handle, log_ind_tbl_size); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ciout: 9162306a36Sopenharmony_ci kfree(req); 9262306a36Sopenharmony_ci return err; 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd, 9662306a36Sopenharmony_ci struct ib_qp_init_attr *attr, 9762306a36Sopenharmony_ci struct ib_udata *udata) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci struct mana_ib_qp *qp = container_of(ibqp, struct mana_ib_qp, ibqp); 10062306a36Sopenharmony_ci struct mana_ib_dev *mdev = 10162306a36Sopenharmony_ci container_of(pd->device, struct mana_ib_dev, ib_dev); 10262306a36Sopenharmony_ci struct ib_rwq_ind_table *ind_tbl = attr->rwq_ind_tbl; 10362306a36Sopenharmony_ci struct mana_ib_create_qp_rss_resp resp = {}; 10462306a36Sopenharmony_ci struct mana_ib_create_qp_rss ucmd = {}; 10562306a36Sopenharmony_ci struct gdma_dev *gd = mdev->gdma_dev; 10662306a36Sopenharmony_ci mana_handle_t *mana_ind_table; 10762306a36Sopenharmony_ci struct mana_port_context *mpc; 10862306a36Sopenharmony_ci struct mana_context *mc; 10962306a36Sopenharmony_ci struct net_device *ndev; 11062306a36Sopenharmony_ci struct mana_ib_cq *cq; 11162306a36Sopenharmony_ci struct mana_ib_wq *wq; 11262306a36Sopenharmony_ci unsigned int ind_tbl_size; 11362306a36Sopenharmony_ci struct ib_cq *ibcq; 11462306a36Sopenharmony_ci struct ib_wq *ibwq; 11562306a36Sopenharmony_ci int i = 0; 11662306a36Sopenharmony_ci u32 port; 11762306a36Sopenharmony_ci int ret; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci mc = gd->driver_data; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci if (!udata || udata->inlen < sizeof(ucmd)) 12262306a36Sopenharmony_ci return -EINVAL; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci ret = ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata->inlen)); 12562306a36Sopenharmony_ci if (ret) { 12662306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 12762306a36Sopenharmony_ci "Failed copy from udata for create rss-qp, err %d\n", 12862306a36Sopenharmony_ci ret); 12962306a36Sopenharmony_ci return ret; 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci if (attr->cap.max_recv_wr > MAX_SEND_BUFFERS_PER_QUEUE) { 13362306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 13462306a36Sopenharmony_ci "Requested max_recv_wr %d exceeding limit\n", 13562306a36Sopenharmony_ci attr->cap.max_recv_wr); 13662306a36Sopenharmony_ci return -EINVAL; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci if (attr->cap.max_recv_sge > MAX_RX_WQE_SGL_ENTRIES) { 14062306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 14162306a36Sopenharmony_ci "Requested max_recv_sge %d exceeding limit\n", 14262306a36Sopenharmony_ci attr->cap.max_recv_sge); 14362306a36Sopenharmony_ci return -EINVAL; 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci ind_tbl_size = 1 << ind_tbl->log_ind_tbl_size; 14762306a36Sopenharmony_ci if (ind_tbl_size > MANA_INDIRECT_TABLE_SIZE) { 14862306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 14962306a36Sopenharmony_ci "Indirect table size %d exceeding limit\n", 15062306a36Sopenharmony_ci ind_tbl_size); 15162306a36Sopenharmony_ci return -EINVAL; 15262306a36Sopenharmony_ci } 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci if (ucmd.rx_hash_function != MANA_IB_RX_HASH_FUNC_TOEPLITZ) { 15562306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 15662306a36Sopenharmony_ci "RX Hash function is not supported, %d\n", 15762306a36Sopenharmony_ci ucmd.rx_hash_function); 15862306a36Sopenharmony_ci return -EINVAL; 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* IB ports start with 1, MANA start with 0 */ 16262306a36Sopenharmony_ci port = ucmd.port; 16362306a36Sopenharmony_ci if (port < 1 || port > mc->num_ports) { 16462306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, "Invalid port %u in creating qp\n", 16562306a36Sopenharmony_ci port); 16662306a36Sopenharmony_ci return -EINVAL; 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci ndev = mc->ports[port - 1]; 16962306a36Sopenharmony_ci mpc = netdev_priv(ndev); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, "rx_hash_function %d port %d\n", 17262306a36Sopenharmony_ci ucmd.rx_hash_function, port); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci mana_ind_table = kcalloc(ind_tbl_size, sizeof(mana_handle_t), 17562306a36Sopenharmony_ci GFP_KERNEL); 17662306a36Sopenharmony_ci if (!mana_ind_table) { 17762306a36Sopenharmony_ci ret = -ENOMEM; 17862306a36Sopenharmony_ci goto fail; 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci qp->port = port; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci for (i = 0; i < ind_tbl_size; i++) { 18462306a36Sopenharmony_ci struct mana_obj_spec wq_spec = {}; 18562306a36Sopenharmony_ci struct mana_obj_spec cq_spec = {}; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci ibwq = ind_tbl->ind_tbl[i]; 18862306a36Sopenharmony_ci wq = container_of(ibwq, struct mana_ib_wq, ibwq); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci ibcq = ibwq->cq; 19162306a36Sopenharmony_ci cq = container_of(ibcq, struct mana_ib_cq, ibcq); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci wq_spec.gdma_region = wq->gdma_region; 19462306a36Sopenharmony_ci wq_spec.queue_size = wq->wq_buf_size; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci cq_spec.gdma_region = cq->gdma_region; 19762306a36Sopenharmony_ci cq_spec.queue_size = cq->cqe * COMP_ENTRY_SIZE; 19862306a36Sopenharmony_ci cq_spec.modr_ctx_id = 0; 19962306a36Sopenharmony_ci cq_spec.attached_eq = GDMA_CQ_NO_EQ; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci ret = mana_create_wq_obj(mpc, mpc->port_handle, GDMA_RQ, 20262306a36Sopenharmony_ci &wq_spec, &cq_spec, &wq->rx_object); 20362306a36Sopenharmony_ci if (ret) 20462306a36Sopenharmony_ci goto fail; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci /* The GDMA regions are now owned by the WQ object */ 20762306a36Sopenharmony_ci wq->gdma_region = GDMA_INVALID_DMA_REGION; 20862306a36Sopenharmony_ci cq->gdma_region = GDMA_INVALID_DMA_REGION; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci wq->id = wq_spec.queue_index; 21162306a36Sopenharmony_ci cq->id = cq_spec.queue_index; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 21462306a36Sopenharmony_ci "ret %d rx_object 0x%llx wq id %llu cq id %llu\n", 21562306a36Sopenharmony_ci ret, wq->rx_object, wq->id, cq->id); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci resp.entries[i].cqid = cq->id; 21862306a36Sopenharmony_ci resp.entries[i].wqid = wq->id; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci mana_ind_table[i] = wq->rx_object; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci resp.num_entries = i; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci ret = mana_ib_cfg_vport_steering(mdev, ndev, wq->rx_object, 22562306a36Sopenharmony_ci mana_ind_table, 22662306a36Sopenharmony_ci ind_tbl->log_ind_tbl_size, 22762306a36Sopenharmony_ci ucmd.rx_hash_key_len, 22862306a36Sopenharmony_ci ucmd.rx_hash_key); 22962306a36Sopenharmony_ci if (ret) 23062306a36Sopenharmony_ci goto fail; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci ret = ib_copy_to_udata(udata, &resp, sizeof(resp)); 23362306a36Sopenharmony_ci if (ret) { 23462306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 23562306a36Sopenharmony_ci "Failed to copy to udata create rss-qp, %d\n", 23662306a36Sopenharmony_ci ret); 23762306a36Sopenharmony_ci goto fail; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci kfree(mana_ind_table); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci return 0; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cifail: 24562306a36Sopenharmony_ci while (i-- > 0) { 24662306a36Sopenharmony_ci ibwq = ind_tbl->ind_tbl[i]; 24762306a36Sopenharmony_ci wq = container_of(ibwq, struct mana_ib_wq, ibwq); 24862306a36Sopenharmony_ci mana_destroy_wq_obj(mpc, GDMA_RQ, wq->rx_object); 24962306a36Sopenharmony_ci } 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci kfree(mana_ind_table); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci return ret; 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd, 25762306a36Sopenharmony_ci struct ib_qp_init_attr *attr, 25862306a36Sopenharmony_ci struct ib_udata *udata) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci struct mana_ib_pd *pd = container_of(ibpd, struct mana_ib_pd, ibpd); 26162306a36Sopenharmony_ci struct mana_ib_qp *qp = container_of(ibqp, struct mana_ib_qp, ibqp); 26262306a36Sopenharmony_ci struct mana_ib_dev *mdev = 26362306a36Sopenharmony_ci container_of(ibpd->device, struct mana_ib_dev, ib_dev); 26462306a36Sopenharmony_ci struct mana_ib_cq *send_cq = 26562306a36Sopenharmony_ci container_of(attr->send_cq, struct mana_ib_cq, ibcq); 26662306a36Sopenharmony_ci struct mana_ib_ucontext *mana_ucontext = 26762306a36Sopenharmony_ci rdma_udata_to_drv_context(udata, struct mana_ib_ucontext, 26862306a36Sopenharmony_ci ibucontext); 26962306a36Sopenharmony_ci struct mana_ib_create_qp_resp resp = {}; 27062306a36Sopenharmony_ci struct gdma_dev *gd = mdev->gdma_dev; 27162306a36Sopenharmony_ci struct mana_ib_create_qp ucmd = {}; 27262306a36Sopenharmony_ci struct mana_obj_spec wq_spec = {}; 27362306a36Sopenharmony_ci struct mana_obj_spec cq_spec = {}; 27462306a36Sopenharmony_ci struct mana_port_context *mpc; 27562306a36Sopenharmony_ci struct mana_context *mc; 27662306a36Sopenharmony_ci struct net_device *ndev; 27762306a36Sopenharmony_ci struct ib_umem *umem; 27862306a36Sopenharmony_ci int err; 27962306a36Sopenharmony_ci u32 port; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci mc = gd->driver_data; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci if (!mana_ucontext || udata->inlen < sizeof(ucmd)) 28462306a36Sopenharmony_ci return -EINVAL; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci err = ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata->inlen)); 28762306a36Sopenharmony_ci if (err) { 28862306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 28962306a36Sopenharmony_ci "Failed to copy from udata create qp-raw, %d\n", err); 29062306a36Sopenharmony_ci return err; 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci /* IB ports start with 1, MANA Ethernet ports start with 0 */ 29462306a36Sopenharmony_ci port = ucmd.port; 29562306a36Sopenharmony_ci if (port < 1 || port > mc->num_ports) 29662306a36Sopenharmony_ci return -EINVAL; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci if (attr->cap.max_send_wr > MAX_SEND_BUFFERS_PER_QUEUE) { 29962306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 30062306a36Sopenharmony_ci "Requested max_send_wr %d exceeding limit\n", 30162306a36Sopenharmony_ci attr->cap.max_send_wr); 30262306a36Sopenharmony_ci return -EINVAL; 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci if (attr->cap.max_send_sge > MAX_TX_WQE_SGL_ENTRIES) { 30662306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 30762306a36Sopenharmony_ci "Requested max_send_sge %d exceeding limit\n", 30862306a36Sopenharmony_ci attr->cap.max_send_sge); 30962306a36Sopenharmony_ci return -EINVAL; 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci ndev = mc->ports[port - 1]; 31362306a36Sopenharmony_ci mpc = netdev_priv(ndev); 31462306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, "port %u ndev %p mpc %p\n", port, ndev, mpc); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci err = mana_ib_cfg_vport(mdev, port - 1, pd, mana_ucontext->doorbell); 31762306a36Sopenharmony_ci if (err) 31862306a36Sopenharmony_ci return -ENODEV; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci qp->port = port; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, "ucmd sq_buf_addr 0x%llx port %u\n", 32362306a36Sopenharmony_ci ucmd.sq_buf_addr, ucmd.port); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci umem = ib_umem_get(ibpd->device, ucmd.sq_buf_addr, ucmd.sq_buf_size, 32662306a36Sopenharmony_ci IB_ACCESS_LOCAL_WRITE); 32762306a36Sopenharmony_ci if (IS_ERR(umem)) { 32862306a36Sopenharmony_ci err = PTR_ERR(umem); 32962306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 33062306a36Sopenharmony_ci "Failed to get umem for create qp-raw, err %d\n", 33162306a36Sopenharmony_ci err); 33262306a36Sopenharmony_ci goto err_free_vport; 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci qp->sq_umem = umem; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci err = mana_ib_gd_create_dma_region(mdev, qp->sq_umem, 33762306a36Sopenharmony_ci &qp->sq_gdma_region); 33862306a36Sopenharmony_ci if (err) { 33962306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 34062306a36Sopenharmony_ci "Failed to create dma region for create qp-raw, %d\n", 34162306a36Sopenharmony_ci err); 34262306a36Sopenharmony_ci goto err_release_umem; 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 34662306a36Sopenharmony_ci "mana_ib_gd_create_dma_region ret %d gdma_region 0x%llx\n", 34762306a36Sopenharmony_ci err, qp->sq_gdma_region); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci /* Create a WQ on the same port handle used by the Ethernet */ 35062306a36Sopenharmony_ci wq_spec.gdma_region = qp->sq_gdma_region; 35162306a36Sopenharmony_ci wq_spec.queue_size = ucmd.sq_buf_size; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci cq_spec.gdma_region = send_cq->gdma_region; 35462306a36Sopenharmony_ci cq_spec.queue_size = send_cq->cqe * COMP_ENTRY_SIZE; 35562306a36Sopenharmony_ci cq_spec.modr_ctx_id = 0; 35662306a36Sopenharmony_ci cq_spec.attached_eq = GDMA_CQ_NO_EQ; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci err = mana_create_wq_obj(mpc, mpc->port_handle, GDMA_SQ, &wq_spec, 35962306a36Sopenharmony_ci &cq_spec, &qp->tx_object); 36062306a36Sopenharmony_ci if (err) { 36162306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 36262306a36Sopenharmony_ci "Failed to create wq for create raw-qp, err %d\n", 36362306a36Sopenharmony_ci err); 36462306a36Sopenharmony_ci goto err_destroy_dma_region; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci /* The GDMA regions are now owned by the WQ object */ 36862306a36Sopenharmony_ci qp->sq_gdma_region = GDMA_INVALID_DMA_REGION; 36962306a36Sopenharmony_ci send_cq->gdma_region = GDMA_INVALID_DMA_REGION; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci qp->sq_id = wq_spec.queue_index; 37262306a36Sopenharmony_ci send_cq->id = cq_spec.queue_index; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 37562306a36Sopenharmony_ci "ret %d qp->tx_object 0x%llx sq id %llu cq id %llu\n", err, 37662306a36Sopenharmony_ci qp->tx_object, qp->sq_id, send_cq->id); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci resp.sqid = qp->sq_id; 37962306a36Sopenharmony_ci resp.cqid = send_cq->id; 38062306a36Sopenharmony_ci resp.tx_vp_offset = pd->tx_vp_offset; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci err = ib_copy_to_udata(udata, &resp, sizeof(resp)); 38362306a36Sopenharmony_ci if (err) { 38462306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, 38562306a36Sopenharmony_ci "Failed copy udata for create qp-raw, %d\n", 38662306a36Sopenharmony_ci err); 38762306a36Sopenharmony_ci goto err_destroy_wq_obj; 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci return 0; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cierr_destroy_wq_obj: 39362306a36Sopenharmony_ci mana_destroy_wq_obj(mpc, GDMA_SQ, qp->tx_object); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_cierr_destroy_dma_region: 39662306a36Sopenharmony_ci mana_ib_gd_destroy_dma_region(mdev, qp->sq_gdma_region); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_cierr_release_umem: 39962306a36Sopenharmony_ci ib_umem_release(umem); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_cierr_free_vport: 40262306a36Sopenharmony_ci mana_ib_uncfg_vport(mdev, pd, port - 1); 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci return err; 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ciint mana_ib_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr, 40862306a36Sopenharmony_ci struct ib_udata *udata) 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci switch (attr->qp_type) { 41162306a36Sopenharmony_ci case IB_QPT_RAW_PACKET: 41262306a36Sopenharmony_ci /* When rwq_ind_tbl is used, it's for creating WQs for RSS */ 41362306a36Sopenharmony_ci if (attr->rwq_ind_tbl) 41462306a36Sopenharmony_ci return mana_ib_create_qp_rss(ibqp, ibqp->pd, attr, 41562306a36Sopenharmony_ci udata); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci return mana_ib_create_qp_raw(ibqp, ibqp->pd, attr, udata); 41862306a36Sopenharmony_ci default: 41962306a36Sopenharmony_ci /* Creating QP other than IB_QPT_RAW_PACKET is not supported */ 42062306a36Sopenharmony_ci ibdev_dbg(ibqp->device, "Creating QP type %u not supported\n", 42162306a36Sopenharmony_ci attr->qp_type); 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci return -EINVAL; 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ciint mana_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, 42862306a36Sopenharmony_ci int attr_mask, struct ib_udata *udata) 42962306a36Sopenharmony_ci{ 43062306a36Sopenharmony_ci /* modify_qp is not supported by this version of the driver */ 43162306a36Sopenharmony_ci return -EOPNOTSUPP; 43262306a36Sopenharmony_ci} 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_cistatic int mana_ib_destroy_qp_rss(struct mana_ib_qp *qp, 43562306a36Sopenharmony_ci struct ib_rwq_ind_table *ind_tbl, 43662306a36Sopenharmony_ci struct ib_udata *udata) 43762306a36Sopenharmony_ci{ 43862306a36Sopenharmony_ci struct mana_ib_dev *mdev = 43962306a36Sopenharmony_ci container_of(qp->ibqp.device, struct mana_ib_dev, ib_dev); 44062306a36Sopenharmony_ci struct gdma_dev *gd = mdev->gdma_dev; 44162306a36Sopenharmony_ci struct mana_port_context *mpc; 44262306a36Sopenharmony_ci struct mana_context *mc; 44362306a36Sopenharmony_ci struct net_device *ndev; 44462306a36Sopenharmony_ci struct mana_ib_wq *wq; 44562306a36Sopenharmony_ci struct ib_wq *ibwq; 44662306a36Sopenharmony_ci int i; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci mc = gd->driver_data; 44962306a36Sopenharmony_ci ndev = mc->ports[qp->port - 1]; 45062306a36Sopenharmony_ci mpc = netdev_priv(ndev); 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci for (i = 0; i < (1 << ind_tbl->log_ind_tbl_size); i++) { 45362306a36Sopenharmony_ci ibwq = ind_tbl->ind_tbl[i]; 45462306a36Sopenharmony_ci wq = container_of(ibwq, struct mana_ib_wq, ibwq); 45562306a36Sopenharmony_ci ibdev_dbg(&mdev->ib_dev, "destroying wq->rx_object %llu\n", 45662306a36Sopenharmony_ci wq->rx_object); 45762306a36Sopenharmony_ci mana_destroy_wq_obj(mpc, GDMA_RQ, wq->rx_object); 45862306a36Sopenharmony_ci } 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci return 0; 46162306a36Sopenharmony_ci} 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_cistatic int mana_ib_destroy_qp_raw(struct mana_ib_qp *qp, struct ib_udata *udata) 46462306a36Sopenharmony_ci{ 46562306a36Sopenharmony_ci struct mana_ib_dev *mdev = 46662306a36Sopenharmony_ci container_of(qp->ibqp.device, struct mana_ib_dev, ib_dev); 46762306a36Sopenharmony_ci struct gdma_dev *gd = mdev->gdma_dev; 46862306a36Sopenharmony_ci struct ib_pd *ibpd = qp->ibqp.pd; 46962306a36Sopenharmony_ci struct mana_port_context *mpc; 47062306a36Sopenharmony_ci struct mana_context *mc; 47162306a36Sopenharmony_ci struct net_device *ndev; 47262306a36Sopenharmony_ci struct mana_ib_pd *pd; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci mc = gd->driver_data; 47562306a36Sopenharmony_ci ndev = mc->ports[qp->port - 1]; 47662306a36Sopenharmony_ci mpc = netdev_priv(ndev); 47762306a36Sopenharmony_ci pd = container_of(ibpd, struct mana_ib_pd, ibpd); 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci mana_destroy_wq_obj(mpc, GDMA_SQ, qp->tx_object); 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci if (qp->sq_umem) { 48262306a36Sopenharmony_ci mana_ib_gd_destroy_dma_region(mdev, qp->sq_gdma_region); 48362306a36Sopenharmony_ci ib_umem_release(qp->sq_umem); 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci mana_ib_uncfg_vport(mdev, pd, qp->port - 1); 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci return 0; 48962306a36Sopenharmony_ci} 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ciint mana_ib_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata) 49262306a36Sopenharmony_ci{ 49362306a36Sopenharmony_ci struct mana_ib_qp *qp = container_of(ibqp, struct mana_ib_qp, ibqp); 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci switch (ibqp->qp_type) { 49662306a36Sopenharmony_ci case IB_QPT_RAW_PACKET: 49762306a36Sopenharmony_ci if (ibqp->rwq_ind_tbl) 49862306a36Sopenharmony_ci return mana_ib_destroy_qp_rss(qp, ibqp->rwq_ind_tbl, 49962306a36Sopenharmony_ci udata); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci return mana_ib_destroy_qp_raw(qp, udata); 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci default: 50462306a36Sopenharmony_ci ibdev_dbg(ibqp->device, "Unexpected QP type %u\n", 50562306a36Sopenharmony_ci ibqp->qp_type); 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci return -ENOENT; 50962306a36Sopenharmony_ci} 510