blob: ee9edd7dc446ae6a879120c0b7ef709ec0db652c [file] [log] [blame] [edit]
/*
* Broadcom NetXtreme-E User Space RoCE driver
*
* Copyright (c) 2015-2017, Broadcom. All rights reserved. The term
* Broadcom refers to Broadcom Limited and/or its subsidiaries.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* BSD license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Description: Device detection and initializatoin
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "main.h"
#include "verbs.h"
static void bnxt_re_free_context(struct ibv_context *ibvctx);
#define PCI_VENDOR_ID_BROADCOM 0x14E4
#define CNA(v, d) VERBS_PCI_MATCH(PCI_VENDOR_ID_##v, d, NULL)
static const struct verbs_match_ent cna_table[] = {
VERBS_DRIVER_ID(RDMA_DRIVER_BNXT_RE),
CNA(BROADCOM, 0x1605), /* BCM57454 NPAR */
CNA(BROADCOM, 0x1606), /* BCM57454 VF */
CNA(BROADCOM, 0x1614), /* BCM57454 */
CNA(BROADCOM, 0x16C0), /* BCM57417 NPAR */
CNA(BROADCOM, 0x16C1), /* BMC57414 VF */
CNA(BROADCOM, 0x16CE), /* BMC57311 */
CNA(BROADCOM, 0x16CF), /* BMC57312 */
CNA(BROADCOM, 0x16D6), /* BMC57412*/
CNA(BROADCOM, 0x16D7), /* BMC57414 */
CNA(BROADCOM, 0x16D8), /* BMC57416 Cu */
CNA(BROADCOM, 0x16D9), /* BMC57417 Cu */
CNA(BROADCOM, 0x16DF), /* BMC57314 */
CNA(BROADCOM, 0x16E2), /* BMC57417 */
CNA(BROADCOM, 0x16E3), /* BMC57416 */
CNA(BROADCOM, 0x16E5), /* BMC57314 VF */
CNA(BROADCOM, 0x16ED), /* BCM57414 NPAR */
CNA(BROADCOM, 0x16EB), /* BCM57412 NPAR */
CNA(BROADCOM, 0x16EF), /* BCM57416 NPAR */
CNA(BROADCOM, 0x16F0), /* BCM58730 */
CNA(BROADCOM, 0x16F1), /* BCM57452 */
CNA(BROADCOM, 0x1750), /* BCM57508 */
CNA(BROADCOM, 0x1751), /* BCM57504 */
CNA(BROADCOM, 0x1752), /* BCM57502 */
CNA(BROADCOM, 0x1803), /* BCM57508 NPAR */
CNA(BROADCOM, 0x1804), /* BCM57504 NPAR */
CNA(BROADCOM, 0x1805), /* BCM57502 NPAR */
CNA(BROADCOM, 0x1807), /* BCM5750x VF */
CNA(BROADCOM, 0xD800), /* BCM880xx VF */
CNA(BROADCOM, 0xD802), /* BCM58802 */
CNA(BROADCOM, 0xD804), /* BCM8804 SR */
{}
};
static const struct verbs_context_ops bnxt_re_cntx_ops = {
.query_device_ex = bnxt_re_query_device,
.query_port = bnxt_re_query_port,
.alloc_pd = bnxt_re_alloc_pd,
.dealloc_pd = bnxt_re_free_pd,
.reg_mr = bnxt_re_reg_mr,
.dereg_mr = bnxt_re_dereg_mr,
.create_cq = bnxt_re_create_cq,
.poll_cq = bnxt_re_poll_cq,
.req_notify_cq = bnxt_re_arm_cq,
.destroy_cq = bnxt_re_destroy_cq,
.create_srq = bnxt_re_create_srq,
.modify_srq = bnxt_re_modify_srq,
.query_srq = bnxt_re_query_srq,
.destroy_srq = bnxt_re_destroy_srq,
.post_srq_recv = bnxt_re_post_srq_recv,
.create_qp = bnxt_re_create_qp,
.query_qp = bnxt_re_query_qp,
.modify_qp = bnxt_re_modify_qp,
.destroy_qp = bnxt_re_destroy_qp,
.post_send = bnxt_re_post_send,
.post_recv = bnxt_re_post_recv,
.create_ah = bnxt_re_create_ah,
.destroy_ah = bnxt_re_destroy_ah,
.free_context = bnxt_re_free_context,
};
bool bnxt_re_is_chip_gen_p5(struct bnxt_re_chip_ctx *cctx)
{
return (cctx->chip_num == CHIP_NUM_57508 ||
cctx->chip_num == CHIP_NUM_57504 ||
cctx->chip_num == CHIP_NUM_57502);
}
/* Context Init functions */
static struct verbs_context *bnxt_re_alloc_context(struct ibv_device *vdev,
int cmd_fd,
void *private_data)
{
struct bnxt_re_dev *rdev = to_bnxt_re_dev(vdev);
struct ubnxt_re_cntx_resp resp;
struct bnxt_re_context *cntx;
struct ibv_get_context cmd;
int ret;
cntx = verbs_init_and_alloc_context(vdev, cmd_fd, cntx, ibvctx,
RDMA_DRIVER_BNXT_RE);
if (!cntx)
return NULL;
memset(&resp, 0, sizeof(resp));
if (ibv_cmd_get_context(&cntx->ibvctx, &cmd, sizeof(cmd),
&resp.ibv_resp, sizeof(resp)))
goto failed;
cntx->dev_id = resp.dev_id;
cntx->max_qp = resp.max_qp;
rdev->pg_size = resp.pg_size;
rdev->cqe_size = resp.cqe_sz;
rdev->max_cq_depth = resp.max_cqd;
if (resp.comp_mask & BNXT_RE_UCNTX_CMASK_HAVE_CCTX) {
cntx->cctx.chip_num = resp.chip_id0 & 0xFFFF;
cntx->cctx.chip_rev = (resp.chip_id0 >>
BNXT_RE_CHIP_ID0_CHIP_REV_SFT) & 0xFF;
cntx->cctx.chip_metal = (resp.chip_id0 >>
BNXT_RE_CHIP_ID0_CHIP_MET_SFT) &
0xFF;
}
if (resp.comp_mask & BNXT_RE_UCNTX_CMASK_HAVE_MODE)
cntx->wqe_mode = resp.mode;
pthread_spin_init(&cntx->fqlock, PTHREAD_PROCESS_PRIVATE);
/* mmap shared page. */
cntx->shpg = mmap(NULL, rdev->pg_size, PROT_READ | PROT_WRITE,
MAP_SHARED, cmd_fd, 0);
if (cntx->shpg == MAP_FAILED) {
cntx->shpg = NULL;
goto failed;
}
pthread_mutex_init(&cntx->shlock, NULL);
verbs_set_ops(&cntx->ibvctx, &bnxt_re_cntx_ops);
cntx->rdev = rdev;
ret = ibv_query_device(&cntx->ibvctx.context, &rdev->devattr);
if (ret)
goto failed;
return &cntx->ibvctx;
failed:
verbs_uninit_context(&cntx->ibvctx);
free(cntx);
return NULL;
}
static void bnxt_re_free_context(struct ibv_context *ibvctx)
{
struct bnxt_re_context *cntx = to_bnxt_re_context(ibvctx);
struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibvctx->device);
/* Unmap if anything device specific was mapped in init_context. */
pthread_mutex_destroy(&cntx->shlock);
if (cntx->shpg)
munmap(cntx->shpg, rdev->pg_size);
pthread_spin_destroy(&cntx->fqlock);
/* Un-map DPI only for the first PD that was
* allocated in this context.
*/
if (cntx->udpi.dbpage && cntx->udpi.dbpage != MAP_FAILED) {
munmap(cntx->udpi.dbpage, rdev->pg_size);
cntx->udpi.dbpage = NULL;
}
verbs_uninit_context(&cntx->ibvctx);
free(cntx);
}
static struct verbs_device *
bnxt_re_device_alloc(struct verbs_sysfs_dev *sysfs_dev)
{
struct bnxt_re_dev *rdev;
rdev = calloc(1, sizeof(*rdev));
if (!rdev)
return NULL;
return &rdev->vdev;
}
static const struct verbs_device_ops bnxt_re_dev_ops = {
.name = "bnxt_re",
.match_min_abi_version = BNXT_RE_ABI_VERSION,
.match_max_abi_version = BNXT_RE_ABI_VERSION,
.match_table = cna_table,
.alloc_device = bnxt_re_device_alloc,
.alloc_context = bnxt_re_alloc_context,
};
PROVIDER_DRIVER(bnxt_re, bnxt_re_dev_ops);